version 5.9.0
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0b6477e..134063d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+## V 5.9.0
+- FEATURE: Added support for using shapes as animated characters
+- FIX: added methods used by expressions to an array to prevent treeshaking
+- DEV: Migrated code to imports
+- DEV: Use Rollup for build process
+
 ## V 5.8.1
 - FEATURE: added more methods available for the lottie worker player
 
diff --git a/History.md b/History.md
index e5bf2c2..b9e59fe 100644
--- a/History.md
+++ b/History.md
@@ -1,3 +1,9 @@
+## V 5.9.0
+- FEATURE: Added support for using shapes as animated characters
+- FIX: added methods used by expressions to an array to prevent treeshaking
+- DEV: Migrated code to imports
+- DEV: Use Rollup for build process
+
 ## V 5.8.1
 - FEATURE: added more methods available for the lottie worker player
 
diff --git a/build/extension/bodymovin.zxp b/build/extension/bodymovin.zxp
index d5e8d92..7e47e4b 100644
--- a/build/extension/bodymovin.zxp
+++ b/build/extension/bodymovin.zxp
Binary files differ
diff --git a/build/player/lottie.js b/build/player/lottie.js
index c106ac3..f027145 100644
--- a/build/player/lottie.js
+++ b/build/player/lottie.js
@@ -1,1911 +1,579 @@
-(typeof navigator !== "undefined") && (function(root, factory) {
-    if (typeof define === "function" && define.amd) {
-        define(function() {
-            return factory(root);
-        });
-    } else if (typeof module === "object" && module.exports) {
-        module.exports = factory(root);
-    } else {
-        root.lottie = factory(root);
-        root.bodymovin = root.lottie;
-    }
-}((window || {}), function(window) {
-	/* global locationHref:writable, animationManager, subframeEnabled:writable, defaultCurveSegments:writable, roundValues,
-expressionsPlugin:writable, PropertyFactory, ShapePropertyFactory, Matrix, idPrefix:writable, _useWebWorker:writable */
-/* exported locationHref, subframeEnabled, expressionsPlugin, idPrefix, _useWebWorker */
+(function (global, factory) {
+  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+  typeof define === 'function' && define.amd ? define(factory) :
+  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lottie = factory());
+})(this, (function () { 'use strict';
 
-'use strict';
+  var svgNS = 'http://www.w3.org/2000/svg';
+  var locationHref = '';
+  var _useWebWorker = false;
+  var initialDefaultFrame = -999999;
 
-/* exported svgNS, locationHref, initialDefaultFrame, _useWebWorker */
+  var setWebWorker = function setWebWorker(flag) {
+    _useWebWorker = !!flag;
+  };
 
-var svgNS = 'http://www.w3.org/2000/svg';
+  var getWebWorker = function getWebWorker() {
+    return _useWebWorker;
+  };
 
-var locationHref = '';
+  var setLocationHref = function setLocationHref(value) {
+    locationHref = value;
+  };
 
-var initialDefaultFrame = -999999;
+  var getLocationHref = function getLocationHref() {
+    return locationHref;
+  };
 
-var _useWebWorker = false;
-
-/* global createSizedArray */
-/* exported subframeEnabled, expressionsPlugin, isSafari, cachedColors, bmPow, bmSqrt, bmFloor, bmMax, bmMin, ProjectInterface,
-defaultCurveSegments, degToRads, roundCorner, bmRnd, styleDiv, BMEnterFrameEvent, BMCompleteEvent, BMCompleteLoopEvent,
-BMSegmentStartEvent, BMDestroyEvent, BMRenderFrameErrorEvent, BMConfigErrorEvent, BMAnimationConfigErrorEvent, createElementID,
-addSaturationToRGB, addBrightnessToRGB, addHueToRGB, rgbToHex */
-
-var subframeEnabled = true;
-var idPrefix = '';
-var expressionsPlugin;
-var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
-var cachedColors = {};
-var bmRnd;
-var bmPow = Math.pow;
-var bmSqrt = Math.sqrt;
-var bmFloor = Math.floor;
-var bmMax = Math.max;
-var bmMin = Math.min;
-
-var BMMath = {};
-(function () {
-  var propertyNames = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atanh', 'atan2', 'ceil', 'cbrt', 'expm1', 'clz32', 'cos', 'cosh', 'exp', 'floor', 'fround', 'hypot', 'imul', 'log', 'log1p', 'log2', 'log10', 'max', 'min', 'pow', 'random', 'round', 'sign', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc', 'E', 'LN10', 'LN2', 'LOG10E', 'LOG2E', 'PI', 'SQRT1_2', 'SQRT2'];
-  var i;
-  var len = propertyNames.length;
-  for (i = 0; i < len; i += 1) {
-    BMMath[propertyNames[i]] = Math[propertyNames[i]];
+  function createTag(type) {
+    // return {appendChild:function(){},setAttribute:function(){},style:{}}
+    return document.createElement(type);
   }
-}());
 
-function ProjectInterface() { return {}; }
-
-BMMath.random = Math.random;
-BMMath.abs = function (val) {
-  var tOfVal = typeof val;
-  if (tOfVal === 'object' && val.length) {
-    var absArr = createSizedArray(val.length);
+  function extendPrototype(sources, destination) {
     var i;
-    var len = val.length;
+    var len = sources.length;
+    var sourcePrototype;
+
     for (i = 0; i < len; i += 1) {
-      absArr[i] = Math.abs(val[i]);
-    }
-    return absArr;
-  }
-  return Math.abs(val);
-};
-var defaultCurveSegments = 150;
-var degToRads = Math.PI / 180;
-var roundCorner = 0.5519;
+      sourcePrototype = sources[i].prototype;
 
-function roundValues(flag) {
-  if (flag) {
-    bmRnd = Math.round;
-  } else {
-    bmRnd = function (val) {
-      return val;
-    };
-  }
-}
-roundValues(false);
-
-function styleDiv(element) {
-  element.style.position = 'absolute';
-  element.style.top = 0;
-  element.style.left = 0;
-  element.style.display = 'block';
-  element.style.transformOrigin = '0 0';
-  element.style.webkitTransformOrigin = '0 0';
-  element.style.backfaceVisibility = 'visible';
-  element.style.webkitBackfaceVisibility = 'visible';
-  element.style.transformStyle = 'preserve-3d';
-  element.style.webkitTransformStyle = 'preserve-3d';
-  element.style.mozTransformStyle = 'preserve-3d';
-}
-
-function BMEnterFrameEvent(type, currentTime, totalTime, frameMultiplier) {
-  this.type = type;
-  this.currentTime = currentTime;
-  this.totalTime = totalTime;
-  this.direction = frameMultiplier < 0 ? -1 : 1;
-}
-
-function BMCompleteEvent(type, frameMultiplier) {
-  this.type = type;
-  this.direction = frameMultiplier < 0 ? -1 : 1;
-}
-
-function BMCompleteLoopEvent(type, totalLoops, currentLoop, frameMultiplier) {
-  this.type = type;
-  this.currentLoop = currentLoop;
-  this.totalLoops = totalLoops;
-  this.direction = frameMultiplier < 0 ? -1 : 1;
-}
-
-function BMSegmentStartEvent(type, firstFrame, totalFrames) {
-  this.type = type;
-  this.firstFrame = firstFrame;
-  this.totalFrames = totalFrames;
-}
-
-function BMDestroyEvent(type, target) {
-  this.type = type;
-  this.target = target;
-}
-
-function BMRenderFrameErrorEvent(nativeError, currentTime) {
-  this.type = 'renderFrameError';
-  this.nativeError = nativeError;
-  this.currentTime = currentTime;
-}
-
-function BMConfigErrorEvent(nativeError) {
-  this.type = 'configError';
-  this.nativeError = nativeError;
-}
-
-function BMAnimationConfigErrorEvent(type, nativeError) {
-  this.type = type;
-  this.nativeError = nativeError;
-}
-
-var createElementID = (function () {
-  var _count = 0;
-  return function createID() {
-    _count += 1;
-    return idPrefix + '__lottie_element_' + _count;
-  };
-}());
-
-function HSVtoRGB(h, s, v) {
-  var r;
-  var g;
-  var b;
-  var i;
-  var f;
-  var p;
-  var q;
-  var t;
-  i = Math.floor(h * 6);
-  f = h * 6 - i;
-  p = v * (1 - s);
-  q = v * (1 - f * s);
-  t = v * (1 - (1 - f) * s);
-  switch (i % 6) {
-    case 0: r = v; g = t; b = p; break;
-    case 1: r = q; g = v; b = p; break;
-    case 2: r = p; g = v; b = t; break;
-    case 3: r = p; g = q; b = v; break;
-    case 4: r = t; g = p; b = v; break;
-    case 5: r = v; g = p; b = q; break;
-    default: break;
-  }
-  return [r,
-    g,
-    b];
-}
-
-function RGBtoHSV(r, g, b) {
-  var max = Math.max(r, g, b);
-  var min = Math.min(r, g, b);
-  var d = max - min;
-  var h;
-  var s = (max === 0 ? 0 : d / max);
-  var v = max / 255;
-
-  switch (max) {
-    case min: h = 0; break;
-    case r: h = (g - b) + d * (g < b ? 6 : 0); h /= 6 * d; break;
-    case g: h = (b - r) + d * 2; h /= 6 * d; break;
-    case b: h = (r - g) + d * 4; h /= 6 * d; break;
-    default: break;
-  }
-
-  return [
-    h,
-    s,
-    v,
-  ];
-}
-
-function addSaturationToRGB(color, offset) {
-  var hsv = RGBtoHSV(color[0] * 255, color[1] * 255, color[2] * 255);
-  hsv[1] += offset;
-  if (hsv[1] > 1) {
-    hsv[1] = 1;
-  } else if (hsv[1] <= 0) {
-    hsv[1] = 0;
-  }
-  return HSVtoRGB(hsv[0], hsv[1], hsv[2]);
-}
-
-function addBrightnessToRGB(color, offset) {
-  var hsv = RGBtoHSV(color[0] * 255, color[1] * 255, color[2] * 255);
-  hsv[2] += offset;
-  if (hsv[2] > 1) {
-    hsv[2] = 1;
-  } else if (hsv[2] < 0) {
-    hsv[2] = 0;
-  }
-  return HSVtoRGB(hsv[0], hsv[1], hsv[2]);
-}
-
-function addHueToRGB(color, offset) {
-  var hsv = RGBtoHSV(color[0] * 255, color[1] * 255, color[2] * 255);
-  hsv[0] += offset / 360;
-  if (hsv[0] > 1) {
-    hsv[0] -= 1;
-  } else if (hsv[0] < 0) {
-    hsv[0] += 1;
-  }
-  return HSVtoRGB(hsv[0], hsv[1], hsv[2]);
-}
-
-var rgbToHex = (function () {
-  var colorMap = [];
-  var i;
-  var hex;
-  for (i = 0; i < 256; i += 1) {
-    hex = i.toString(16);
-    colorMap[i] = hex.length === 1 ? '0' + hex : hex;
-  }
-
-  return function (r, g, b) {
-    if (r < 0) {
-      r = 0;
-    }
-    if (g < 0) {
-      g = 0;
-    }
-    if (b < 0) {
-      b = 0;
-    }
-    return '#' + colorMap[r] + colorMap[g] + colorMap[b];
-  };
-}());
-
-function BaseEvent() {}
-BaseEvent.prototype = {
-  triggerEvent: function (eventName, args) {
-    if (this._cbs[eventName]) {
-      var callbacks = this._cbs[eventName];
-      for (var i = 0; i < callbacks.length; i += 1) {
-        callbacks[i](args);
+      for (var attr in sourcePrototype) {
+        if (Object.prototype.hasOwnProperty.call(sourcePrototype, attr)) destination.prototype[attr] = sourcePrototype[attr];
       }
     }
-  },
-  addEventListener: function (eventName, callback) {
-    if (!this._cbs[eventName]) {
-      this._cbs[eventName] = [];
-    }
-    this._cbs[eventName].push(callback);
-
-    return function () {
-      this.removeEventListener(eventName, callback);
-    }.bind(this);
-  },
-  removeEventListener: function (eventName, callback) {
-    if (!callback) {
-      this._cbs[eventName] = null;
-    } else if (this._cbs[eventName]) {
-      var i = 0;
-      var len = this._cbs[eventName].length;
-      while (i < len) {
-        if (this._cbs[eventName][i] === callback) {
-          this._cbs[eventName].splice(i, 1);
-          i -= 1;
-          len -= 1;
-        }
-        i += 1;
-      }
-      if (!this._cbs[eventName].length) {
-        this._cbs[eventName] = null;
-      }
-    }
-  },
-};
-
-/* exported createTypedArray, createSizedArray */
-
-var createTypedArray = (function () {
-  function createRegularArray(type, len) {
-    var i = 0;
-    var arr = [];
-    var value;
-    switch (type) {
-      case 'int16':
-      case 'uint8c':
-        value = 1;
-        break;
-      default:
-        value = 1.1;
-        break;
-    }
-    for (i = 0; i < len; i += 1) {
-      arr.push(value);
-    }
-    return arr;
-  }
-  function createTypedArrayFactory(type, len) {
-    if (type === 'float32') {
-      return new Float32Array(len);
-    } if (type === 'int16') {
-      return new Int16Array(len);
-    } if (type === 'uint8c') {
-      return new Uint8ClampedArray(len);
-    }
-    return createRegularArray(type, len);
-  }
-  if (typeof Uint8ClampedArray === 'function' && typeof Float32Array === 'function') {
-    return createTypedArrayFactory;
-  }
-  return createRegularArray;
-}());
-
-function createSizedArray(len) {
-  return Array.apply(null, { length: len });
-}
-
-/* global svgNS */
-/* exported createNS */
-
-function createNS(type) {
-  // return {appendChild:function(){},setAttribute:function(){},style:{}}
-  return document.createElementNS(svgNS, type);
-}
-
-/* exported createTag */
-
-function createTag(type) {
-  // return {appendChild:function(){},setAttribute:function(){},style:{}}
-  return document.createElement(type);
-}
-
-function DynamicPropertyContainer() {}
-DynamicPropertyContainer.prototype = {
-  addDynamicProperty: function (prop) {
-    if (this.dynamicProperties.indexOf(prop) === -1) {
-      this.dynamicProperties.push(prop);
-      this.container.addDynamicProperty(this);
-      this._isAnimated = true;
-    }
-  },
-  iterateDynamicProperties: function () {
-    this._mdf = false;
-    var i;
-    var len = this.dynamicProperties.length;
-    for (i = 0; i < len; i += 1) {
-      this.dynamicProperties[i].getValue();
-      if (this.dynamicProperties[i]._mdf) {
-        this._mdf = true;
-      }
-    }
-  },
-  initDynamicPropertyContainer: function (container) {
-    this.container = container;
-    this.dynamicProperties = [];
-    this._mdf = false;
-    this._isAnimated = false;
-  },
-};
-
-/* exported getBlendMode */
-
-var getBlendMode = (function () {
-  var blendModeEnums = {
-    0: 'source-over',
-    1: 'multiply',
-    2: 'screen',
-    3: 'overlay',
-    4: 'darken',
-    5: 'lighten',
-    6: 'color-dodge',
-    7: 'color-burn',
-    8: 'hard-light',
-    9: 'soft-light',
-    10: 'difference',
-    11: 'exclusion',
-    12: 'hue',
-    13: 'saturation',
-    14: 'color',
-    15: 'luminosity',
-  };
-
-  return function (mode) {
-    return blendModeEnums[mode] || '';
-  };
-}());
-
-/* exported lineCapEnum, lineJoinEnum */
-
-var lineCapEnum = {
-  1: 'butt',
-  2: 'round',
-  3: 'square',
-};
-
-var lineJoinEnum = {
-  1: 'miter',
-  2: 'round',
-  3: 'bevel',
-};
-
-/* global createTypedArray */
-
-/*!
- Transformation Matrix v2.0
- (c) Epistemex 2014-2015
- www.epistemex.com
- By Ken Fyrstenberg
- Contributions by leeoniya.
- License: MIT, header required.
- */
-
-/**
- * 2D transformation matrix object initialized with identity matrix.
- *
- * The matrix can synchronize a canvas context by supplying the context
- * as an argument, or later apply current absolute transform to an
- * existing context.
- *
- * All values are handled as floating point values.
- *
- * @param {CanvasRenderingContext2D} [context] - Optional context to sync with Matrix
- * @prop {number} a - scale x
- * @prop {number} b - shear y
- * @prop {number} c - shear x
- * @prop {number} d - scale y
- * @prop {number} e - translate x
- * @prop {number} f - translate y
- * @prop {CanvasRenderingContext2D|null} [context=null] - set or get current canvas context
- * @constructor
- */
-
-var Matrix = (function () {
-  var _cos = Math.cos;
-  var _sin = Math.sin;
-  var _tan = Math.tan;
-  var _rnd = Math.round;
-
-  function reset() {
-    this.props[0] = 1;
-    this.props[1] = 0;
-    this.props[2] = 0;
-    this.props[3] = 0;
-    this.props[4] = 0;
-    this.props[5] = 1;
-    this.props[6] = 0;
-    this.props[7] = 0;
-    this.props[8] = 0;
-    this.props[9] = 0;
-    this.props[10] = 1;
-    this.props[11] = 0;
-    this.props[12] = 0;
-    this.props[13] = 0;
-    this.props[14] = 0;
-    this.props[15] = 1;
-    return this;
   }
 
-  function rotate(angle) {
-    if (angle === 0) {
-      return this;
-    }
-    var mCos = _cos(angle);
-    var mSin = _sin(angle);
-    return this._t(mCos, -mSin, 0, 0, mSin, mCos, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
+  function getDescriptor(object, prop) {
+    return Object.getOwnPropertyDescriptor(object, prop);
   }
 
-  function rotateX(angle) {
-    if (angle === 0) {
-      return this;
-    }
-    var mCos = _cos(angle);
-    var mSin = _sin(angle);
-    return this._t(1, 0, 0, 0, 0, mCos, -mSin, 0, 0, mSin, mCos, 0, 0, 0, 0, 1);
+  function createProxyFunction(prototype) {
+    function ProxyFunction() {}
+
+    ProxyFunction.prototype = prototype;
+    return ProxyFunction;
   }
 
-  function rotateY(angle) {
-    if (angle === 0) {
-      return this;
-    }
-    var mCos = _cos(angle);
-    var mSin = _sin(angle);
-    return this._t(mCos, 0, mSin, 0, 0, 1, 0, 0, -mSin, 0, mCos, 0, 0, 0, 0, 1);
-  }
-
-  function rotateZ(angle) {
-    if (angle === 0) {
-      return this;
-    }
-    var mCos = _cos(angle);
-    var mSin = _sin(angle);
-    return this._t(mCos, -mSin, 0, 0, mSin, mCos, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
-  }
-
-  function shear(sx, sy) {
-    return this._t(1, sy, sx, 1, 0, 0);
-  }
-
-  function skew(ax, ay) {
-    return this.shear(_tan(ax), _tan(ay));
-  }
-
-  function skewFromAxis(ax, angle) {
-    var mCos = _cos(angle);
-    var mSin = _sin(angle);
-    return this._t(mCos, mSin, 0, 0, -mSin, mCos, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)
-      ._t(1, 0, 0, 0, _tan(ax), 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)
-      ._t(mCos, -mSin, 0, 0, mSin, mCos, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
-    // return this._t(mCos, mSin, -mSin, mCos, 0, 0)._t(1, 0, _tan(ax), 1, 0, 0)._t(mCos, -mSin, mSin, mCos, 0, 0);
-  }
-
-  function scale(sx, sy, sz) {
-    if (!sz && sz !== 0) {
-      sz = 1;
-    }
-    if (sx === 1 && sy === 1 && sz === 1) {
-      return this;
-    }
-    return this._t(sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, sz, 0, 0, 0, 0, 1);
-  }
-
-  function setTransform(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {
-    this.props[0] = a;
-    this.props[1] = b;
-    this.props[2] = c;
-    this.props[3] = d;
-    this.props[4] = e;
-    this.props[5] = f;
-    this.props[6] = g;
-    this.props[7] = h;
-    this.props[8] = i;
-    this.props[9] = j;
-    this.props[10] = k;
-    this.props[11] = l;
-    this.props[12] = m;
-    this.props[13] = n;
-    this.props[14] = o;
-    this.props[15] = p;
-    return this;
-  }
-
-  function translate(tx, ty, tz) {
-    tz = tz || 0;
-    if (tx !== 0 || ty !== 0 || tz !== 0) {
-      return this._t(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, tx, ty, tz, 1);
-    }
-    return this;
-  }
-
-  function transform(a2, b2, c2, d2, e2, f2, g2, h2, i2, j2, k2, l2, m2, n2, o2, p2) {
-    var _p = this.props;
-
-    if (a2 === 1 && b2 === 0 && c2 === 0 && d2 === 0 && e2 === 0 && f2 === 1 && g2 === 0 && h2 === 0 && i2 === 0 && j2 === 0 && k2 === 1 && l2 === 0) {
-      // NOTE: commenting this condition because TurboFan deoptimizes code when present
-      // if(m2 !== 0 || n2 !== 0 || o2 !== 0){
-      _p[12] = _p[12] * a2 + _p[15] * m2;
-      _p[13] = _p[13] * f2 + _p[15] * n2;
-      _p[14] = _p[14] * k2 + _p[15] * o2;
-      _p[15] *= p2;
-      // }
-      this._identityCalculated = false;
-      return this;
+  // import Howl from '../../3rd_party/howler';
+  var audioControllerFactory = function () {
+    function AudioController(audioFactory) {
+      this.audios = [];
+      this.audioFactory = audioFactory;
+      this._volume = 1;
+      this._isMuted = false;
     }
 
-    var a1 = _p[0];
-    var b1 = _p[1];
-    var c1 = _p[2];
-    var d1 = _p[3];
-    var e1 = _p[4];
-    var f1 = _p[5];
-    var g1 = _p[6];
-    var h1 = _p[7];
-    var i1 = _p[8];
-    var j1 = _p[9];
-    var k1 = _p[10];
-    var l1 = _p[11];
-    var m1 = _p[12];
-    var n1 = _p[13];
-    var o1 = _p[14];
-    var p1 = _p[15];
-
-    /* matrix order (canvas compatible):
-         * ace
-         * bdf
-         * 001
-         */
-    _p[0] = a1 * a2 + b1 * e2 + c1 * i2 + d1 * m2;
-    _p[1] = a1 * b2 + b1 * f2 + c1 * j2 + d1 * n2;
-    _p[2] = a1 * c2 + b1 * g2 + c1 * k2 + d1 * o2;
-    _p[3] = a1 * d2 + b1 * h2 + c1 * l2 + d1 * p2;
-
-    _p[4] = e1 * a2 + f1 * e2 + g1 * i2 + h1 * m2;
-    _p[5] = e1 * b2 + f1 * f2 + g1 * j2 + h1 * n2;
-    _p[6] = e1 * c2 + f1 * g2 + g1 * k2 + h1 * o2;
-    _p[7] = e1 * d2 + f1 * h2 + g1 * l2 + h1 * p2;
-
-    _p[8] = i1 * a2 + j1 * e2 + k1 * i2 + l1 * m2;
-    _p[9] = i1 * b2 + j1 * f2 + k1 * j2 + l1 * n2;
-    _p[10] = i1 * c2 + j1 * g2 + k1 * k2 + l1 * o2;
-    _p[11] = i1 * d2 + j1 * h2 + k1 * l2 + l1 * p2;
-
-    _p[12] = m1 * a2 + n1 * e2 + o1 * i2 + p1 * m2;
-    _p[13] = m1 * b2 + n1 * f2 + o1 * j2 + p1 * n2;
-    _p[14] = m1 * c2 + n1 * g2 + o1 * k2 + p1 * o2;
-    _p[15] = m1 * d2 + n1 * h2 + o1 * l2 + p1 * p2;
-
-    this._identityCalculated = false;
-    return this;
-  }
-
-  function isIdentity() {
-    if (!this._identityCalculated) {
-      this._identity = !(this.props[0] !== 1 || this.props[1] !== 0 || this.props[2] !== 0 || this.props[3] !== 0 || this.props[4] !== 0 || this.props[5] !== 1 || this.props[6] !== 0 || this.props[7] !== 0 || this.props[8] !== 0 || this.props[9] !== 0 || this.props[10] !== 1 || this.props[11] !== 0 || this.props[12] !== 0 || this.props[13] !== 0 || this.props[14] !== 0 || this.props[15] !== 1);
-      this._identityCalculated = true;
-    }
-    return this._identity;
-  }
-
-  function equals(matr) {
-    var i = 0;
-    while (i < 16) {
-      if (matr.props[i] !== this.props[i]) {
-        return false;
-      }
-      i += 1;
-    }
-    return true;
-  }
-
-  function clone(matr) {
-    var i;
-    for (i = 0; i < 16; i += 1) {
-      matr.props[i] = this.props[i];
-    }
-    return matr;
-  }
-
-  function cloneFromProps(props) {
-    var i;
-    for (i = 0; i < 16; i += 1) {
-      this.props[i] = props[i];
-    }
-  }
-
-  function applyToPoint(x, y, z) {
-    return {
-      x: x * this.props[0] + y * this.props[4] + z * this.props[8] + this.props[12],
-      y: x * this.props[1] + y * this.props[5] + z * this.props[9] + this.props[13],
-      z: x * this.props[2] + y * this.props[6] + z * this.props[10] + this.props[14],
-    };
-    /* return {
-         x: x * me.a + y * me.c + me.e,
-         y: x * me.b + y * me.d + me.f
-         }; */
-  }
-  function applyToX(x, y, z) {
-    return x * this.props[0] + y * this.props[4] + z * this.props[8] + this.props[12];
-  }
-  function applyToY(x, y, z) {
-    return x * this.props[1] + y * this.props[5] + z * this.props[9] + this.props[13];
-  }
-  function applyToZ(x, y, z) {
-    return x * this.props[2] + y * this.props[6] + z * this.props[10] + this.props[14];
-  }
-
-  function getInverseMatrix() {
-    var determinant = this.props[0] * this.props[5] - this.props[1] * this.props[4];
-    var a = this.props[5] / determinant;
-    var b = -this.props[1] / determinant;
-    var c = -this.props[4] / determinant;
-    var d = this.props[0] / determinant;
-    var e = (this.props[4] * this.props[13] - this.props[5] * this.props[12]) / determinant;
-    var f = -(this.props[0] * this.props[13] - this.props[1] * this.props[12]) / determinant;
-    var inverseMatrix = new Matrix();
-    inverseMatrix.props[0] = a;
-    inverseMatrix.props[1] = b;
-    inverseMatrix.props[4] = c;
-    inverseMatrix.props[5] = d;
-    inverseMatrix.props[12] = e;
-    inverseMatrix.props[13] = f;
-    return inverseMatrix;
-  }
-
-  function inversePoint(pt) {
-    var inverseMatrix = this.getInverseMatrix();
-    return inverseMatrix.applyToPointArray(pt[0], pt[1], pt[2] || 0);
-  }
-
-  function inversePoints(pts) {
-    var i;
-    var len = pts.length;
-    var retPts = [];
-    for (i = 0; i < len; i += 1) {
-      retPts[i] = inversePoint(pts[i]);
-    }
-    return retPts;
-  }
-
-  function applyToTriplePoints(pt1, pt2, pt3) {
-    var arr = createTypedArray('float32', 6);
-    if (this.isIdentity()) {
-      arr[0] = pt1[0];
-      arr[1] = pt1[1];
-      arr[2] = pt2[0];
-      arr[3] = pt2[1];
-      arr[4] = pt3[0];
-      arr[5] = pt3[1];
-    } else {
-      var p0 = this.props[0];
-      var p1 = this.props[1];
-      var p4 = this.props[4];
-      var p5 = this.props[5];
-      var p12 = this.props[12];
-      var p13 = this.props[13];
-      arr[0] = pt1[0] * p0 + pt1[1] * p4 + p12;
-      arr[1] = pt1[0] * p1 + pt1[1] * p5 + p13;
-      arr[2] = pt2[0] * p0 + pt2[1] * p4 + p12;
-      arr[3] = pt2[0] * p1 + pt2[1] * p5 + p13;
-      arr[4] = pt3[0] * p0 + pt3[1] * p4 + p12;
-      arr[5] = pt3[0] * p1 + pt3[1] * p5 + p13;
-    }
-    return arr;
-  }
-
-  function applyToPointArray(x, y, z) {
-    var arr;
-    if (this.isIdentity()) {
-      arr = [x, y, z];
-    } else {
-      arr = [
-        x * this.props[0] + y * this.props[4] + z * this.props[8] + this.props[12],
-        x * this.props[1] + y * this.props[5] + z * this.props[9] + this.props[13],
-        x * this.props[2] + y * this.props[6] + z * this.props[10] + this.props[14],
-      ];
-    }
-    return arr;
-  }
-
-  function applyToPointStringified(x, y) {
-    if (this.isIdentity()) {
-      return x + ',' + y;
-    }
-    var _p = this.props;
-    return Math.round((x * _p[0] + y * _p[4] + _p[12]) * 100) / 100 + ',' + Math.round((x * _p[1] + y * _p[5] + _p[13]) * 100) / 100;
-  }
-
-  function toCSS() {
-    // Doesn't make much sense to add this optimization. If it is an identity matrix, it's very likely this will get called only once since it won't be keyframed.
-    /* if(this.isIdentity()) {
-            return '';
-        } */
-    var i = 0;
-    var props = this.props;
-    var cssValue = 'matrix3d(';
-    var v = 10000;
-    while (i < 16) {
-      cssValue += _rnd(props[i] * v) / v;
-      cssValue += i === 15 ? ')' : ',';
-      i += 1;
-    }
-    return cssValue;
-  }
-
-  function roundMatrixProperty(val) {
-    var v = 10000;
-    if ((val < 0.000001 && val > 0) || (val > -0.000001 && val < 0)) {
-      return _rnd(val * v) / v;
-    }
-    return val;
-  }
-
-  function to2dCSS() {
-    // Doesn't make much sense to add this optimization. If it is an identity matrix, it's very likely this will get called only once since it won't be keyframed.
-    /* if(this.isIdentity()) {
-            return '';
-        } */
-    var props = this.props;
-    var _a = roundMatrixProperty(props[0]);
-    var _b = roundMatrixProperty(props[1]);
-    var _c = roundMatrixProperty(props[4]);
-    var _d = roundMatrixProperty(props[5]);
-    var _e = roundMatrixProperty(props[12]);
-    var _f = roundMatrixProperty(props[13]);
-    return 'matrix(' + _a + ',' + _b + ',' + _c + ',' + _d + ',' + _e + ',' + _f + ')';
-  }
-
-  return function () {
-    this.reset = reset;
-    this.rotate = rotate;
-    this.rotateX = rotateX;
-    this.rotateY = rotateY;
-    this.rotateZ = rotateZ;
-    this.skew = skew;
-    this.skewFromAxis = skewFromAxis;
-    this.shear = shear;
-    this.scale = scale;
-    this.setTransform = setTransform;
-    this.translate = translate;
-    this.transform = transform;
-    this.applyToPoint = applyToPoint;
-    this.applyToX = applyToX;
-    this.applyToY = applyToY;
-    this.applyToZ = applyToZ;
-    this.applyToPointArray = applyToPointArray;
-    this.applyToTriplePoints = applyToTriplePoints;
-    this.applyToPointStringified = applyToPointStringified;
-    this.toCSS = toCSS;
-    this.to2dCSS = to2dCSS;
-    this.clone = clone;
-    this.cloneFromProps = cloneFromProps;
-    this.equals = equals;
-    this.inversePoints = inversePoints;
-    this.inversePoint = inversePoint;
-    this.getInverseMatrix = getInverseMatrix;
-    this._t = this.transform;
-    this.isIdentity = isIdentity;
-    this._identity = true;
-    this._identityCalculated = false;
-
-    this.props = createTypedArray('float32', 16);
-    this.reset();
-  };
-}());
-
-/* eslint-disable */
-/*
- Copyright 2014 David Bau.
-
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- "Software"), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
-
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
- */
-
-(function (pool, math) {
-//
-// The following constants are related to IEEE 754 limits.
-//
-    var global = this,
-        width = 256,        // each RC4 output is 0 <= x < 256
-        chunks = 6,         // at least six RC4 outputs for each double
-        digits = 52,        // there are 52 significant digits in a double
-        rngname = 'random', // rngname: name for Math.random and Math.seedrandom
-        startdenom = math.pow(width, chunks),
-        significance = math.pow(2, digits),
-        overflow = significance * 2,
-        mask = width - 1,
-        nodecrypto;         // node.js crypto module, initialized at the bottom.
-
-//
-// seedrandom()
-// This is the seedrandom function described above.
-//
-    function seedrandom(seed, options, callback) {
-        var key = [];
-        options = (options === true) ? { entropy: true } : (options || {});
-
-        // Flatten the seed string or build one from local entropy if needed.
-        var shortseed = mixkey(flatten(
-            options.entropy ? [seed, tostring(pool)] :
-                (seed === null) ? autoseed() : seed, 3), key);
-
-        // Use the seed to initialize an ARC4 generator.
-        var arc4 = new ARC4(key);
-
-        // This function returns a random double in [0, 1) that contains
-        // randomness in every bit of the mantissa of the IEEE 754 value.
-        var prng = function() {
-            var n = arc4.g(chunks),             // Start with a numerator n < 2 ^ 48
-                d = startdenom,                 //   and denominator d = 2 ^ 48.
-                x = 0;                          //   and no 'extra last byte'.
-            while (n < significance) {          // Fill up all significant digits by
-                n = (n + x) * width;              //   shifting numerator and
-                d *= width;                       //   denominator and generating a
-                x = arc4.g(1);                    //   new least-significant-byte.
-            }
-            while (n >= overflow) {             // To avoid rounding up, before adding
-                n /= 2;                           //   last byte, shift everything
-                d /= 2;                           //   right using integer math until
-                x >>>= 1;                         //   we have exactly the desired bits.
-            }
-            return (n + x) / d;                 // Form the number within [0, 1).
-        };
-
-        prng.int32 = function() { return arc4.g(4) | 0; };
-        prng.quick = function() { return arc4.g(4) / 0x100000000; };
-        prng.double = prng;
-
-        // Mix the randomness into accumulated entropy.
-        mixkey(tostring(arc4.S), pool);
-
-        // Calling convention: what to return as a function of prng, seed, is_math.
-        return (options.pass || callback ||
-        function(prng, seed, is_math_call, state) {
-            if (state) {
-                // Load the arc4 state from the given state if it has an S array.
-                if (state.S) { copy(state, arc4); }
-                // Only provide the .state method if requested via options.state.
-                prng.state = function() { return copy(arc4, {}); };
-            }
-
-            // If called as a method of Math (Math.seedrandom()), mutate
-            // Math.random because that is how seedrandom.js has worked since v1.0.
-            if (is_math_call) { math[rngname] = prng; return seed; }
-
-            // Otherwise, it is a newer calling convention, so return the
-            // prng directly.
-            else return prng;
-        })(
-            prng,
-            shortseed,
-            'global' in options ? options.global : (this == math),
-            options.state);
-    }
-    math['seed' + rngname] = seedrandom;
-
-//
-// ARC4
-//
-// An ARC4 implementation.  The constructor takes a key in the form of
-// an array of at most (width) integers that should be 0 <= x < (width).
-//
-// The g(count) method returns a pseudorandom integer that concatenates
-// the next (count) outputs from ARC4.  Its return value is a number x
-// that is in the range 0 <= x < (width ^ count).
-//
-    function ARC4(key) {
-        var t, keylen = key.length,
-            me = this, i = 0, j = me.i = me.j = 0, s = me.S = [];
-
-        // The empty key [] is treated as [0].
-        if (!keylen) { key = [keylen++]; }
-
-        // Set up S using the standard key scheduling algorithm.
-        while (i < width) {
-            s[i] = i++;
-        }
-        for (i = 0; i < width; i++) {
-            s[i] = s[j = mask & (j + key[i % keylen] + (t = s[i]))];
-            s[j] = t;
-        }
-
-        // The "g" method returns the next (count) outputs as one number.
-        me.g = function(count) {
-            // Using instance members instead of closure state nearly doubles speed.
-            var t, r = 0,
-                i = me.i, j = me.j, s = me.S;
-            while (count--) {
-                t = s[i = mask & (i + 1)];
-                r = r * width + s[mask & ((s[i] = s[j = mask & (j + t)]) + (s[j] = t))];
-            }
-            me.i = i; me.j = j;
-            return r;
-            // For robust unpredictability, the function call below automatically
-            // discards an initial batch of values.  This is called RC4-drop[256].
-            // See http://google.com/search?q=rsa+fluhrer+response&btnI
-        };
-    }
-
-//
-// copy()
-// Copies internal state of ARC4 to or from a plain object.
-//
-    function copy(f, t) {
-        t.i = f.i;
-        t.j = f.j;
-        t.S = f.S.slice();
-        return t;
-    }
-
-//
-// flatten()
-// Converts an object tree to nested arrays of strings.
-//
-    function flatten(obj, depth) {
-        var result = [], typ = (typeof obj), prop;
-        if (depth && typ == 'object') {
-            for (prop in obj) {
-                try { result.push(flatten(obj[prop], depth - 1)); } catch (e) {}
-            }
-        }
-        return (result.length ? result : typ == 'string' ? obj : obj + '\0');
-    }
-
-//
-// mixkey()
-// Mixes a string seed into a key that is an array of integers, and
-// returns a shortened string seed that is equivalent to the result key.
-//
-    function mixkey(seed, key) {
-        var stringseed = seed + '', smear, j = 0;
-        while (j < stringseed.length) {
-            key[mask & j] =
-                mask & ((smear ^= key[mask & j] * 19) + stringseed.charCodeAt(j++));
-        }
-        return tostring(key);
-    }
-
-//
-// autoseed()
-// Returns an object for autoseeding, using window.crypto and Node crypto
-// module if available.
-//
-    function autoseed() {
-        try {
-            if (nodecrypto) { return tostring(nodecrypto.randomBytes(width)); }
-            var out = new Uint8Array(width);
-            (global.crypto || global.msCrypto).getRandomValues(out);
-            return tostring(out);
-        } catch (e) {
-            var browser = global.navigator,
-                plugins = browser && browser.plugins;
-            return [+new Date(), global, plugins, global.screen, tostring(pool)];
-        }
-    }
-
-//
-// tostring()
-// Converts an array of charcodes to a string
-//
-    function tostring(a) {
-        return String.fromCharCode.apply(0, a);
-    }
-
-//
-// When seedrandom.js is loaded, we immediately mix a few bits
-// from the built-in RNG into the entropy pool.  Because we do
-// not want to interfere with deterministic PRNG state later,
-// seedrandom will not call math.random on its own again after
-// initialization.
-//
-    mixkey(math.random(), pool);
-
-//
-// Nodejs and AMD support: export the implementation as a module using
-// either convention.
-//
-
-// End anonymous scope, and pass initial values.
-})(
-    [],     // pool: entropy pool starts empty
-    BMMath    // math: package containing random, pow, and seedrandom
-);
-/* eslint-disable */
-var BezierFactory = (function () {
-  /**
-     * BezierEasing - use bezier curve for transition easing function
-     * by Gaëtan Renaudeau 2014 - 2015 – MIT License
-     *
-     * Credits: is based on Firefox's nsSMILKeySpline.cpp
-     * Usage:
-     * var spline = BezierEasing([ 0.25, 0.1, 0.25, 1.0 ])
-     * spline.get(x) => returns the easing value | x must be in [0, 1] range
-     *
-     */
-
-  var ob = {};
-  ob.getBezierEasing = getBezierEasing;
-  var beziers = {};
-
-  function getBezierEasing(a, b, c, d, nm) {
-    var str = nm || ('bez_' + a + '_' + b + '_' + c + '_' + d).replace(/\./g, 'p');
-    if (beziers[str]) {
-      return beziers[str];
-    }
-    var bezEasing = new BezierEasing([a, b, c, d]);
-    beziers[str] = bezEasing;
-    return bezEasing;
-  }
-
-  // These values are established by empiricism with tests (tradeoff: performance VS precision)
-  var NEWTON_ITERATIONS = 4;
-  var NEWTON_MIN_SLOPE = 0.001;
-  var SUBDIVISION_PRECISION = 0.0000001;
-  var SUBDIVISION_MAX_ITERATIONS = 10;
-
-  var kSplineTableSize = 11;
-  var kSampleStepSize = 1.0 / (kSplineTableSize - 1.0);
-
-  var float32ArraySupported = typeof Float32Array === 'function';
-
-  function A(aA1, aA2) { return 1.0 - 3.0 * aA2 + 3.0 * aA1; }
-  function B(aA1, aA2) { return 3.0 * aA2 - 6.0 * aA1; }
-  function C(aA1) { return 3.0 * aA1; }
-
-  // Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
-  function calcBezier(aT, aA1, aA2) {
-    return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT;
-  }
-
-  // Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.
-  function getSlope(aT, aA1, aA2) {
-    return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1);
-  }
-
-  function binarySubdivide(aX, aA, aB, mX1, mX2) {
-    var currentX,
-      currentT,
-      i = 0;
-    do {
-      currentT = aA + (aB - aA) / 2.0;
-      currentX = calcBezier(currentT, mX1, mX2) - aX;
-      if (currentX > 0.0) {
-        aB = currentT;
-      } else {
-        aA = currentT;
-      }
-    } while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);
-    return currentT;
-  }
-
-  function newtonRaphsonIterate(aX, aGuessT, mX1, mX2) {
-    for (var i = 0; i < NEWTON_ITERATIONS; ++i) {
-      var currentSlope = getSlope(aGuessT, mX1, mX2);
-      if (currentSlope === 0.0) return aGuessT;
-      var currentX = calcBezier(aGuessT, mX1, mX2) - aX;
-      aGuessT -= currentX / currentSlope;
-    }
-    return aGuessT;
-  }
-
-  /**
-     * points is an array of [ mX1, mY1, mX2, mY2 ]
-     */
-  function BezierEasing(points) {
-    this._p = points;
-    this._mSampleValues = float32ArraySupported ? new Float32Array(kSplineTableSize) : new Array(kSplineTableSize);
-    this._precomputed = false;
-
-    this.get = this.get.bind(this);
-  }
-
-  BezierEasing.prototype = {
-
-    get: function (x) {
-      var mX1 = this._p[0],
-        mY1 = this._p[1],
-        mX2 = this._p[2],
-        mY2 = this._p[3];
-      if (!this._precomputed) this._precompute();
-      if (mX1 === mY1 && mX2 === mY2) return x; // linear
-      // Because JavaScript number are imprecise, we should guarantee the extremes are right.
-      if (x === 0) return 0;
-      if (x === 1) return 1;
-      return calcBezier(this._getTForX(x), mY1, mY2);
-    },
-
-    // Private part
-
-    _precompute: function () {
-      var mX1 = this._p[0],
-        mY1 = this._p[1],
-        mX2 = this._p[2],
-        mY2 = this._p[3];
-      this._precomputed = true;
-      if (mX1 !== mY1 || mX2 !== mY2) { this._calcSampleValues(); }
-    },
-
-    _calcSampleValues: function () {
-      var mX1 = this._p[0],
-        mX2 = this._p[2];
-      for (var i = 0; i < kSplineTableSize; ++i) {
-        this._mSampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2);
-      }
-    },
-
-    /**
-         * getTForX chose the fastest heuristic to determine the percentage value precisely from a given X projection.
-         */
-    _getTForX: function (aX) {
-      var mX1 = this._p[0],
-        mX2 = this._p[2],
-        mSampleValues = this._mSampleValues;
-
-      var intervalStart = 0.0;
-      var currentSample = 1;
-      var lastSample = kSplineTableSize - 1;
-
-      for (; currentSample !== lastSample && mSampleValues[currentSample] <= aX; ++currentSample) {
-        intervalStart += kSampleStepSize;
-      }
-      --currentSample;
-
-      // Interpolate to provide an initial guess for t
-      var dist = (aX - mSampleValues[currentSample]) / (mSampleValues[currentSample + 1] - mSampleValues[currentSample]);
-      var guessForT = intervalStart + dist * kSampleStepSize;
-
-      var initialSlope = getSlope(guessForT, mX1, mX2);
-      if (initialSlope >= NEWTON_MIN_SLOPE) {
-        return newtonRaphsonIterate(aX, guessForT, mX1, mX2);
-      } if (initialSlope === 0.0) {
-        return guessForT;
-      }
-      return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize, mX1, mX2);
-    },
-  };
-
-  return ob;
-}());
-
-(function () {
-  var lastTime = 0;
-  var vendors = ['ms', 'moz', 'webkit', 'o'];
-  for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { // eslint-disable-line no-plusplus
-    window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
-    window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame'];
-  }
-  if (!window.requestAnimationFrame) {
-    window.requestAnimationFrame = function (callback) {
-      var currTime = new Date().getTime();
-      var timeToCall = Math.max(0, 16 - (currTime - lastTime));
-      var id = setTimeout(function () {
-        callback(currTime + timeToCall);
+    AudioController.prototype = {
+      addAudio: function addAudio(audio) {
+        this.audios.push(audio);
       },
-      timeToCall);
-      lastTime = currTime + timeToCall;
-      return id;
-    };
-  }
-  if (!window.cancelAnimationFrame) {
-    window.cancelAnimationFrame = function (id) {
-      clearTimeout(id);
-    };
-  }
-}());
-
-/* exported extendPrototype, getDescriptor, createProxyFunction */
-
-function extendPrototype(sources, destination) {
-  var i;
-  var len = sources.length;
-  var sourcePrototype;
-  for (i = 0; i < len; i += 1) {
-    sourcePrototype = sources[i].prototype;
-    for (var attr in sourcePrototype) {
-      if (Object.prototype.hasOwnProperty.call(sourcePrototype, attr)) destination.prototype[attr] = sourcePrototype[attr];
-    }
-  }
-}
-
-function getDescriptor(object, prop) {
-  return Object.getOwnPropertyDescriptor(object, prop);
-}
-
-function createProxyFunction(prototype) {
-  function ProxyFunction() {}
-  ProxyFunction.prototype = prototype;
-  return ProxyFunction;
-}
-
-/* global segmentsLengthPool, defaultCurveSegments, createSizedArray, bmPow, bmSqrt, bmFloor, createTypedArray, bezierLengthPool */
-/* exported bez */
-
-function bezFunction() {
-  var math = Math;
-
-  function pointOnLine2D(x1, y1, x2, y2, x3, y3) {
-    var det1 = (x1 * y2) + (y1 * x3) + (x2 * y3) - (x3 * y2) - (y3 * x1) - (x2 * y1);
-    return det1 > -0.001 && det1 < 0.001;
-  }
-
-  function pointOnLine3D(x1, y1, z1, x2, y2, z2, x3, y3, z3) {
-    if (z1 === 0 && z2 === 0 && z3 === 0) {
-      return pointOnLine2D(x1, y1, x2, y2, x3, y3);
-    }
-    var dist1 = math.sqrt(math.pow(x2 - x1, 2) + math.pow(y2 - y1, 2) + math.pow(z2 - z1, 2));
-    var dist2 = math.sqrt(math.pow(x3 - x1, 2) + math.pow(y3 - y1, 2) + math.pow(z3 - z1, 2));
-    var dist3 = math.sqrt(math.pow(x3 - x2, 2) + math.pow(y3 - y2, 2) + math.pow(z3 - z2, 2));
-    var diffDist;
-    if (dist1 > dist2) {
-      if (dist1 > dist3) {
-        diffDist = dist1 - dist2 - dist3;
-      } else {
-        diffDist = dist3 - dist2 - dist1;
-      }
-    } else if (dist3 > dist2) {
-      diffDist = dist3 - dist2 - dist1;
-    } else {
-      diffDist = dist2 - dist1 - dist3;
-    }
-    return diffDist > -0.0001 && diffDist < 0.0001;
-  }
-
-  var getBezierLength = (function () {
-    return function (pt1, pt2, pt3, pt4) {
-      var curveSegments = defaultCurveSegments;
-      var k;
-      var i;
-      var len;
-      var ptCoord;
-      var perc;
-      var addedLength = 0;
-      var ptDistance;
-      var point = [];
-      var lastPoint = [];
-      var lengthData = bezierLengthPool.newElement();
-      len = pt3.length;
-      for (k = 0; k < curveSegments; k += 1) {
-        perc = k / (curveSegments - 1);
-        ptDistance = 0;
-        for (i = 0; i < len; i += 1) {
-          ptCoord = bmPow(1 - perc, 3) * pt1[i] + 3 * bmPow(1 - perc, 2) * perc * pt3[i] + 3 * (1 - perc) * bmPow(perc, 2) * pt4[i] + bmPow(perc, 3) * pt2[i];
-          point[i] = ptCoord;
-          if (lastPoint[i] !== null) {
-            ptDistance += bmPow(point[i] - lastPoint[i], 2);
-          }
-          lastPoint[i] = point[i];
-        }
-        if (ptDistance) {
-          ptDistance = bmSqrt(ptDistance);
-          addedLength += ptDistance;
-        }
-        lengthData.percents[k] = perc;
-        lengthData.lengths[k] = addedLength;
-      }
-      lengthData.addedLength = addedLength;
-      return lengthData;
-    };
-  }());
-
-  function getSegmentsLength(shapeData) {
-    var segmentsLength = segmentsLengthPool.newElement();
-    var closed = shapeData.c;
-    var pathV = shapeData.v;
-    var pathO = shapeData.o;
-    var pathI = shapeData.i;
-    var i;
-    var len = shapeData._length;
-    var lengths = segmentsLength.lengths;
-    var totalLength = 0;
-    for (i = 0; i < len - 1; i += 1) {
-      lengths[i] = getBezierLength(pathV[i], pathV[i + 1], pathO[i], pathI[i + 1]);
-      totalLength += lengths[i].addedLength;
-    }
-    if (closed && len) {
-      lengths[i] = getBezierLength(pathV[i], pathV[0], pathO[i], pathI[0]);
-      totalLength += lengths[i].addedLength;
-    }
-    segmentsLength.totalLength = totalLength;
-    return segmentsLength;
-  }
-
-  function BezierData(length) {
-    this.segmentLength = 0;
-    this.points = new Array(length);
-  }
-
-  function PointData(partial, point) {
-    this.partialLength = partial;
-    this.point = point;
-  }
-
-  var buildBezierData = (function () {
-    var storedData = {};
-
-    return function (pt1, pt2, pt3, pt4) {
-      var bezierName = (pt1[0] + '_' + pt1[1] + '_' + pt2[0] + '_' + pt2[1] + '_' + pt3[0] + '_' + pt3[1] + '_' + pt4[0] + '_' + pt4[1]).replace(/\./g, 'p');
-      if (!storedData[bezierName]) {
-        var curveSegments = defaultCurveSegments;
-        var k;
+      pause: function pause() {
         var i;
-        var len;
-        var ptCoord;
-        var perc;
-        var addedLength = 0;
-        var ptDistance;
-        var point;
-        var lastPoint = null;
-        if (pt1.length === 2 && (pt1[0] !== pt2[0] || pt1[1] !== pt2[1]) && pointOnLine2D(pt1[0], pt1[1], pt2[0], pt2[1], pt1[0] + pt3[0], pt1[1] + pt3[1]) && pointOnLine2D(pt1[0], pt1[1], pt2[0], pt2[1], pt2[0] + pt4[0], pt2[1] + pt4[1])) {
-          curveSegments = 2;
+        var len = this.audios.length;
+
+        for (i = 0; i < len; i += 1) {
+          this.audios[i].pause();
         }
-        var bezierData = new BezierData(curveSegments);
-        len = pt3.length;
-        for (k = 0; k < curveSegments; k += 1) {
-          point = createSizedArray(len);
-          perc = k / (curveSegments - 1);
-          ptDistance = 0;
-          for (i = 0; i < len; i += 1) {
-            ptCoord = bmPow(1 - perc, 3) * pt1[i] + 3 * bmPow(1 - perc, 2) * perc * (pt1[i] + pt3[i]) + 3 * (1 - perc) * bmPow(perc, 2) * (pt2[i] + pt4[i]) + bmPow(perc, 3) * pt2[i];
-            point[i] = ptCoord;
-            if (lastPoint !== null) {
-              ptDistance += bmPow(point[i] - lastPoint[i], 2);
-            }
-          }
-          ptDistance = bmSqrt(ptDistance);
-          addedLength += ptDistance;
-          bezierData.points[k] = new PointData(ptDistance, point);
-          lastPoint = point;
+      },
+      resume: function resume() {
+        var i;
+        var len = this.audios.length;
+
+        for (i = 0; i < len; i += 1) {
+          this.audios[i].resume();
         }
-        bezierData.segmentLength = addedLength;
-        storedData[bezierName] = bezierData;
+      },
+      setRate: function setRate(rateValue) {
+        var i;
+        var len = this.audios.length;
+
+        for (i = 0; i < len; i += 1) {
+          this.audios[i].setRate(rateValue);
+        }
+      },
+      createAudio: function createAudio(assetPath) {
+        if (this.audioFactory) {
+          return this.audioFactory(assetPath);
+        }
+
+        if (window.Howl) {
+          return new window.Howl({
+            src: [assetPath]
+          });
+        }
+
+        return {
+          isPlaying: false,
+          play: function play() {
+            this.isPlaying = true;
+          },
+          seek: function seek() {
+            this.isPlaying = false;
+          },
+          playing: function playing() {},
+          rate: function rate() {},
+          setVolume: function setVolume() {}
+        };
+      },
+      setAudioFactory: function setAudioFactory(audioFactory) {
+        this.audioFactory = audioFactory;
+      },
+      setVolume: function setVolume(value) {
+        this._volume = value;
+
+        this._updateVolume();
+      },
+      mute: function mute() {
+        this._isMuted = true;
+
+        this._updateVolume();
+      },
+      unmute: function unmute() {
+        this._isMuted = false;
+
+        this._updateVolume();
+      },
+      getVolume: function getVolume() {
+        return this._volume;
+      },
+      _updateVolume: function _updateVolume() {
+        var i;
+        var len = this.audios.length;
+
+        for (i = 0; i < len; i += 1) {
+          this.audios[i].volume(this._volume * (this._isMuted ? 0 : 1));
+        }
       }
-      return storedData[bezierName];
     };
-  }());
+    return function () {
+      return new AudioController();
+    };
+  }();
 
-  function getDistancePerc(perc, bezierData) {
-    var percents = bezierData.percents;
-    var lengths = bezierData.lengths;
-    var len = percents.length;
-    var initPos = bmFloor((len - 1) * perc);
-    var lengthPos = perc * bezierData.addedLength;
-    var lPerc = 0;
-    if (initPos === len - 1 || initPos === 0 || lengthPos === lengths[initPos]) {
-      return percents[initPos];
-    }
-    var dir = lengths[initPos] > lengthPos ? -1 : 1;
-    var flag = true;
-    while (flag) {
-      if (lengths[initPos] <= lengthPos && lengths[initPos + 1] > lengthPos) {
-        lPerc = (lengthPos - lengths[initPos]) / (lengths[initPos + 1] - lengths[initPos]);
-        flag = false;
-      } else {
-        initPos += dir;
+  var createTypedArray = function () {
+    function createRegularArray(type, len) {
+      var i = 0;
+      var arr = [];
+      var value;
+
+      switch (type) {
+        case 'int16':
+        case 'uint8c':
+          value = 1;
+          break;
+
+        default:
+          value = 1.1;
+          break;
       }
-      if (initPos < 0 || initPos >= len - 1) {
-        // FIX for TypedArrays that don't store floating point values with enough accuracy
-        if (initPos === len - 1) {
-          return percents[initPos];
-        }
-        flag = false;
+
+      for (i = 0; i < len; i += 1) {
+        arr.push(value);
       }
+
+      return arr;
     }
-    return percents[initPos] + (percents[initPos + 1] - percents[initPos]) * lPerc;
+
+    function createTypedArrayFactory(type, len) {
+      if (type === 'float32') {
+        return new Float32Array(len);
+      }
+
+      if (type === 'int16') {
+        return new Int16Array(len);
+      }
+
+      if (type === 'uint8c') {
+        return new Uint8ClampedArray(len);
+      }
+
+      return createRegularArray(type, len);
+    }
+
+    if (typeof Uint8ClampedArray === 'function' && typeof Float32Array === 'function') {
+      return createTypedArrayFactory;
+    }
+
+    return createRegularArray;
+  }();
+
+  function createSizedArray(len) {
+    return Array.apply(null, {
+      length: len
+    });
   }
 
-  function getPointInSegment(pt1, pt2, pt3, pt4, percent, bezierData) {
-    var t1 = getDistancePerc(percent, bezierData);
-    var u1 = 1 - t1;
-    var ptX = math.round((u1 * u1 * u1 * pt1[0] + (t1 * u1 * u1 + u1 * t1 * u1 + u1 * u1 * t1) * pt3[0] + (t1 * t1 * u1 + u1 * t1 * t1 + t1 * u1 * t1) * pt4[0] + t1 * t1 * t1 * pt2[0]) * 1000) / 1000;
-    var ptY = math.round((u1 * u1 * u1 * pt1[1] + (t1 * u1 * u1 + u1 * t1 * u1 + u1 * u1 * t1) * pt3[1] + (t1 * t1 * u1 + u1 * t1 * t1 + t1 * u1 * t1) * pt4[1] + t1 * t1 * t1 * pt2[1]) * 1000) / 1000;
-    return [ptX, ptY];
-  }
+  function _typeof$6(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof$6 = function _typeof(obj) { return typeof obj; }; } else { _typeof$6 = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof$6(obj); }
+  var subframeEnabled = true;
+  var expressionsPlugin = null;
+  var idPrefix = '';
+  var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
+  var _shouldRoundValues = false;
+  var bmPow = Math.pow;
+  var bmSqrt = Math.sqrt;
+  var bmFloor = Math.floor;
+  var bmMax = Math.max;
+  var bmMin = Math.min;
+  var BMMath = {};
 
-  var bezierSegmentPoints = createTypedArray('float32', 8);
-
-  function getNewSegment(pt1, pt2, pt3, pt4, startPerc, endPerc, bezierData) {
-    if (startPerc < 0) {
-      startPerc = 0;
-    } else if (startPerc > 1) {
-      startPerc = 1;
-    }
-    var t0 = getDistancePerc(startPerc, bezierData);
-    endPerc = endPerc > 1 ? 1 : endPerc;
-    var t1 = getDistancePerc(endPerc, bezierData);
+  (function () {
+    var propertyNames = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atanh', 'atan2', 'ceil', 'cbrt', 'expm1', 'clz32', 'cos', 'cosh', 'exp', 'floor', 'fround', 'hypot', 'imul', 'log', 'log1p', 'log2', 'log10', 'max', 'min', 'pow', 'random', 'round', 'sign', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc', 'E', 'LN10', 'LN2', 'LOG10E', 'LOG2E', 'PI', 'SQRT1_2', 'SQRT2'];
     var i;
-    var len = pt1.length;
-    var u0 = 1 - t0;
-    var u1 = 1 - t1;
-    var u0u0u0 = u0 * u0 * u0;
-    var t0u0u0_3 = t0 * u0 * u0 * 3; // eslint-disable-line camelcase
-    var t0t0u0_3 = t0 * t0 * u0 * 3; // eslint-disable-line camelcase
-    var t0t0t0 = t0 * t0 * t0;
-    //
-    var u0u0u1 = u0 * u0 * u1;
-    var t0u0u1_3 = t0 * u0 * u1 + u0 * t0 * u1 + u0 * u0 * t1; // eslint-disable-line camelcase
-    var t0t0u1_3 = t0 * t0 * u1 + u0 * t0 * t1 + t0 * u0 * t1; // eslint-disable-line camelcase
-    var t0t0t1 = t0 * t0 * t1;
-    //
-    var u0u1u1 = u0 * u1 * u1;
-    var t0u1u1_3 = t0 * u1 * u1 + u0 * t1 * u1 + u0 * u1 * t1; // eslint-disable-line camelcase
-    var t0t1u1_3 = t0 * t1 * u1 + u0 * t1 * t1 + t0 * u1 * t1; // eslint-disable-line camelcase
-    var t0t1t1 = t0 * t1 * t1;
-    //
-    var u1u1u1 = u1 * u1 * u1;
-    var t1u1u1_3 = t1 * u1 * u1 + u1 * t1 * u1 + u1 * u1 * t1; // eslint-disable-line camelcase
-    var t1t1u1_3 = t1 * t1 * u1 + u1 * t1 * t1 + t1 * u1 * t1; // eslint-disable-line camelcase
-    var t1t1t1 = t1 * t1 * t1;
+    var len = propertyNames.length;
+
     for (i = 0; i < len; i += 1) {
-      bezierSegmentPoints[i * 4] = math.round((u0u0u0 * pt1[i] + t0u0u0_3 * pt3[i] + t0t0u0_3 * pt4[i] + t0t0t0 * pt2[i]) * 1000) / 1000; // eslint-disable-line camelcase
-      bezierSegmentPoints[i * 4 + 1] = math.round((u0u0u1 * pt1[i] + t0u0u1_3 * pt3[i] + t0t0u1_3 * pt4[i] + t0t0t1 * pt2[i]) * 1000) / 1000; // eslint-disable-line camelcase
-      bezierSegmentPoints[i * 4 + 2] = math.round((u0u1u1 * pt1[i] + t0u1u1_3 * pt3[i] + t0t1u1_3 * pt4[i] + t0t1t1 * pt2[i]) * 1000) / 1000; // eslint-disable-line camelcase
-      bezierSegmentPoints[i * 4 + 3] = math.round((u1u1u1 * pt1[i] + t1u1u1_3 * pt3[i] + t1t1u1_3 * pt4[i] + t1t1t1 * pt2[i]) * 1000) / 1000; // eslint-disable-line camelcase
+      BMMath[propertyNames[i]] = Math[propertyNames[i]];
     }
+  })();
 
-    return bezierSegmentPoints;
+  function ProjectInterface$1() {
+    return {};
   }
 
-  return {
-    getSegmentsLength: getSegmentsLength,
-    getNewSegment: getNewSegment,
-    getPointInSegment: getPointInSegment,
-    buildBezierData: buildBezierData,
-    pointOnLine2D: pointOnLine2D,
-    pointOnLine3D: pointOnLine3D,
-  };
-}
+  BMMath.random = Math.random;
 
-var bez = bezFunction();
+  BMMath.abs = function (val) {
+    var tOfVal = _typeof$6(val);
 
-/* global _useWebWorker */
+    if (tOfVal === 'object' && val.length) {
+      var absArr = createSizedArray(val.length);
+      var i;
+      var len = val.length;
 
-var dataManager = (function () {
-  var _counterId = 1;
-  var processes = [];
-  var workerFn;
-  var workerInstance;
-  var workerProxy = {
-    onmessage: function () {
+      for (i = 0; i < len; i += 1) {
+        absArr[i] = Math.abs(val[i]);
+      }
 
-    },
-    postMessage: function (path) {
-      workerFn({
-        data: path,
-      });
-    },
-  };
-  var _workerSelf = {
-    postMessage: function (data) {
-      workerProxy.onmessage({
-        data: data,
-      });
-    },
-  };
-  function createWorker(fn) {
-    if (window.Worker && window.Blob && _useWebWorker) {
-      var blob = new Blob(['var _workerSelf = self; self.onmessage = ', fn.toString()], { type: 'text/javascript' });
-      // var blob = new Blob(['self.onmessage = ', fn.toString()], { type: 'text/javascript' });
-      var url = URL.createObjectURL(blob);
-      return new Worker(url);
+      return absArr;
     }
-    workerFn = fn;
-    return workerProxy;
+
+    return Math.abs(val);
+  };
+
+  var defaultCurveSegments = 150;
+  var degToRads = Math.PI / 180;
+  var roundCorner = 0.5519;
+
+  function roundValues(flag) {
+    _shouldRoundValues = !!flag;
   }
 
-  function setupWorker() {
-    if (!workerInstance) {
-      workerInstance = createWorker(function workerStart(e) {
-        /* exported dataManager */
+  function bmRnd(value) {
+    if (_shouldRoundValues) {
+      return Math.round(value);
+    }
 
-        function dataFunctionManager() {
-          // var tCanvasHelper = createTag('canvas').getContext('2d');
+    return value;
+  }
 
-          function completeLayers(layers, comps) {
-            var layerData;
-            var i;
-            var len = layers.length;
-            var j;
-            var jLen;
-            var k;
-            var kLen;
-            for (i = 0; i < len; i += 1) {
-              layerData = layers[i];
-              if (('ks' in layerData) && !layerData.completed) {
-                layerData.completed = true;
-                if (layerData.tt) {
-                  layers[i - 1].td = layerData.tt;
-                }
-                if (layerData.hasMask) {
-                  var maskProps = layerData.masksProperties;
-                  jLen = maskProps.length;
-                  for (j = 0; j < jLen; j += 1) {
-                    if (maskProps[j].pt.k.i) {
-                      convertPathsToAbsoluteValues(maskProps[j].pt.k);
-                    } else {
-                      kLen = maskProps[j].pt.k.length;
-                      for (k = 0; k < kLen; k += 1) {
-                        if (maskProps[j].pt.k[k].s) {
-                          convertPathsToAbsoluteValues(maskProps[j].pt.k[k].s[0]);
-                        }
-                        if (maskProps[j].pt.k[k].e) {
-                          convertPathsToAbsoluteValues(maskProps[j].pt.k[k].e[0]);
-                        }
-                      }
-                    }
-                  }
-                }
-                if (layerData.ty === 0) {
-                  layerData.layers = findCompLayers(layerData.refId, comps);
-                  completeLayers(layerData.layers, comps);
-                } else if (layerData.ty === 4) {
-                  completeShapes(layerData.shapes);
-                } else if (layerData.ty === 5) {
-                  completeText(layerData);
-                }
-              }
-            }
-          }
+  function styleDiv(element) {
+    element.style.position = 'absolute';
+    element.style.top = 0;
+    element.style.left = 0;
+    element.style.display = 'block';
+    element.style.transformOrigin = '0 0';
+    element.style.webkitTransformOrigin = '0 0';
+    element.style.backfaceVisibility = 'visible';
+    element.style.webkitBackfaceVisibility = 'visible';
+    element.style.transformStyle = 'preserve-3d';
+    element.style.webkitTransformStyle = 'preserve-3d';
+    element.style.mozTransformStyle = 'preserve-3d';
+  }
 
-          function findCompLayers(id, comps) {
-            var i = 0;
-            var len = comps.length;
-            while (i < len) {
-              if (comps[i].id === id) {
-                if (!comps[i].layers.__used) {
-                  comps[i].layers.__used = true;
-                  return comps[i].layers;
-                }
-                return JSON.parse(JSON.stringify(comps[i].layers));
-              }
-              i += 1;
-            }
-            return null;
-          }
+  function BMEnterFrameEvent(type, currentTime, totalTime, frameMultiplier) {
+    this.type = type;
+    this.currentTime = currentTime;
+    this.totalTime = totalTime;
+    this.direction = frameMultiplier < 0 ? -1 : 1;
+  }
 
-          function completeShapes(arr) {
-            var i;
-            var len = arr.length;
-            var j;
-            var jLen;
-            for (i = len - 1; i >= 0; i -= 1) {
-              if (arr[i].ty === 'sh') {
-                if (arr[i].ks.k.i) {
-                  convertPathsToAbsoluteValues(arr[i].ks.k);
-                } else {
-                  jLen = arr[i].ks.k.length;
-                  for (j = 0; j < jLen; j += 1) {
-                    if (arr[i].ks.k[j].s) {
-                      convertPathsToAbsoluteValues(arr[i].ks.k[j].s[0]);
-                    }
-                    if (arr[i].ks.k[j].e) {
-                      convertPathsToAbsoluteValues(arr[i].ks.k[j].e[0]);
-                    }
-                  }
-                }
-              } else if (arr[i].ty === 'gr') {
-                completeShapes(arr[i].it);
-              }
-            }
-          }
+  function BMCompleteEvent(type, frameMultiplier) {
+    this.type = type;
+    this.direction = frameMultiplier < 0 ? -1 : 1;
+  }
 
-          function convertPathsToAbsoluteValues(path) {
-            var i;
-            var len = path.i.length;
-            for (i = 0; i < len; i += 1) {
-              path.i[i][0] += path.v[i][0];
-              path.i[i][1] += path.v[i][1];
-              path.o[i][0] += path.v[i][0];
-              path.o[i][1] += path.v[i][1];
-            }
-          }
+  function BMCompleteLoopEvent(type, totalLoops, currentLoop, frameMultiplier) {
+    this.type = type;
+    this.currentLoop = currentLoop;
+    this.totalLoops = totalLoops;
+    this.direction = frameMultiplier < 0 ? -1 : 1;
+  }
 
-          function checkVersion(minimum, animVersionString) {
-            var animVersion = animVersionString ? animVersionString.split('.') : [100, 100, 100];
-            if (minimum[0] > animVersion[0]) {
-              return true;
-            } if (animVersion[0] > minimum[0]) {
-              return false;
-            }
-            if (minimum[1] > animVersion[1]) {
-              return true;
-            } if (animVersion[1] > minimum[1]) {
-              return false;
-            }
-            if (minimum[2] > animVersion[2]) {
-              return true;
-            } if (animVersion[2] > minimum[2]) {
-              return false;
-            }
-            return null;
-          }
+  function BMSegmentStartEvent(type, firstFrame, totalFrames) {
+    this.type = type;
+    this.firstFrame = firstFrame;
+    this.totalFrames = totalFrames;
+  }
 
-          var checkText = (function () {
-            var minimumVersion = [4, 4, 14];
+  function BMDestroyEvent(type, target) {
+    this.type = type;
+    this.target = target;
+  }
 
-            function updateTextLayer(textLayer) {
-              var documentData = textLayer.t.d;
-              textLayer.t.d = {
-                k: [
-                  {
-                    s: documentData,
-                    t: 0,
-                  },
-                ],
-              };
-            }
+  function BMRenderFrameErrorEvent(nativeError, currentTime) {
+    this.type = 'renderFrameError';
+    this.nativeError = nativeError;
+    this.currentTime = currentTime;
+  }
 
-            function iterateLayers(layers) {
-              var i;
-              var len = layers.length;
-              for (i = 0; i < len; i += 1) {
-                if (layers[i].ty === 5) {
-                  updateTextLayer(layers[i]);
-                }
-              }
-            }
+  function BMConfigErrorEvent(nativeError) {
+    this.type = 'configError';
+    this.nativeError = nativeError;
+  }
 
-            return function (animationData) {
-              if (checkVersion(minimumVersion, animationData.v)) {
-                iterateLayers(animationData.layers);
-                if (animationData.assets) {
-                  var i;
-                  var len = animationData.assets.length;
-                  for (i = 0; i < len; i += 1) {
-                    if (animationData.assets[i].layers) {
-                      iterateLayers(animationData.assets[i].layers);
-                    }
-                  }
-                }
-              }
-            };
-          }());
+  function BMAnimationConfigErrorEvent(type, nativeError) {
+    this.type = type;
+    this.nativeError = nativeError;
+  }
 
-          var checkChars = (function () {
-            var minimumVersion = [4, 7, 99];
-            return function (animationData) {
-              if (animationData.chars && !checkVersion(minimumVersion, animationData.v)) {
-                var i;
-                var len = animationData.chars.length;
-                var j;
-                var jLen;
-                var pathData;
-                var paths;
-                for (i = 0; i < len; i += 1) {
-                  if (animationData.chars[i].data && animationData.chars[i].data.shapes) {
-                    paths = animationData.chars[i].data.shapes[0].it;
-                    jLen = paths.length;
+  var createElementID = function () {
+    var _count = 0;
+    return function createID() {
+      _count += 1;
+      return idPrefix + '__lottie_element_' + _count;
+    };
+  }();
 
-                    for (j = 0; j < jLen; j += 1) {
-                      pathData = paths[j].ks.k;
-                      if (!pathData.__converted) {
-                        convertPathsToAbsoluteValues(paths[j].ks.k);
-                        pathData.__converted = true;
-                      }
-                    }
-                  }
-                }
-              }
-            };
-          }());
+  function HSVtoRGB(h, s, v) {
+    var r;
+    var g;
+    var b;
+    var i;
+    var f;
+    var p;
+    var q;
+    var t;
+    i = Math.floor(h * 6);
+    f = h * 6 - i;
+    p = v * (1 - s);
+    q = v * (1 - f * s);
+    t = v * (1 - (1 - f) * s);
 
-          var checkPathProperties = (function () {
-            var minimumVersion = [5, 7, 15];
+    switch (i % 6) {
+      case 0:
+        r = v;
+        g = t;
+        b = p;
+        break;
 
-            function updateTextLayer(textLayer) {
-              var pathData = textLayer.t.p;
-              if (typeof pathData.a === 'number') {
-                pathData.a = {
-                  a: 0,
-                  k: pathData.a,
-                };
-              }
-              if (typeof pathData.p === 'number') {
-                pathData.p = {
-                  a: 0,
-                  k: pathData.p,
-                };
-              }
-              if (typeof pathData.r === 'number') {
-                pathData.r = {
-                  a: 0,
-                  k: pathData.r,
-                };
-              }
-            }
+      case 1:
+        r = q;
+        g = v;
+        b = p;
+        break;
 
-            function iterateLayers(layers) {
-              var i;
-              var len = layers.length;
-              for (i = 0; i < len; i += 1) {
-                if (layers[i].ty === 5) {
-                  updateTextLayer(layers[i]);
-                }
-              }
-            }
+      case 2:
+        r = p;
+        g = v;
+        b = t;
+        break;
 
-            return function (animationData) {
-              if (checkVersion(minimumVersion, animationData.v)) {
-                iterateLayers(animationData.layers);
-                if (animationData.assets) {
-                  var i;
-                  var len = animationData.assets.length;
-                  for (i = 0; i < len; i += 1) {
-                    if (animationData.assets[i].layers) {
-                      iterateLayers(animationData.assets[i].layers);
-                    }
-                  }
-                }
-              }
-            };
-          }());
+      case 3:
+        r = p;
+        g = q;
+        b = v;
+        break;
 
-          var checkColors = (function () {
-            var minimumVersion = [4, 1, 9];
+      case 4:
+        r = t;
+        g = p;
+        b = v;
+        break;
 
-            function iterateShapes(shapes) {
-              var i;
-              var len = shapes.length;
-              var j;
-              var jLen;
-              for (i = 0; i < len; i += 1) {
-                if (shapes[i].ty === 'gr') {
-                  iterateShapes(shapes[i].it);
-                } else if (shapes[i].ty === 'fl' || shapes[i].ty === 'st') {
-                  if (shapes[i].c.k && shapes[i].c.k[0].i) {
-                    jLen = shapes[i].c.k.length;
-                    for (j = 0; j < jLen; j += 1) {
-                      if (shapes[i].c.k[j].s) {
-                        shapes[i].c.k[j].s[0] /= 255;
-                        shapes[i].c.k[j].s[1] /= 255;
-                        shapes[i].c.k[j].s[2] /= 255;
-                        shapes[i].c.k[j].s[3] /= 255;
-                      }
-                      if (shapes[i].c.k[j].e) {
-                        shapes[i].c.k[j].e[0] /= 255;
-                        shapes[i].c.k[j].e[1] /= 255;
-                        shapes[i].c.k[j].e[2] /= 255;
-                        shapes[i].c.k[j].e[3] /= 255;
-                      }
-                    }
-                  } else {
-                    shapes[i].c.k[0] /= 255;
-                    shapes[i].c.k[1] /= 255;
-                    shapes[i].c.k[2] /= 255;
-                    shapes[i].c.k[3] /= 255;
-                  }
-                }
-              }
-            }
+      case 5:
+        r = v;
+        g = p;
+        b = q;
+        break;
 
-            function iterateLayers(layers) {
-              var i;
-              var len = layers.length;
-              for (i = 0; i < len; i += 1) {
-                if (layers[i].ty === 4) {
-                  iterateShapes(layers[i].shapes);
-                }
-              }
-            }
+      default:
+        break;
+    }
 
-            return function (animationData) {
-              if (checkVersion(minimumVersion, animationData.v)) {
-                iterateLayers(animationData.layers);
-                if (animationData.assets) {
-                  var i;
-                  var len = animationData.assets.length;
-                  for (i = 0; i < len; i += 1) {
-                    if (animationData.assets[i].layers) {
-                      iterateLayers(animationData.assets[i].layers);
-                    }
-                  }
-                }
-              }
-            };
-          }());
+    return [r, g, b];
+  }
 
-          var checkShapes = (function () {
-            var minimumVersion = [4, 4, 18];
+  function RGBtoHSV(r, g, b) {
+    var max = Math.max(r, g, b);
+    var min = Math.min(r, g, b);
+    var d = max - min;
+    var h;
+    var s = max === 0 ? 0 : d / max;
+    var v = max / 255;
 
-            function completeClosingShapes(arr) {
-              var i;
-              var len = arr.length;
-              var j;
-              var jLen;
-              for (i = len - 1; i >= 0; i -= 1) {
-                if (arr[i].ty === 'sh') {
-                  if (arr[i].ks.k.i) {
-                    arr[i].ks.k.c = arr[i].closed;
-                  } else {
-                    jLen = arr[i].ks.k.length;
-                    for (j = 0; j < jLen; j += 1) {
-                      if (arr[i].ks.k[j].s) {
-                        arr[i].ks.k[j].s[0].c = arr[i].closed;
-                      }
-                      if (arr[i].ks.k[j].e) {
-                        arr[i].ks.k[j].e[0].c = arr[i].closed;
-                      }
-                    }
-                  }
-                } else if (arr[i].ty === 'gr') {
-                  completeClosingShapes(arr[i].it);
-                }
-              }
-            }
+    switch (max) {
+      case min:
+        h = 0;
+        break;
 
-            function iterateLayers(layers) {
+      case r:
+        h = g - b + d * (g < b ? 6 : 0);
+        h /= 6 * d;
+        break;
+
+      case g:
+        h = b - r + d * 2;
+        h /= 6 * d;
+        break;
+
+      case b:
+        h = r - g + d * 4;
+        h /= 6 * d;
+        break;
+
+      default:
+        break;
+    }
+
+    return [h, s, v];
+  }
+
+  function addSaturationToRGB(color, offset) {
+    var hsv = RGBtoHSV(color[0] * 255, color[1] * 255, color[2] * 255);
+    hsv[1] += offset;
+
+    if (hsv[1] > 1) {
+      hsv[1] = 1;
+    } else if (hsv[1] <= 0) {
+      hsv[1] = 0;
+    }
+
+    return HSVtoRGB(hsv[0], hsv[1], hsv[2]);
+  }
+
+  function addBrightnessToRGB(color, offset) {
+    var hsv = RGBtoHSV(color[0] * 255, color[1] * 255, color[2] * 255);
+    hsv[2] += offset;
+
+    if (hsv[2] > 1) {
+      hsv[2] = 1;
+    } else if (hsv[2] < 0) {
+      hsv[2] = 0;
+    }
+
+    return HSVtoRGB(hsv[0], hsv[1], hsv[2]);
+  }
+
+  function addHueToRGB(color, offset) {
+    var hsv = RGBtoHSV(color[0] * 255, color[1] * 255, color[2] * 255);
+    hsv[0] += offset / 360;
+
+    if (hsv[0] > 1) {
+      hsv[0] -= 1;
+    } else if (hsv[0] < 0) {
+      hsv[0] += 1;
+    }
+
+    return HSVtoRGB(hsv[0], hsv[1], hsv[2]);
+  }
+
+  var rgbToHex = function () {
+    var colorMap = [];
+    var i;
+    var hex;
+
+    for (i = 0; i < 256; i += 1) {
+      hex = i.toString(16);
+      colorMap[i] = hex.length === 1 ? '0' + hex : hex;
+    }
+
+    return function (r, g, b) {
+      if (r < 0) {
+        r = 0;
+      }
+
+      if (g < 0) {
+        g = 0;
+      }
+
+      if (b < 0) {
+        b = 0;
+      }
+
+      return '#' + colorMap[r] + colorMap[g] + colorMap[b];
+    };
+  }();
+
+  var setSubframeEnabled = function setSubframeEnabled(flag) {
+    subframeEnabled = !!flag;
+  };
+
+  var getSubframeEnabled = function getSubframeEnabled() {
+    return subframeEnabled;
+  };
+
+  var setExpressionsPlugin = function setExpressionsPlugin(value) {
+    expressionsPlugin = value;
+  };
+
+  var getExpressionsPlugin = function getExpressionsPlugin() {
+    return expressionsPlugin;
+  };
+
+  var setDefaultCurveSegments = function setDefaultCurveSegments(value) {
+    defaultCurveSegments = value;
+  };
+
+  var getDefaultCurveSegments = function getDefaultCurveSegments() {
+    return defaultCurveSegments;
+  };
+
+  var setIdPrefix = function setIdPrefix(value) {
+    idPrefix = value;
+  };
+
+  var getIdPrefix = function getIdPrefix() {
+    return idPrefix;
+  };
+
+  function createNS(type) {
+    // return {appendChild:function(){},setAttribute:function(){},style:{}}
+    return document.createElementNS(svgNS, type);
+  }
+
+  function _typeof$5(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof$5 = function _typeof(obj) { return typeof obj; }; } else { _typeof$5 = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof$5(obj); }
+
+  var dataManager = function () {
+    var _counterId = 1;
+    var processes = [];
+    var workerFn;
+    var workerInstance;
+    var workerProxy = {
+      onmessage: function onmessage() {},
+      postMessage: function postMessage(path) {
+        workerFn({
+          data: path
+        });
+      }
+    };
+    var _workerSelf = {
+      postMessage: function postMessage(data) {
+        workerProxy.onmessage({
+          data: data
+        });
+      }
+    };
+
+    function createWorker(fn) {
+      if (window.Worker && window.Blob && getWebWorker()) {
+        var blob = new Blob(['var _workerSelf = self; self.onmessage = ', fn.toString()], {
+          type: 'text/javascript'
+        }); // var blob = new Blob(['self.onmessage = ', fn.toString()], { type: 'text/javascript' });
+
+        var url = URL.createObjectURL(blob);
+        return new Worker(url);
+      }
+
+      workerFn = fn;
+      return workerProxy;
+    }
+
+    function setupWorker() {
+      if (!workerInstance) {
+        workerInstance = createWorker(function workerStart(e) {
+          function dataFunctionManager() {
+            function completeLayers(layers, comps) {
               var layerData;
               var i;
               var len = layers.length;
@@ -1913,4860 +581,1038 @@
               var jLen;
               var k;
               var kLen;
+
               for (i = 0; i < len; i += 1) {
                 layerData = layers[i];
-                if (layerData.hasMask) {
-                  var maskProps = layerData.masksProperties;
-                  jLen = maskProps.length;
-                  for (j = 0; j < jLen; j += 1) {
-                    if (maskProps[j].pt.k.i) {
-                      maskProps[j].pt.k.c = maskProps[j].cl;
-                    } else {
-                      kLen = maskProps[j].pt.k.length;
-                      for (k = 0; k < kLen; k += 1) {
-                        if (maskProps[j].pt.k[k].s) {
-                          maskProps[j].pt.k[k].s[0].c = maskProps[j].cl;
-                        }
-                        if (maskProps[j].pt.k[k].e) {
-                          maskProps[j].pt.k[k].e[0].c = maskProps[j].cl;
+
+                if ('ks' in layerData && !layerData.completed) {
+                  layerData.completed = true;
+
+                  if (layerData.tt) {
+                    layers[i - 1].td = layerData.tt;
+                  }
+
+                  if (layerData.hasMask) {
+                    var maskProps = layerData.masksProperties;
+                    jLen = maskProps.length;
+
+                    for (j = 0; j < jLen; j += 1) {
+                      if (maskProps[j].pt.k.i) {
+                        convertPathsToAbsoluteValues(maskProps[j].pt.k);
+                      } else {
+                        kLen = maskProps[j].pt.k.length;
+
+                        for (k = 0; k < kLen; k += 1) {
+                          if (maskProps[j].pt.k[k].s) {
+                            convertPathsToAbsoluteValues(maskProps[j].pt.k[k].s[0]);
+                          }
+
+                          if (maskProps[j].pt.k[k].e) {
+                            convertPathsToAbsoluteValues(maskProps[j].pt.k[k].e[0]);
+                          }
                         }
                       }
                     }
                   }
-                }
-                if (layerData.ty === 4) {
-                  completeClosingShapes(layerData.shapes);
-                }
-              }
-            }
 
-            return function (animationData) {
-              if (checkVersion(minimumVersion, animationData.v)) {
-                iterateLayers(animationData.layers);
-                if (animationData.assets) {
-                  var i;
-                  var len = animationData.assets.length;
-                  for (i = 0; i < len; i += 1) {
-                    if (animationData.assets[i].layers) {
-                      iterateLayers(animationData.assets[i].layers);
-                    }
+                  if (layerData.ty === 0) {
+                    layerData.layers = findCompLayers(layerData.refId, comps);
+                    completeLayers(layerData.layers, comps);
+                  } else if (layerData.ty === 4) {
+                    completeShapes(layerData.shapes);
+                  } else if (layerData.ty === 5) {
+                    completeText(layerData);
                   }
                 }
               }
-            };
-          }());
-
-          function completeData(animationData) {
-            if (animationData.__complete) {
-              return;
             }
-            checkColors(animationData);
-            checkText(animationData);
-            checkChars(animationData);
-            checkPathProperties(animationData);
-            checkShapes(animationData);
-            completeLayers(animationData.layers, animationData.assets);
-            animationData.__complete = true;
-          }
 
-          function completeText(data) {
-            if (data.t.a.length === 0 && !('m' in data.t.p)) {
-              data.singleShape = true;
+            function completeChars(chars, assets) {
+              if (chars) {
+                var i = 0;
+                var len = chars.length;
+
+                for (i = 0; i < len; i += 1) {
+                  if (chars[i].t === 1) {
+                    // var compData = findComp(chars[i].data.refId, assets);
+                    chars[i].data.layers = findCompLayers(chars[i].data.refId, assets); // chars[i].data.ip = 0;
+                    // chars[i].data.op = 99999;
+                    // chars[i].data.st = 0;
+                    // chars[i].data.sr = 1;
+                    // chars[i].w = compData.w;
+                    // chars[i].data.ks = {
+                    //   a: { k: [0, 0, 0], a: 0 },
+                    //   p: { k: [0, -compData.h, 0], a: 0 },
+                    //   r: { k: 0, a: 0 },
+                    //   s: { k: [100, 100], a: 0 },
+                    //   o: { k: 100, a: 0 },
+                    // };
+
+                    completeLayers(chars[i].data.layers, assets);
+                  }
+                }
+              }
             }
-          }
 
-          var moduleOb = {};
-          moduleOb.completeData = completeData;
-          moduleOb.checkColors = checkColors;
-          moduleOb.checkChars = checkChars;
-          moduleOb.checkPathProperties = checkPathProperties;
-          moduleOb.checkShapes = checkShapes;
-          moduleOb.completeLayers = completeLayers;
+            function findComp(id, comps) {
+              var i = 0;
+              var len = comps.length;
 
-          return moduleOb;
-        }
-        if (!_workerSelf.dataManager) {
-          _workerSelf.dataManager = dataFunctionManager();
-        }
+              while (i < len) {
+                if (comps[i].id === id) {
+                  return comps[i];
+                }
 
-        /* exported assetLoader */
-        if (!_workerSelf.assetLoader) {
-          _workerSelf.assetLoader = (function () {
-            function formatResponse(xhr) {
-              // using typeof doubles the time of execution of this method,
-              // so if available, it's better to use the header to validate the type
-              var contentTypeHeader = xhr.getResponseHeader('content-type');
-              if (contentTypeHeader && xhr.responseType === 'json' && contentTypeHeader.indexOf('json') !== -1) {
-                return xhr.response;
+                i += 1;
               }
-              if (xhr.response && typeof xhr.response === 'object') {
-                return xhr.response;
-              } if (xhr.response && typeof xhr.response === 'string') {
-                return JSON.parse(xhr.response);
-              } if (xhr.responseText) {
-                return JSON.parse(xhr.responseText);
-              }
+
               return null;
             }
 
-            function loadAsset(path, fullPath, callback, errorCallback) {
-              var response;
-              var xhr = new XMLHttpRequest();
-              // set responseType after calling open or IE will break.
-              try {
-                // This crashes on Android WebView prior to KitKat
-                xhr.responseType = 'json';
-              } catch (err) {} // eslint-disable-line no-empty
-              xhr.onreadystatechange = function () {
-                if (xhr.readyState === 4) {
-                  if (xhr.status === 200) {
-                    response = formatResponse(xhr);
-                    callback(response);
+            function findCompLayers(id, comps) {
+              var comp = findComp(id, comps);
+
+              if (comp) {
+                if (!comp.layers.__used) {
+                  comp.layers.__used = true;
+                  return comp.layers;
+                }
+
+                return JSON.parse(JSON.stringify(comp.layers));
+              }
+
+              return null;
+            }
+
+            function completeShapes(arr) {
+              var i;
+              var len = arr.length;
+              var j;
+              var jLen;
+
+              for (i = len - 1; i >= 0; i -= 1) {
+                if (arr[i].ty === 'sh') {
+                  if (arr[i].ks.k.i) {
+                    convertPathsToAbsoluteValues(arr[i].ks.k);
                   } else {
-                    try {
-                      response = formatResponse(xhr);
-                      callback(response);
-                    } catch (err) {
-                      if (errorCallback) {
-                        errorCallback(err);
+                    jLen = arr[i].ks.k.length;
+
+                    for (j = 0; j < jLen; j += 1) {
+                      if (arr[i].ks.k[j].s) {
+                        convertPathsToAbsoluteValues(arr[i].ks.k[j].s[0]);
+                      }
+
+                      if (arr[i].ks.k[j].e) {
+                        convertPathsToAbsoluteValues(arr[i].ks.k[j].e[0]);
+                      }
+                    }
+                  }
+                } else if (arr[i].ty === 'gr') {
+                  completeShapes(arr[i].it);
+                }
+              }
+            }
+
+            function convertPathsToAbsoluteValues(path) {
+              var i;
+              var len = path.i.length;
+
+              for (i = 0; i < len; i += 1) {
+                path.i[i][0] += path.v[i][0];
+                path.i[i][1] += path.v[i][1];
+                path.o[i][0] += path.v[i][0];
+                path.o[i][1] += path.v[i][1];
+              }
+            }
+
+            function checkVersion(minimum, animVersionString) {
+              var animVersion = animVersionString ? animVersionString.split('.') : [100, 100, 100];
+
+              if (minimum[0] > animVersion[0]) {
+                return true;
+              }
+
+              if (animVersion[0] > minimum[0]) {
+                return false;
+              }
+
+              if (minimum[1] > animVersion[1]) {
+                return true;
+              }
+
+              if (animVersion[1] > minimum[1]) {
+                return false;
+              }
+
+              if (minimum[2] > animVersion[2]) {
+                return true;
+              }
+
+              if (animVersion[2] > minimum[2]) {
+                return false;
+              }
+
+              return null;
+            }
+
+            var checkText = function () {
+              var minimumVersion = [4, 4, 14];
+
+              function updateTextLayer(textLayer) {
+                var documentData = textLayer.t.d;
+                textLayer.t.d = {
+                  k: [{
+                    s: documentData,
+                    t: 0
+                  }]
+                };
+              }
+
+              function iterateLayers(layers) {
+                var i;
+                var len = layers.length;
+
+                for (i = 0; i < len; i += 1) {
+                  if (layers[i].ty === 5) {
+                    updateTextLayer(layers[i]);
+                  }
+                }
+              }
+
+              return function (animationData) {
+                if (checkVersion(minimumVersion, animationData.v)) {
+                  iterateLayers(animationData.layers);
+
+                  if (animationData.assets) {
+                    var i;
+                    var len = animationData.assets.length;
+
+                    for (i = 0; i < len; i += 1) {
+                      if (animationData.assets[i].layers) {
+                        iterateLayers(animationData.assets[i].layers);
                       }
                     }
                   }
                 }
               };
-              try {
-                xhr.open('GET', path, true);
-              } catch (error) {
-                xhr.open('GET', fullPath + '/' + path, true);
-              }
-              xhr.send();
-            }
-            return {
-              load: loadAsset,
-            };
-          }());
-        }
+            }();
 
-        if (e.data.type === 'loadAnimation') {
-          _workerSelf.assetLoader.load(
-            e.data.path,
-            e.data.fullPath,
-            function (data) {
+            var checkChars = function () {
+              var minimumVersion = [4, 7, 99];
+              return function (animationData) {
+                if (animationData.chars && !checkVersion(minimumVersion, animationData.v)) {
+                  var i;
+                  var len = animationData.chars.length;
+
+                  for (i = 0; i < len; i += 1) {
+                    var charData = animationData.chars[i];
+
+                    if (charData.data && charData.data.shapes) {
+                      completeShapes(charData.data.shapes);
+                      charData.data.ip = 0;
+                      charData.data.op = 99999;
+                      charData.data.st = 0;
+                      charData.data.sr = 1;
+                      charData.data.ks = {
+                        p: {
+                          k: [0, 0],
+                          a: 0
+                        },
+                        s: {
+                          k: [100, 100],
+                          a: 0
+                        },
+                        a: {
+                          k: [0, 0],
+                          a: 0
+                        },
+                        r: {
+                          k: 0,
+                          a: 0
+                        },
+                        o: {
+                          k: 100,
+                          a: 0
+                        }
+                      };
+
+                      if (!animationData.chars[i].t) {
+                        charData.data.shapes.push({
+                          ty: 'no'
+                        });
+                        charData.data.shapes[0].it.push({
+                          p: {
+                            k: [0, 0],
+                            a: 0
+                          },
+                          s: {
+                            k: [100, 100],
+                            a: 0
+                          },
+                          a: {
+                            k: [0, 0],
+                            a: 0
+                          },
+                          r: {
+                            k: 0,
+                            a: 0
+                          },
+                          o: {
+                            k: 100,
+                            a: 0
+                          },
+                          sk: {
+                            k: 0,
+                            a: 0
+                          },
+                          sa: {
+                            k: 0,
+                            a: 0
+                          },
+                          ty: 'tr'
+                        });
+                      }
+                    }
+                  }
+                }
+              };
+            }();
+
+            var checkPathProperties = function () {
+              var minimumVersion = [5, 7, 15];
+
+              function updateTextLayer(textLayer) {
+                var pathData = textLayer.t.p;
+
+                if (typeof pathData.a === 'number') {
+                  pathData.a = {
+                    a: 0,
+                    k: pathData.a
+                  };
+                }
+
+                if (typeof pathData.p === 'number') {
+                  pathData.p = {
+                    a: 0,
+                    k: pathData.p
+                  };
+                }
+
+                if (typeof pathData.r === 'number') {
+                  pathData.r = {
+                    a: 0,
+                    k: pathData.r
+                  };
+                }
+              }
+
+              function iterateLayers(layers) {
+                var i;
+                var len = layers.length;
+
+                for (i = 0; i < len; i += 1) {
+                  if (layers[i].ty === 5) {
+                    updateTextLayer(layers[i]);
+                  }
+                }
+              }
+
+              return function (animationData) {
+                if (checkVersion(minimumVersion, animationData.v)) {
+                  iterateLayers(animationData.layers);
+
+                  if (animationData.assets) {
+                    var i;
+                    var len = animationData.assets.length;
+
+                    for (i = 0; i < len; i += 1) {
+                      if (animationData.assets[i].layers) {
+                        iterateLayers(animationData.assets[i].layers);
+                      }
+                    }
+                  }
+                }
+              };
+            }();
+
+            var checkColors = function () {
+              var minimumVersion = [4, 1, 9];
+
+              function iterateShapes(shapes) {
+                var i;
+                var len = shapes.length;
+                var j;
+                var jLen;
+
+                for (i = 0; i < len; i += 1) {
+                  if (shapes[i].ty === 'gr') {
+                    iterateShapes(shapes[i].it);
+                  } else if (shapes[i].ty === 'fl' || shapes[i].ty === 'st') {
+                    if (shapes[i].c.k && shapes[i].c.k[0].i) {
+                      jLen = shapes[i].c.k.length;
+
+                      for (j = 0; j < jLen; j += 1) {
+                        if (shapes[i].c.k[j].s) {
+                          shapes[i].c.k[j].s[0] /= 255;
+                          shapes[i].c.k[j].s[1] /= 255;
+                          shapes[i].c.k[j].s[2] /= 255;
+                          shapes[i].c.k[j].s[3] /= 255;
+                        }
+
+                        if (shapes[i].c.k[j].e) {
+                          shapes[i].c.k[j].e[0] /= 255;
+                          shapes[i].c.k[j].e[1] /= 255;
+                          shapes[i].c.k[j].e[2] /= 255;
+                          shapes[i].c.k[j].e[3] /= 255;
+                        }
+                      }
+                    } else {
+                      shapes[i].c.k[0] /= 255;
+                      shapes[i].c.k[1] /= 255;
+                      shapes[i].c.k[2] /= 255;
+                      shapes[i].c.k[3] /= 255;
+                    }
+                  }
+                }
+              }
+
+              function iterateLayers(layers) {
+                var i;
+                var len = layers.length;
+
+                for (i = 0; i < len; i += 1) {
+                  if (layers[i].ty === 4) {
+                    iterateShapes(layers[i].shapes);
+                  }
+                }
+              }
+
+              return function (animationData) {
+                if (checkVersion(minimumVersion, animationData.v)) {
+                  iterateLayers(animationData.layers);
+
+                  if (animationData.assets) {
+                    var i;
+                    var len = animationData.assets.length;
+
+                    for (i = 0; i < len; i += 1) {
+                      if (animationData.assets[i].layers) {
+                        iterateLayers(animationData.assets[i].layers);
+                      }
+                    }
+                  }
+                }
+              };
+            }();
+
+            var checkShapes = function () {
+              var minimumVersion = [4, 4, 18];
+
+              function completeClosingShapes(arr) {
+                var i;
+                var len = arr.length;
+                var j;
+                var jLen;
+
+                for (i = len - 1; i >= 0; i -= 1) {
+                  if (arr[i].ty === 'sh') {
+                    if (arr[i].ks.k.i) {
+                      arr[i].ks.k.c = arr[i].closed;
+                    } else {
+                      jLen = arr[i].ks.k.length;
+
+                      for (j = 0; j < jLen; j += 1) {
+                        if (arr[i].ks.k[j].s) {
+                          arr[i].ks.k[j].s[0].c = arr[i].closed;
+                        }
+
+                        if (arr[i].ks.k[j].e) {
+                          arr[i].ks.k[j].e[0].c = arr[i].closed;
+                        }
+                      }
+                    }
+                  } else if (arr[i].ty === 'gr') {
+                    completeClosingShapes(arr[i].it);
+                  }
+                }
+              }
+
+              function iterateLayers(layers) {
+                var layerData;
+                var i;
+                var len = layers.length;
+                var j;
+                var jLen;
+                var k;
+                var kLen;
+
+                for (i = 0; i < len; i += 1) {
+                  layerData = layers[i];
+
+                  if (layerData.hasMask) {
+                    var maskProps = layerData.masksProperties;
+                    jLen = maskProps.length;
+
+                    for (j = 0; j < jLen; j += 1) {
+                      if (maskProps[j].pt.k.i) {
+                        maskProps[j].pt.k.c = maskProps[j].cl;
+                      } else {
+                        kLen = maskProps[j].pt.k.length;
+
+                        for (k = 0; k < kLen; k += 1) {
+                          if (maskProps[j].pt.k[k].s) {
+                            maskProps[j].pt.k[k].s[0].c = maskProps[j].cl;
+                          }
+
+                          if (maskProps[j].pt.k[k].e) {
+                            maskProps[j].pt.k[k].e[0].c = maskProps[j].cl;
+                          }
+                        }
+                      }
+                    }
+                  }
+
+                  if (layerData.ty === 4) {
+                    completeClosingShapes(layerData.shapes);
+                  }
+                }
+              }
+
+              return function (animationData) {
+                if (checkVersion(minimumVersion, animationData.v)) {
+                  iterateLayers(animationData.layers);
+
+                  if (animationData.assets) {
+                    var i;
+                    var len = animationData.assets.length;
+
+                    for (i = 0; i < len; i += 1) {
+                      if (animationData.assets[i].layers) {
+                        iterateLayers(animationData.assets[i].layers);
+                      }
+                    }
+                  }
+                }
+              };
+            }();
+
+            function completeData(animationData) {
+              if (animationData.__complete) {
+                return;
+              }
+
+              checkColors(animationData);
+              checkText(animationData);
+              checkChars(animationData);
+              checkPathProperties(animationData);
+              checkShapes(animationData);
+              completeLayers(animationData.layers, animationData.assets);
+              completeChars(animationData.chars, animationData.assets);
+              animationData.__complete = true;
+            }
+
+            function completeText(data) {
+              if (data.t.a.length === 0 && !('m' in data.t.p)) {// data.singleShape = true;
+              }
+            }
+
+            var moduleOb = {};
+            moduleOb.completeData = completeData;
+            moduleOb.checkColors = checkColors;
+            moduleOb.checkChars = checkChars;
+            moduleOb.checkPathProperties = checkPathProperties;
+            moduleOb.checkShapes = checkShapes;
+            moduleOb.completeLayers = completeLayers;
+            return moduleOb;
+          }
+
+          if (!_workerSelf.dataManager) {
+            _workerSelf.dataManager = dataFunctionManager();
+          }
+
+          if (!_workerSelf.assetLoader) {
+            _workerSelf.assetLoader = function () {
+              function formatResponse(xhr) {
+                // using typeof doubles the time of execution of this method,
+                // so if available, it's better to use the header to validate the type
+                var contentTypeHeader = xhr.getResponseHeader('content-type');
+
+                if (contentTypeHeader && xhr.responseType === 'json' && contentTypeHeader.indexOf('json') !== -1) {
+                  return xhr.response;
+                }
+
+                if (xhr.response && _typeof$5(xhr.response) === 'object') {
+                  return xhr.response;
+                }
+
+                if (xhr.response && typeof xhr.response === 'string') {
+                  return JSON.parse(xhr.response);
+                }
+
+                if (xhr.responseText) {
+                  return JSON.parse(xhr.responseText);
+                }
+
+                return null;
+              }
+
+              function loadAsset(path, fullPath, callback, errorCallback) {
+                var response;
+                var xhr = new XMLHttpRequest(); // set responseType after calling open or IE will break.
+
+                try {
+                  // This crashes on Android WebView prior to KitKat
+                  xhr.responseType = 'json';
+                } catch (err) {} // eslint-disable-line no-empty
+
+
+                xhr.onreadystatechange = function () {
+                  if (xhr.readyState === 4) {
+                    if (xhr.status === 200) {
+                      response = formatResponse(xhr);
+                      callback(response);
+                    } else {
+                      try {
+                        response = formatResponse(xhr);
+                        callback(response);
+                      } catch (err) {
+                        if (errorCallback) {
+                          errorCallback(err);
+                        }
+                      }
+                    }
+                  }
+                };
+
+                try {
+                  xhr.open('GET', path, true);
+                } catch (error) {
+                  xhr.open('GET', fullPath + '/' + path, true);
+                }
+
+                xhr.send();
+              }
+
+              return {
+                load: loadAsset
+              };
+            }();
+          }
+
+          if (e.data.type === 'loadAnimation') {
+            _workerSelf.assetLoader.load(e.data.path, e.data.fullPath, function (data) {
               _workerSelf.dataManager.completeData(data);
+
               _workerSelf.postMessage({
                 id: e.data.id,
                 payload: data,
-                status: 'success',
+                status: 'success'
               });
-            },
-            function () {
+            }, function () {
               _workerSelf.postMessage({
                 id: e.data.id,
-                status: 'error',
+                status: 'error'
               });
-            }
-          );
-        } else if (e.data.type === 'complete') {
-          var animation = e.data.animation;
-          _workerSelf.dataManager.completeData(animation);
-          _workerSelf.postMessage({
-            id: e.data.id,
-            payload: animation,
-            status: 'success',
-          });
-        } else if (e.data.type === 'loadData') {
-          _workerSelf.assetLoader.load(
-            e.data.path,
-            e.data.fullPath,
-            function (data) {
+            });
+          } else if (e.data.type === 'complete') {
+            var animation = e.data.animation;
+
+            _workerSelf.dataManager.completeData(animation);
+
+            _workerSelf.postMessage({
+              id: e.data.id,
+              payload: animation,
+              status: 'success'
+            });
+          } else if (e.data.type === 'loadData') {
+            _workerSelf.assetLoader.load(e.data.path, e.data.fullPath, function (data) {
               _workerSelf.postMessage({
                 id: e.data.id,
                 payload: data,
-                status: 'success',
+                status: 'success'
               });
-            },
-            function () {
+            }, function () {
               _workerSelf.postMessage({
                 id: e.data.id,
-                status: 'error',
+                status: 'error'
               });
-            }
-          );
-        }
-      });
-
-      workerInstance.onmessage = function (event) {
-        var data = event.data;
-        var id = data.id;
-        var process = processes[id];
-        processes[id] = null;
-        if (data.status === 'success') {
-          process.onComplete(data.payload);
-        } else if (process.onError) {
-          process.onError();
-        }
-      };
-    }
-  }
-
-  function createProcess(onComplete, onError) {
-    _counterId += 1;
-    var id = 'processId_' + _counterId;
-    processes[id] = {
-      onComplete: onComplete,
-      onError: onError,
-    };
-    return id;
-  }
-
-  function loadAnimation(path, onComplete, onError) {
-    setupWorker();
-    var processId = createProcess(onComplete, onError);
-    workerInstance.postMessage({
-      type: 'loadAnimation',
-      path: path,
-      fullPath: window.location.origin + window.location.pathname,
-      id: processId,
-    });
-  }
-
-  function loadData(path, onComplete, onError) {
-    setupWorker();
-    var processId = createProcess(onComplete, onError);
-    workerInstance.postMessage({
-      type: 'loadData',
-      path: path,
-      fullPath: window.location.origin + window.location.pathname,
-      id: processId,
-    });
-  }
-
-  function completeAnimation(anim, onComplete, onError) {
-    setupWorker();
-    var processId = createProcess(onComplete, onError);
-    workerInstance.postMessage({
-      type: 'complete',
-      animation: anim,
-      id: processId,
-    });
-  }
-
-  return {
-    loadAnimation: loadAnimation,
-    loadData: loadData,
-    completeAnimation: completeAnimation,
-  };
-}());
-
-/* exported getFontProperties */
-
-function getFontProperties(fontData) {
-  var styles = fontData.fStyle ? fontData.fStyle.split(' ') : [];
-
-  var fWeight = 'normal'; var
-    fStyle = 'normal';
-  var len = styles.length;
-  var styleName;
-  for (var i = 0; i < len; i += 1) {
-    styleName = styles[i].toLowerCase();
-    switch (styleName) {
-      case 'italic':
-        fStyle = 'italic';
-        break;
-      case 'bold':
-        fWeight = '700';
-        break;
-      case 'black':
-        fWeight = '900';
-        break;
-      case 'medium':
-        fWeight = '500';
-        break;
-      case 'regular':
-      case 'normal':
-        fWeight = '400';
-        break;
-      case 'light':
-      case 'thin':
-        fWeight = '200';
-        break;
-      default:
-        break;
-    }
-  }
-
-  return {
-    style: fStyle,
-    weight: fontData.fWeight || fWeight,
-  };
-}
-
-/* global createNS, createTag, getFontProperties */
-/* exported FontManager */
-
-var FontManager = (function () {
-  var maxWaitingTime = 5000;
-  var emptyChar = {
-    w: 0,
-    size: 0,
-    shapes: [],
-  };
-  var combinedCharacters = [];
-  // Hindi characters
-  combinedCharacters = combinedCharacters.concat([2304, 2305, 2306, 2307, 2362, 2363, 2364, 2364, 2366,
-    2367, 2368, 2369, 2370, 2371, 2372, 2373, 2374, 2375, 2376, 2377, 2378, 2379,
-    2380, 2381, 2382, 2383, 2387, 2388, 2389, 2390, 2391, 2402, 2403]);
-
-  var surrogateModifiers = [
-    'd83cdffb',
-    'd83cdffc',
-    'd83cdffd',
-    'd83cdffe',
-    'd83cdfff',
-  ];
-
-  var zeroWidthJoiner = [65039, 8205];
-
-  function trimFontOptions(font) {
-    var familyArray = font.split(',');
-    var i;
-    var len = familyArray.length;
-    var enabledFamilies = [];
-    for (i = 0; i < len; i += 1) {
-      if (familyArray[i] !== 'sans-serif' && familyArray[i] !== 'monospace') {
-        enabledFamilies.push(familyArray[i]);
-      }
-    }
-    return enabledFamilies.join(',');
-  }
-
-  function setUpNode(font, family) {
-    var parentNode = createTag('span');
-    // Node is invisible to screen readers.
-    parentNode.setAttribute('aria-hidden', true);
-    parentNode.style.fontFamily = family;
-    var node = createTag('span');
-    // Characters that vary significantly among different fonts
-    node.innerText = 'giItT1WQy@!-/#';
-    // Visible - so we can measure it - but not on the screen
-    parentNode.style.position = 'absolute';
-    parentNode.style.left = '-10000px';
-    parentNode.style.top = '-10000px';
-    // Large font size makes even subtle changes obvious
-    parentNode.style.fontSize = '300px';
-    // Reset any font properties
-    parentNode.style.fontVariant = 'normal';
-    parentNode.style.fontStyle = 'normal';
-    parentNode.style.fontWeight = 'normal';
-    parentNode.style.letterSpacing = '0';
-    parentNode.appendChild(node);
-    document.body.appendChild(parentNode);
-
-    // Remember width with no applied web font
-    var width = node.offsetWidth;
-    node.style.fontFamily = trimFontOptions(font) + ', ' + family;
-    return { node: node, w: width, parent: parentNode };
-  }
-
-  function checkLoadedFonts() {
-    var i;
-    var len = this.fonts.length;
-    var node;
-    var w;
-    var loadedCount = len;
-    for (i = 0; i < len; i += 1) {
-      if (this.fonts[i].loaded) {
-        loadedCount -= 1;
-      } else if (this.fonts[i].fOrigin === 'n' || this.fonts[i].origin === 0) {
-        this.fonts[i].loaded = true;
-      } else {
-        node = this.fonts[i].monoCase.node;
-        w = this.fonts[i].monoCase.w;
-        if (node.offsetWidth !== w) {
-          loadedCount -= 1;
-          this.fonts[i].loaded = true;
-        } else {
-          node = this.fonts[i].sansCase.node;
-          w = this.fonts[i].sansCase.w;
-          if (node.offsetWidth !== w) {
-            loadedCount -= 1;
-            this.fonts[i].loaded = true;
-          }
-        }
-        if (this.fonts[i].loaded) {
-          this.fonts[i].sansCase.parent.parentNode.removeChild(this.fonts[i].sansCase.parent);
-          this.fonts[i].monoCase.parent.parentNode.removeChild(this.fonts[i].monoCase.parent);
-        }
-      }
-    }
-
-    if (loadedCount !== 0 && Date.now() - this.initTime < maxWaitingTime) {
-      setTimeout(this.checkLoadedFontsBinded, 20);
-    } else {
-      setTimeout(this.setIsLoadedBinded, 10);
-    }
-  }
-
-  function createHelper(def, fontData) {
-    var tHelper = createNS('text');
-    tHelper.style.fontSize = '100px';
-    // tHelper.style.fontFamily = fontData.fFamily;
-
-    var fontProps = getFontProperties(fontData);
-    tHelper.setAttribute('font-family', fontData.fFamily);
-    tHelper.setAttribute('font-style', fontProps.style);
-    tHelper.setAttribute('font-weight', fontProps.weight);
-    tHelper.textContent = '1';
-    if (fontData.fClass) {
-      tHelper.style.fontFamily = 'inherit';
-      tHelper.setAttribute('class', fontData.fClass);
-    } else {
-      tHelper.style.fontFamily = fontData.fFamily;
-    }
-    def.appendChild(tHelper);
-    var tCanvasHelper = createTag('canvas').getContext('2d');
-    tCanvasHelper.font = fontData.fWeight + ' ' + fontData.fStyle + ' 100px ' + fontData.fFamily;
-    // tCanvasHelper.font = ' 100px '+ fontData.fFamily;
-    return tHelper;
-  }
-
-  function addFonts(fontData, defs) {
-    if (!fontData) {
-      this.isLoaded = true;
-      return;
-    }
-    if (this.chars) {
-      this.isLoaded = true;
-      this.fonts = fontData.list;
-      return;
-    }
-
-    var fontArr = fontData.list;
-    var i;
-    var len = fontArr.length;
-    var _pendingFonts = len;
-    for (i = 0; i < len; i += 1) {
-      var shouldLoadFont = true;
-      var loadedSelector;
-      var j;
-      fontArr[i].loaded = false;
-      fontArr[i].monoCase = setUpNode(fontArr[i].fFamily, 'monospace');
-      fontArr[i].sansCase = setUpNode(fontArr[i].fFamily, 'sans-serif');
-      if (!fontArr[i].fPath) {
-        fontArr[i].loaded = true;
-        _pendingFonts -= 1;
-      } else if (fontArr[i].fOrigin === 'p' || fontArr[i].origin === 3) {
-        loadedSelector = document.querySelectorAll('style[f-forigin="p"][f-family="' + fontArr[i].fFamily + '"], style[f-origin="3"][f-family="' + fontArr[i].fFamily + '"]');
-
-        if (loadedSelector.length > 0) {
-          shouldLoadFont = false;
-        }
-
-        if (shouldLoadFont) {
-          var s = createTag('style');
-          s.setAttribute('f-forigin', fontArr[i].fOrigin);
-          s.setAttribute('f-origin', fontArr[i].origin);
-          s.setAttribute('f-family', fontArr[i].fFamily);
-          s.type = 'text/css';
-          s.innerText = '@font-face {font-family: ' + fontArr[i].fFamily + "; font-style: normal; src: url('" + fontArr[i].fPath + "');}";
-          defs.appendChild(s);
-        }
-      } else if (fontArr[i].fOrigin === 'g' || fontArr[i].origin === 1) {
-        loadedSelector = document.querySelectorAll('link[f-forigin="g"], link[f-origin="1"]');
-
-        for (j = 0; j < loadedSelector.length; j += 1) {
-          if (loadedSelector[j].href.indexOf(fontArr[i].fPath) !== -1) {
-            // Font is already loaded
-            shouldLoadFont = false;
-          }
-        }
-
-        if (shouldLoadFont) {
-          var l = createTag('link');
-          l.setAttribute('f-forigin', fontArr[i].fOrigin);
-          l.setAttribute('f-origin', fontArr[i].origin);
-          l.type = 'text/css';
-          l.rel = 'stylesheet';
-          l.href = fontArr[i].fPath;
-          document.body.appendChild(l);
-        }
-      } else if (fontArr[i].fOrigin === 't' || fontArr[i].origin === 2) {
-        loadedSelector = document.querySelectorAll('script[f-forigin="t"], script[f-origin="2"]');
-
-        for (j = 0; j < loadedSelector.length; j += 1) {
-          if (fontArr[i].fPath === loadedSelector[j].src) {
-            // Font is already loaded
-            shouldLoadFont = false;
-          }
-        }
-
-        if (shouldLoadFont) {
-          var sc = createTag('link');
-          sc.setAttribute('f-forigin', fontArr[i].fOrigin);
-          sc.setAttribute('f-origin', fontArr[i].origin);
-          sc.setAttribute('rel', 'stylesheet');
-          sc.setAttribute('href', fontArr[i].fPath);
-          defs.appendChild(sc);
-        }
-      }
-      fontArr[i].helper = createHelper(defs, fontArr[i]);
-      fontArr[i].cache = {};
-      this.fonts.push(fontArr[i]);
-    }
-    if (_pendingFonts === 0) {
-      this.isLoaded = true;
-    } else {
-      // On some cases even if the font is loaded, it won't load correctly when measuring text on canvas.
-      // Adding this timeout seems to fix it
-      setTimeout(this.checkLoadedFonts.bind(this), 100);
-    }
-  }
-
-  function addChars(chars) {
-    if (!chars) {
-      return;
-    }
-    if (!this.chars) {
-      this.chars = [];
-    }
-    var i;
-    var len = chars.length;
-    var j;
-    var jLen = this.chars.length;
-    var found;
-    for (i = 0; i < len; i += 1) {
-      j = 0;
-      found = false;
-      while (j < jLen) {
-        if (this.chars[j].style === chars[i].style && this.chars[j].fFamily === chars[i].fFamily && this.chars[j].ch === chars[i].ch) {
-          found = true;
-        }
-        j += 1;
-      }
-      if (!found) {
-        this.chars.push(chars[i]);
-        jLen += 1;
-      }
-    }
-  }
-
-  function getCharData(char, style, font) {
-    var i = 0;
-    var len = this.chars.length;
-    while (i < len) {
-      if (this.chars[i].ch === char && this.chars[i].style === style && this.chars[i].fFamily === font) {
-        return this.chars[i];
-      }
-      i += 1;
-    }
-    if (((typeof char === 'string' && char.charCodeAt(0) !== 13) || !char)
-            && console
-            && console.warn // eslint-disable-line no-console
-            && !this._warned
-    ) {
-      this._warned = true;
-      console.warn('Missing character from exported characters list: ', char, style, font); // eslint-disable-line no-console
-    }
-    return emptyChar;
-  }
-
-  function measureText(char, fontName, size) {
-    var fontData = this.getFontByName(fontName);
-    var index = char.charCodeAt(0);
-    if (!fontData.cache[index + 1]) {
-      var tHelper = fontData.helper;
-      // Canvas version
-      // fontData.cache[index] = tHelper.measureText(char).width / 100;
-      // SVG version
-      // console.log(tHelper.getBBox().width)
-      if (char === ' ') {
-        tHelper.textContent = '|' + char + '|';
-        var doubleSize = tHelper.getComputedTextLength();
-        tHelper.textContent = '||';
-        var singleSize = tHelper.getComputedTextLength();
-        fontData.cache[index + 1] = (doubleSize - singleSize) / 100;
-      } else {
-        tHelper.textContent = char;
-        fontData.cache[index + 1] = (tHelper.getComputedTextLength()) / 100;
-      }
-    }
-    return fontData.cache[index + 1] * size;
-  }
-
-  function getFontByName(name) {
-    var i = 0;
-    var len = this.fonts.length;
-    while (i < len) {
-      if (this.fonts[i].fName === name) {
-        return this.fonts[i];
-      }
-      i += 1;
-    }
-    return this.fonts[0];
-  }
-
-  function isModifier(firstCharCode, secondCharCode) {
-    var sum = firstCharCode.toString(16) + secondCharCode.toString(16);
-    return surrogateModifiers.indexOf(sum) !== -1;
-  }
-
-  function isZeroWidthJoiner(firstCharCode, secondCharCode) {
-    if (!secondCharCode) {
-      return firstCharCode === zeroWidthJoiner[1];
-    }
-    return firstCharCode === zeroWidthJoiner[0] && secondCharCode === zeroWidthJoiner[1];
-  }
-
-  function isCombinedCharacter(char) {
-    return combinedCharacters.indexOf(char) !== -1;
-  }
-
-  function setIsLoaded() {
-    this.isLoaded = true;
-  }
-
-  var Font = function () {
-    this.fonts = [];
-    this.chars = null;
-    this.typekitLoaded = 0;
-    this.isLoaded = false;
-    this._warned = false;
-    this.initTime = Date.now();
-    this.setIsLoadedBinded = this.setIsLoaded.bind(this);
-    this.checkLoadedFontsBinded = this.checkLoadedFonts.bind(this);
-  };
-  Font.isModifier = isModifier;
-  Font.isZeroWidthJoiner = isZeroWidthJoiner;
-  Font.isCombinedCharacter = isCombinedCharacter;
-
-  var fontPrototype = {
-    addChars: addChars,
-    addFonts: addFonts,
-    getCharData: getCharData,
-    getFontByName: getFontByName,
-    measureText: measureText,
-    checkLoadedFonts: checkLoadedFonts,
-    setIsLoaded: setIsLoaded,
-  };
-
-  Font.prototype = fontPrototype;
-
-  return Font;
-}());
-
-/* global initialDefaultFrame, BezierFactory, degToRads, bez, createTypedArray */
-/* exported PropertyFactory */
-
-var PropertyFactory = (function () {
-  var initFrame = initialDefaultFrame;
-  var mathAbs = Math.abs;
-
-  function interpolateValue(frameNum, caching) {
-    var offsetTime = this.offsetTime;
-    var newValue;
-    if (this.propType === 'multidimensional') {
-      newValue = createTypedArray('float32', this.pv.length);
-    }
-    var iterationIndex = caching.lastIndex;
-    var i = iterationIndex;
-    var len = this.keyframes.length - 1;
-    var flag = true;
-    var keyData;
-    var nextKeyData;
-    var keyframeMetadata;
-
-    while (flag) {
-      keyData = this.keyframes[i];
-      nextKeyData = this.keyframes[i + 1];
-      if (i === len - 1 && frameNum >= nextKeyData.t - offsetTime) {
-        if (keyData.h) {
-          keyData = nextKeyData;
-        }
-        iterationIndex = 0;
-        break;
-      }
-      if ((nextKeyData.t - offsetTime) > frameNum) {
-        iterationIndex = i;
-        break;
-      }
-      if (i < len - 1) {
-        i += 1;
-      } else {
-        iterationIndex = 0;
-        flag = false;
-      }
-    }
-    keyframeMetadata = this.keyframesMetadata[i] || {};
-
-    var k;
-    var kLen;
-    var perc;
-    var jLen;
-    var j;
-    var fnc;
-    var nextKeyTime = nextKeyData.t - offsetTime;
-    var keyTime = keyData.t - offsetTime;
-    var endValue;
-    if (keyData.to) {
-      if (!keyframeMetadata.bezierData) {
-        keyframeMetadata.bezierData = bez.buildBezierData(keyData.s, nextKeyData.s || keyData.e, keyData.to, keyData.ti);
-      }
-      var bezierData = keyframeMetadata.bezierData;
-      if (frameNum >= nextKeyTime || frameNum < keyTime) {
-        var ind = frameNum >= nextKeyTime ? bezierData.points.length - 1 : 0;
-        kLen = bezierData.points[ind].point.length;
-        for (k = 0; k < kLen; k += 1) {
-          newValue[k] = bezierData.points[ind].point[k];
-        }
-        // caching._lastKeyframeIndex = -1;
-      } else {
-        if (keyframeMetadata.__fnct) {
-          fnc = keyframeMetadata.__fnct;
-        } else {
-          fnc = BezierFactory.getBezierEasing(keyData.o.x, keyData.o.y, keyData.i.x, keyData.i.y, keyData.n).get;
-          keyframeMetadata.__fnct = fnc;
-        }
-        perc = fnc((frameNum - keyTime) / (nextKeyTime - keyTime));
-        var distanceInLine = bezierData.segmentLength * perc;
-
-        var segmentPerc;
-        var addedLength = (caching.lastFrame < frameNum && caching._lastKeyframeIndex === i) ? caching._lastAddedLength : 0;
-        j = (caching.lastFrame < frameNum && caching._lastKeyframeIndex === i) ? caching._lastPoint : 0;
-        flag = true;
-        jLen = bezierData.points.length;
-        while (flag) {
-          addedLength += bezierData.points[j].partialLength;
-          if (distanceInLine === 0 || perc === 0 || j === bezierData.points.length - 1) {
-            kLen = bezierData.points[j].point.length;
-            for (k = 0; k < kLen; k += 1) {
-              newValue[k] = bezierData.points[j].point[k];
-            }
-            break;
-          } else if (distanceInLine >= addedLength && distanceInLine < addedLength + bezierData.points[j + 1].partialLength) {
-            segmentPerc = (distanceInLine - addedLength) / bezierData.points[j + 1].partialLength;
-            kLen = bezierData.points[j].point.length;
-            for (k = 0; k < kLen; k += 1) {
-              newValue[k] = bezierData.points[j].point[k] + (bezierData.points[j + 1].point[k] - bezierData.points[j].point[k]) * segmentPerc;
-            }
-            break;
-          }
-          if (j < jLen - 1) {
-            j += 1;
-          } else {
-            flag = false;
-          }
-        }
-        caching._lastPoint = j;
-        caching._lastAddedLength = addedLength - bezierData.points[j].partialLength;
-        caching._lastKeyframeIndex = i;
-      }
-    } else {
-      var outX;
-      var outY;
-      var inX;
-      var inY;
-      var keyValue;
-      len = keyData.s.length;
-      endValue = nextKeyData.s || keyData.e;
-      if (this.sh && keyData.h !== 1) {
-        if (frameNum >= nextKeyTime) {
-          newValue[0] = endValue[0];
-          newValue[1] = endValue[1];
-          newValue[2] = endValue[2];
-        } else if (frameNum <= keyTime) {
-          newValue[0] = keyData.s[0];
-          newValue[1] = keyData.s[1];
-          newValue[2] = keyData.s[2];
-        } else {
-          var quatStart = createQuaternion(keyData.s);
-          var quatEnd = createQuaternion(endValue);
-          var time = (frameNum - keyTime) / (nextKeyTime - keyTime);
-          quaternionToEuler(newValue, slerp(quatStart, quatEnd, time));
-        }
-      } else {
-        for (i = 0; i < len; i += 1) {
-          if (keyData.h !== 1) {
-            if (frameNum >= nextKeyTime) {
-              perc = 1;
-            } else if (frameNum < keyTime) {
-              perc = 0;
-            } else {
-              if (keyData.o.x.constructor === Array) {
-                if (!keyframeMetadata.__fnct) {
-                  keyframeMetadata.__fnct = [];
-                }
-                if (!keyframeMetadata.__fnct[i]) {
-                  outX = keyData.o.x[i] === undefined ? keyData.o.x[0] : keyData.o.x[i];
-                  outY = keyData.o.y[i] === undefined ? keyData.o.y[0] : keyData.o.y[i];
-                  inX = keyData.i.x[i] === undefined ? keyData.i.x[0] : keyData.i.x[i];
-                  inY = keyData.i.y[i] === undefined ? keyData.i.y[0] : keyData.i.y[i];
-                  fnc = BezierFactory.getBezierEasing(outX, outY, inX, inY).get;
-                  keyframeMetadata.__fnct[i] = fnc;
-                } else {
-                  fnc = keyframeMetadata.__fnct[i];
-                }
-              } else if (!keyframeMetadata.__fnct) {
-                outX = keyData.o.x;
-                outY = keyData.o.y;
-                inX = keyData.i.x;
-                inY = keyData.i.y;
-                fnc = BezierFactory.getBezierEasing(outX, outY, inX, inY).get;
-                keyData.keyframeMetadata = fnc;
-              } else {
-                fnc = keyframeMetadata.__fnct;
-              }
-              perc = fnc((frameNum - keyTime) / (nextKeyTime - keyTime));
-            }
-          }
-
-          endValue = nextKeyData.s || keyData.e;
-          keyValue = keyData.h === 1 ? keyData.s[i] : keyData.s[i] + (endValue[i] - keyData.s[i]) * perc;
-
-          if (this.propType === 'multidimensional') {
-            newValue[i] = keyValue;
-          } else {
-            newValue = keyValue;
-          }
-        }
-      }
-    }
-    caching.lastIndex = iterationIndex;
-    return newValue;
-  }
-
-  // based on @Toji's https://github.com/toji/gl-matrix/
-  function slerp(a, b, t) {
-    var out = [];
-    var ax = a[0];
-    var ay = a[1];
-    var az = a[2];
-    var aw = a[3];
-    var bx = b[0];
-    var by = b[1];
-    var bz = b[2];
-    var bw = b[3];
-
-    var omega;
-    var cosom;
-    var sinom;
-    var scale0;
-    var scale1;
-
-    cosom = ax * bx + ay * by + az * bz + aw * bw;
-    if (cosom < 0.0) {
-      cosom = -cosom;
-      bx = -bx;
-      by = -by;
-      bz = -bz;
-      bw = -bw;
-    }
-    if ((1.0 - cosom) > 0.000001) {
-      omega = Math.acos(cosom);
-      sinom = Math.sin(omega);
-      scale0 = Math.sin((1.0 - t) * omega) / sinom;
-      scale1 = Math.sin(t * omega) / sinom;
-    } else {
-      scale0 = 1.0 - t;
-      scale1 = t;
-    }
-    out[0] = scale0 * ax + scale1 * bx;
-    out[1] = scale0 * ay + scale1 * by;
-    out[2] = scale0 * az + scale1 * bz;
-    out[3] = scale0 * aw + scale1 * bw;
-
-    return out;
-  }
-
-  function quaternionToEuler(out, quat) {
-    var qx = quat[0];
-    var qy = quat[1];
-    var qz = quat[2];
-    var qw = quat[3];
-    var heading = Math.atan2(2 * qy * qw - 2 * qx * qz, 1 - 2 * qy * qy - 2 * qz * qz);
-    var attitude = Math.asin(2 * qx * qy + 2 * qz * qw);
-    var bank = Math.atan2(2 * qx * qw - 2 * qy * qz, 1 - 2 * qx * qx - 2 * qz * qz);
-    out[0] = heading / degToRads;
-    out[1] = attitude / degToRads;
-    out[2] = bank / degToRads;
-  }
-
-  function createQuaternion(values) {
-    var heading = values[0] * degToRads;
-    var attitude = values[1] * degToRads;
-    var bank = values[2] * degToRads;
-    var c1 = Math.cos(heading / 2);
-    var c2 = Math.cos(attitude / 2);
-    var c3 = Math.cos(bank / 2);
-    var s1 = Math.sin(heading / 2);
-    var s2 = Math.sin(attitude / 2);
-    var s3 = Math.sin(bank / 2);
-    var w = c1 * c2 * c3 - s1 * s2 * s3;
-    var x = s1 * s2 * c3 + c1 * c2 * s3;
-    var y = s1 * c2 * c3 + c1 * s2 * s3;
-    var z = c1 * s2 * c3 - s1 * c2 * s3;
-
-    return [x, y, z, w];
-  }
-
-  function getValueAtCurrentTime() {
-    var frameNum = this.comp.renderedFrame - this.offsetTime;
-    var initTime = this.keyframes[0].t - this.offsetTime;
-    var endTime = this.keyframes[this.keyframes.length - 1].t - this.offsetTime;
-    if (!(frameNum === this._caching.lastFrame || (this._caching.lastFrame !== initFrame && ((this._caching.lastFrame >= endTime && frameNum >= endTime) || (this._caching.lastFrame < initTime && frameNum < initTime))))) {
-      if (this._caching.lastFrame >= frameNum) {
-        this._caching._lastKeyframeIndex = -1;
-        this._caching.lastIndex = 0;
-      }
-
-      var renderResult = this.interpolateValue(frameNum, this._caching);
-      this.pv = renderResult;
-    }
-    this._caching.lastFrame = frameNum;
-    return this.pv;
-  }
-
-  function setVValue(val) {
-    var multipliedValue;
-    if (this.propType === 'unidimensional') {
-      multipliedValue = val * this.mult;
-      if (mathAbs(this.v - multipliedValue) > 0.00001) {
-        this.v = multipliedValue;
-        this._mdf = true;
-      }
-    } else {
-      var i = 0;
-      var len = this.v.length;
-      while (i < len) {
-        multipliedValue = val[i] * this.mult;
-        if (mathAbs(this.v[i] - multipliedValue) > 0.00001) {
-          this.v[i] = multipliedValue;
-          this._mdf = true;
-        }
-        i += 1;
-      }
-    }
-  }
-
-  function processEffectsSequence() {
-    if (this.elem.globalData.frameId === this.frameId || !this.effectsSequence.length) {
-      return;
-    }
-    if (this.lock) {
-      this.setVValue(this.pv);
-      return;
-    }
-    this.lock = true;
-    this._mdf = this._isFirstFrame;
-    var i;
-    var len = this.effectsSequence.length;
-    var finalValue = this.kf ? this.pv : this.data.k;
-    for (i = 0; i < len; i += 1) {
-      finalValue = this.effectsSequence[i](finalValue);
-    }
-    this.setVValue(finalValue);
-    this._isFirstFrame = false;
-    this.lock = false;
-    this.frameId = this.elem.globalData.frameId;
-  }
-
-  function addEffect(effectFunction) {
-    this.effectsSequence.push(effectFunction);
-    this.container.addDynamicProperty(this);
-  }
-
-  function ValueProperty(elem, data, mult, container) {
-    this.propType = 'unidimensional';
-    this.mult = mult || 1;
-    this.data = data;
-    this.v = mult ? data.k * mult : data.k;
-    this.pv = data.k;
-    this._mdf = false;
-    this.elem = elem;
-    this.container = container;
-    this.comp = elem.comp;
-    this.k = false;
-    this.kf = false;
-    this.vel = 0;
-    this.effectsSequence = [];
-    this._isFirstFrame = true;
-    this.getValue = processEffectsSequence;
-    this.setVValue = setVValue;
-    this.addEffect = addEffect;
-  }
-
-  function MultiDimensionalProperty(elem, data, mult, container) {
-    this.propType = 'multidimensional';
-    this.mult = mult || 1;
-    this.data = data;
-    this._mdf = false;
-    this.elem = elem;
-    this.container = container;
-    this.comp = elem.comp;
-    this.k = false;
-    this.kf = false;
-    this.frameId = -1;
-    var i;
-    var len = data.k.length;
-    this.v = createTypedArray('float32', len);
-    this.pv = createTypedArray('float32', len);
-    this.vel = createTypedArray('float32', len);
-    for (i = 0; i < len; i += 1) {
-      this.v[i] = data.k[i] * this.mult;
-      this.pv[i] = data.k[i];
-    }
-    this._isFirstFrame = true;
-    this.effectsSequence = [];
-    this.getValue = processEffectsSequence;
-    this.setVValue = setVValue;
-    this.addEffect = addEffect;
-  }
-
-  function KeyframedValueProperty(elem, data, mult, container) {
-    this.propType = 'unidimensional';
-    this.keyframes = data.k;
-    this.keyframesMetadata = [];
-    this.offsetTime = elem.data.st;
-    this.frameId = -1;
-    this._caching = {
-      lastFrame: initFrame, lastIndex: 0, value: 0, _lastKeyframeIndex: -1,
-    };
-    this.k = true;
-    this.kf = true;
-    this.data = data;
-    this.mult = mult || 1;
-    this.elem = elem;
-    this.container = container;
-    this.comp = elem.comp;
-    this.v = initFrame;
-    this.pv = initFrame;
-    this._isFirstFrame = true;
-    this.getValue = processEffectsSequence;
-    this.setVValue = setVValue;
-    this.interpolateValue = interpolateValue;
-    this.effectsSequence = [getValueAtCurrentTime.bind(this)];
-    this.addEffect = addEffect;
-  }
-
-  function KeyframedMultidimensionalProperty(elem, data, mult, container) {
-    this.propType = 'multidimensional';
-    var i;
-    var len = data.k.length;
-    var s;
-    var e;
-    var to;
-    var ti;
-    for (i = 0; i < len - 1; i += 1) {
-      if (data.k[i].to && data.k[i].s && data.k[i + 1] && data.k[i + 1].s) {
-        s = data.k[i].s;
-        e = data.k[i + 1].s;
-        to = data.k[i].to;
-        ti = data.k[i].ti;
-        if ((s.length === 2 && !(s[0] === e[0] && s[1] === e[1]) && bez.pointOnLine2D(s[0], s[1], e[0], e[1], s[0] + to[0], s[1] + to[1]) && bez.pointOnLine2D(s[0], s[1], e[0], e[1], e[0] + ti[0], e[1] + ti[1])) || (s.length === 3 && !(s[0] === e[0] && s[1] === e[1] && s[2] === e[2]) && bez.pointOnLine3D(s[0], s[1], s[2], e[0], e[1], e[2], s[0] + to[0], s[1] + to[1], s[2] + to[2]) && bez.pointOnLine3D(s[0], s[1], s[2], e[0], e[1], e[2], e[0] + ti[0], e[1] + ti[1], e[2] + ti[2]))) {
-          data.k[i].to = null;
-          data.k[i].ti = null;
-        }
-        if (s[0] === e[0] && s[1] === e[1] && to[0] === 0 && to[1] === 0 && ti[0] === 0 && ti[1] === 0) {
-          if (s.length === 2 || (s[2] === e[2] && to[2] === 0 && ti[2] === 0)) {
-            data.k[i].to = null;
-            data.k[i].ti = null;
-          }
-        }
-      }
-    }
-    this.effectsSequence = [getValueAtCurrentTime.bind(this)];
-    this.data = data;
-    this.keyframes = data.k;
-    this.keyframesMetadata = [];
-    this.offsetTime = elem.data.st;
-    this.k = true;
-    this.kf = true;
-    this._isFirstFrame = true;
-    this.mult = mult || 1;
-    this.elem = elem;
-    this.container = container;
-    this.comp = elem.comp;
-    this.getValue = processEffectsSequence;
-    this.setVValue = setVValue;
-    this.interpolateValue = interpolateValue;
-    this.frameId = -1;
-    var arrLen = data.k[0].s.length;
-    this.v = createTypedArray('float32', arrLen);
-    this.pv = createTypedArray('float32', arrLen);
-    for (i = 0; i < arrLen; i += 1) {
-      this.v[i] = initFrame;
-      this.pv[i] = initFrame;
-    }
-    this._caching = { lastFrame: initFrame, lastIndex: 0, value: createTypedArray('float32', arrLen) };
-    this.addEffect = addEffect;
-  }
-
-  function getProp(elem, data, type, mult, container) {
-    var p;
-    if (!data.k.length) {
-      p = new ValueProperty(elem, data, mult, container);
-    } else if (typeof (data.k[0]) === 'number') {
-      p = new MultiDimensionalProperty(elem, data, mult, container);
-    } else {
-      switch (type) {
-        case 0:
-          p = new KeyframedValueProperty(elem, data, mult, container);
-          break;
-        case 1:
-          p = new KeyframedMultidimensionalProperty(elem, data, mult, container);
-          break;
-        default:
-          break;
-      }
-    }
-    if (p.effectsSequence.length) {
-      container.addDynamicProperty(p);
-    }
-    return p;
-  }
-
-  var ob = {
-    getProp: getProp,
-  };
-  return ob;
-}());
-
-/* global Matrix, degToRads, PropertyFactory, extendPrototype, DynamicPropertyContainer */
-/* exported TransformPropertyFactory */
-
-var TransformPropertyFactory = (function () {
-  var defaultVector = [0, 0];
-
-  function applyToMatrix(mat) {
-    var _mdf = this._mdf;
-    this.iterateDynamicProperties();
-    this._mdf = this._mdf || _mdf;
-    if (this.a) {
-      mat.translate(-this.a.v[0], -this.a.v[1], this.a.v[2]);
-    }
-    if (this.s) {
-      mat.scale(this.s.v[0], this.s.v[1], this.s.v[2]);
-    }
-    if (this.sk) {
-      mat.skewFromAxis(-this.sk.v, this.sa.v);
-    }
-    if (this.r) {
-      mat.rotate(-this.r.v);
-    } else {
-      mat.rotateZ(-this.rz.v).rotateY(this.ry.v).rotateX(this.rx.v).rotateZ(-this.or.v[2])
-        .rotateY(this.or.v[1])
-        .rotateX(this.or.v[0]);
-    }
-    if (this.data.p.s) {
-      if (this.data.p.z) {
-        mat.translate(this.px.v, this.py.v, -this.pz.v);
-      } else {
-        mat.translate(this.px.v, this.py.v, 0);
-      }
-    } else {
-      mat.translate(this.p.v[0], this.p.v[1], -this.p.v[2]);
-    }
-  }
-  function processKeys(forceRender) {
-    if (this.elem.globalData.frameId === this.frameId) {
-      return;
-    }
-    if (this._isDirty) {
-      this.precalculateMatrix();
-      this._isDirty = false;
-    }
-
-    this.iterateDynamicProperties();
-
-    if (this._mdf || forceRender) {
-      var frameRate;
-      this.v.cloneFromProps(this.pre.props);
-      if (this.appliedTransformations < 1) {
-        this.v.translate(-this.a.v[0], -this.a.v[1], this.a.v[2]);
-      }
-      if (this.appliedTransformations < 2) {
-        this.v.scale(this.s.v[0], this.s.v[1], this.s.v[2]);
-      }
-      if (this.sk && this.appliedTransformations < 3) {
-        this.v.skewFromAxis(-this.sk.v, this.sa.v);
-      }
-      if (this.r && this.appliedTransformations < 4) {
-        this.v.rotate(-this.r.v);
-      } else if (!this.r && this.appliedTransformations < 4) {
-        this.v.rotateZ(-this.rz.v).rotateY(this.ry.v).rotateX(this.rx.v).rotateZ(-this.or.v[2])
-          .rotateY(this.or.v[1])
-          .rotateX(this.or.v[0]);
-      }
-      if (this.autoOriented) {
-        var v1;
-        var v2;
-        frameRate = this.elem.globalData.frameRate;
-        if (this.p && this.p.keyframes && this.p.getValueAtTime) {
-          if (this.p._caching.lastFrame + this.p.offsetTime <= this.p.keyframes[0].t) {
-            v1 = this.p.getValueAtTime((this.p.keyframes[0].t + 0.01) / frameRate, 0);
-            v2 = this.p.getValueAtTime(this.p.keyframes[0].t / frameRate, 0);
-          } else if (this.p._caching.lastFrame + this.p.offsetTime >= this.p.keyframes[this.p.keyframes.length - 1].t) {
-            v1 = this.p.getValueAtTime((this.p.keyframes[this.p.keyframes.length - 1].t / frameRate), 0);
-            v2 = this.p.getValueAtTime((this.p.keyframes[this.p.keyframes.length - 1].t - 0.05) / frameRate, 0);
-          } else {
-            v1 = this.p.pv;
-            v2 = this.p.getValueAtTime((this.p._caching.lastFrame + this.p.offsetTime - 0.01) / frameRate, this.p.offsetTime);
-          }
-        } else if (this.px && this.px.keyframes && this.py.keyframes && this.px.getValueAtTime && this.py.getValueAtTime) {
-          v1 = [];
-          v2 = [];
-          var px = this.px;
-          var py = this.py;
-          if (px._caching.lastFrame + px.offsetTime <= px.keyframes[0].t) {
-            v1[0] = px.getValueAtTime((px.keyframes[0].t + 0.01) / frameRate, 0);
-            v1[1] = py.getValueAtTime((py.keyframes[0].t + 0.01) / frameRate, 0);
-            v2[0] = px.getValueAtTime((px.keyframes[0].t) / frameRate, 0);
-            v2[1] = py.getValueAtTime((py.keyframes[0].t) / frameRate, 0);
-          } else if (px._caching.lastFrame + px.offsetTime >= px.keyframes[px.keyframes.length - 1].t) {
-            v1[0] = px.getValueAtTime((px.keyframes[px.keyframes.length - 1].t / frameRate), 0);
-            v1[1] = py.getValueAtTime((py.keyframes[py.keyframes.length - 1].t / frameRate), 0);
-            v2[0] = px.getValueAtTime((px.keyframes[px.keyframes.length - 1].t - 0.01) / frameRate, 0);
-            v2[1] = py.getValueAtTime((py.keyframes[py.keyframes.length - 1].t - 0.01) / frameRate, 0);
-          } else {
-            v1 = [px.pv, py.pv];
-            v2[0] = px.getValueAtTime((px._caching.lastFrame + px.offsetTime - 0.01) / frameRate, px.offsetTime);
-            v2[1] = py.getValueAtTime((py._caching.lastFrame + py.offsetTime - 0.01) / frameRate, py.offsetTime);
-          }
-        } else {
-          v2 = defaultVector;
-          v1 = v2;
-        }
-        this.v.rotate(-Math.atan2(v1[1] - v2[1], v1[0] - v2[0]));
-      }
-      if (this.data.p && this.data.p.s) {
-        if (this.data.p.z) {
-          this.v.translate(this.px.v, this.py.v, -this.pz.v);
-        } else {
-          this.v.translate(this.px.v, this.py.v, 0);
-        }
-      } else {
-        this.v.translate(this.p.v[0], this.p.v[1], -this.p.v[2]);
-      }
-    }
-    this.frameId = this.elem.globalData.frameId;
-  }
-
-  function precalculateMatrix() {
-    if (!this.a.k) {
-      this.pre.translate(-this.a.v[0], -this.a.v[1], this.a.v[2]);
-      this.appliedTransformations = 1;
-    } else {
-      return;
-    }
-    if (!this.s.effectsSequence.length) {
-      this.pre.scale(this.s.v[0], this.s.v[1], this.s.v[2]);
-      this.appliedTransformations = 2;
-    } else {
-      return;
-    }
-    if (this.sk) {
-      if (!this.sk.effectsSequence.length && !this.sa.effectsSequence.length) {
-        this.pre.skewFromAxis(-this.sk.v, this.sa.v);
-        this.appliedTransformations = 3;
-      } else {
-        return;
-      }
-    }
-    if (this.r) {
-      if (!this.r.effectsSequence.length) {
-        this.pre.rotate(-this.r.v);
-        this.appliedTransformations = 4;
-      }
-    } else if (!this.rz.effectsSequence.length && !this.ry.effectsSequence.length && !this.rx.effectsSequence.length && !this.or.effectsSequence.length) {
-      this.pre.rotateZ(-this.rz.v).rotateY(this.ry.v).rotateX(this.rx.v).rotateZ(-this.or.v[2])
-        .rotateY(this.or.v[1])
-        .rotateX(this.or.v[0]);
-      this.appliedTransformations = 4;
-    }
-  }
-
-  function autoOrient() {
-    //
-    // var prevP = this.getValueAtTime();
-  }
-
-  function addDynamicProperty(prop) {
-    this._addDynamicProperty(prop);
-    this.elem.addDynamicProperty(prop);
-    this._isDirty = true;
-  }
-
-  function TransformProperty(elem, data, container) {
-    this.elem = elem;
-    this.frameId = -1;
-    this.propType = 'transform';
-    this.data = data;
-    this.v = new Matrix();
-    // Precalculated matrix with non animated properties
-    this.pre = new Matrix();
-    this.appliedTransformations = 0;
-    this.initDynamicPropertyContainer(container || elem);
-    if (data.p && data.p.s) {
-      this.px = PropertyFactory.getProp(elem, data.p.x, 0, 0, this);
-      this.py = PropertyFactory.getProp(elem, data.p.y, 0, 0, this);
-      if (data.p.z) {
-        this.pz = PropertyFactory.getProp(elem, data.p.z, 0, 0, this);
-      }
-    } else {
-      this.p = PropertyFactory.getProp(elem, data.p || { k: [0, 0, 0] }, 1, 0, this);
-    }
-    if (data.rx) {
-      this.rx = PropertyFactory.getProp(elem, data.rx, 0, degToRads, this);
-      this.ry = PropertyFactory.getProp(elem, data.ry, 0, degToRads, this);
-      this.rz = PropertyFactory.getProp(elem, data.rz, 0, degToRads, this);
-      if (data.or.k[0].ti) {
-        var i;
-        var len = data.or.k.length;
-        for (i = 0; i < len; i += 1) {
-          data.or.k[i].to = null;
-          data.or.k[i].ti = null;
-        }
-      }
-      this.or = PropertyFactory.getProp(elem, data.or, 1, degToRads, this);
-      // sh Indicates it needs to be capped between -180 and 180
-      this.or.sh = true;
-    } else {
-      this.r = PropertyFactory.getProp(elem, data.r || { k: 0 }, 0, degToRads, this);
-    }
-    if (data.sk) {
-      this.sk = PropertyFactory.getProp(elem, data.sk, 0, degToRads, this);
-      this.sa = PropertyFactory.getProp(elem, data.sa, 0, degToRads, this);
-    }
-    this.a = PropertyFactory.getProp(elem, data.a || { k: [0, 0, 0] }, 1, 0, this);
-    this.s = PropertyFactory.getProp(elem, data.s || { k: [100, 100, 100] }, 1, 0.01, this);
-    // Opacity is not part of the transform properties, that's why it won't use this.dynamicProperties. That way transforms won't get updated if opacity changes.
-    if (data.o) {
-      this.o = PropertyFactory.getProp(elem, data.o, 0, 0.01, elem);
-    } else {
-      this.o = { _mdf: false, v: 1 };
-    }
-    this._isDirty = true;
-    if (!this.dynamicProperties.length) {
-      this.getValue(true);
-    }
-  }
-
-  TransformProperty.prototype = {
-    applyToMatrix: applyToMatrix,
-    getValue: processKeys,
-    precalculateMatrix: precalculateMatrix,
-    autoOrient: autoOrient,
-  };
-
-  extendPrototype([DynamicPropertyContainer], TransformProperty);
-  TransformProperty.prototype.addDynamicProperty = addDynamicProperty;
-  TransformProperty.prototype._addDynamicProperty = DynamicPropertyContainer.prototype.addDynamicProperty;
-
-  function getTransformProperty(elem, data, container) {
-    return new TransformProperty(elem, data, container);
-  }
-
-  return {
-    getTransformProperty: getTransformProperty,
-  };
-}());
-
-/* global createSizedArray, createSizedArray, pointPool */
-
-function ShapePath() {
-  this.c = false;
-  this._length = 0;
-  this._maxLength = 8;
-  this.v = createSizedArray(this._maxLength);
-  this.o = createSizedArray(this._maxLength);
-  this.i = createSizedArray(this._maxLength);
-}
-
-ShapePath.prototype.setPathData = function (closed, len) {
-  this.c = closed;
-  this.setLength(len);
-  var i = 0;
-  while (i < len) {
-    this.v[i] = pointPool.newElement();
-    this.o[i] = pointPool.newElement();
-    this.i[i] = pointPool.newElement();
-    i += 1;
-  }
-};
-
-ShapePath.prototype.setLength = function (len) {
-  while (this._maxLength < len) {
-    this.doubleArrayLength();
-  }
-  this._length = len;
-};
-
-ShapePath.prototype.doubleArrayLength = function () {
-  this.v = this.v.concat(createSizedArray(this._maxLength));
-  this.i = this.i.concat(createSizedArray(this._maxLength));
-  this.o = this.o.concat(createSizedArray(this._maxLength));
-  this._maxLength *= 2;
-};
-
-ShapePath.prototype.setXYAt = function (x, y, type, pos, replace) {
-  var arr;
-  this._length = Math.max(this._length, pos + 1);
-  if (this._length >= this._maxLength) {
-    this.doubleArrayLength();
-  }
-  switch (type) {
-    case 'v':
-      arr = this.v;
-      break;
-    case 'i':
-      arr = this.i;
-      break;
-    case 'o':
-      arr = this.o;
-      break;
-    default:
-      arr = [];
-      break;
-  }
-  if (!arr[pos] || (arr[pos] && !replace)) {
-    arr[pos] = pointPool.newElement();
-  }
-  arr[pos][0] = x;
-  arr[pos][1] = y;
-};
-
-ShapePath.prototype.setTripleAt = function (vX, vY, oX, oY, iX, iY, pos, replace) {
-  this.setXYAt(vX, vY, 'v', pos, replace);
-  this.setXYAt(oX, oY, 'o', pos, replace);
-  this.setXYAt(iX, iY, 'i', pos, replace);
-};
-
-ShapePath.prototype.reverse = function () {
-  var newPath = new ShapePath();
-  newPath.setPathData(this.c, this._length);
-  var vertices = this.v;
-  var outPoints = this.o;
-  var inPoints = this.i;
-  var init = 0;
-  if (this.c) {
-    newPath.setTripleAt(vertices[0][0], vertices[0][1], inPoints[0][0], inPoints[0][1], outPoints[0][0], outPoints[0][1], 0, false);
-    init = 1;
-  }
-  var cnt = this._length - 1;
-  var len = this._length;
-
-  var i;
-  for (i = init; i < len; i += 1) {
-    newPath.setTripleAt(vertices[cnt][0], vertices[cnt][1], inPoints[cnt][0], inPoints[cnt][1], outPoints[cnt][0], outPoints[cnt][1], i, false);
-    cnt -= 1;
-  }
-  return newPath;
-};
-
-/* global extendPrototype, roundCorner, BezierFactory, shapePool, degToRads,
-  shapeCollectionPool, PropertyFactory, bmMin, DynamicPropertyContainer */
-/* exported ShapePropertyFactory */
-
-var ShapePropertyFactory = (function () {
-  var initFrame = -999999;
-
-  function interpolateShape(frameNum, previousValue, caching) {
-    var iterationIndex = caching.lastIndex;
-    var keyPropS;
-    var keyPropE;
-    var isHold;
-    var j;
-    var k;
-    var jLen;
-    var kLen;
-    var perc;
-    var vertexValue;
-    var kf = this.keyframes;
-    if (frameNum < kf[0].t - this.offsetTime) {
-      keyPropS = kf[0].s[0];
-      isHold = true;
-      iterationIndex = 0;
-    } else if (frameNum >= kf[kf.length - 1].t - this.offsetTime) {
-      keyPropS = kf[kf.length - 1].s ? kf[kf.length - 1].s[0] : kf[kf.length - 2].e[0];
-      /* if(kf[kf.length - 1].s){
-                keyPropS = kf[kf.length - 1].s[0];
-            }else{
-                keyPropS = kf[kf.length - 2].e[0];
-            } */
-      isHold = true;
-    } else {
-      var i = iterationIndex;
-      var len = kf.length - 1;
-      var flag = true;
-      var keyData;
-      var nextKeyData;
-      var keyframeMetadata;
-      while (flag) {
-        keyData = kf[i];
-        nextKeyData = kf[i + 1];
-        if ((nextKeyData.t - this.offsetTime) > frameNum) {
-          break;
-        }
-        if (i < len - 1) {
-          i += 1;
-        } else {
-          flag = false;
-        }
-      }
-      keyframeMetadata = this.keyframesMetadata[i] || {};
-      isHold = keyData.h === 1;
-      iterationIndex = i;
-      if (!isHold) {
-        if (frameNum >= nextKeyData.t - this.offsetTime) {
-          perc = 1;
-        } else if (frameNum < keyData.t - this.offsetTime) {
-          perc = 0;
-        } else {
-          var fnc;
-          if (keyframeMetadata.__fnct) {
-            fnc = keyframeMetadata.__fnct;
-          } else {
-            fnc = BezierFactory.getBezierEasing(keyData.o.x, keyData.o.y, keyData.i.x, keyData.i.y).get;
-            keyframeMetadata.__fnct = fnc;
-          }
-          perc = fnc((frameNum - (keyData.t - this.offsetTime)) / ((nextKeyData.t - this.offsetTime) - (keyData.t - this.offsetTime)));
-        }
-        keyPropE = nextKeyData.s ? nextKeyData.s[0] : keyData.e[0];
-      }
-      keyPropS = keyData.s[0];
-    }
-    jLen = previousValue._length;
-    kLen = keyPropS.i[0].length;
-    caching.lastIndex = iterationIndex;
-
-    for (j = 0; j < jLen; j += 1) {
-      for (k = 0; k < kLen; k += 1) {
-        vertexValue = isHold ? keyPropS.i[j][k] : keyPropS.i[j][k] + (keyPropE.i[j][k] - keyPropS.i[j][k]) * perc;
-        previousValue.i[j][k] = vertexValue;
-        vertexValue = isHold ? keyPropS.o[j][k] : keyPropS.o[j][k] + (keyPropE.o[j][k] - keyPropS.o[j][k]) * perc;
-        previousValue.o[j][k] = vertexValue;
-        vertexValue = isHold ? keyPropS.v[j][k] : keyPropS.v[j][k] + (keyPropE.v[j][k] - keyPropS.v[j][k]) * perc;
-        previousValue.v[j][k] = vertexValue;
-      }
-    }
-  }
-
-  function interpolateShapeCurrentTime() {
-    var frameNum = this.comp.renderedFrame - this.offsetTime;
-    var initTime = this.keyframes[0].t - this.offsetTime;
-    var endTime = this.keyframes[this.keyframes.length - 1].t - this.offsetTime;
-    var lastFrame = this._caching.lastFrame;
-    if (!(lastFrame !== initFrame && ((lastFrame < initTime && frameNum < initTime) || (lastFrame > endTime && frameNum > endTime)))) {
-      /// /
-      this._caching.lastIndex = lastFrame < frameNum ? this._caching.lastIndex : 0;
-      this.interpolateShape(frameNum, this.pv, this._caching);
-      /// /
-    }
-    this._caching.lastFrame = frameNum;
-    return this.pv;
-  }
-
-  function resetShape() {
-    this.paths = this.localShapeCollection;
-  }
-
-  function shapesEqual(shape1, shape2) {
-    if (shape1._length !== shape2._length || shape1.c !== shape2.c) {
-      return false;
-    }
-    var i;
-    var len = shape1._length;
-    for (i = 0; i < len; i += 1) {
-      if (shape1.v[i][0] !== shape2.v[i][0]
-            || shape1.v[i][1] !== shape2.v[i][1]
-            || shape1.o[i][0] !== shape2.o[i][0]
-            || shape1.o[i][1] !== shape2.o[i][1]
-            || shape1.i[i][0] !== shape2.i[i][0]
-            || shape1.i[i][1] !== shape2.i[i][1]) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  function setVValue(newPath) {
-    if (!shapesEqual(this.v, newPath)) {
-      this.v = shapePool.clone(newPath);
-      this.localShapeCollection.releaseShapes();
-      this.localShapeCollection.addShape(this.v);
-      this._mdf = true;
-      this.paths = this.localShapeCollection;
-    }
-  }
-
-  function processEffectsSequence() {
-    if (this.elem.globalData.frameId === this.frameId) {
-      return;
-    } if (!this.effectsSequence.length) {
-      this._mdf = false;
-      return;
-    }
-    if (this.lock) {
-      this.setVValue(this.pv);
-      return;
-    }
-    this.lock = true;
-    this._mdf = false;
-    var finalValue;
-    if (this.kf) {
-      finalValue = this.pv;
-    } else if (this.data.ks) {
-      finalValue = this.data.ks.k;
-    } else {
-      finalValue = this.data.pt.k;
-    }
-    var i;
-    var len = this.effectsSequence.length;
-    for (i = 0; i < len; i += 1) {
-      finalValue = this.effectsSequence[i](finalValue);
-    }
-    this.setVValue(finalValue);
-    this.lock = false;
-    this.frameId = this.elem.globalData.frameId;
-  }
-
-  function ShapeProperty(elem, data, type) {
-    this.propType = 'shape';
-    this.comp = elem.comp;
-    this.container = elem;
-    this.elem = elem;
-    this.data = data;
-    this.k = false;
-    this.kf = false;
-    this._mdf = false;
-    var pathData = type === 3 ? data.pt.k : data.ks.k;
-    this.v = shapePool.clone(pathData);
-    this.pv = shapePool.clone(this.v);
-    this.localShapeCollection = shapeCollectionPool.newShapeCollection();
-    this.paths = this.localShapeCollection;
-    this.paths.addShape(this.v);
-    this.reset = resetShape;
-    this.effectsSequence = [];
-  }
-
-  function addEffect(effectFunction) {
-    this.effectsSequence.push(effectFunction);
-    this.container.addDynamicProperty(this);
-  }
-
-  ShapeProperty.prototype.interpolateShape = interpolateShape;
-  ShapeProperty.prototype.getValue = processEffectsSequence;
-  ShapeProperty.prototype.setVValue = setVValue;
-  ShapeProperty.prototype.addEffect = addEffect;
-
-  function KeyframedShapeProperty(elem, data, type) {
-    this.propType = 'shape';
-    this.comp = elem.comp;
-    this.elem = elem;
-    this.container = elem;
-    this.offsetTime = elem.data.st;
-    this.keyframes = type === 3 ? data.pt.k : data.ks.k;
-    this.keyframesMetadata = [];
-    this.k = true;
-    this.kf = true;
-    var len = this.keyframes[0].s[0].i.length;
-    this.v = shapePool.newElement();
-    this.v.setPathData(this.keyframes[0].s[0].c, len);
-    this.pv = shapePool.clone(this.v);
-    this.localShapeCollection = shapeCollectionPool.newShapeCollection();
-    this.paths = this.localShapeCollection;
-    this.paths.addShape(this.v);
-    this.lastFrame = initFrame;
-    this.reset = resetShape;
-    this._caching = { lastFrame: initFrame, lastIndex: 0 };
-    this.effectsSequence = [interpolateShapeCurrentTime.bind(this)];
-  }
-  KeyframedShapeProperty.prototype.getValue = processEffectsSequence;
-  KeyframedShapeProperty.prototype.interpolateShape = interpolateShape;
-  KeyframedShapeProperty.prototype.setVValue = setVValue;
-  KeyframedShapeProperty.prototype.addEffect = addEffect;
-
-  var EllShapeProperty = (function () {
-    var cPoint = roundCorner;
-
-    function EllShapePropertyFactory(elem, data) {
-      /* this.v = {
-                v: createSizedArray(4),
-                i: createSizedArray(4),
-                o: createSizedArray(4),
-                c: true
-            }; */
-      this.v = shapePool.newElement();
-      this.v.setPathData(true, 4);
-      this.localShapeCollection = shapeCollectionPool.newShapeCollection();
-      this.paths = this.localShapeCollection;
-      this.localShapeCollection.addShape(this.v);
-      this.d = data.d;
-      this.elem = elem;
-      this.comp = elem.comp;
-      this.frameId = -1;
-      this.initDynamicPropertyContainer(elem);
-      this.p = PropertyFactory.getProp(elem, data.p, 1, 0, this);
-      this.s = PropertyFactory.getProp(elem, data.s, 1, 0, this);
-      if (this.dynamicProperties.length) {
-        this.k = true;
-      } else {
-        this.k = false;
-        this.convertEllToPath();
-      }
-    }
-
-    EllShapePropertyFactory.prototype = {
-      reset: resetShape,
-      getValue: function () {
-        if (this.elem.globalData.frameId === this.frameId) {
-          return;
-        }
-        this.frameId = this.elem.globalData.frameId;
-        this.iterateDynamicProperties();
-
-        if (this._mdf) {
-          this.convertEllToPath();
-        }
-      },
-      convertEllToPath: function () {
-        var p0 = this.p.v[0];
-        var p1 = this.p.v[1];
-        var s0 = this.s.v[0] / 2;
-        var s1 = this.s.v[1] / 2;
-        var _cw = this.d !== 3;
-        var _v = this.v;
-        _v.v[0][0] = p0;
-        _v.v[0][1] = p1 - s1;
-        _v.v[1][0] = _cw ? p0 + s0 : p0 - s0;
-        _v.v[1][1] = p1;
-        _v.v[2][0] = p0;
-        _v.v[2][1] = p1 + s1;
-        _v.v[3][0] = _cw ? p0 - s0 : p0 + s0;
-        _v.v[3][1] = p1;
-        _v.i[0][0] = _cw ? p0 - s0 * cPoint : p0 + s0 * cPoint;
-        _v.i[0][1] = p1 - s1;
-        _v.i[1][0] = _cw ? p0 + s0 : p0 - s0;
-        _v.i[1][1] = p1 - s1 * cPoint;
-        _v.i[2][0] = _cw ? p0 + s0 * cPoint : p0 - s0 * cPoint;
-        _v.i[2][1] = p1 + s1;
-        _v.i[3][0] = _cw ? p0 - s0 : p0 + s0;
-        _v.i[3][1] = p1 + s1 * cPoint;
-        _v.o[0][0] = _cw ? p0 + s0 * cPoint : p0 - s0 * cPoint;
-        _v.o[0][1] = p1 - s1;
-        _v.o[1][0] = _cw ? p0 + s0 : p0 - s0;
-        _v.o[1][1] = p1 + s1 * cPoint;
-        _v.o[2][0] = _cw ? p0 - s0 * cPoint : p0 + s0 * cPoint;
-        _v.o[2][1] = p1 + s1;
-        _v.o[3][0] = _cw ? p0 - s0 : p0 + s0;
-        _v.o[3][1] = p1 - s1 * cPoint;
-      },
-    };
-
-    extendPrototype([DynamicPropertyContainer], EllShapePropertyFactory);
-
-    return EllShapePropertyFactory;
-  }());
-
-  var StarShapeProperty = (function () {
-    function StarShapePropertyFactory(elem, data) {
-      this.v = shapePool.newElement();
-      this.v.setPathData(true, 0);
-      this.elem = elem;
-      this.comp = elem.comp;
-      this.data = data;
-      this.frameId = -1;
-      this.d = data.d;
-      this.initDynamicPropertyContainer(elem);
-      if (data.sy === 1) {
-        this.ir = PropertyFactory.getProp(elem, data.ir, 0, 0, this);
-        this.is = PropertyFactory.getProp(elem, data.is, 0, 0.01, this);
-        this.convertToPath = this.convertStarToPath;
-      } else {
-        this.convertToPath = this.convertPolygonToPath;
-      }
-      this.pt = PropertyFactory.getProp(elem, data.pt, 0, 0, this);
-      this.p = PropertyFactory.getProp(elem, data.p, 1, 0, this);
-      this.r = PropertyFactory.getProp(elem, data.r, 0, degToRads, this);
-      this.or = PropertyFactory.getProp(elem, data.or, 0, 0, this);
-      this.os = PropertyFactory.getProp(elem, data.os, 0, 0.01, this);
-      this.localShapeCollection = shapeCollectionPool.newShapeCollection();
-      this.localShapeCollection.addShape(this.v);
-      this.paths = this.localShapeCollection;
-      if (this.dynamicProperties.length) {
-        this.k = true;
-      } else {
-        this.k = false;
-        this.convertToPath();
-      }
-    }
-
-    StarShapePropertyFactory.prototype = {
-      reset: resetShape,
-      getValue: function () {
-        if (this.elem.globalData.frameId === this.frameId) {
-          return;
-        }
-        this.frameId = this.elem.globalData.frameId;
-        this.iterateDynamicProperties();
-        if (this._mdf) {
-          this.convertToPath();
-        }
-      },
-      convertStarToPath: function () {
-        var numPts = Math.floor(this.pt.v) * 2;
-        var angle = (Math.PI * 2) / numPts;
-        /* this.v.v.length = numPts;
-                this.v.i.length = numPts;
-                this.v.o.length = numPts; */
-        var longFlag = true;
-        var longRad = this.or.v;
-        var shortRad = this.ir.v;
-        var longRound = this.os.v;
-        var shortRound = this.is.v;
-        var longPerimSegment = (2 * Math.PI * longRad) / (numPts * 2);
-        var shortPerimSegment = (2 * Math.PI * shortRad) / (numPts * 2);
-        var i;
-        var rad;
-        var roundness;
-        var perimSegment;
-        var currentAng = -Math.PI / 2;
-        currentAng += this.r.v;
-        var dir = this.data.d === 3 ? -1 : 1;
-        this.v._length = 0;
-        for (i = 0; i < numPts; i += 1) {
-          rad = longFlag ? longRad : shortRad;
-          roundness = longFlag ? longRound : shortRound;
-          perimSegment = longFlag ? longPerimSegment : shortPerimSegment;
-          var x = rad * Math.cos(currentAng);
-          var y = rad * Math.sin(currentAng);
-          var ox = x === 0 && y === 0 ? 0 : y / Math.sqrt(x * x + y * y);
-          var oy = x === 0 && y === 0 ? 0 : -x / Math.sqrt(x * x + y * y);
-          x += +this.p.v[0];
-          y += +this.p.v[1];
-          this.v.setTripleAt(x, y, x - ox * perimSegment * roundness * dir, y - oy * perimSegment * roundness * dir, x + ox * perimSegment * roundness * dir, y + oy * perimSegment * roundness * dir, i, true);
-
-          /* this.v.v[i] = [x,y];
-                    this.v.i[i] = [x+ox*perimSegment*roundness*dir,y+oy*perimSegment*roundness*dir];
-                    this.v.o[i] = [x-ox*perimSegment*roundness*dir,y-oy*perimSegment*roundness*dir];
-                    this.v._length = numPts; */
-          longFlag = !longFlag;
-          currentAng += angle * dir;
-        }
-      },
-      convertPolygonToPath: function () {
-        var numPts = Math.floor(this.pt.v);
-        var angle = (Math.PI * 2) / numPts;
-        var rad = this.or.v;
-        var roundness = this.os.v;
-        var perimSegment = (2 * Math.PI * rad) / (numPts * 4);
-        var i;
-        var currentAng = -Math.PI * 0.5;
-        var dir = this.data.d === 3 ? -1 : 1;
-        currentAng += this.r.v;
-        this.v._length = 0;
-        for (i = 0; i < numPts; i += 1) {
-          var x = rad * Math.cos(currentAng);
-          var y = rad * Math.sin(currentAng);
-          var ox = x === 0 && y === 0 ? 0 : y / Math.sqrt(x * x + y * y);
-          var oy = x === 0 && y === 0 ? 0 : -x / Math.sqrt(x * x + y * y);
-          x += +this.p.v[0];
-          y += +this.p.v[1];
-          this.v.setTripleAt(x, y, x - ox * perimSegment * roundness * dir, y - oy * perimSegment * roundness * dir, x + ox * perimSegment * roundness * dir, y + oy * perimSegment * roundness * dir, i, true);
-          currentAng += angle * dir;
-        }
-        this.paths.length = 0;
-        this.paths[0] = this.v;
-      },
-
-    };
-    extendPrototype([DynamicPropertyContainer], StarShapePropertyFactory);
-
-    return StarShapePropertyFactory;
-  }());
-
-  var RectShapeProperty = (function () {
-    function RectShapePropertyFactory(elem, data) {
-      this.v = shapePool.newElement();
-      this.v.c = true;
-      this.localShapeCollection = shapeCollectionPool.newShapeCollection();
-      this.localShapeCollection.addShape(this.v);
-      this.paths = this.localShapeCollection;
-      this.elem = elem;
-      this.comp = elem.comp;
-      this.frameId = -1;
-      this.d = data.d;
-      this.initDynamicPropertyContainer(elem);
-      this.p = PropertyFactory.getProp(elem, data.p, 1, 0, this);
-      this.s = PropertyFactory.getProp(elem, data.s, 1, 0, this);
-      this.r = PropertyFactory.getProp(elem, data.r, 0, 0, this);
-      if (this.dynamicProperties.length) {
-        this.k = true;
-      } else {
-        this.k = false;
-        this.convertRectToPath();
-      }
-    }
-
-    RectShapePropertyFactory.prototype = {
-      convertRectToPath: function () {
-        var p0 = this.p.v[0];
-        var p1 = this.p.v[1];
-        var v0 = this.s.v[0] / 2;
-        var v1 = this.s.v[1] / 2;
-        var round = bmMin(v0, v1, this.r.v);
-        var cPoint = round * (1 - roundCorner);
-        this.v._length = 0;
-
-        if (this.d === 2 || this.d === 1) {
-          this.v.setTripleAt(p0 + v0, p1 - v1 + round, p0 + v0, p1 - v1 + round, p0 + v0, p1 - v1 + cPoint, 0, true);
-          this.v.setTripleAt(p0 + v0, p1 + v1 - round, p0 + v0, p1 + v1 - cPoint, p0 + v0, p1 + v1 - round, 1, true);
-          if (round !== 0) {
-            this.v.setTripleAt(p0 + v0 - round, p1 + v1, p0 + v0 - round, p1 + v1, p0 + v0 - cPoint, p1 + v1, 2, true);
-            this.v.setTripleAt(p0 - v0 + round, p1 + v1, p0 - v0 + cPoint, p1 + v1, p0 - v0 + round, p1 + v1, 3, true);
-            this.v.setTripleAt(p0 - v0, p1 + v1 - round, p0 - v0, p1 + v1 - round, p0 - v0, p1 + v1 - cPoint, 4, true);
-            this.v.setTripleAt(p0 - v0, p1 - v1 + round, p0 - v0, p1 - v1 + cPoint, p0 - v0, p1 - v1 + round, 5, true);
-            this.v.setTripleAt(p0 - v0 + round, p1 - v1, p0 - v0 + round, p1 - v1, p0 - v0 + cPoint, p1 - v1, 6, true);
-            this.v.setTripleAt(p0 + v0 - round, p1 - v1, p0 + v0 - cPoint, p1 - v1, p0 + v0 - round, p1 - v1, 7, true);
-          } else {
-            this.v.setTripleAt(p0 - v0, p1 + v1, p0 - v0 + cPoint, p1 + v1, p0 - v0, p1 + v1, 2);
-            this.v.setTripleAt(p0 - v0, p1 - v1, p0 - v0, p1 - v1 + cPoint, p0 - v0, p1 - v1, 3);
-          }
-        } else {
-          this.v.setTripleAt(p0 + v0, p1 - v1 + round, p0 + v0, p1 - v1 + cPoint, p0 + v0, p1 - v1 + round, 0, true);
-          if (round !== 0) {
-            this.v.setTripleAt(p0 + v0 - round, p1 - v1, p0 + v0 - round, p1 - v1, p0 + v0 - cPoint, p1 - v1, 1, true);
-            this.v.setTripleAt(p0 - v0 + round, p1 - v1, p0 - v0 + cPoint, p1 - v1, p0 - v0 + round, p1 - v1, 2, true);
-            this.v.setTripleAt(p0 - v0, p1 - v1 + round, p0 - v0, p1 - v1 + round, p0 - v0, p1 - v1 + cPoint, 3, true);
-            this.v.setTripleAt(p0 - v0, p1 + v1 - round, p0 - v0, p1 + v1 - cPoint, p0 - v0, p1 + v1 - round, 4, true);
-            this.v.setTripleAt(p0 - v0 + round, p1 + v1, p0 - v0 + round, p1 + v1, p0 - v0 + cPoint, p1 + v1, 5, true);
-            this.v.setTripleAt(p0 + v0 - round, p1 + v1, p0 + v0 - cPoint, p1 + v1, p0 + v0 - round, p1 + v1, 6, true);
-            this.v.setTripleAt(p0 + v0, p1 + v1 - round, p0 + v0, p1 + v1 - round, p0 + v0, p1 + v1 - cPoint, 7, true);
-          } else {
-            this.v.setTripleAt(p0 - v0, p1 - v1, p0 - v0 + cPoint, p1 - v1, p0 - v0, p1 - v1, 1, true);
-            this.v.setTripleAt(p0 - v0, p1 + v1, p0 - v0, p1 + v1 - cPoint, p0 - v0, p1 + v1, 2, true);
-            this.v.setTripleAt(p0 + v0, p1 + v1, p0 + v0 - cPoint, p1 + v1, p0 + v0, p1 + v1, 3, true);
-          }
-        }
-      },
-      getValue: function () {
-        if (this.elem.globalData.frameId === this.frameId) {
-          return;
-        }
-        this.frameId = this.elem.globalData.frameId;
-        this.iterateDynamicProperties();
-        if (this._mdf) {
-          this.convertRectToPath();
-        }
-      },
-      reset: resetShape,
-    };
-    extendPrototype([DynamicPropertyContainer], RectShapePropertyFactory);
-
-    return RectShapePropertyFactory;
-  }());
-
-  function getShapeProp(elem, data, type) {
-    var prop;
-    if (type === 3 || type === 4) {
-      var dataProp = type === 3 ? data.pt : data.ks;
-      var keys = dataProp.k;
-      if (keys.length) {
-        prop = new KeyframedShapeProperty(elem, data, type);
-      } else {
-        prop = new ShapeProperty(elem, data, type);
-      }
-    } else if (type === 5) {
-      prop = new RectShapeProperty(elem, data);
-    } else if (type === 6) {
-      prop = new EllShapeProperty(elem, data);
-    } else if (type === 7) {
-      prop = new StarShapeProperty(elem, data);
-    }
-    if (prop.k) {
-      elem.addDynamicProperty(prop);
-    }
-    return prop;
-  }
-
-  function getConstructorFunction() {
-    return ShapeProperty;
-  }
-
-  function getKeyframedConstructorFunction() {
-    return KeyframedShapeProperty;
-  }
-
-  var ob = {};
-  ob.getShapeProp = getShapeProp;
-  ob.getConstructorFunction = getConstructorFunction;
-  ob.getKeyframedConstructorFunction = getKeyframedConstructorFunction;
-  return ob;
-}());
-
-/* global shapeCollectionPool, initialDefaultFrame, extendPrototype, DynamicPropertyContainer */
-/* exported ShapeModifiers */
-
-var ShapeModifiers = (function () {
-  var ob = {};
-  var modifiers = {};
-  ob.registerModifier = registerModifier;
-  ob.getModifier = getModifier;
-
-  function registerModifier(nm, factory) {
-    if (!modifiers[nm]) {
-      modifiers[nm] = factory;
-    }
-  }
-
-  function getModifier(nm, elem, data) {
-    return new modifiers[nm](elem, data);
-  }
-
-  return ob;
-}());
-
-function ShapeModifier() {}
-ShapeModifier.prototype.initModifierProperties = function () {};
-ShapeModifier.prototype.addShapeToModifier = function () {};
-ShapeModifier.prototype.addShape = function (data) {
-  if (!this.closed) {
-    // Adding shape to dynamic properties. It covers the case where a shape has no effects applied, to reset it's _mdf state on every tick.
-    data.sh.container.addDynamicProperty(data.sh);
-    var shapeData = { shape: data.sh, data: data, localShapeCollection: shapeCollectionPool.newShapeCollection() };
-    this.shapes.push(shapeData);
-    this.addShapeToModifier(shapeData);
-    if (this._isAnimated) {
-      data.setAsAnimated();
-    }
-  }
-};
-ShapeModifier.prototype.init = function (elem, data) {
-  this.shapes = [];
-  this.elem = elem;
-  this.initDynamicPropertyContainer(elem);
-  this.initModifierProperties(elem, data);
-  this.frameId = initialDefaultFrame;
-  this.closed = false;
-  this.k = false;
-  if (this.dynamicProperties.length) {
-    this.k = true;
-  } else {
-    this.getValue(true);
-  }
-};
-ShapeModifier.prototype.processKeys = function () {
-  if (this.elem.globalData.frameId === this.frameId) {
-    return;
-  }
-  this.frameId = this.elem.globalData.frameId;
-  this.iterateDynamicProperties();
-};
-
-extendPrototype([DynamicPropertyContainer], ShapeModifier);
-
-/* global extendPrototype, ShapeModifier, PropertyFactory, segmentsLengthPool, bez, shapePool, ShapeModifiers */
-
-function TrimModifier() {
-}
-extendPrototype([ShapeModifier], TrimModifier);
-TrimModifier.prototype.initModifierProperties = function (elem, data) {
-  this.s = PropertyFactory.getProp(elem, data.s, 0, 0.01, this);
-  this.e = PropertyFactory.getProp(elem, data.e, 0, 0.01, this);
-  this.o = PropertyFactory.getProp(elem, data.o, 0, 0, this);
-  this.sValue = 0;
-  this.eValue = 0;
-  this.getValue = this.processKeys;
-  this.m = data.m;
-  this._isAnimated = !!this.s.effectsSequence.length || !!this.e.effectsSequence.length || !!this.o.effectsSequence.length;
-};
-
-TrimModifier.prototype.addShapeToModifier = function (shapeData) {
-  shapeData.pathsData = [];
-};
-
-TrimModifier.prototype.calculateShapeEdges = function (s, e, shapeLength, addedLength, totalModifierLength) {
-  var segments = [];
-  if (e <= 1) {
-    segments.push({
-      s: s,
-      e: e,
-    });
-  } else if (s >= 1) {
-    segments.push({
-      s: s - 1,
-      e: e - 1,
-    });
-  } else {
-    segments.push({
-      s: s,
-      e: 1,
-    });
-    segments.push({
-      s: 0,
-      e: e - 1,
-    });
-  }
-  var shapeSegments = [];
-  var i;
-  var len = segments.length;
-  var segmentOb;
-  for (i = 0; i < len; i += 1) {
-    segmentOb = segments[i];
-    if (!(segmentOb.e * totalModifierLength < addedLength || segmentOb.s * totalModifierLength > addedLength + shapeLength)) {
-      var shapeS;
-      var shapeE;
-      if (segmentOb.s * totalModifierLength <= addedLength) {
-        shapeS = 0;
-      } else {
-        shapeS = (segmentOb.s * totalModifierLength - addedLength) / shapeLength;
-      }
-      if (segmentOb.e * totalModifierLength >= addedLength + shapeLength) {
-        shapeE = 1;
-      } else {
-        shapeE = ((segmentOb.e * totalModifierLength - addedLength) / shapeLength);
-      }
-      shapeSegments.push([shapeS, shapeE]);
-    }
-  }
-  if (!shapeSegments.length) {
-    shapeSegments.push([0, 0]);
-  }
-  return shapeSegments;
-};
-
-TrimModifier.prototype.releasePathsData = function (pathsData) {
-  var i;
-  var len = pathsData.length;
-  for (i = 0; i < len; i += 1) {
-    segmentsLengthPool.release(pathsData[i]);
-  }
-  pathsData.length = 0;
-  return pathsData;
-};
-
-TrimModifier.prototype.processShapes = function (_isFirstFrame) {
-  var s;
-  var e;
-  if (this._mdf || _isFirstFrame) {
-    var o = (this.o.v % 360) / 360;
-    if (o < 0) {
-      o += 1;
-    }
-    if (this.s.v > 1) {
-      s = 1 + o;
-    } else if (this.s.v < 0) {
-      s = 0 + o;
-    } else {
-      s = this.s.v + o;
-    }
-    if (this.e.v > 1) {
-      e = 1 + o;
-    } else if (this.e.v < 0) {
-      e = 0 + o;
-    } else {
-      e = this.e.v + o;
-    }
-
-    if (s > e) {
-      var _s = s;
-      s = e;
-      e = _s;
-    }
-    s = Math.round(s * 10000) * 0.0001;
-    e = Math.round(e * 10000) * 0.0001;
-    this.sValue = s;
-    this.eValue = e;
-  } else {
-    s = this.sValue;
-    e = this.eValue;
-  }
-  var shapePaths;
-  var i;
-  var len = this.shapes.length;
-  var j;
-  var jLen;
-  var pathsData;
-  var pathData;
-  var totalShapeLength;
-  var totalModifierLength = 0;
-
-  if (e === s) {
-    for (i = 0; i < len; i += 1) {
-      this.shapes[i].localShapeCollection.releaseShapes();
-      this.shapes[i].shape._mdf = true;
-      this.shapes[i].shape.paths = this.shapes[i].localShapeCollection;
-      if (this._mdf) {
-        this.shapes[i].pathsData.length = 0;
-      }
-    }
-  } else if (!((e === 1 && s === 0) || (e === 0 && s === 1))) {
-    var segments = [];
-    var shapeData;
-    var localShapeCollection;
-    for (i = 0; i < len; i += 1) {
-      shapeData = this.shapes[i];
-      // if shape hasn't changed and trim properties haven't changed, cached previous path can be used
-      if (!shapeData.shape._mdf && !this._mdf && !_isFirstFrame && this.m !== 2) {
-        shapeData.shape.paths = shapeData.localShapeCollection;
-      } else {
-        shapePaths = shapeData.shape.paths;
-        jLen = shapePaths._length;
-        totalShapeLength = 0;
-        if (!shapeData.shape._mdf && shapeData.pathsData.length) {
-          totalShapeLength = shapeData.totalShapeLength;
-        } else {
-          pathsData = this.releasePathsData(shapeData.pathsData);
-          for (j = 0; j < jLen; j += 1) {
-            pathData = bez.getSegmentsLength(shapePaths.shapes[j]);
-            pathsData.push(pathData);
-            totalShapeLength += pathData.totalLength;
-          }
-          shapeData.totalShapeLength = totalShapeLength;
-          shapeData.pathsData = pathsData;
-        }
-
-        totalModifierLength += totalShapeLength;
-        shapeData.shape._mdf = true;
-      }
-    }
-    var shapeS = s;
-    var shapeE = e;
-    var addedLength = 0;
-    var edges;
-    for (i = len - 1; i >= 0; i -= 1) {
-      shapeData = this.shapes[i];
-      if (shapeData.shape._mdf) {
-        localShapeCollection = shapeData.localShapeCollection;
-        localShapeCollection.releaseShapes();
-        // if m === 2 means paths are trimmed individually so edges need to be found for this specific shape relative to whoel group
-        if (this.m === 2 && len > 1) {
-          edges = this.calculateShapeEdges(s, e, shapeData.totalShapeLength, addedLength, totalModifierLength);
-          addedLength += shapeData.totalShapeLength;
-        } else {
-          edges = [[shapeS, shapeE]];
-        }
-        jLen = edges.length;
-        for (j = 0; j < jLen; j += 1) {
-          shapeS = edges[j][0];
-          shapeE = edges[j][1];
-          segments.length = 0;
-          if (shapeE <= 1) {
-            segments.push({
-              s: shapeData.totalShapeLength * shapeS,
-              e: shapeData.totalShapeLength * shapeE,
-            });
-          } else if (shapeS >= 1) {
-            segments.push({
-              s: shapeData.totalShapeLength * (shapeS - 1),
-              e: shapeData.totalShapeLength * (shapeE - 1),
-            });
-          } else {
-            segments.push({
-              s: shapeData.totalShapeLength * shapeS,
-              e: shapeData.totalShapeLength,
-            });
-            segments.push({
-              s: 0,
-              e: shapeData.totalShapeLength * (shapeE - 1),
             });
           }
-          var newShapesData = this.addShapes(shapeData, segments[0]);
-          if (segments[0].s !== segments[0].e) {
-            if (segments.length > 1) {
-              var lastShapeInCollection = shapeData.shape.paths.shapes[shapeData.shape.paths._length - 1];
-              if (lastShapeInCollection.c) {
-                var lastShape = newShapesData.pop();
-                this.addPaths(newShapesData, localShapeCollection);
-                newShapesData = this.addShapes(shapeData, segments[1], lastShape);
-              } else {
-                this.addPaths(newShapesData, localShapeCollection);
-                newShapesData = this.addShapes(shapeData, segments[1]);
-              }
-            }
-            this.addPaths(newShapesData, localShapeCollection);
+        });
+
+        workerInstance.onmessage = function (event) {
+          var data = event.data;
+          var id = data.id;
+          var process = processes[id];
+          processes[id] = null;
+
+          if (data.status === 'success') {
+            process.onComplete(data.payload);
+          } else if (process.onError) {
+            process.onError();
           }
-        }
-        shapeData.shape.paths = localShapeCollection;
-      }
-    }
-  } else if (this._mdf) {
-    for (i = 0; i < len; i += 1) {
-      // Releasign Trim Cached paths data when no trim applied in case shapes are modified inbetween.
-      // Don't remove this even if it's losing cached info.
-      this.shapes[i].pathsData.length = 0;
-      this.shapes[i].shape._mdf = true;
-    }
-  }
-};
-
-TrimModifier.prototype.addPaths = function (newPaths, localShapeCollection) {
-  var i;
-  var len = newPaths.length;
-  for (i = 0; i < len; i += 1) {
-    localShapeCollection.addShape(newPaths[i]);
-  }
-};
-
-TrimModifier.prototype.addSegment = function (pt1, pt2, pt3, pt4, shapePath, pos, newShape) {
-  shapePath.setXYAt(pt2[0], pt2[1], 'o', pos);
-  shapePath.setXYAt(pt3[0], pt3[1], 'i', pos + 1);
-  if (newShape) {
-    shapePath.setXYAt(pt1[0], pt1[1], 'v', pos);
-  }
-  shapePath.setXYAt(pt4[0], pt4[1], 'v', pos + 1);
-};
-
-TrimModifier.prototype.addSegmentFromArray = function (points, shapePath, pos, newShape) {
-  shapePath.setXYAt(points[1], points[5], 'o', pos);
-  shapePath.setXYAt(points[2], points[6], 'i', pos + 1);
-  if (newShape) {
-    shapePath.setXYAt(points[0], points[4], 'v', pos);
-  }
-  shapePath.setXYAt(points[3], points[7], 'v', pos + 1);
-};
-
-TrimModifier.prototype.addShapes = function (shapeData, shapeSegment, shapePath) {
-  var pathsData = shapeData.pathsData;
-  var shapePaths = shapeData.shape.paths.shapes;
-  var i;
-  var len = shapeData.shape.paths._length;
-  var j;
-  var jLen;
-  var addedLength = 0;
-  var currentLengthData;
-  var segmentCount;
-  var lengths;
-  var segment;
-  var shapes = [];
-  var initPos;
-  var newShape = true;
-  if (!shapePath) {
-    shapePath = shapePool.newElement();
-    segmentCount = 0;
-    initPos = 0;
-  } else {
-    segmentCount = shapePath._length;
-    initPos = shapePath._length;
-  }
-  shapes.push(shapePath);
-  for (i = 0; i < len; i += 1) {
-    lengths = pathsData[i].lengths;
-    shapePath.c = shapePaths[i].c;
-    jLen = shapePaths[i].c ? lengths.length : lengths.length + 1;
-    for (j = 1; j < jLen; j += 1) {
-      currentLengthData = lengths[j - 1];
-      if (addedLength + currentLengthData.addedLength < shapeSegment.s) {
-        addedLength += currentLengthData.addedLength;
-        shapePath.c = false;
-      } else if (addedLength > shapeSegment.e) {
-        shapePath.c = false;
-        break;
-      } else {
-        if (shapeSegment.s <= addedLength && shapeSegment.e >= addedLength + currentLengthData.addedLength) {
-          this.addSegment(shapePaths[i].v[j - 1], shapePaths[i].o[j - 1], shapePaths[i].i[j], shapePaths[i].v[j], shapePath, segmentCount, newShape);
-          newShape = false;
-        } else {
-          segment = bez.getNewSegment(shapePaths[i].v[j - 1], shapePaths[i].v[j], shapePaths[i].o[j - 1], shapePaths[i].i[j], (shapeSegment.s - addedLength) / currentLengthData.addedLength, (shapeSegment.e - addedLength) / currentLengthData.addedLength, lengths[j - 1]);
-          this.addSegmentFromArray(segment, shapePath, segmentCount, newShape);
-          // this.addSegment(segment.pt1, segment.pt3, segment.pt4, segment.pt2, shapePath, segmentCount, newShape);
-          newShape = false;
-          shapePath.c = false;
-        }
-        addedLength += currentLengthData.addedLength;
-        segmentCount += 1;
-      }
-    }
-    if (shapePaths[i].c && lengths.length) {
-      currentLengthData = lengths[j - 1];
-      if (addedLength <= shapeSegment.e) {
-        var segmentLength = lengths[j - 1].addedLength;
-        if (shapeSegment.s <= addedLength && shapeSegment.e >= addedLength + segmentLength) {
-          this.addSegment(shapePaths[i].v[j - 1], shapePaths[i].o[j - 1], shapePaths[i].i[0], shapePaths[i].v[0], shapePath, segmentCount, newShape);
-          newShape = false;
-        } else {
-          segment = bez.getNewSegment(shapePaths[i].v[j - 1], shapePaths[i].v[0], shapePaths[i].o[j - 1], shapePaths[i].i[0], (shapeSegment.s - addedLength) / segmentLength, (shapeSegment.e - addedLength) / segmentLength, lengths[j - 1]);
-          this.addSegmentFromArray(segment, shapePath, segmentCount, newShape);
-          // this.addSegment(segment.pt1, segment.pt3, segment.pt4, segment.pt2, shapePath, segmentCount, newShape);
-          newShape = false;
-          shapePath.c = false;
-        }
-      } else {
-        shapePath.c = false;
-      }
-      addedLength += currentLengthData.addedLength;
-      segmentCount += 1;
-    }
-    if (shapePath._length) {
-      shapePath.setXYAt(shapePath.v[initPos][0], shapePath.v[initPos][1], 'i', initPos);
-      shapePath.setXYAt(shapePath.v[shapePath._length - 1][0], shapePath.v[shapePath._length - 1][1], 'o', shapePath._length - 1);
-    }
-    if (addedLength > shapeSegment.e) {
-      break;
-    }
-    if (i < len - 1) {
-      shapePath = shapePool.newElement();
-      newShape = true;
-      shapes.push(shapePath);
-      segmentCount = 0;
-    }
-  }
-  return shapes;
-};
-
-ShapeModifiers.registerModifier('tm', TrimModifier);
-
-/* global extendPrototype, ShapeModifier, PropertyFactory, shapePool, roundCorner, ShapeModifiers */
-
-function RoundCornersModifier() {}
-extendPrototype([ShapeModifier], RoundCornersModifier);
-RoundCornersModifier.prototype.initModifierProperties = function (elem, data) {
-  this.getValue = this.processKeys;
-  this.rd = PropertyFactory.getProp(elem, data.r, 0, null, this);
-  this._isAnimated = !!this.rd.effectsSequence.length;
-};
-
-RoundCornersModifier.prototype.processPath = function (path, round) {
-  var clonedPath = shapePool.newElement();
-  clonedPath.c = path.c;
-  var i;
-  var len = path._length;
-  var currentV;
-  var currentI;
-  var currentO;
-  var closerV;
-  var distance;
-  var newPosPerc;
-  var index = 0;
-  var vX;
-  var vY;
-  var oX;
-  var oY;
-  var iX;
-  var iY;
-  for (i = 0; i < len; i += 1) {
-    currentV = path.v[i];
-    currentO = path.o[i];
-    currentI = path.i[i];
-    if (currentV[0] === currentO[0] && currentV[1] === currentO[1] && currentV[0] === currentI[0] && currentV[1] === currentI[1]) {
-      if ((i === 0 || i === len - 1) && !path.c) {
-        clonedPath.setTripleAt(currentV[0], currentV[1], currentO[0], currentO[1], currentI[0], currentI[1], index);
-        /* clonedPath.v[index] = currentV;
-                clonedPath.o[index] = currentO;
-                clonedPath.i[index] = currentI; */
-        index += 1;
-      } else {
-        if (i === 0) {
-          closerV = path.v[len - 1];
-        } else {
-          closerV = path.v[i - 1];
-        }
-        distance = Math.sqrt(Math.pow(currentV[0] - closerV[0], 2) + Math.pow(currentV[1] - closerV[1], 2));
-        newPosPerc = distance ? Math.min(distance / 2, round) / distance : 0;
-        iX = currentV[0] + (closerV[0] - currentV[0]) * newPosPerc;
-        vX = iX;
-        iY = currentV[1] - (currentV[1] - closerV[1]) * newPosPerc;
-        vY = iY;
-        oX = vX - (vX - currentV[0]) * roundCorner;
-        oY = vY - (vY - currentV[1]) * roundCorner;
-        clonedPath.setTripleAt(vX, vY, oX, oY, iX, iY, index);
-        index += 1;
-
-        if (i === len - 1) {
-          closerV = path.v[0];
-        } else {
-          closerV = path.v[i + 1];
-        }
-        distance = Math.sqrt(Math.pow(currentV[0] - closerV[0], 2) + Math.pow(currentV[1] - closerV[1], 2));
-        newPosPerc = distance ? Math.min(distance / 2, round) / distance : 0;
-        oX = currentV[0] + (closerV[0] - currentV[0]) * newPosPerc;
-        vX = oX;
-        oY = currentV[1] + (closerV[1] - currentV[1]) * newPosPerc;
-        vY = oY;
-        iX = vX - (vX - currentV[0]) * roundCorner;
-        iY = vY - (vY - currentV[1]) * roundCorner;
-        clonedPath.setTripleAt(vX, vY, oX, oY, iX, iY, index);
-        index += 1;
-      }
-    } else {
-      clonedPath.setTripleAt(path.v[i][0], path.v[i][1], path.o[i][0], path.o[i][1], path.i[i][0], path.i[i][1], index);
-      index += 1;
-    }
-  }
-  return clonedPath;
-};
-
-RoundCornersModifier.prototype.processShapes = function (_isFirstFrame) {
-  var shapePaths;
-  var i;
-  var len = this.shapes.length;
-  var j;
-  var jLen;
-  var rd = this.rd.v;
-
-  if (rd !== 0) {
-    var shapeData;
-    var localShapeCollection;
-    for (i = 0; i < len; i += 1) {
-      shapeData = this.shapes[i];
-      localShapeCollection = shapeData.localShapeCollection;
-      if (!(!shapeData.shape._mdf && !this._mdf && !_isFirstFrame)) {
-        localShapeCollection.releaseShapes();
-        shapeData.shape._mdf = true;
-        shapePaths = shapeData.shape.paths.shapes;
-        jLen = shapeData.shape.paths._length;
-        for (j = 0; j < jLen; j += 1) {
-          localShapeCollection.addShape(this.processPath(shapePaths[j], rd));
-        }
-      }
-      shapeData.shape.paths = shapeData.localShapeCollection;
-    }
-  }
-  if (!this.dynamicProperties.length) {
-    this._mdf = false;
-  }
-};
-
-ShapeModifiers.registerModifier('rd', RoundCornersModifier);
-
-/* global extendPrototype, ShapeModifier, PropertyFactory, shapePool, ShapeModifiers */
-
-function PuckerAndBloatModifier() {}
-extendPrototype([ShapeModifier], PuckerAndBloatModifier);
-PuckerAndBloatModifier.prototype.initModifierProperties = function (elem, data) {
-  this.getValue = this.processKeys;
-  this.amount = PropertyFactory.getProp(elem, data.a, 0, null, this);
-  this._isAnimated = !!this.amount.effectsSequence.length;
-};
-
-PuckerAndBloatModifier.prototype.processPath = function (path, amount) {
-  var percent = amount / 100;
-  var centerPoint = [0, 0];
-  var pathLength = path._length;
-  var i = 0;
-  for (i = 0; i < pathLength; i += 1) {
-    centerPoint[0] += path.v[i][0];
-    centerPoint[1] += path.v[i][1];
-  }
-  centerPoint[0] /= pathLength;
-  centerPoint[1] /= pathLength;
-  var clonedPath = shapePool.newElement();
-  clonedPath.c = path.c;
-  var vX;
-  var vY;
-  var oX;
-  var oY;
-  var iX;
-  var iY;
-  for (i = 0; i < pathLength; i += 1) {
-    vX = path.v[i][0] + (centerPoint[0] - path.v[i][0]) * percent;
-    vY = path.v[i][1] + (centerPoint[1] - path.v[i][1]) * percent;
-    oX = path.o[i][0] + (centerPoint[0] - path.o[i][0]) * -percent;
-    oY = path.o[i][1] + (centerPoint[1] - path.o[i][1]) * -percent;
-    iX = path.i[i][0] + (centerPoint[0] - path.i[i][0]) * -percent;
-    iY = path.i[i][1] + (centerPoint[1] - path.i[i][1]) * -percent;
-    clonedPath.setTripleAt(vX, vY, oX, oY, iX, iY, i);
-  }
-  return clonedPath;
-};
-
-PuckerAndBloatModifier.prototype.processShapes = function (_isFirstFrame) {
-  var shapePaths;
-  var i;
-  var len = this.shapes.length;
-  var j;
-  var jLen;
-  var amount = this.amount.v;
-
-  if (amount !== 0) {
-    var shapeData;
-    var localShapeCollection;
-    for (i = 0; i < len; i += 1) {
-      shapeData = this.shapes[i];
-      localShapeCollection = shapeData.localShapeCollection;
-      if (!(!shapeData.shape._mdf && !this._mdf && !_isFirstFrame)) {
-        localShapeCollection.releaseShapes();
-        shapeData.shape._mdf = true;
-        shapePaths = shapeData.shape.paths.shapes;
-        jLen = shapeData.shape.paths._length;
-        for (j = 0; j < jLen; j += 1) {
-          localShapeCollection.addShape(this.processPath(shapePaths[j], amount));
-        }
-      }
-      shapeData.shape.paths = shapeData.localShapeCollection;
-    }
-  }
-  if (!this.dynamicProperties.length) {
-    this._mdf = false;
-  }
-};
-ShapeModifiers.registerModifier('pb', PuckerAndBloatModifier);
-
-/* global extendPrototype, ShapeModifier, TransformPropertyFactory, PropertyFactory, Matrix, ShapeModifiers */
-
-function RepeaterModifier() {}
-extendPrototype([ShapeModifier], RepeaterModifier);
-
-RepeaterModifier.prototype.initModifierProperties = function (elem, data) {
-  this.getValue = this.processKeys;
-  this.c = PropertyFactory.getProp(elem, data.c, 0, null, this);
-  this.o = PropertyFactory.getProp(elem, data.o, 0, null, this);
-  this.tr = TransformPropertyFactory.getTransformProperty(elem, data.tr, this);
-  this.so = PropertyFactory.getProp(elem, data.tr.so, 0, 0.01, this);
-  this.eo = PropertyFactory.getProp(elem, data.tr.eo, 0, 0.01, this);
-  this.data = data;
-  if (!this.dynamicProperties.length) {
-    this.getValue(true);
-  }
-  this._isAnimated = !!this.dynamicProperties.length;
-  this.pMatrix = new Matrix();
-  this.rMatrix = new Matrix();
-  this.sMatrix = new Matrix();
-  this.tMatrix = new Matrix();
-  this.matrix = new Matrix();
-};
-
-RepeaterModifier.prototype.applyTransforms = function (pMatrix, rMatrix, sMatrix, transform, perc, inv) {
-  var dir = inv ? -1 : 1;
-  var scaleX = transform.s.v[0] + (1 - transform.s.v[0]) * (1 - perc);
-  var scaleY = transform.s.v[1] + (1 - transform.s.v[1]) * (1 - perc);
-  pMatrix.translate(transform.p.v[0] * dir * perc, transform.p.v[1] * dir * perc, transform.p.v[2]);
-  rMatrix.translate(-transform.a.v[0], -transform.a.v[1], transform.a.v[2]);
-  rMatrix.rotate(-transform.r.v * dir * perc);
-  rMatrix.translate(transform.a.v[0], transform.a.v[1], transform.a.v[2]);
-  sMatrix.translate(-transform.a.v[0], -transform.a.v[1], transform.a.v[2]);
-  sMatrix.scale(inv ? 1 / scaleX : scaleX, inv ? 1 / scaleY : scaleY);
-  sMatrix.translate(transform.a.v[0], transform.a.v[1], transform.a.v[2]);
-};
-
-RepeaterModifier.prototype.init = function (elem, arr, pos, elemsData) {
-  this.elem = elem;
-  this.arr = arr;
-  this.pos = pos;
-  this.elemsData = elemsData;
-  this._currentCopies = 0;
-  this._elements = [];
-  this._groups = [];
-  this.frameId = -1;
-  this.initDynamicPropertyContainer(elem);
-  this.initModifierProperties(elem, arr[pos]);
-  while (pos > 0) {
-    pos -= 1;
-    // this._elements.unshift(arr.splice(pos,1)[0]);
-    this._elements.unshift(arr[pos]);
-  }
-  if (this.dynamicProperties.length) {
-    this.k = true;
-  } else {
-    this.getValue(true);
-  }
-};
-
-RepeaterModifier.prototype.resetElements = function (elements) {
-  var i;
-  var len = elements.length;
-  for (i = 0; i < len; i += 1) {
-    elements[i]._processed = false;
-    if (elements[i].ty === 'gr') {
-      this.resetElements(elements[i].it);
-    }
-  }
-};
-
-RepeaterModifier.prototype.cloneElements = function (elements) {
-  var newElements = JSON.parse(JSON.stringify(elements));
-  this.resetElements(newElements);
-  return newElements;
-};
-
-RepeaterModifier.prototype.changeGroupRender = function (elements, renderFlag) {
-  var i;
-  var len = elements.length;
-  for (i = 0; i < len; i += 1) {
-    elements[i]._render = renderFlag;
-    if (elements[i].ty === 'gr') {
-      this.changeGroupRender(elements[i].it, renderFlag);
-    }
-  }
-};
-
-RepeaterModifier.prototype.processShapes = function (_isFirstFrame) {
-  var items;
-  var itemsTransform;
-  var i;
-  var dir;
-  var cont;
-  var hasReloaded = false;
-  if (this._mdf || _isFirstFrame) {
-    var copies = Math.ceil(this.c.v);
-    if (this._groups.length < copies) {
-      while (this._groups.length < copies) {
-        var group = {
-          it: this.cloneElements(this._elements),
-          ty: 'gr',
         };
-        group.it.push({
-          a: { a: 0, ix: 1, k: [0, 0] }, nm: 'Transform', o: { a: 0, ix: 7, k: 100 }, p: { a: 0, ix: 2, k: [0, 0] }, r: { a: 1, ix: 6, k: [{ s: 0, e: 0, t: 0 }, { s: 0, e: 0, t: 1 }] }, s: { a: 0, ix: 3, k: [100, 100] }, sa: { a: 0, ix: 5, k: 0 }, sk: { a: 0, ix: 4, k: 0 }, ty: 'tr',
-        });
-
-        this.arr.splice(0, 0, group);
-        this._groups.splice(0, 0, group);
-        this._currentCopies += 1;
-      }
-      this.elem.reloadShapes();
-      hasReloaded = true;
-    }
-    cont = 0;
-    var renderFlag;
-    for (i = 0; i <= this._groups.length - 1; i += 1) {
-      renderFlag = cont < copies;
-      this._groups[i]._render = renderFlag;
-      this.changeGroupRender(this._groups[i].it, renderFlag);
-      if (!renderFlag) {
-        var elems = this.elemsData[i].it;
-        var transformData = elems[elems.length - 1];
-        if (transformData.transform.op.v !== 0) {
-          transformData.transform.op._mdf = true;
-          transformData.transform.op.v = 0;
-        } else {
-          transformData.transform.op._mdf = false;
-        }
-      }
-      cont += 1;
-    }
-
-    this._currentCopies = copies;
-    /// /
-
-    var offset = this.o.v;
-    var offsetModulo = offset % 1;
-    var roundOffset = offset > 0 ? Math.floor(offset) : Math.ceil(offset);
-    var pProps = this.pMatrix.props;
-    var rProps = this.rMatrix.props;
-    var sProps = this.sMatrix.props;
-    this.pMatrix.reset();
-    this.rMatrix.reset();
-    this.sMatrix.reset();
-    this.tMatrix.reset();
-    this.matrix.reset();
-    var iteration = 0;
-
-    if (offset > 0) {
-      while (iteration < roundOffset) {
-        this.applyTransforms(this.pMatrix, this.rMatrix, this.sMatrix, this.tr, 1, false);
-        iteration += 1;
-      }
-      if (offsetModulo) {
-        this.applyTransforms(this.pMatrix, this.rMatrix, this.sMatrix, this.tr, offsetModulo, false);
-        iteration += offsetModulo;
-      }
-    } else if (offset < 0) {
-      while (iteration > roundOffset) {
-        this.applyTransforms(this.pMatrix, this.rMatrix, this.sMatrix, this.tr, 1, true);
-        iteration -= 1;
-      }
-      if (offsetModulo) {
-        this.applyTransforms(this.pMatrix, this.rMatrix, this.sMatrix, this.tr, -offsetModulo, true);
-        iteration -= offsetModulo;
       }
     }
-    i = this.data.m === 1 ? 0 : this._currentCopies - 1;
-    dir = this.data.m === 1 ? 1 : -1;
-    cont = this._currentCopies;
-    var j;
-    var jLen;
-    while (cont) {
-      items = this.elemsData[i].it;
-      itemsTransform = items[items.length - 1].transform.mProps.v.props;
-      jLen = itemsTransform.length;
-      items[items.length - 1].transform.mProps._mdf = true;
-      items[items.length - 1].transform.op._mdf = true;
-      items[items.length - 1].transform.op.v = this._currentCopies === 1
-        ? this.so.v
-        : this.so.v + (this.eo.v - this.so.v) * (i / (this._currentCopies - 1));
 
-      if (iteration !== 0) {
-        if ((i !== 0 && dir === 1) || (i !== this._currentCopies - 1 && dir === -1)) {
-          this.applyTransforms(this.pMatrix, this.rMatrix, this.sMatrix, this.tr, 1, false);
-        }
-        this.matrix.transform(rProps[0], rProps[1], rProps[2], rProps[3], rProps[4], rProps[5], rProps[6], rProps[7], rProps[8], rProps[9], rProps[10], rProps[11], rProps[12], rProps[13], rProps[14], rProps[15]);
-        this.matrix.transform(sProps[0], sProps[1], sProps[2], sProps[3], sProps[4], sProps[5], sProps[6], sProps[7], sProps[8], sProps[9], sProps[10], sProps[11], sProps[12], sProps[13], sProps[14], sProps[15]);
-        this.matrix.transform(pProps[0], pProps[1], pProps[2], pProps[3], pProps[4], pProps[5], pProps[6], pProps[7], pProps[8], pProps[9], pProps[10], pProps[11], pProps[12], pProps[13], pProps[14], pProps[15]);
-
-        for (j = 0; j < jLen; j += 1) {
-          itemsTransform[j] = this.matrix.props[j];
-        }
-        this.matrix.reset();
-      } else {
-        this.matrix.reset();
-        for (j = 0; j < jLen; j += 1) {
-          itemsTransform[j] = this.matrix.props[j];
-        }
-      }
-      iteration += 1;
-      cont -= 1;
-      i += dir;
-    }
-  } else {
-    cont = this._currentCopies;
-    i = 0;
-    dir = 1;
-    while (cont) {
-      items = this.elemsData[i].it;
-      itemsTransform = items[items.length - 1].transform.mProps.v.props;
-      items[items.length - 1].transform.mProps._mdf = false;
-      items[items.length - 1].transform.op._mdf = false;
-      cont -= 1;
-      i += dir;
-    }
-  }
-  return hasReloaded;
-};
-
-RepeaterModifier.prototype.addShape = function () {};
-
-ShapeModifiers.registerModifier('rp', RepeaterModifier);
-
-/* global createSizedArray, shapePool */
-
-function ShapeCollection() {
-  this._length = 0;
-  this._maxLength = 4;
-  this.shapes = createSizedArray(this._maxLength);
-}
-
-ShapeCollection.prototype.addShape = function (shapeData) {
-  if (this._length === this._maxLength) {
-    this.shapes = this.shapes.concat(createSizedArray(this._maxLength));
-    this._maxLength *= 2;
-  }
-  this.shapes[this._length] = shapeData;
-  this._length += 1;
-};
-
-ShapeCollection.prototype.releaseShapes = function () {
-  var i;
-  for (i = 0; i < this._length; i += 1) {
-    shapePool.release(this.shapes[i]);
-  }
-  this._length = 0;
-};
-
-/* global createSizedArray, createTypedArray, PropertyFactory, extendPrototype, DynamicPropertyContainer */
-
-function DashProperty(elem, data, renderer, container) {
-  this.elem = elem;
-  this.frameId = -1;
-  this.dataProps = createSizedArray(data.length);
-  this.renderer = renderer;
-  this.k = false;
-  this.dashStr = '';
-  this.dashArray = createTypedArray('float32', data.length ? data.length - 1 : 0);
-  this.dashoffset = createTypedArray('float32', 1);
-  this.initDynamicPropertyContainer(container);
-  var i;
-  var len = data.length || 0;
-  var prop;
-  for (i = 0; i < len; i += 1) {
-    prop = PropertyFactory.getProp(elem, data[i].v, 0, 0, this);
-    this.k = prop.k || this.k;
-    this.dataProps[i] = { n: data[i].n, p: prop };
-  }
-  if (!this.k) {
-    this.getValue(true);
-  }
-  this._isAnimated = this.k;
-}
-
-DashProperty.prototype.getValue = function (forceRender) {
-  if (this.elem.globalData.frameId === this.frameId && !forceRender) {
-    return;
-  }
-  this.frameId = this.elem.globalData.frameId;
-  this.iterateDynamicProperties();
-  this._mdf = this._mdf || forceRender;
-  if (this._mdf) {
-    var i = 0;
-    var len = this.dataProps.length;
-    if (this.renderer === 'svg') {
-      this.dashStr = '';
-    }
-    for (i = 0; i < len; i += 1) {
-      if (this.dataProps[i].n !== 'o') {
-        if (this.renderer === 'svg') {
-          this.dashStr += ' ' + this.dataProps[i].p.v;
-        } else {
-          this.dashArray[i] = this.dataProps[i].p.v;
-        }
-      } else {
-        this.dashoffset[0] = this.dataProps[i].p.v;
-      }
-    }
-  }
-};
-extendPrototype([DynamicPropertyContainer], DashProperty);
-
-/* global createTypedArray, PropertyFactory, extendPrototype, DynamicPropertyContainer */
-function GradientProperty(elem, data, container) {
-  this.data = data;
-  this.c = createTypedArray('uint8c', data.p * 4);
-  var cLength = data.k.k[0].s ? (data.k.k[0].s.length - data.p * 4) : data.k.k.length - data.p * 4;
-  this.o = createTypedArray('float32', cLength);
-  this._cmdf = false;
-  this._omdf = false;
-  this._collapsable = this.checkCollapsable();
-  this._hasOpacity = cLength;
-  this.initDynamicPropertyContainer(container);
-  this.prop = PropertyFactory.getProp(elem, data.k, 1, null, this);
-  this.k = this.prop.k;
-  this.getValue(true);
-}
-
-GradientProperty.prototype.comparePoints = function (values, points) {
-  var i = 0;
-  var len = this.o.length / 2;
-  var diff;
-  while (i < len) {
-    diff = Math.abs(values[i * 4] - values[points * 4 + i * 2]);
-    if (diff > 0.01) {
-      return false;
-    }
-    i += 1;
-  }
-  return true;
-};
-
-GradientProperty.prototype.checkCollapsable = function () {
-  if (this.o.length / 2 !== this.c.length / 4) {
-    return false;
-  }
-  if (this.data.k.k[0].s) {
-    var i = 0;
-    var len = this.data.k.k.length;
-    while (i < len) {
-      if (!this.comparePoints(this.data.k.k[i].s, this.data.p)) {
-        return false;
-      }
-      i += 1;
-    }
-  } else if (!this.comparePoints(this.data.k.k, this.data.p)) {
-    return false;
-  }
-  return true;
-};
-
-GradientProperty.prototype.getValue = function (forceRender) {
-  this.prop.getValue();
-  this._mdf = false;
-  this._cmdf = false;
-  this._omdf = false;
-  if (this.prop._mdf || forceRender) {
-    var i;
-    var len = this.data.p * 4;
-    var mult;
-    var val;
-    for (i = 0; i < len; i += 1) {
-      mult = i % 4 === 0 ? 100 : 255;
-      val = Math.round(this.prop.v[i] * mult);
-      if (this.c[i] !== val) {
-        this.c[i] = val;
-        this._cmdf = !forceRender;
-      }
-    }
-    if (this.o.length) {
-      len = this.prop.v.length;
-      for (i = this.data.p * 4; i < len; i += 1) {
-        mult = i % 2 === 0 ? 100 : 1;
-        val = i % 2 === 0 ? Math.round(this.prop.v[i] * 100) : this.prop.v[i];
-        if (this.o[i - this.data.p * 4] !== val) {
-          this.o[i - this.data.p * 4] = val;
-          this._omdf = !forceRender;
-        }
-      }
-    }
-    this._mdf = !forceRender;
-  }
-};
-
-extendPrototype([DynamicPropertyContainer], GradientProperty);
-
-/* exported buildShapeString */
-
-var buildShapeString = function (pathNodes, length, closed, mat) {
-  if (length === 0) {
-    return '';
-  }
-  var _o = pathNodes.o;
-  var _i = pathNodes.i;
-  var _v = pathNodes.v;
-  var i;
-  var shapeString = ' M' + mat.applyToPointStringified(_v[0][0], _v[0][1]);
-  for (i = 1; i < length; i += 1) {
-    shapeString += ' C' + mat.applyToPointStringified(_o[i - 1][0], _o[i - 1][1]) + ' ' + mat.applyToPointStringified(_i[i][0], _i[i][1]) + ' ' + mat.applyToPointStringified(_v[i][0], _v[i][1]);
-  }
-  if (closed && length) {
-    shapeString += ' C' + mat.applyToPointStringified(_o[i - 1][0], _o[i - 1][1]) + ' ' + mat.applyToPointStringified(_i[0][0], _i[0][1]) + ' ' + mat.applyToPointStringified(_v[0][0], _v[0][1]);
-    shapeString += 'z';
-  }
-  return shapeString;
-};
-
-/* global Howl */
-/* exported audioControllerFactory */
-
-var audioControllerFactory = (function () {
-  function AudioController(audioFactory) {
-    this.audios = [];
-    this.audioFactory = audioFactory;
-    this._volume = 1;
-    this._isMuted = false;
-  }
-
-  AudioController.prototype = {
-    addAudio: function (audio) {
-      this.audios.push(audio);
-    },
-    pause: function () {
-      var i;
-      var len = this.audios.length;
-      for (i = 0; i < len; i += 1) {
-        this.audios[i].pause();
-      }
-    },
-    resume: function () {
-      var i;
-      var len = this.audios.length;
-      for (i = 0; i < len; i += 1) {
-        this.audios[i].resume();
-      }
-    },
-    setRate: function (rateValue) {
-      var i;
-      var len = this.audios.length;
-      for (i = 0; i < len; i += 1) {
-        this.audios[i].setRate(rateValue);
-      }
-    },
-    createAudio: function (assetPath) {
-      if (this.audioFactory) {
-        return this.audioFactory(assetPath);
-      } if (Howl) {
-        return new Howl({
-          src: [assetPath],
-        });
-      }
-      return {
-        isPlaying: false,
-        play: function () { this.isPlaying = true; },
-        seek: function () { this.isPlaying = false; },
-        playing: function () {},
-        rate: function () {},
-        setVolume: function () {},
+    function createProcess(onComplete, onError) {
+      _counterId += 1;
+      var id = 'processId_' + _counterId;
+      processes[id] = {
+        onComplete: onComplete,
+        onError: onError
       };
-    },
-    setAudioFactory: function (audioFactory) {
-      this.audioFactory = audioFactory;
-    },
-    setVolume: function (value) {
-      this._volume = value;
-      this._updateVolume();
-    },
-    mute: function () {
-      this._isMuted = true;
-      this._updateVolume();
-    },
-    unmute: function () {
-      this._isMuted = false;
-      this._updateVolume();
-    },
-    getVolume: function () {
-      return this._volume;
-    },
-    _updateVolume: function () {
-      var i;
-      var len = this.audios.length;
-      for (i = 0; i < len; i += 1) {
-        this.audios[i].volume(this._volume * (this._isMuted ? 0 : 1));
-      }
-    },
-  };
+      return id;
+    }
 
-  return function () {
-    return new AudioController();
-  };
-}());
+    function loadAnimation(path, onComplete, onError) {
+      setupWorker();
+      var processId = createProcess(onComplete, onError);
+      workerInstance.postMessage({
+        type: 'loadAnimation',
+        path: path,
+        fullPath: window.location.origin + window.location.pathname,
+        id: processId
+      });
+    }
 
-/* global createTag, createNS, isSafari, dataManager */
-/* exported ImagePreloader */
+    function loadData(path, onComplete, onError) {
+      setupWorker();
+      var processId = createProcess(onComplete, onError);
+      workerInstance.postMessage({
+        type: 'loadData',
+        path: path,
+        fullPath: window.location.origin + window.location.pathname,
+        id: processId
+      });
+    }
 
-var ImagePreloader = (function () {
-  var proxyImage = (function () {
-    var canvas = createTag('canvas');
-    canvas.width = 1;
-    canvas.height = 1;
-    var ctx = canvas.getContext('2d');
-    ctx.fillStyle = 'rgba(0,0,0,0)';
-    ctx.fillRect(0, 0, 1, 1);
-    return canvas;
-  }());
+    function completeAnimation(anim, onComplete, onError) {
+      setupWorker();
+      var processId = createProcess(onComplete, onError);
+      workerInstance.postMessage({
+        type: 'complete',
+        animation: anim,
+        id: processId
+      });
+    }
 
-  function imageLoaded() {
-    this.loadedAssets += 1;
-    if (this.loadedAssets === this.totalImages && this.loadedFootagesCount === this.totalFootages) {
-      if (this.imagesLoadedCb) {
-        this.imagesLoadedCb(null);
+    return {
+      loadAnimation: loadAnimation,
+      loadData: loadData,
+      completeAnimation: completeAnimation
+    };
+  }();
+
+  var ImagePreloader = function () {
+    var proxyImage = function () {
+      var canvas = createTag('canvas');
+      canvas.width = 1;
+      canvas.height = 1;
+      var ctx = canvas.getContext('2d');
+      ctx.fillStyle = 'rgba(0,0,0,0)';
+      ctx.fillRect(0, 0, 1, 1);
+      return canvas;
+    }();
+
+    function imageLoaded() {
+      this.loadedAssets += 1;
+
+      if (this.loadedAssets === this.totalImages && this.loadedFootagesCount === this.totalFootages) {
+        if (this.imagesLoadedCb) {
+          this.imagesLoadedCb(null);
+        }
       }
     }
-  }
-  function footageLoaded() {
-    this.loadedFootagesCount += 1;
-    if (this.loadedAssets === this.totalImages && this.loadedFootagesCount === this.totalFootages) {
-      if (this.imagesLoadedCb) {
-        this.imagesLoadedCb(null);
+
+    function footageLoaded() {
+      this.loadedFootagesCount += 1;
+
+      if (this.loadedAssets === this.totalImages && this.loadedFootagesCount === this.totalFootages) {
+        if (this.imagesLoadedCb) {
+          this.imagesLoadedCb(null);
+        }
       }
     }
-  }
 
-  function getAssetsPath(assetData, assetsPath, originalPath) {
-    var path = '';
-    if (assetData.e) {
-      path = assetData.p;
-    } else if (assetsPath) {
-      var imagePath = assetData.p;
-      if (imagePath.indexOf('images/') !== -1) {
-        imagePath = imagePath.split('/')[1];
+    function getAssetsPath(assetData, assetsPath, originalPath) {
+      var path = '';
+
+      if (assetData.e) {
+        path = assetData.p;
+      } else if (assetsPath) {
+        var imagePath = assetData.p;
+
+        if (imagePath.indexOf('images/') !== -1) {
+          imagePath = imagePath.split('/')[1];
+        }
+
+        path = assetsPath + imagePath;
+      } else {
+        path = originalPath;
+        path += assetData.u ? assetData.u : '';
+        path += assetData.p;
       }
-      path = assetsPath + imagePath;
-    } else {
-      path = originalPath;
-      path += assetData.u ? assetData.u : '';
-      path += assetData.p;
-    }
-    return path;
-  }
 
-  function testImageLoaded(img) {
-    var _count = 0;
-    var intervalId = setInterval(function () {
-      var box = img.getBBox();
-      if (box.width || _count > 500) {
+      return path;
+    }
+
+    function testImageLoaded(img) {
+      var _count = 0;
+      var intervalId = setInterval(function () {
+        var box = img.getBBox();
+
+        if (box.width || _count > 500) {
+          this._imageLoaded();
+
+          clearInterval(intervalId);
+        }
+
+        _count += 1;
+      }.bind(this), 50);
+    }
+
+    function createImageData(assetData) {
+      var path = getAssetsPath(assetData, this.assetsPath, this.path);
+      var img = createNS('image');
+
+      if (isSafari) {
+        this.testImageLoaded(img);
+      } else {
+        img.addEventListener('load', this._imageLoaded, false);
+      }
+
+      img.addEventListener('error', function () {
+        ob.img = proxyImage;
+
         this._imageLoaded();
-        clearInterval(intervalId);
+      }.bind(this), false);
+      img.setAttributeNS('http://www.w3.org/1999/xlink', 'href', path);
+
+      if (this._elementHelper.append) {
+        this._elementHelper.append(img);
+      } else {
+        this._elementHelper.appendChild(img);
       }
-      _count += 1;
-    }.bind(this), 50);
-  }
 
-  function createImageData(assetData) {
-    var path = getAssetsPath(assetData, this.assetsPath, this.path);
-    var img = createNS('image');
-    if (isSafari) {
-      this.testImageLoaded(img);
-    } else {
-      img.addEventListener('load', this._imageLoaded, false);
-    }
-    img.addEventListener('error', function () {
-      ob.img = proxyImage;
-      this._imageLoaded();
-    }.bind(this), false);
-    img.setAttributeNS('http://www.w3.org/1999/xlink', 'href', path);
-    if (this._elementHelper.append) {
-      this._elementHelper.append(img);
-    } else {
-      this._elementHelper.appendChild(img);
-    }
-    var ob = {
-      img: img,
-      assetData: assetData,
-    };
-    return ob;
-  }
-
-  function createImgData(assetData) {
-    var path = getAssetsPath(assetData, this.assetsPath, this.path);
-    var img = createTag('img');
-    img.crossOrigin = 'anonymous';
-    img.addEventListener('load', this._imageLoaded, false);
-    img.addEventListener('error', function () {
-      ob.img = proxyImage;
-      this._imageLoaded();
-    }.bind(this), false);
-    img.src = path;
-    var ob = {
-      img: img,
-      assetData: assetData,
-    };
-    return ob;
-  }
-
-  function createFootageData(data) {
-    var ob = {
-      assetData: data,
-    };
-    var path = getAssetsPath(data, this.assetsPath, this.path);
-    dataManager.loadData(path, function (footageData) {
-      ob.img = footageData;
-      this._footageLoaded();
-    }.bind(this), function () {
-      ob.img = {};
-      this._footageLoaded();
-    }.bind(this));
-    return ob;
-  }
-
-  function loadAssets(assets, cb) {
-    this.imagesLoadedCb = cb;
-    var i;
-    var len = assets.length;
-    for (i = 0; i < len; i += 1) {
-      if (!assets[i].layers) {
-        if (!assets[i].t || assets[i].t === 'seq') {
-          this.totalImages += 1;
-          this.images.push(this._createImageData(assets[i]));
-        } else if (assets[i].t === 3) {
-          this.totalFootages += 1;
-          this.images.push(this.createFootageData(assets[i]));
-        }
-      }
-    }
-  }
-
-  function setPath(path) {
-    this.path = path || '';
-  }
-
-  function setAssetsPath(path) {
-    this.assetsPath = path || '';
-  }
-
-  function getAsset(assetData) {
-    var i = 0;
-    var len = this.images.length;
-    while (i < len) {
-      if (this.images[i].assetData === assetData) {
-        return this.images[i].img;
-      }
-      i += 1;
-    }
-    return null;
-  }
-
-  function destroy() {
-    this.imagesLoadedCb = null;
-    this.images.length = 0;
-  }
-
-  function loadedImages() {
-    return this.totalImages === this.loadedAssets;
-  }
-
-  function loadedFootages() {
-    return this.totalFootages === this.loadedFootagesCount;
-  }
-
-  function setCacheType(type, elementHelper) {
-    if (type === 'svg') {
-      this._elementHelper = elementHelper;
-      this._createImageData = this.createImageData.bind(this);
-    } else {
-      this._createImageData = this.createImgData.bind(this);
-    }
-  }
-
-  function ImagePreloaderFactory() {
-    this._imageLoaded = imageLoaded.bind(this);
-    this._footageLoaded = footageLoaded.bind(this);
-    this.testImageLoaded = testImageLoaded.bind(this);
-    this.createFootageData = createFootageData.bind(this);
-    this.assetsPath = '';
-    this.path = '';
-    this.totalImages = 0;
-    this.totalFootages = 0;
-    this.loadedAssets = 0;
-    this.loadedFootagesCount = 0;
-    this.imagesLoadedCb = null;
-    this.images = [];
-  }
-
-  ImagePreloaderFactory.prototype = {
-    loadAssets: loadAssets,
-    setAssetsPath: setAssetsPath,
-    setPath: setPath,
-    loadedImages: loadedImages,
-    loadedFootages: loadedFootages,
-    destroy: destroy,
-    getAsset: getAsset,
-    createImgData: createImgData,
-    createImageData: createImageData,
-    imageLoaded: imageLoaded,
-    footageLoaded: footageLoaded,
-    setCacheType: setCacheType,
-  };
-
-  return ImagePreloaderFactory;
-}());
-
-/* exported featureSupport */
-
-var featureSupport = (function () {
-  var ob = {
-    maskType: true,
-  };
-  if (/MSIE 10/i.test(navigator.userAgent) || /MSIE 9/i.test(navigator.userAgent) || /rv:11.0/i.test(navigator.userAgent) || /Edge\/\d./i.test(navigator.userAgent)) {
-    ob.maskType = false;
-  }
-  return ob;
-}());
-
-/* global createNS */
-/* exported filtersFactory */
-
-var filtersFactory = (function () {
-  var ob = {};
-  ob.createFilter = createFilter;
-  ob.createAlphaToLuminanceFilter = createAlphaToLuminanceFilter;
-
-  function createFilter(filId, skipCoordinates) {
-    var fil = createNS('filter');
-    fil.setAttribute('id', filId);
-    if (skipCoordinates !== true) {
-      fil.setAttribute('filterUnits', 'objectBoundingBox');
-      fil.setAttribute('x', '0%');
-      fil.setAttribute('y', '0%');
-      fil.setAttribute('width', '100%');
-      fil.setAttribute('height', '100%');
-    }
-    return fil;
-  }
-
-  function createAlphaToLuminanceFilter() {
-    var feColorMatrix = createNS('feColorMatrix');
-    feColorMatrix.setAttribute('type', 'matrix');
-    feColorMatrix.setAttribute('color-interpolation-filters', 'sRGB');
-    feColorMatrix.setAttribute('values', '0 0 0 1 0  0 0 0 1 0  0 0 0 1 0  0 0 0 1 1');
-    return feColorMatrix;
-  }
-
-  return ob;
-}());
-
-/* global createSizedArray, PropertyFactory, TextAnimatorDataProperty, bez, addHueToRGB,
-  addSaturationToRGB, addBrightnessToRGB, LetterProps, Matrix, extendPrototype, DynamicPropertyContainer */
-
-function TextAnimatorProperty(textData, renderType, elem) {
-  this._isFirstFrame = true;
-  this._hasMaskedPath = false;
-  this._frameId = -1;
-  this._textData = textData;
-  this._renderType = renderType;
-  this._elem = elem;
-  this._animatorsData = createSizedArray(this._textData.a.length);
-  this._pathData = {};
-  this._moreOptions = {
-    alignment: {},
-  };
-  this.renderedLetters = [];
-  this.lettersChangedFlag = false;
-  this.initDynamicPropertyContainer(elem);
-}
-
-TextAnimatorProperty.prototype.searchProperties = function () {
-  var i;
-  var len = this._textData.a.length;
-  var animatorProps;
-  var getProp = PropertyFactory.getProp;
-  for (i = 0; i < len; i += 1) {
-    animatorProps = this._textData.a[i];
-    this._animatorsData[i] = new TextAnimatorDataProperty(this._elem, animatorProps, this);
-  }
-  if (this._textData.p && 'm' in this._textData.p) {
-    this._pathData = {
-      a: getProp(this._elem, this._textData.p.a, 0, 0, this),
-      f: getProp(this._elem, this._textData.p.f, 0, 0, this),
-      l: getProp(this._elem, this._textData.p.l, 0, 0, this),
-      r: getProp(this._elem, this._textData.p.r, 0, 0, this),
-      p: getProp(this._elem, this._textData.p.p, 0, 0, this),
-      m: this._elem.maskManager.getMaskProperty(this._textData.p.m),
-    };
-    this._hasMaskedPath = true;
-  } else {
-    this._hasMaskedPath = false;
-  }
-  this._moreOptions.alignment = getProp(this._elem, this._textData.m.a, 1, 0, this);
-};
-
-TextAnimatorProperty.prototype.getMeasures = function (documentData, lettersChangedFlag) {
-  this.lettersChangedFlag = lettersChangedFlag;
-  if (!this._mdf && !this._isFirstFrame && !lettersChangedFlag && (!this._hasMaskedPath || !this._pathData.m._mdf)) {
-    return;
-  }
-  this._isFirstFrame = false;
-  var alignment = this._moreOptions.alignment.v;
-  var animators = this._animatorsData;
-  var textData = this._textData;
-  var matrixHelper = this.mHelper;
-  var renderType = this._renderType;
-  var renderedLettersCount = this.renderedLetters.length;
-  var xPos;
-  var yPos;
-  var i;
-  var len;
-  var letters = documentData.l;
-  var pathInfo;
-  var currentLength;
-  var currentPoint;
-  var segmentLength;
-  var flag;
-  var pointInd;
-  var segmentInd;
-  var prevPoint;
-  var points;
-  var segments;
-  var partialLength;
-  var totalLength;
-  var perc;
-  var tanAngle;
-  var mask;
-  if (this._hasMaskedPath) {
-    mask = this._pathData.m;
-    if (!this._pathData.n || this._pathData._mdf) {
-      var paths = mask.v;
-      if (this._pathData.r.v) {
-        paths = paths.reverse();
-      }
-      // TODO: release bezier data cached from previous pathInfo: this._pathData.pi
-      pathInfo = {
-        tLength: 0,
-        segments: [],
+      var ob = {
+        img: img,
+        assetData: assetData
       };
-      len = paths._length - 1;
-      var bezierData;
-      totalLength = 0;
+      return ob;
+    }
+
+    function createImgData(assetData) {
+      var path = getAssetsPath(assetData, this.assetsPath, this.path);
+      var img = createTag('img');
+      img.crossOrigin = 'anonymous';
+      img.addEventListener('load', this._imageLoaded, false);
+      img.addEventListener('error', function () {
+        ob.img = proxyImage;
+
+        this._imageLoaded();
+      }.bind(this), false);
+      img.src = path;
+      var ob = {
+        img: img,
+        assetData: assetData
+      };
+      return ob;
+    }
+
+    function createFootageData(data) {
+      var ob = {
+        assetData: data
+      };
+      var path = getAssetsPath(data, this.assetsPath, this.path);
+      dataManager.loadData(path, function (footageData) {
+        ob.img = footageData;
+
+        this._footageLoaded();
+      }.bind(this), function () {
+        ob.img = {};
+
+        this._footageLoaded();
+      }.bind(this));
+      return ob;
+    }
+
+    function loadAssets(assets, cb) {
+      this.imagesLoadedCb = cb;
+      var i;
+      var len = assets.length;
+
       for (i = 0; i < len; i += 1) {
-        bezierData = bez.buildBezierData(paths.v[i],
-          paths.v[i + 1],
-          [paths.o[i][0] - paths.v[i][0], paths.o[i][1] - paths.v[i][1]],
-          [paths.i[i + 1][0] - paths.v[i + 1][0], paths.i[i + 1][1] - paths.v[i + 1][1]]);
-        pathInfo.tLength += bezierData.segmentLength;
-        pathInfo.segments.push(bezierData);
-        totalLength += bezierData.segmentLength;
-      }
-      i = len;
-      if (mask.v.c) {
-        bezierData = bez.buildBezierData(paths.v[i],
-          paths.v[0],
-          [paths.o[i][0] - paths.v[i][0], paths.o[i][1] - paths.v[i][1]],
-          [paths.i[0][0] - paths.v[0][0], paths.i[0][1] - paths.v[0][1]]);
-        pathInfo.tLength += bezierData.segmentLength;
-        pathInfo.segments.push(bezierData);
-        totalLength += bezierData.segmentLength;
-      }
-      this._pathData.pi = pathInfo;
-    }
-    pathInfo = this._pathData.pi;
-
-    currentLength = this._pathData.f.v;
-    segmentInd = 0;
-    pointInd = 1;
-    segmentLength = 0;
-    flag = true;
-    segments = pathInfo.segments;
-    if (currentLength < 0 && mask.v.c) {
-      if (pathInfo.tLength < Math.abs(currentLength)) {
-        currentLength = -Math.abs(currentLength) % pathInfo.tLength;
-      }
-      segmentInd = segments.length - 1;
-      points = segments[segmentInd].points;
-      pointInd = points.length - 1;
-      while (currentLength < 0) {
-        currentLength += points[pointInd].partialLength;
-        pointInd -= 1;
-        if (pointInd < 0) {
-          segmentInd -= 1;
-          points = segments[segmentInd].points;
-          pointInd = points.length - 1;
+        if (!assets[i].layers) {
+          if (!assets[i].t || assets[i].t === 'seq') {
+            this.totalImages += 1;
+            this.images.push(this._createImageData(assets[i]));
+          } else if (assets[i].t === 3) {
+            this.totalFootages += 1;
+            this.images.push(this.createFootageData(assets[i]));
+          }
         }
       }
     }
-    points = segments[segmentInd].points;
-    prevPoint = points[pointInd - 1];
-    currentPoint = points[pointInd];
-    partialLength = currentPoint.partialLength;
-  }
 
-  len = letters.length;
-  xPos = 0;
-  yPos = 0;
-  var yOff = documentData.finalSize * 1.2 * 0.714;
-  var firstLine = true;
-  var animatorProps;
-  var animatorSelector;
-  var j;
-  var jLen;
-  var letterValue;
-
-  jLen = animators.length;
-
-  var mult;
-  var ind = -1;
-  var offf;
-  var xPathPos;
-  var yPathPos;
-  var initPathPos = currentLength;
-  var initSegmentInd = segmentInd;
-  var initPointInd = pointInd;
-  var currentLine = -1;
-  var elemOpacity;
-  var sc;
-  var sw;
-  var fc;
-  var k;
-  var letterSw;
-  var letterSc;
-  var letterFc;
-  var letterM = '';
-  var letterP = this.defaultPropsArray;
-  var letterO;
-
-  //
-  if (documentData.j === 2 || documentData.j === 1) {
-    var animatorJustifyOffset = 0;
-    var animatorFirstCharOffset = 0;
-    var justifyOffsetMult = documentData.j === 2 ? -0.5 : -1;
-    var lastIndex = 0;
-    var isNewLine = true;
-
-    for (i = 0; i < len; i += 1) {
-      if (letters[i].n) {
-        if (animatorJustifyOffset) {
-          animatorJustifyOffset += animatorFirstCharOffset;
-        }
-        while (lastIndex < i) {
-          letters[lastIndex].animatorJustifyOffset = animatorJustifyOffset;
-          lastIndex += 1;
-        }
-        animatorJustifyOffset = 0;
-        isNewLine = true;
-      } else {
-        for (j = 0; j < jLen; j += 1) {
-          animatorProps = animators[j].a;
-          if (animatorProps.t.propType) {
-            if (isNewLine && documentData.j === 2) {
-              animatorFirstCharOffset += animatorProps.t.v * justifyOffsetMult;
-            }
-            animatorSelector = animators[j].s;
-            mult = animatorSelector.getMult(letters[i].anIndexes[j], textData.a[j].s.totalChars);
-            if (mult.length) {
-              animatorJustifyOffset += animatorProps.t.v * mult[0] * justifyOffsetMult;
-            } else {
-              animatorJustifyOffset += animatorProps.t.v * mult * justifyOffsetMult;
-            }
-          }
-        }
-        isNewLine = false;
-      }
-    }
-    if (animatorJustifyOffset) {
-      animatorJustifyOffset += animatorFirstCharOffset;
-    }
-    while (lastIndex < i) {
-      letters[lastIndex].animatorJustifyOffset = animatorJustifyOffset;
-      lastIndex += 1;
-    }
-  }
-  //
-
-  for (i = 0; i < len; i += 1) {
-    matrixHelper.reset();
-    elemOpacity = 1;
-    if (letters[i].n) {
-      xPos = 0;
-      yPos += documentData.yOffset;
-      yPos += firstLine ? 1 : 0;
-      currentLength = initPathPos;
-      firstLine = false;
-      if (this._hasMaskedPath) {
-        segmentInd = initSegmentInd;
-        pointInd = initPointInd;
-        points = segments[segmentInd].points;
-        prevPoint = points[pointInd - 1];
-        currentPoint = points[pointInd];
-        partialLength = currentPoint.partialLength;
-        segmentLength = 0;
-      }
-      letterM = '';
-      letterFc = '';
-      letterSw = '';
-      letterO = '';
-      letterP = this.defaultPropsArray;
-    } else {
-      if (this._hasMaskedPath) {
-        if (currentLine !== letters[i].line) {
-          switch (documentData.j) {
-            case 1:
-              currentLength += totalLength - documentData.lineWidths[letters[i].line];
-              break;
-            case 2:
-              currentLength += (totalLength - documentData.lineWidths[letters[i].line]) / 2;
-              break;
-            default:
-              break;
-          }
-          currentLine = letters[i].line;
-        }
-        if (ind !== letters[i].ind) {
-          if (letters[ind]) {
-            currentLength += letters[ind].extra;
-          }
-          currentLength += letters[i].an / 2;
-          ind = letters[i].ind;
-        }
-        currentLength += (alignment[0] * letters[i].an) * 0.005;
-        var animatorOffset = 0;
-        for (j = 0; j < jLen; j += 1) {
-          animatorProps = animators[j].a;
-          if (animatorProps.p.propType) {
-            animatorSelector = animators[j].s;
-            mult = animatorSelector.getMult(letters[i].anIndexes[j], textData.a[j].s.totalChars);
-            if (mult.length) {
-              animatorOffset += animatorProps.p.v[0] * mult[0];
-            } else {
-              animatorOffset += animatorProps.p.v[0] * mult;
-            }
-          }
-          if (animatorProps.a.propType) {
-            animatorSelector = animators[j].s;
-            mult = animatorSelector.getMult(letters[i].anIndexes[j], textData.a[j].s.totalChars);
-            if (mult.length) {
-              animatorOffset += animatorProps.a.v[0] * mult[0];
-            } else {
-              animatorOffset += animatorProps.a.v[0] * mult;
-            }
-          }
-        }
-        flag = true;
-        // Force alignment only works with a single line for now
-        if (this._pathData.a.v) {
-          currentLength = letters[0].an * 0.5 + ((totalLength - this._pathData.f.v - letters[0].an * 0.5 - letters[letters.length - 1].an * 0.5) * ind) / (len - 1);
-          currentLength += this._pathData.f.v;
-        }
-        while (flag) {
-          if (segmentLength + partialLength >= currentLength + animatorOffset || !points) {
-            perc = (currentLength + animatorOffset - segmentLength) / currentPoint.partialLength;
-            xPathPos = prevPoint.point[0] + (currentPoint.point[0] - prevPoint.point[0]) * perc;
-            yPathPos = prevPoint.point[1] + (currentPoint.point[1] - prevPoint.point[1]) * perc;
-            matrixHelper.translate((-alignment[0] * letters[i].an) * 0.005, -(alignment[1] * yOff) * 0.01);
-            flag = false;
-          } else if (points) {
-            segmentLength += currentPoint.partialLength;
-            pointInd += 1;
-            if (pointInd >= points.length) {
-              pointInd = 0;
-              segmentInd += 1;
-              if (!segments[segmentInd]) {
-                if (mask.v.c) {
-                  pointInd = 0;
-                  segmentInd = 0;
-                  points = segments[segmentInd].points;
-                } else {
-                  segmentLength -= currentPoint.partialLength;
-                  points = null;
-                }
-              } else {
-                points = segments[segmentInd].points;
-              }
-            }
-            if (points) {
-              prevPoint = currentPoint;
-              currentPoint = points[pointInd];
-              partialLength = currentPoint.partialLength;
-            }
-          }
-        }
-        offf = letters[i].an / 2 - letters[i].add;
-        matrixHelper.translate(-offf, 0, 0);
-      } else {
-        offf = letters[i].an / 2 - letters[i].add;
-        matrixHelper.translate(-offf, 0, 0);
-
-        // Grouping alignment
-        matrixHelper.translate((-alignment[0] * letters[i].an) * 0.005, (-alignment[1] * yOff) * 0.01, 0);
-      }
-
-      for (j = 0; j < jLen; j += 1) {
-        animatorProps = animators[j].a;
-        if (animatorProps.t.propType) {
-          animatorSelector = animators[j].s;
-          mult = animatorSelector.getMult(letters[i].anIndexes[j], textData.a[j].s.totalChars);
-          // This condition is to prevent applying tracking to first character in each line. Might be better to use a boolean "isNewLine"
-          if (xPos !== 0 || documentData.j !== 0) {
-            if (this._hasMaskedPath) {
-              if (mult.length) {
-                currentLength += animatorProps.t.v * mult[0];
-              } else {
-                currentLength += animatorProps.t.v * mult;
-              }
-            } else if (mult.length) {
-              xPos += animatorProps.t.v * mult[0];
-            } else {
-              xPos += animatorProps.t.v * mult;
-            }
-          }
-        }
-      }
-      if (documentData.strokeWidthAnim) {
-        sw = documentData.sw || 0;
-      }
-      if (documentData.strokeColorAnim) {
-        if (documentData.sc) {
-          sc = [documentData.sc[0], documentData.sc[1], documentData.sc[2]];
-        } else {
-          sc = [0, 0, 0];
-        }
-      }
-      if (documentData.fillColorAnim && documentData.fc) {
-        fc = [documentData.fc[0], documentData.fc[1], documentData.fc[2]];
-      }
-      for (j = 0; j < jLen; j += 1) {
-        animatorProps = animators[j].a;
-        if (animatorProps.a.propType) {
-          animatorSelector = animators[j].s;
-          mult = animatorSelector.getMult(letters[i].anIndexes[j], textData.a[j].s.totalChars);
-
-          if (mult.length) {
-            matrixHelper.translate(-animatorProps.a.v[0] * mult[0], -animatorProps.a.v[1] * mult[1], animatorProps.a.v[2] * mult[2]);
-          } else {
-            matrixHelper.translate(-animatorProps.a.v[0] * mult, -animatorProps.a.v[1] * mult, animatorProps.a.v[2] * mult);
-          }
-        }
-      }
-      for (j = 0; j < jLen; j += 1) {
-        animatorProps = animators[j].a;
-        if (animatorProps.s.propType) {
-          animatorSelector = animators[j].s;
-          mult = animatorSelector.getMult(letters[i].anIndexes[j], textData.a[j].s.totalChars);
-          if (mult.length) {
-            matrixHelper.scale(1 + ((animatorProps.s.v[0] - 1) * mult[0]), 1 + ((animatorProps.s.v[1] - 1) * mult[1]), 1);
-          } else {
-            matrixHelper.scale(1 + ((animatorProps.s.v[0] - 1) * mult), 1 + ((animatorProps.s.v[1] - 1) * mult), 1);
-          }
-        }
-      }
-      for (j = 0; j < jLen; j += 1) {
-        animatorProps = animators[j].a;
-        animatorSelector = animators[j].s;
-        mult = animatorSelector.getMult(letters[i].anIndexes[j], textData.a[j].s.totalChars);
-        if (animatorProps.sk.propType) {
-          if (mult.length) {
-            matrixHelper.skewFromAxis(-animatorProps.sk.v * mult[0], animatorProps.sa.v * mult[1]);
-          } else {
-            matrixHelper.skewFromAxis(-animatorProps.sk.v * mult, animatorProps.sa.v * mult);
-          }
-        }
-        if (animatorProps.r.propType) {
-          if (mult.length) {
-            matrixHelper.rotateZ(-animatorProps.r.v * mult[2]);
-          } else {
-            matrixHelper.rotateZ(-animatorProps.r.v * mult);
-          }
-        }
-        if (animatorProps.ry.propType) {
-          if (mult.length) {
-            matrixHelper.rotateY(animatorProps.ry.v * mult[1]);
-          } else {
-            matrixHelper.rotateY(animatorProps.ry.v * mult);
-          }
-        }
-        if (animatorProps.rx.propType) {
-          if (mult.length) {
-            matrixHelper.rotateX(animatorProps.rx.v * mult[0]);
-          } else {
-            matrixHelper.rotateX(animatorProps.rx.v * mult);
-          }
-        }
-        if (animatorProps.o.propType) {
-          if (mult.length) {
-            elemOpacity += ((animatorProps.o.v) * mult[0] - elemOpacity) * mult[0];
-          } else {
-            elemOpacity += ((animatorProps.o.v) * mult - elemOpacity) * mult;
-          }
-        }
-        if (documentData.strokeWidthAnim && animatorProps.sw.propType) {
-          if (mult.length) {
-            sw += animatorProps.sw.v * mult[0];
-          } else {
-            sw += animatorProps.sw.v * mult;
-          }
-        }
-        if (documentData.strokeColorAnim && animatorProps.sc.propType) {
-          for (k = 0; k < 3; k += 1) {
-            if (mult.length) {
-              sc[k] += (animatorProps.sc.v[k] - sc[k]) * mult[0];
-            } else {
-              sc[k] += (animatorProps.sc.v[k] - sc[k]) * mult;
-            }
-          }
-        }
-        if (documentData.fillColorAnim && documentData.fc) {
-          if (animatorProps.fc.propType) {
-            for (k = 0; k < 3; k += 1) {
-              if (mult.length) {
-                fc[k] += (animatorProps.fc.v[k] - fc[k]) * mult[0];
-              } else {
-                fc[k] += (animatorProps.fc.v[k] - fc[k]) * mult;
-              }
-            }
-          }
-          if (animatorProps.fh.propType) {
-            if (mult.length) {
-              fc = addHueToRGB(fc, animatorProps.fh.v * mult[0]);
-            } else {
-              fc = addHueToRGB(fc, animatorProps.fh.v * mult);
-            }
-          }
-          if (animatorProps.fs.propType) {
-            if (mult.length) {
-              fc = addSaturationToRGB(fc, animatorProps.fs.v * mult[0]);
-            } else {
-              fc = addSaturationToRGB(fc, animatorProps.fs.v * mult);
-            }
-          }
-          if (animatorProps.fb.propType) {
-            if (mult.length) {
-              fc = addBrightnessToRGB(fc, animatorProps.fb.v * mult[0]);
-            } else {
-              fc = addBrightnessToRGB(fc, animatorProps.fb.v * mult);
-            }
-          }
-        }
-      }
-
-      for (j = 0; j < jLen; j += 1) {
-        animatorProps = animators[j].a;
-
-        if (animatorProps.p.propType) {
-          animatorSelector = animators[j].s;
-          mult = animatorSelector.getMult(letters[i].anIndexes[j], textData.a[j].s.totalChars);
-          if (this._hasMaskedPath) {
-            if (mult.length) {
-              matrixHelper.translate(0, animatorProps.p.v[1] * mult[0], -animatorProps.p.v[2] * mult[1]);
-            } else {
-              matrixHelper.translate(0, animatorProps.p.v[1] * mult, -animatorProps.p.v[2] * mult);
-            }
-          } else if (mult.length) {
-            matrixHelper.translate(animatorProps.p.v[0] * mult[0], animatorProps.p.v[1] * mult[1], -animatorProps.p.v[2] * mult[2]);
-          } else {
-            matrixHelper.translate(animatorProps.p.v[0] * mult, animatorProps.p.v[1] * mult, -animatorProps.p.v[2] * mult);
-          }
-        }
-      }
-      if (documentData.strokeWidthAnim) {
-        letterSw = sw < 0 ? 0 : sw;
-      }
-      if (documentData.strokeColorAnim) {
-        letterSc = 'rgb(' + Math.round(sc[0] * 255) + ',' + Math.round(sc[1] * 255) + ',' + Math.round(sc[2] * 255) + ')';
-      }
-      if (documentData.fillColorAnim && documentData.fc) {
-        letterFc = 'rgb(' + Math.round(fc[0] * 255) + ',' + Math.round(fc[1] * 255) + ',' + Math.round(fc[2] * 255) + ')';
-      }
-
-      if (this._hasMaskedPath) {
-        matrixHelper.translate(0, -documentData.ls);
-
-        matrixHelper.translate(0, (alignment[1] * yOff) * 0.01 + yPos, 0);
-        if (this._pathData.p.v) {
-          tanAngle = (currentPoint.point[1] - prevPoint.point[1]) / (currentPoint.point[0] - prevPoint.point[0]);
-          var rot = (Math.atan(tanAngle) * 180) / Math.PI;
-          if (currentPoint.point[0] < prevPoint.point[0]) {
-            rot += 180;
-          }
-          matrixHelper.rotate((-rot * Math.PI) / 180);
-        }
-        matrixHelper.translate(xPathPos, yPathPos, 0);
-        currentLength -= (alignment[0] * letters[i].an) * 0.005;
-        if (letters[i + 1] && ind !== letters[i + 1].ind) {
-          currentLength += letters[i].an / 2;
-          currentLength += (documentData.tr * 0.001) * documentData.finalSize;
-        }
-      } else {
-        matrixHelper.translate(xPos, yPos, 0);
-
-        if (documentData.ps) {
-          // matrixHelper.translate(documentData.ps[0],documentData.ps[1],0);
-          matrixHelper.translate(documentData.ps[0], documentData.ps[1] + documentData.ascent, 0);
-        }
-        switch (documentData.j) {
-          case 1:
-            matrixHelper.translate(letters[i].animatorJustifyOffset + documentData.justifyOffset + (documentData.boxWidth - documentData.lineWidths[letters[i].line]), 0, 0);
-            break;
-          case 2:
-            matrixHelper.translate(letters[i].animatorJustifyOffset + documentData.justifyOffset + (documentData.boxWidth - documentData.lineWidths[letters[i].line]) / 2, 0, 0);
-            break;
-          default:
-            break;
-        }
-        matrixHelper.translate(0, -documentData.ls);
-        matrixHelper.translate(offf, 0, 0);
-        matrixHelper.translate((alignment[0] * letters[i].an) * 0.005, (alignment[1] * yOff) * 0.01, 0);
-        xPos += letters[i].l + (documentData.tr * 0.001) * documentData.finalSize;
-      }
-      if (renderType === 'html') {
-        letterM = matrixHelper.toCSS();
-      } else if (renderType === 'svg') {
-        letterM = matrixHelper.to2dCSS();
-      } else {
-        letterP = [matrixHelper.props[0], matrixHelper.props[1], matrixHelper.props[2], matrixHelper.props[3], matrixHelper.props[4], matrixHelper.props[5], matrixHelper.props[6], matrixHelper.props[7], matrixHelper.props[8], matrixHelper.props[9], matrixHelper.props[10], matrixHelper.props[11], matrixHelper.props[12], matrixHelper.props[13], matrixHelper.props[14], matrixHelper.props[15]];
-      }
-      letterO = elemOpacity;
+    function setPath(path) {
+      this.path = path || '';
     }
 
-    if (renderedLettersCount <= i) {
-      letterValue = new LetterProps(letterO, letterSw, letterSc, letterFc, letterM, letterP);
-      this.renderedLetters.push(letterValue);
-      renderedLettersCount += 1;
-      this.lettersChangedFlag = true;
-    } else {
-      letterValue = this.renderedLetters[i];
-      this.lettersChangedFlag = letterValue.update(letterO, letterSw, letterSc, letterFc, letterM, letterP) || this.lettersChangedFlag;
+    function setAssetsPath(path) {
+      this.assetsPath = path || '';
     }
-  }
-};
 
-TextAnimatorProperty.prototype.getValue = function () {
-  if (this._elem.globalData.frameId === this._frameId) {
-    return;
-  }
-  this._frameId = this._elem.globalData.frameId;
-  this.iterateDynamicProperties();
-};
+    function getAsset(assetData) {
+      var i = 0;
+      var len = this.images.length;
 
-TextAnimatorProperty.prototype.mHelper = new Matrix();
-TextAnimatorProperty.prototype.defaultPropsArray = [];
-extendPrototype([DynamicPropertyContainer], TextAnimatorProperty);
-
-/* global PropertyFactory, degToRads, TextSelectorProp */
-/* exported TextAnimatorDataProperty */
-
-function TextAnimatorDataProperty(elem, animatorProps, container) {
-  var defaultData = { propType: false };
-  var getProp = PropertyFactory.getProp;
-  var textAnimatorAnimatables = animatorProps.a;
-  this.a = {
-    r: textAnimatorAnimatables.r ? getProp(elem, textAnimatorAnimatables.r, 0, degToRads, container) : defaultData,
-    rx: textAnimatorAnimatables.rx ? getProp(elem, textAnimatorAnimatables.rx, 0, degToRads, container) : defaultData,
-    ry: textAnimatorAnimatables.ry ? getProp(elem, textAnimatorAnimatables.ry, 0, degToRads, container) : defaultData,
-    sk: textAnimatorAnimatables.sk ? getProp(elem, textAnimatorAnimatables.sk, 0, degToRads, container) : defaultData,
-    sa: textAnimatorAnimatables.sa ? getProp(elem, textAnimatorAnimatables.sa, 0, degToRads, container) : defaultData,
-    s: textAnimatorAnimatables.s ? getProp(elem, textAnimatorAnimatables.s, 1, 0.01, container) : defaultData,
-    a: textAnimatorAnimatables.a ? getProp(elem, textAnimatorAnimatables.a, 1, 0, container) : defaultData,
-    o: textAnimatorAnimatables.o ? getProp(elem, textAnimatorAnimatables.o, 0, 0.01, container) : defaultData,
-    p: textAnimatorAnimatables.p ? getProp(elem, textAnimatorAnimatables.p, 1, 0, container) : defaultData,
-    sw: textAnimatorAnimatables.sw ? getProp(elem, textAnimatorAnimatables.sw, 0, 0, container) : defaultData,
-    sc: textAnimatorAnimatables.sc ? getProp(elem, textAnimatorAnimatables.sc, 1, 0, container) : defaultData,
-    fc: textAnimatorAnimatables.fc ? getProp(elem, textAnimatorAnimatables.fc, 1, 0, container) : defaultData,
-    fh: textAnimatorAnimatables.fh ? getProp(elem, textAnimatorAnimatables.fh, 0, 0, container) : defaultData,
-    fs: textAnimatorAnimatables.fs ? getProp(elem, textAnimatorAnimatables.fs, 0, 0.01, container) : defaultData,
-    fb: textAnimatorAnimatables.fb ? getProp(elem, textAnimatorAnimatables.fb, 0, 0.01, container) : defaultData,
-    t: textAnimatorAnimatables.t ? getProp(elem, textAnimatorAnimatables.t, 0, 0, container) : defaultData,
-  };
-
-  this.s = TextSelectorProp.getTextSelectorProp(elem, animatorProps.s, container);
-  this.s.t = animatorProps.s.t;
-}
-
-function LetterProps(o, sw, sc, fc, m, p) {
-  this.o = o;
-  this.sw = sw;
-  this.sc = sc;
-  this.fc = fc;
-  this.m = m;
-  this.p = p;
-  this._mdf = {
-    o: true,
-    sw: !!sw,
-    sc: !!sc,
-    fc: !!fc,
-    m: true,
-    p: true,
-  };
-}
-
-LetterProps.prototype.update = function (o, sw, sc, fc, m, p) {
-  this._mdf.o = false;
-  this._mdf.sw = false;
-  this._mdf.sc = false;
-  this._mdf.fc = false;
-  this._mdf.m = false;
-  this._mdf.p = false;
-  var updated = false;
-
-  if (this.o !== o) {
-    this.o = o;
-    this._mdf.o = true;
-    updated = true;
-  }
-  if (this.sw !== sw) {
-    this.sw = sw;
-    this._mdf.sw = true;
-    updated = true;
-  }
-  if (this.sc !== sc) {
-    this.sc = sc;
-    this._mdf.sc = true;
-    updated = true;
-  }
-  if (this.fc !== fc) {
-    this.fc = fc;
-    this._mdf.fc = true;
-    updated = true;
-  }
-  if (this.m !== m) {
-    this.m = m;
-    this._mdf.m = true;
-    updated = true;
-  }
-  if (p.length && (this.p[0] !== p[0] || this.p[1] !== p[1] || this.p[4] !== p[4] || this.p[5] !== p[5] || this.p[12] !== p[12] || this.p[13] !== p[13])) {
-    this.p = p;
-    this._mdf.p = true;
-    updated = true;
-  }
-  return updated;
-};
-
-/* global FontManager, initialDefaultFrame, getFontProperties */
-/* exported TextProperty */
-
-function TextProperty(elem, data) {
-  this._frameId = initialDefaultFrame;
-  this.pv = '';
-  this.v = '';
-  this.kf = false;
-  this._isFirstFrame = true;
-  this._mdf = false;
-  this.data = data;
-  this.elem = elem;
-  this.comp = this.elem.comp;
-  this.keysIndex = 0;
-  this.canResize = false;
-  this.minimumFontSize = 1;
-  this.effectsSequence = [];
-  this.currentData = {
-    ascent: 0,
-    boxWidth: this.defaultBoxWidth,
-    f: '',
-    fStyle: '',
-    fWeight: '',
-    fc: '',
-    j: '',
-    justifyOffset: '',
-    l: [],
-    lh: 0,
-    lineWidths: [],
-    ls: '',
-    of: '',
-    s: '',
-    sc: '',
-    sw: 0,
-    t: 0,
-    tr: 0,
-    sz: 0,
-    ps: null,
-    fillColorAnim: false,
-    strokeColorAnim: false,
-    strokeWidthAnim: false,
-    yOffset: 0,
-    finalSize: 0,
-    finalText: [],
-    finalLineHeight: 0,
-    __complete: false,
-
-  };
-  this.copyData(this.currentData, this.data.d.k[0].s);
-
-  if (!this.searchProperty()) {
-    this.completeTextData(this.currentData);
-  }
-}
-
-TextProperty.prototype.defaultBoxWidth = [0, 0];
-
-TextProperty.prototype.copyData = function (obj, data) {
-  for (var s in data) {
-    if (Object.prototype.hasOwnProperty.call(data, s)) {
-      obj[s] = data[s];
-    }
-  }
-  return obj;
-};
-
-TextProperty.prototype.setCurrentData = function (data) {
-  if (!data.__complete) {
-    this.completeTextData(data);
-  }
-  this.currentData = data;
-  this.currentData.boxWidth = this.currentData.boxWidth || this.defaultBoxWidth;
-  this._mdf = true;
-};
-
-TextProperty.prototype.searchProperty = function () {
-  return this.searchKeyframes();
-};
-
-TextProperty.prototype.searchKeyframes = function () {
-  this.kf = this.data.d.k.length > 1;
-  if (this.kf) {
-    this.addEffect(this.getKeyframeValue.bind(this));
-  }
-  return this.kf;
-};
-
-TextProperty.prototype.addEffect = function (effectFunction) {
-  this.effectsSequence.push(effectFunction);
-  this.elem.addDynamicProperty(this);
-};
-
-TextProperty.prototype.getValue = function (_finalValue) {
-  if ((this.elem.globalData.frameId === this.frameId || !this.effectsSequence.length) && !_finalValue) {
-    return;
-  }
-  this.currentData.t = this.data.d.k[this.keysIndex].s.t;
-  var currentValue = this.currentData;
-  var currentIndex = this.keysIndex;
-  if (this.lock) {
-    this.setCurrentData(this.currentData);
-    return;
-  }
-  this.lock = true;
-  this._mdf = false;
-  var i; var
-    len = this.effectsSequence.length;
-  var finalValue = _finalValue || this.data.d.k[this.keysIndex].s;
-  for (i = 0; i < len; i += 1) {
-    // Checking if index changed to prevent creating a new object every time the expression updates.
-    if (currentIndex !== this.keysIndex) {
-      finalValue = this.effectsSequence[i](finalValue, finalValue.t);
-    } else {
-      finalValue = this.effectsSequence[i](this.currentData, finalValue.t);
-    }
-  }
-  if (currentValue !== finalValue) {
-    this.setCurrentData(finalValue);
-  }
-  this.v = this.currentData;
-  this.pv = this.v;
-  this.lock = false;
-  this.frameId = this.elem.globalData.frameId;
-};
-
-TextProperty.prototype.getKeyframeValue = function () {
-  var textKeys = this.data.d.k;
-  var frameNum = this.elem.comp.renderedFrame;
-  var i = 0; var
-    len = textKeys.length;
-  while (i <= len - 1) {
-    if (i === len - 1 || textKeys[i + 1].t > frameNum) {
-      break;
-    }
-    i += 1;
-  }
-  if (this.keysIndex !== i) {
-    this.keysIndex = i;
-  }
-  return this.data.d.k[this.keysIndex].s;
-};
-
-TextProperty.prototype.buildFinalText = function (text) {
-  var charactersArray = [];
-  var i = 0;
-  var len = text.length;
-  var charCode;
-  var secondCharCode;
-  var shouldCombine = false;
-  while (i < len) {
-    charCode = text.charCodeAt(i);
-    if (FontManager.isCombinedCharacter(charCode)) {
-      charactersArray[charactersArray.length - 1] += text.charAt(i);
-    } else if (charCode >= 0xD800 && charCode <= 0xDBFF) {
-      secondCharCode = text.charCodeAt(i + 1);
-      if (secondCharCode >= 0xDC00 && secondCharCode <= 0xDFFF) {
-        if (shouldCombine || FontManager.isModifier(charCode, secondCharCode)) {
-          charactersArray[charactersArray.length - 1] += text.substr(i, 2);
-          shouldCombine = false;
-        } else {
-          charactersArray.push(text.substr(i, 2));
+      while (i < len) {
+        if (this.images[i].assetData === assetData) {
+          return this.images[i].img;
         }
+
         i += 1;
+      }
+
+      return null;
+    }
+
+    function destroy() {
+      this.imagesLoadedCb = null;
+      this.images.length = 0;
+    }
+
+    function loadedImages() {
+      return this.totalImages === this.loadedAssets;
+    }
+
+    function loadedFootages() {
+      return this.totalFootages === this.loadedFootagesCount;
+    }
+
+    function setCacheType(type, elementHelper) {
+      if (type === 'svg') {
+        this._elementHelper = elementHelper;
+        this._createImageData = this.createImageData.bind(this);
       } else {
-        charactersArray.push(text.charAt(i));
-      }
-    } else if (charCode > 0xDBFF) {
-      secondCharCode = text.charCodeAt(i + 1);
-      if (FontManager.isZeroWidthJoiner(charCode, secondCharCode)) {
-        shouldCombine = true;
-        charactersArray[charactersArray.length - 1] += text.substr(i, 2);
-        i += 1;
-      } else {
-        charactersArray.push(text.charAt(i));
-      }
-    } else if (FontManager.isZeroWidthJoiner(charCode)) {
-      charactersArray[charactersArray.length - 1] += text.charAt(i);
-      shouldCombine = true;
-    } else {
-      charactersArray.push(text.charAt(i));
-    }
-    i += 1;
-  }
-  return charactersArray;
-};
-
-TextProperty.prototype.completeTextData = function (documentData) {
-  documentData.__complete = true;
-  var fontManager = this.elem.globalData.fontManager;
-  var data = this.data;
-  var letters = [];
-  var i; var
-    len;
-  var newLineFlag; var index = 0; var
-    val;
-  var anchorGrouping = data.m.g;
-  var currentSize = 0; var currentPos = 0; var currentLine = 0; var
-    lineWidths = [];
-  var lineWidth = 0;
-  var maxLineWidth = 0;
-  var j; var
-    jLen;
-  var fontData = fontManager.getFontByName(documentData.f);
-  var charData; var
-    cLength = 0;
-
-  var fontProps = getFontProperties(fontData);
-  documentData.fWeight = fontProps.weight;
-  documentData.fStyle = fontProps.style;
-  documentData.finalSize = documentData.s;
-  documentData.finalText = this.buildFinalText(documentData.t);
-  len = documentData.finalText.length;
-  documentData.finalLineHeight = documentData.lh;
-  var trackingOffset = (documentData.tr / 1000) * documentData.finalSize;
-  var charCode;
-  if (documentData.sz) {
-    var flag = true;
-    var boxWidth = documentData.sz[0];
-    var boxHeight = documentData.sz[1];
-    var currentHeight; var
-      finalText;
-    while (flag) {
-      finalText = this.buildFinalText(documentData.t);
-      currentHeight = 0;
-      lineWidth = 0;
-      len = finalText.length;
-      trackingOffset = (documentData.tr / 1000) * documentData.finalSize;
-      var lastSpaceIndex = -1;
-      for (i = 0; i < len; i += 1) {
-        charCode = finalText[i].charCodeAt(0);
-        newLineFlag = false;
-        if (finalText[i] === ' ') {
-          lastSpaceIndex = i;
-        } else if (charCode === 13 || charCode === 3) {
-          lineWidth = 0;
-          newLineFlag = true;
-          currentHeight += documentData.finalLineHeight || documentData.finalSize * 1.2;
-        }
-        if (fontManager.chars) {
-          charData = fontManager.getCharData(finalText[i], fontData.fStyle, fontData.fFamily);
-          cLength = newLineFlag ? 0 : (charData.w * documentData.finalSize) / 100;
-        } else {
-          // tCanvasHelper.font = documentData.s + 'px '+ fontData.fFamily;
-          cLength = fontManager.measureText(finalText[i], documentData.f, documentData.finalSize);
-        }
-        if (lineWidth + cLength > boxWidth && finalText[i] !== ' ') {
-          if (lastSpaceIndex === -1) {
-            len += 1;
-          } else {
-            i = lastSpaceIndex;
-          }
-          currentHeight += documentData.finalLineHeight || documentData.finalSize * 1.2;
-          finalText.splice(i, lastSpaceIndex === i ? 1 : 0, '\r');
-          // finalText = finalText.substr(0,i) + "\r" + finalText.substr(i === lastSpaceIndex ? i + 1 : i);
-          lastSpaceIndex = -1;
-          lineWidth = 0;
-        } else {
-          lineWidth += cLength;
-          lineWidth += trackingOffset;
-        }
-      }
-      currentHeight += (fontData.ascent * documentData.finalSize) / 100;
-      if (this.canResize && documentData.finalSize > this.minimumFontSize && boxHeight < currentHeight) {
-        documentData.finalSize -= 1;
-        documentData.finalLineHeight = (documentData.finalSize * documentData.lh) / documentData.s;
-      } else {
-        documentData.finalText = finalText;
-        len = documentData.finalText.length;
-        flag = false;
+        this._createImageData = this.createImgData.bind(this);
       }
     }
-  }
-  lineWidth = -trackingOffset;
-  cLength = 0;
-  var uncollapsedSpaces = 0;
-  var currentChar;
-  for (i = 0; i < len; i += 1) {
-    newLineFlag = false;
-    currentChar = documentData.finalText[i];
-    charCode = currentChar.charCodeAt(0);
-    if (charCode === 13 || charCode === 3) {
-      uncollapsedSpaces = 0;
-      lineWidths.push(lineWidth);
-      maxLineWidth = lineWidth > maxLineWidth ? lineWidth : maxLineWidth;
-      lineWidth = -2 * trackingOffset;
-      val = '';
-      newLineFlag = true;
-      currentLine += 1;
-    } else {
-      val = currentChar;
-    }
-    if (fontManager.chars) {
-      charData = fontManager.getCharData(currentChar, fontData.fStyle, fontManager.getFontByName(documentData.f).fFamily);
-      cLength = newLineFlag ? 0 : (charData.w * documentData.finalSize) / 100;
-    } else {
-      // var charWidth = fontManager.measureText(val, documentData.f, documentData.finalSize);
-      // tCanvasHelper.font = documentData.finalSize + 'px '+ fontManager.getFontByName(documentData.f).fFamily;
-      cLength = fontManager.measureText(val, documentData.f, documentData.finalSize);
+
+    function ImagePreloaderFactory() {
+      this._imageLoaded = imageLoaded.bind(this);
+      this._footageLoaded = footageLoaded.bind(this);
+      this.testImageLoaded = testImageLoaded.bind(this);
+      this.createFootageData = createFootageData.bind(this);
+      this.assetsPath = '';
+      this.path = '';
+      this.totalImages = 0;
+      this.totalFootages = 0;
+      this.loadedAssets = 0;
+      this.loadedFootagesCount = 0;
+      this.imagesLoadedCb = null;
+      this.images = [];
     }
 
-    //
-    if (currentChar === ' ') {
-      uncollapsedSpaces += cLength + trackingOffset;
-    } else {
-      lineWidth += cLength + trackingOffset + uncollapsedSpaces;
-      uncollapsedSpaces = 0;
-    }
-    letters.push({
-      l: cLength, an: cLength, add: currentSize, n: newLineFlag, anIndexes: [], val: val, line: currentLine, animatorJustifyOffset: 0,
-    });
-    if (anchorGrouping == 2) { // eslint-disable-line eqeqeq
-      currentSize += cLength;
-      if (val === '' || val === ' ' || i === len - 1) {
-        if (val === '' || val === ' ') {
-          currentSize -= cLength;
-        }
-        while (currentPos <= i) {
-          letters[currentPos].an = currentSize;
-          letters[currentPos].ind = index;
-          letters[currentPos].extra = cLength;
-          currentPos += 1;
-        }
-        index += 1;
-        currentSize = 0;
-      }
-    } else if (anchorGrouping == 3) { // eslint-disable-line eqeqeq
-      currentSize += cLength;
-      if (val === '' || i === len - 1) {
-        if (val === '') {
-          currentSize -= cLength;
-        }
-        while (currentPos <= i) {
-          letters[currentPos].an = currentSize;
-          letters[currentPos].ind = index;
-          letters[currentPos].extra = cLength;
-          currentPos += 1;
-        }
-        currentSize = 0;
-        index += 1;
-      }
-    } else {
-      letters[index].ind = index;
-      letters[index].extra = 0;
-      index += 1;
-    }
-  }
-  documentData.l = letters;
-  maxLineWidth = lineWidth > maxLineWidth ? lineWidth : maxLineWidth;
-  lineWidths.push(lineWidth);
-  if (documentData.sz) {
-    documentData.boxWidth = documentData.sz[0];
-    documentData.justifyOffset = 0;
-  } else {
-    documentData.boxWidth = maxLineWidth;
-    switch (documentData.j) {
-      case 1:
-        documentData.justifyOffset = -documentData.boxWidth;
-        break;
-      case 2:
-        documentData.justifyOffset = -documentData.boxWidth / 2;
-        break;
-      default:
-        documentData.justifyOffset = 0;
-    }
-  }
-  documentData.lineWidths = lineWidths;
+    ImagePreloaderFactory.prototype = {
+      loadAssets: loadAssets,
+      setAssetsPath: setAssetsPath,
+      setPath: setPath,
+      loadedImages: loadedImages,
+      loadedFootages: loadedFootages,
+      destroy: destroy,
+      getAsset: getAsset,
+      createImgData: createImgData,
+      createImageData: createImageData,
+      imageLoaded: imageLoaded,
+      footageLoaded: footageLoaded,
+      setCacheType: setCacheType
+    };
+    return ImagePreloaderFactory;
+  }();
 
-  var animators = data.a; var animatorData; var
-    letterData;
-  jLen = animators.length;
-  var based; var ind; var
-    indexes = [];
-  for (j = 0; j < jLen; j += 1) {
-    animatorData = animators[j];
-    if (animatorData.a.sc) {
-      documentData.strokeColorAnim = true;
-    }
-    if (animatorData.a.sw) {
-      documentData.strokeWidthAnim = true;
-    }
-    if (animatorData.a.fc || animatorData.a.fh || animatorData.a.fs || animatorData.a.fb) {
-      documentData.fillColorAnim = true;
-    }
-    ind = 0;
-    based = animatorData.s.b;
-    for (i = 0; i < len; i += 1) {
-      letterData = letters[i];
-      letterData.anIndexes[j] = ind;
-      if ((based == 1 && letterData.val !== '') || (based == 2 && letterData.val !== '' && letterData.val !== ' ') || (based == 3 && (letterData.n || letterData.val == ' ' || i == len - 1)) || (based == 4 && (letterData.n || i == len - 1))) { // eslint-disable-line eqeqeq
-        if (animatorData.s.rn === 1) {
-          indexes.push(ind);
-        }
-        ind += 1;
-      }
-    }
-    data.a[j].s.totalChars = ind;
-    var currentInd = -1; var
-      newInd;
-    if (animatorData.s.rn === 1) {
-      for (i = 0; i < len; i += 1) {
-        letterData = letters[i];
-        if (currentInd != letterData.anIndexes[j]) { // eslint-disable-line eqeqeq
-          currentInd = letterData.anIndexes[j];
-          newInd = indexes.splice(Math.floor(Math.random() * indexes.length), 1)[0];
-        }
-        letterData.anIndexes[j] = newInd;
-      }
-    }
-  }
-  documentData.yOffset = documentData.finalLineHeight || documentData.finalSize * 1.2;
-  documentData.ls = documentData.ls || 0;
-  documentData.ascent = (fontData.ascent * documentData.finalSize) / 100;
-};
+  function BaseEvent() {}
 
-TextProperty.prototype.updateDocumentData = function (newData, index) {
-  index = index === undefined ? this.keysIndex : index;
-  var dData = this.copyData({}, this.data.d.k[index].s);
-  dData = this.copyData(dData, newData);
-  this.data.d.k[index].s = dData;
-  this.recalculate(index);
-  this.elem.addDynamicProperty(this);
-};
+  BaseEvent.prototype = {
+    triggerEvent: function triggerEvent(eventName, args) {
+      if (this._cbs[eventName]) {
+        var callbacks = this._cbs[eventName];
 
-TextProperty.prototype.recalculate = function (index) {
-  var dData = this.data.d.k[index].s;
-  dData.__complete = false;
-  this.keysIndex = 0;
-  this._isFirstFrame = true;
-  this.getValue(dData);
-};
-
-TextProperty.prototype.canResizeFont = function (_canResize) {
-  this.canResize = _canResize;
-  this.recalculate(this.keysIndex);
-  this.elem.addDynamicProperty(this);
-};
-
-TextProperty.prototype.setMinimumFontSize = function (_fontValue) {
-  this.minimumFontSize = Math.floor(_fontValue) || 1;
-  this.recalculate(this.keysIndex);
-  this.elem.addDynamicProperty(this);
-};
-
-/* global extendPrototype, BezierFactory, PropertyFactory, DynamicPropertyContainer */
-/* exported TextSelectorProp */
-
-var TextSelectorProp = (function () {
-  var max = Math.max;
-  var min = Math.min;
-  var floor = Math.floor;
-
-  function TextSelectorPropFactory(elem, data) {
-    this._currentTextLength = -1;
-    this.k = false;
-    this.data = data;
-    this.elem = elem;
-    this.comp = elem.comp;
-    this.finalS = 0;
-    this.finalE = 0;
-    this.initDynamicPropertyContainer(elem);
-    this.s = PropertyFactory.getProp(elem, data.s || { k: 0 }, 0, 0, this);
-    if ('e' in data) {
-      this.e = PropertyFactory.getProp(elem, data.e, 0, 0, this);
-    } else {
-      this.e = { v: 100 };
-    }
-    this.o = PropertyFactory.getProp(elem, data.o || { k: 0 }, 0, 0, this);
-    this.xe = PropertyFactory.getProp(elem, data.xe || { k: 0 }, 0, 0, this);
-    this.ne = PropertyFactory.getProp(elem, data.ne || { k: 0 }, 0, 0, this);
-    this.sm = PropertyFactory.getProp(elem, data.sm || { k: 100 }, 0, 0, this);
-    this.a = PropertyFactory.getProp(elem, data.a, 0, 0.01, this);
-    if (!this.dynamicProperties.length) {
-      this.getValue();
-    }
-  }
-
-  TextSelectorPropFactory.prototype = {
-    getMult: function (ind) {
-      if (this._currentTextLength !== this.elem.textProperty.currentData.l.length) {
-        this.getValue();
-      }
-      // var easer = bez.getEasingCurve(this.ne.v/100,0,1-this.xe.v/100,1);
-      var x1 = 0;
-      var y1 = 0;
-      var x2 = 1;
-      var y2 = 1;
-      if (this.ne.v > 0) {
-        x1 = this.ne.v / 100.0;
-      } else {
-        y1 = -this.ne.v / 100.0;
-      }
-      if (this.xe.v > 0) {
-        x2 = 1.0 - this.xe.v / 100.0;
-      } else {
-        y2 = 1.0 + this.xe.v / 100.0;
-      }
-      var easer = BezierFactory.getBezierEasing(x1, y1, x2, y2).get;
-
-      var mult = 0;
-      var s = this.finalS;
-      var e = this.finalE;
-      var type = this.data.sh;
-      if (type === 2) {
-        if (e === s) {
-          mult = ind >= e ? 1 : 0;
-        } else {
-          mult = max(0, min(0.5 / (e - s) + (ind - s) / (e - s), 1));
-        }
-        mult = easer(mult);
-      } else if (type === 3) {
-        if (e === s) {
-          mult = ind >= e ? 0 : 1;
-        } else {
-          mult = 1 - max(0, min(0.5 / (e - s) + (ind - s) / (e - s), 1));
-        }
-
-        mult = easer(mult);
-      } else if (type === 4) {
-        if (e === s) {
-          mult = 0;
-        } else {
-          mult = max(0, min(0.5 / (e - s) + (ind - s) / (e - s), 1));
-          if (mult < 0.5) {
-            mult *= 2;
-          } else {
-            mult = 1 - 2 * (mult - 0.5);
-          }
-        }
-        mult = easer(mult);
-      } else if (type === 5) {
-        if (e === s) {
-          mult = 0;
-        } else {
-          var tot = e - s;
-          /* ind += 0.5;
-                    mult = -4/(tot*tot)*(ind*ind)+(4/tot)*ind; */
-          ind = min(max(0, ind + 0.5 - s), e - s);
-          var x = -tot / 2 + ind;
-          var a = tot / 2;
-          mult = Math.sqrt(1 - (x * x) / (a * a));
-        }
-        mult = easer(mult);
-      } else if (type === 6) {
-        if (e === s) {
-          mult = 0;
-        } else {
-          ind = min(max(0, ind + 0.5 - s), e - s);
-          mult = (1 + (Math.cos((Math.PI + Math.PI * 2 * (ind) / (e - s))))) / 2; // eslint-disable-line
-        }
-        mult = easer(mult);
-      } else {
-        if (ind >= floor(s)) {
-          if (ind - s < 0) {
-            mult = max(0, min(min(e, 1) - (s - ind), 1));
-          } else {
-            mult = max(0, min(e - ind, 1));
-          }
-        }
-        mult = easer(mult);
-      }
-      // Smoothness implementation.
-      // The smoothness represents a reduced range of the original [0; 1] range.
-      // if smoothness is 25%, the new range will be [0.375; 0.625]
-      // Steps are:
-      // - find the lower value of the new range (threshold)
-      // - if multiplier is smaller than that value, floor it to 0
-      // - if it is larger,
-      //     - subtract the threshold
-      //     - divide it by the smoothness (this will return the range to [0; 1])
-      // Note: If it doesn't work on some scenarios, consider applying it before the easer.
-      if (this.sm.v !== 100) {
-        var smoothness = this.sm.v * 0.01;
-        if (smoothness === 0) {
-          smoothness = 0.00000001;
-        }
-        var threshold = 0.5 - smoothness * 0.5;
-        if (mult < threshold) {
-          mult = 0;
-        } else {
-          mult = (mult - threshold) / smoothness;
-          if (mult > 1) {
-            mult = 1;
-          }
+        for (var i = 0; i < callbacks.length; i += 1) {
+          callbacks[i](args);
         }
       }
-      return mult * this.a.v;
     },
-    getValue: function (newCharsFlag) {
-      this.iterateDynamicProperties();
-      this._mdf = newCharsFlag || this._mdf;
-      this._currentTextLength = this.elem.textProperty.currentData.l.length || 0;
-      if (newCharsFlag && this.data.r === 2) {
-        this.e.v = this._currentTextLength;
+    addEventListener: function addEventListener(eventName, callback) {
+      if (!this._cbs[eventName]) {
+        this._cbs[eventName] = [];
       }
-      var divisor = this.data.r === 2 ? 1 : 100 / this.data.totalChars;
-      var o = this.o.v / divisor;
-      var s = this.s.v / divisor + o;
-      var e = (this.e.v / divisor) + o;
-      if (s > e) {
-        var _s = s;
-        s = e;
-        e = _s;
-      }
-      this.finalS = s;
-      this.finalE = e;
+
+      this._cbs[eventName].push(callback);
+
+      return function () {
+        this.removeEventListener(eventName, callback);
+      }.bind(this);
     },
-  };
-  extendPrototype([DynamicPropertyContainer], TextSelectorPropFactory);
+    removeEventListener: function removeEventListener(eventName, callback) {
+      if (!callback) {
+        this._cbs[eventName] = null;
+      } else if (this._cbs[eventName]) {
+        var i = 0;
+        var len = this._cbs[eventName].length;
 
-  function getTextSelectorProp(elem, data, arr) {
-    return new TextSelectorPropFactory(elem, data, arr);
-  }
+        while (i < len) {
+          if (this._cbs[eventName][i] === callback) {
+            this._cbs[eventName].splice(i, 1);
 
-  return {
-    getTextSelectorProp: getTextSelectorProp,
-  };
-}());
+            i -= 1;
+            len -= 1;
+          }
 
-/* global createSizedArray, pooling */
-/* exported poolFactory */
+          i += 1;
+        }
 
-var poolFactory = (function () {
-  return function (initialLength, _create, _release) {
-    var _length = 0;
-    var _maxLength = initialLength;
-    var pool = createSizedArray(_maxLength);
-
-    var ob = {
-      newElement: newElement,
-      release: release,
-    };
-
-    function newElement() {
-      var element;
-      if (_length) {
-        _length -= 1;
-        element = pool[_length];
-      } else {
-        element = _create();
+        if (!this._cbs[eventName].length) {
+          this._cbs[eventName] = null;
+        }
       }
-      return element;
     }
-
-    function release(element) {
-      if (_length === _maxLength) {
-        pool = pooling.double(pool);
-        _maxLength *= 2;
-      }
-      if (_release) {
-        _release(element);
-      }
-      pool[_length] = element;
-      _length += 1;
-    }
-
-    return ob;
-  };
-}());
-
-/* global createSizedArray */
-/* exported pooling */
-
-var pooling = (function () {
-  function double(arr) {
-    return arr.concat(createSizedArray(arr.length));
-  }
-
-  return {
-    double: double,
-  };
-}());
-
-/* global createTypedArray, poolFactory */
-/* exported pointPool */
-
-var pointPool = (function () {
-  function create() {
-    return createTypedArray('float32', 2);
-  }
-  return poolFactory(8, create);
-}());
-
-/* global ShapePath, pointPool, poolFactory */
-/* exported shapePool */
-
-var shapePool = (function () {
-  function create() {
-    return new ShapePath();
-  }
-
-  function release(shapePath) {
-    var len = shapePath._length;
-    var i;
-    for (i = 0; i < len; i += 1) {
-      pointPool.release(shapePath.v[i]);
-      pointPool.release(shapePath.i[i]);
-      pointPool.release(shapePath.o[i]);
-      shapePath.v[i] = null;
-      shapePath.i[i] = null;
-      shapePath.o[i] = null;
-    }
-    shapePath._length = 0;
-    shapePath.c = false;
-  }
-
-  function clone(shape) {
-    var cloned = factory.newElement();
-    var i;
-    var len = shape._length === undefined ? shape.v.length : shape._length;
-    cloned.setLength(len);
-    cloned.c = shape.c;
-
-    for (i = 0; i < len; i += 1) {
-      cloned.setTripleAt(shape.v[i][0], shape.v[i][1], shape.o[i][0], shape.o[i][1], shape.i[i][0], shape.i[i][1], i);
-    }
-    return cloned;
-  }
-
-  var factory = poolFactory(4, create, release);
-  factory.clone = clone;
-
-  return factory;
-}());
-
-/* global createSizedArray, ShapeCollection, shapePool, pooling */
-/* exported shapeCollectionPool */
-
-var shapeCollectionPool = (function () {
-  var ob = {
-    newShapeCollection: newShapeCollection,
-    release: release,
   };
 
-  var _length = 0;
-  var _maxLength = 4;
-  var pool = createSizedArray(_maxLength);
-
-  function newShapeCollection() {
-    var shapeCollection;
-    if (_length) {
-      _length -= 1;
-      shapeCollection = pool[_length];
-    } else {
-      shapeCollection = new ShapeCollection();
-    }
-    return shapeCollection;
-  }
-
-  function release(shapeCollection) {
-    var i;
-    var len = shapeCollection._length;
-    for (i = 0; i < len; i += 1) {
-      shapePool.release(shapeCollection.shapes[i]);
-    }
-    shapeCollection._length = 0;
-
-    if (_length === _maxLength) {
-      pool = pooling.double(pool);
-      _maxLength *= 2;
-    }
-    pool[_length] = shapeCollection;
-    _length += 1;
-  }
-
-  return ob;
-}());
-
-/* global poolFactory, bezierLengthPool */
-/* exported segmentsLengthPool */
-
-var segmentsLengthPool = (function () {
-  function create() {
-    return {
-      lengths: [],
-      totalLength: 0,
-    };
-  }
-
-  function release(element) {
-    var i;
-    var len = element.lengths.length;
-    for (i = 0; i < len; i += 1) {
-      bezierLengthPool.release(element.lengths[i]);
-    }
-    element.lengths.length = 0;
-  }
-
-  return poolFactory(8, create, release);
-}());
-
-/* global createTypedArray, defaultCurveSegments, poolFactory */
-/* exported bezierLengthPool */
-
-var bezierLengthPool = (function () {
-  function create() {
-    return {
-      addedLength: 0,
-      percents: createTypedArray('float32', defaultCurveSegments),
-      lengths: createTypedArray('float32', defaultCurveSegments),
-    };
-  }
-  return poolFactory(8, create);
-}());
-
-/* exported markerParser */
-
-var markerParser = (
-
-  function () {
+  var markerParser = function () {
     function parsePayloadLines(payload) {
       var lines = payload.split('\r\n');
       var keys = {};
       var line;
       var keysCount = 0;
+
       for (var i = 0; i < lines.length; i += 1) {
         line = lines[i].split(':');
+
         if (line.length === 2) {
           keys[line[0]] = line[1].trim();
           keysCount += 1;
         }
       }
+
       if (keysCount === 0) {
         throw new Error();
       }
+
       return keys;
     }
 
     return function (_markers) {
       var markers = [];
+
       for (var i = 0; i < _markers.length; i += 1) {
         var _marker = _markers[i];
         var markerData = {
           time: _marker.tm,
-          duration: _marker.dr,
+          duration: _marker.dr
         };
+
         try {
           markerData.payload = JSON.parse(_markers[i].cm);
         } catch (_) {
@@ -6774,8212 +1620,6062 @@
             markerData.payload = parsePayloadLines(_markers[i].cm);
           } catch (__) {
             markerData.payload = {
-              name: _markers[i],
+              name: _markers[i]
             };
           }
         }
+
         markers.push(markerData);
       }
+
       return markers;
     };
-  }());
+  }();
 
-/* global AudioElement, FootageElement, FontManager */
-
-function BaseRenderer() {}
-BaseRenderer.prototype.checkLayers = function (num) {
-  var i;
-  var len = this.layers.length;
-  var data;
-  this.completeLayers = true;
-  for (i = len - 1; i >= 0; i -= 1) {
-    if (!this.elements[i]) {
-      data = this.layers[i];
-      if (data.ip - data.st <= (num - this.layers[i].st) && data.op - data.st > (num - this.layers[i].st)) {
-        this.buildItem(i);
-      }
+  var ProjectInterface = function () {
+    function registerComposition(comp) {
+      this.compositions.push(comp);
     }
-    this.completeLayers = this.elements[i] ? this.completeLayers : false;
-  }
-  this.checkPendingElements();
-};
 
-BaseRenderer.prototype.createItem = function (layer) {
-  switch (layer.ty) {
-    case 2:
-      return this.createImage(layer);
-    case 0:
-      return this.createComp(layer);
-    case 1:
-      return this.createSolid(layer);
-    case 3:
-      return this.createNull(layer);
-    case 4:
-      return this.createShape(layer);
-    case 5:
-      return this.createText(layer);
-    case 6:
-      return this.createAudio(layer);
-    case 13:
-      return this.createCamera(layer);
-    case 15:
-      return this.createFootage(layer);
-    default:
-      return this.createNull(layer);
-  }
-};
+    return function () {
+      function _thisProjectFunction(name) {
+        var i = 0;
+        var len = this.compositions.length;
 
-BaseRenderer.prototype.createCamera = function () {
-  throw new Error('You\'re using a 3d camera. Try the html renderer.');
-};
+        while (i < len) {
+          if (this.compositions[i].data && this.compositions[i].data.nm === name) {
+            if (this.compositions[i].prepareFrame && this.compositions[i].data.xt) {
+              this.compositions[i].prepareFrame(this.currentFrame);
+            }
 
-BaseRenderer.prototype.createAudio = function (data) {
-  return new AudioElement(data, this.globalData, this);
-};
+            return this.compositions[i].compInterface;
+          }
 
-BaseRenderer.prototype.createFootage = function (data) {
-  return new FootageElement(data, this.globalData, this);
-};
-
-BaseRenderer.prototype.buildAllItems = function () {
-  var i;
-  var len = this.layers.length;
-  for (i = 0; i < len; i += 1) {
-    this.buildItem(i);
-  }
-  this.checkPendingElements();
-};
-
-BaseRenderer.prototype.includeLayers = function (newLayers) {
-  this.completeLayers = false;
-  var i;
-  var len = newLayers.length;
-  var j;
-  var jLen = this.layers.length;
-  for (i = 0; i < len; i += 1) {
-    j = 0;
-    while (j < jLen) {
-      if (this.layers[j].id === newLayers[i].id) {
-        this.layers[j] = newLayers[i];
-        break;
-      }
-      j += 1;
-    }
-  }
-};
-
-BaseRenderer.prototype.setProjectInterface = function (pInterface) {
-  this.globalData.projectInterface = pInterface;
-};
-
-BaseRenderer.prototype.initItems = function () {
-  if (!this.globalData.progressiveLoad) {
-    this.buildAllItems();
-  }
-};
-BaseRenderer.prototype.buildElementParenting = function (element, parentName, hierarchy) {
-  var elements = this.elements;
-  var layers = this.layers;
-  var i = 0;
-  var len = layers.length;
-  while (i < len) {
-    if (layers[i].ind == parentName) { // eslint-disable-line eqeqeq
-      if (!elements[i] || elements[i] === true) {
-        this.buildItem(i);
-        this.addPendingElement(element);
-      } else {
-        hierarchy.push(elements[i]);
-        elements[i].setAsParent();
-        if (layers[i].parent !== undefined) {
-          this.buildElementParenting(element, layers[i].parent, hierarchy);
-        } else {
-          element.setHierarchy(hierarchy);
+          i += 1;
         }
+
+        return null;
+      }
+
+      _thisProjectFunction.compositions = [];
+      _thisProjectFunction.currentFrame = 0;
+      _thisProjectFunction.registerComposition = registerComposition;
+      return _thisProjectFunction;
+    };
+  }();
+
+  var renderers = {};
+
+  var registerRenderer = function registerRenderer(key, value) {
+    renderers[key] = value;
+  };
+
+  function getRenderer(key) {
+    return renderers[key];
+  }
+
+  function _typeof$4(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof$4 = function _typeof(obj) { return typeof obj; }; } else { _typeof$4 = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof$4(obj); }
+
+  var AnimationItem = function AnimationItem() {
+    this._cbs = [];
+    this.name = '';
+    this.path = '';
+    this.isLoaded = false;
+    this.currentFrame = 0;
+    this.currentRawFrame = 0;
+    this.firstFrame = 0;
+    this.totalFrames = 0;
+    this.frameRate = 0;
+    this.frameMult = 0;
+    this.playSpeed = 1;
+    this.playDirection = 1;
+    this.playCount = 0;
+    this.animationData = {};
+    this.assets = [];
+    this.isPaused = true;
+    this.autoplay = false;
+    this.loop = true;
+    this.renderer = null;
+    this.animationID = createElementID();
+    this.assetsPath = '';
+    this.timeCompleted = 0;
+    this.segmentPos = 0;
+    this.isSubframeEnabled = getSubframeEnabled();
+    this.segments = [];
+    this._idle = true;
+    this._completedLoop = false;
+    this.projectInterface = ProjectInterface();
+    this.imagePreloader = new ImagePreloader();
+    this.audioController = audioControllerFactory();
+    this.markers = [];
+    this.configAnimation = this.configAnimation.bind(this);
+    this.onSetupError = this.onSetupError.bind(this);
+    this.onSegmentComplete = this.onSegmentComplete.bind(this);
+  };
+
+  extendPrototype([BaseEvent], AnimationItem);
+
+  AnimationItem.prototype.setParams = function (params) {
+    if (params.wrapper || params.container) {
+      this.wrapper = params.wrapper || params.container;
+    }
+
+    var animType = 'svg';
+
+    if (params.animType) {
+      animType = params.animType;
+    } else if (params.renderer) {
+      animType = params.renderer;
+    }
+
+    var RendererClass = getRenderer(animType);
+    this.renderer = new RendererClass(this, params.rendererSettings);
+    this.imagePreloader.setCacheType(animType, this.renderer.globalData.defs);
+    this.renderer.setProjectInterface(this.projectInterface);
+    this.animType = animType;
+
+    if (params.loop === '' || params.loop === null || params.loop === undefined || params.loop === true) {
+      this.loop = true;
+    } else if (params.loop === false) {
+      this.loop = false;
+    } else {
+      this.loop = parseInt(params.loop, 10);
+    }
+
+    this.autoplay = 'autoplay' in params ? params.autoplay : true;
+    this.name = params.name ? params.name : '';
+    this.autoloadSegments = Object.prototype.hasOwnProperty.call(params, 'autoloadSegments') ? params.autoloadSegments : true;
+    this.assetsPath = params.assetsPath;
+    this.initialSegment = params.initialSegment;
+
+    if (params.audioFactory) {
+      this.audioController.setAudioFactory(params.audioFactory);
+    }
+
+    if (params.animationData) {
+      this.setupAnimation(params.animationData);
+    } else if (params.path) {
+      if (params.path.lastIndexOf('\\') !== -1) {
+        this.path = params.path.substr(0, params.path.lastIndexOf('\\') + 1);
+      } else {
+        this.path = params.path.substr(0, params.path.lastIndexOf('/') + 1);
+      }
+
+      this.fileName = params.path.substr(params.path.lastIndexOf('/') + 1);
+      this.fileName = this.fileName.substr(0, this.fileName.lastIndexOf('.json'));
+      dataManager.loadAnimation(params.path, this.configAnimation, this.onSetupError);
+    }
+  };
+
+  AnimationItem.prototype.onSetupError = function () {
+    this.trigger('data_failed');
+  };
+
+  AnimationItem.prototype.setupAnimation = function (data) {
+    dataManager.completeAnimation(data, this.configAnimation);
+  };
+
+  AnimationItem.prototype.setData = function (wrapper, animationData) {
+    if (animationData) {
+      if (_typeof$4(animationData) !== 'object') {
+        animationData = JSON.parse(animationData);
       }
     }
-    i += 1;
-  }
-};
 
-BaseRenderer.prototype.addPendingElement = function (element) {
-  this.pendingElements.push(element);
-};
+    var params = {
+      wrapper: wrapper,
+      animationData: animationData
+    };
+    var wrapperAttributes = wrapper.attributes;
+    params.path = wrapperAttributes.getNamedItem('data-animation-path') // eslint-disable-line no-nested-ternary
+    ? wrapperAttributes.getNamedItem('data-animation-path').value : wrapperAttributes.getNamedItem('data-bm-path') // eslint-disable-line no-nested-ternary
+    ? wrapperAttributes.getNamedItem('data-bm-path').value : wrapperAttributes.getNamedItem('bm-path') ? wrapperAttributes.getNamedItem('bm-path').value : '';
+    params.animType = wrapperAttributes.getNamedItem('data-anim-type') // eslint-disable-line no-nested-ternary
+    ? wrapperAttributes.getNamedItem('data-anim-type').value : wrapperAttributes.getNamedItem('data-bm-type') // eslint-disable-line no-nested-ternary
+    ? wrapperAttributes.getNamedItem('data-bm-type').value : wrapperAttributes.getNamedItem('bm-type') // eslint-disable-line no-nested-ternary
+    ? wrapperAttributes.getNamedItem('bm-type').value : wrapperAttributes.getNamedItem('data-bm-renderer') // eslint-disable-line no-nested-ternary
+    ? wrapperAttributes.getNamedItem('data-bm-renderer').value : wrapperAttributes.getNamedItem('bm-renderer') ? wrapperAttributes.getNamedItem('bm-renderer').value : 'canvas';
+    var loop = wrapperAttributes.getNamedItem('data-anim-loop') // eslint-disable-line no-nested-ternary
+    ? wrapperAttributes.getNamedItem('data-anim-loop').value : wrapperAttributes.getNamedItem('data-bm-loop') // eslint-disable-line no-nested-ternary
+    ? wrapperAttributes.getNamedItem('data-bm-loop').value : wrapperAttributes.getNamedItem('bm-loop') ? wrapperAttributes.getNamedItem('bm-loop').value : '';
 
-BaseRenderer.prototype.searchExtraCompositions = function (assets) {
-  var i;
-  var len = assets.length;
-  for (i = 0; i < len; i += 1) {
-    if (assets[i].xt) {
-      var comp = this.createComp(assets[i]);
-      comp.initExpressions();
-      this.globalData.projectInterface.registerComposition(comp);
+    if (loop === 'false') {
+      params.loop = false;
+    } else if (loop === 'true') {
+      params.loop = true;
+    } else if (loop !== '') {
+      params.loop = parseInt(loop, 10);
     }
-  }
-};
 
-BaseRenderer.prototype.setupGlobalData = function (animData, fontsContainer) {
-  this.globalData.fontManager = new FontManager();
-  this.globalData.fontManager.addChars(animData.chars);
-  this.globalData.fontManager.addFonts(animData.fonts, fontsContainer);
-  this.globalData.getAssetData = this.animationItem.getAssetData.bind(this.animationItem);
-  this.globalData.getAssetsPath = this.animationItem.getAssetsPath.bind(this.animationItem);
-  this.globalData.imageLoader = this.animationItem.imagePreloader;
-  this.globalData.audioController = this.animationItem.audioController;
-  this.globalData.frameId = 0;
-  this.globalData.frameRate = animData.fr;
-  this.globalData.nm = animData.nm;
-  this.globalData.compSize = {
-    w: animData.w,
-    h: animData.h,
-  };
-};
+    var autoplay = wrapperAttributes.getNamedItem('data-anim-autoplay') // eslint-disable-line no-nested-ternary
+    ? wrapperAttributes.getNamedItem('data-anim-autoplay').value : wrapperAttributes.getNamedItem('data-bm-autoplay') // eslint-disable-line no-nested-ternary
+    ? wrapperAttributes.getNamedItem('data-bm-autoplay').value : wrapperAttributes.getNamedItem('bm-autoplay') ? wrapperAttributes.getNamedItem('bm-autoplay').value : true;
+    params.autoplay = autoplay !== 'false';
+    params.name = wrapperAttributes.getNamedItem('data-name') // eslint-disable-line no-nested-ternary
+    ? wrapperAttributes.getNamedItem('data-name').value : wrapperAttributes.getNamedItem('data-bm-name') // eslint-disable-line no-nested-ternary
+    ? wrapperAttributes.getNamedItem('data-bm-name').value : wrapperAttributes.getNamedItem('bm-name') ? wrapperAttributes.getNamedItem('bm-name').value : '';
+    var prerender = wrapperAttributes.getNamedItem('data-anim-prerender') // eslint-disable-line no-nested-ternary
+    ? wrapperAttributes.getNamedItem('data-anim-prerender').value : wrapperAttributes.getNamedItem('data-bm-prerender') // eslint-disable-line no-nested-ternary
+    ? wrapperAttributes.getNamedItem('data-bm-prerender').value : wrapperAttributes.getNamedItem('bm-prerender') ? wrapperAttributes.getNamedItem('bm-prerender').value : '';
 
-/* global createElementID, extendPrototype, BaseRenderer, NullElement, SVGShapeElement, SVGTextLottieElement,
-IImageElement, SVGCompElement, ISolidElement, createNS, locationHref, createSizedArray, expressionsPlugin */
+    if (prerender === 'false') {
+      params.prerender = false;
+    }
 
-function SVGRenderer(animationItem, config) {
-  this.animationItem = animationItem;
-  this.layers = null;
-  this.renderedFrame = -1;
-  this.svgElement = createNS('svg');
-  var ariaLabel = '';
-  if (config && config.title) {
-    var titleElement = createNS('title');
-    var titleId = createElementID();
-    titleElement.setAttribute('id', titleId);
-    titleElement.textContent = config.title;
-    this.svgElement.appendChild(titleElement);
-    ariaLabel += titleId;
-  }
-  if (config && config.description) {
-    var descElement = createNS('desc');
-    var descId = createElementID();
-    descElement.setAttribute('id', descId);
-    descElement.textContent = config.description;
-    this.svgElement.appendChild(descElement);
-    ariaLabel += ' ' + descId;
-  }
-  if (ariaLabel) {
-    this.svgElement.setAttribute('aria-labelledby', ariaLabel);
-  }
-  var defs = createNS('defs');
-  this.svgElement.appendChild(defs);
-  var maskElement = createNS('g');
-  this.svgElement.appendChild(maskElement);
-  this.layerElement = maskElement;
-  this.renderConfig = {
-    preserveAspectRatio: (config && config.preserveAspectRatio) || 'xMidYMid meet',
-    imagePreserveAspectRatio: (config && config.imagePreserveAspectRatio) || 'xMidYMid slice',
-    contentVisibility: (config && config.contentVisibility) || 'visible',
-    progressiveLoad: (config && config.progressiveLoad) || false,
-    hideOnTransparent: !((config && config.hideOnTransparent === false)),
-    viewBoxOnly: (config && config.viewBoxOnly) || false,
-    viewBoxSize: (config && config.viewBoxSize) || false,
-    className: (config && config.className) || '',
-    id: (config && config.id) || '',
-    focusable: config && config.focusable,
-    filterSize: {
-      width: (config && config.filterSize && config.filterSize.width) || '100%',
-      height: (config && config.filterSize && config.filterSize.height) || '100%',
-      x: (config && config.filterSize && config.filterSize.x) || '0%',
-      y: (config && config.filterSize && config.filterSize.y) || '0%',
-    },
+    this.setParams(params);
   };
 
-  this.globalData = {
-    _mdf: false,
-    frameNum: -1,
-    defs: defs,
-    renderConfig: this.renderConfig,
-  };
-  this.elements = [];
-  this.pendingElements = [];
-  this.destroyed = false;
-  this.rendererType = 'svg';
-}
-
-extendPrototype([BaseRenderer], SVGRenderer);
-
-SVGRenderer.prototype.createNull = function (data) {
-  return new NullElement(data, this.globalData, this);
-};
-
-SVGRenderer.prototype.createShape = function (data) {
-  return new SVGShapeElement(data, this.globalData, this);
-};
-
-SVGRenderer.prototype.createText = function (data) {
-  return new SVGTextLottieElement(data, this.globalData, this);
-};
-
-SVGRenderer.prototype.createImage = function (data) {
-  return new IImageElement(data, this.globalData, this);
-};
-
-SVGRenderer.prototype.createComp = function (data) {
-  return new SVGCompElement(data, this.globalData, this);
-};
-
-SVGRenderer.prototype.createSolid = function (data) {
-  return new ISolidElement(data, this.globalData, this);
-};
-
-SVGRenderer.prototype.configAnimation = function (animData) {
-  this.svgElement.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
-  if (this.renderConfig.viewBoxSize) {
-    this.svgElement.setAttribute('viewBox', this.renderConfig.viewBoxSize);
-  } else {
-    this.svgElement.setAttribute('viewBox', '0 0 ' + animData.w + ' ' + animData.h);
-  }
-
-  if (!this.renderConfig.viewBoxOnly) {
-    this.svgElement.setAttribute('width', animData.w);
-    this.svgElement.setAttribute('height', animData.h);
-    this.svgElement.style.width = '100%';
-    this.svgElement.style.height = '100%';
-    this.svgElement.style.transform = 'translate3d(0,0,0)';
-    this.svgElement.style.contentVisibility = this.renderConfig.contentVisibility;
-  }
-  if (this.renderConfig.className) {
-    this.svgElement.setAttribute('class', this.renderConfig.className);
-  }
-  if (this.renderConfig.id) {
-    this.svgElement.setAttribute('id', this.renderConfig.id);
-  }
-  if (this.renderConfig.focusable !== undefined) {
-    this.svgElement.setAttribute('focusable', this.renderConfig.focusable);
-  }
-  this.svgElement.setAttribute('preserveAspectRatio', this.renderConfig.preserveAspectRatio);
-  // this.layerElement.style.transform = 'translate3d(0,0,0)';
-  // this.layerElement.style.transformOrigin = this.layerElement.style.mozTransformOrigin = this.layerElement.style.webkitTransformOrigin = this.layerElement.style['-webkit-transform'] = "0px 0px 0px";
-  this.animationItem.wrapper.appendChild(this.svgElement);
-  // Mask animation
-  var defs = this.globalData.defs;
-
-  this.setupGlobalData(animData, defs);
-  this.globalData.progressiveLoad = this.renderConfig.progressiveLoad;
-  this.data = animData;
-
-  var maskElement = createNS('clipPath');
-  var rect = createNS('rect');
-  rect.setAttribute('width', animData.w);
-  rect.setAttribute('height', animData.h);
-  rect.setAttribute('x', 0);
-  rect.setAttribute('y', 0);
-  var maskId = createElementID();
-  maskElement.setAttribute('id', maskId);
-  maskElement.appendChild(rect);
-  this.layerElement.setAttribute('clip-path', 'url(' + locationHref + '#' + maskId + ')');
-
-  defs.appendChild(maskElement);
-  this.layers = animData.layers;
-  this.elements = createSizedArray(animData.layers.length);
-};
-
-SVGRenderer.prototype.destroy = function () {
-  if (this.animationItem.wrapper) {
-    this.animationItem.wrapper.innerText = '';
-  }
-  this.layerElement = null;
-  this.globalData.defs = null;
-  var i;
-  var len = this.layers ? this.layers.length : 0;
-  for (i = 0; i < len; i += 1) {
-    if (this.elements[i]) {
-      this.elements[i].destroy();
+  AnimationItem.prototype.includeLayers = function (data) {
+    if (data.op > this.animationData.op) {
+      this.animationData.op = data.op;
+      this.totalFrames = Math.floor(data.op - this.animationData.ip);
     }
-  }
-  this.elements.length = 0;
-  this.destroyed = true;
-  this.animationItem = null;
-};
 
-SVGRenderer.prototype.updateContainerSize = function () {
-};
+    var layers = this.animationData.layers;
+    var i;
+    var len = layers.length;
+    var newLayers = data.layers;
+    var j;
+    var jLen = newLayers.length;
 
-SVGRenderer.prototype.buildItem = function (pos) {
-  var elements = this.elements;
-  if (elements[pos] || this.layers[pos].ty === 99) {
-    return;
-  }
-  elements[pos] = true;
-  var element = this.createItem(this.layers[pos]);
+    for (j = 0; j < jLen; j += 1) {
+      i = 0;
 
-  elements[pos] = element;
-  if (expressionsPlugin) {
-    if (this.layers[pos].ty === 0) {
-      this.globalData.projectInterface.registerComposition(element);
-    }
-    element.initExpressions();
-  }
-  this.appendElementInPos(element, pos);
-  if (this.layers[pos].tt) {
-    if (!this.elements[pos - 1] || this.elements[pos - 1] === true) {
-      this.buildItem(pos - 1);
-      this.addPendingElement(element);
-    } else {
-      element.setMatte(elements[pos - 1].layerId);
-    }
-  }
-};
-
-SVGRenderer.prototype.checkPendingElements = function () {
-  while (this.pendingElements.length) {
-    var element = this.pendingElements.pop();
-    element.checkParenting();
-    if (element.data.tt) {
-      var i = 0;
-      var len = this.elements.length;
       while (i < len) {
-        if (this.elements[i] === element) {
-          element.setMatte(this.elements[i - 1].layerId);
+        if (layers[i].id === newLayers[j].id) {
+          layers[i] = newLayers[j];
           break;
         }
+
         i += 1;
       }
     }
-  }
-};
 
-SVGRenderer.prototype.renderFrame = function (num) {
-  if (this.renderedFrame === num || this.destroyed) {
-    return;
-  }
-  if (num === null) {
-    num = this.renderedFrame;
-  } else {
-    this.renderedFrame = num;
-  }
-  // console.log('-------');
-  // console.log('FRAME ',num);
-  this.globalData.frameNum = num;
-  this.globalData.frameId += 1;
-  this.globalData.projectInterface.currentFrame = num;
-  this.globalData._mdf = false;
-  var i;
-  var len = this.layers.length;
-  if (!this.completeLayers) {
-    this.checkLayers(num);
-  }
-  for (i = len - 1; i >= 0; i -= 1) {
-    if (this.completeLayers || this.elements[i]) {
-      this.elements[i].prepareFrame(num - this.layers[i].st);
+    if (data.chars || data.fonts) {
+      this.renderer.globalData.fontManager.addChars(data.chars);
+      this.renderer.globalData.fontManager.addFonts(data.fonts, this.renderer.globalData.defs);
     }
-  }
-  if (this.globalData._mdf) {
-    for (i = 0; i < len; i += 1) {
-      if (this.completeLayers || this.elements[i]) {
-        this.elements[i].renderFrame();
+
+    if (data.assets) {
+      len = data.assets.length;
+
+      for (i = 0; i < len; i += 1) {
+        this.animationData.assets.push(data.assets[i]);
       }
     }
-  }
-};
 
-SVGRenderer.prototype.appendElementInPos = function (element, pos) {
-  var newElement = element.getBaseElement();
-  if (!newElement) {
-    return;
-  }
-  var i = 0;
-  var nextElement;
-  while (i < pos) {
-    if (this.elements[i] && this.elements[i] !== true && this.elements[i].getBaseElement()) {
-      nextElement = this.elements[i].getBaseElement();
-    }
-    i += 1;
-  }
-  if (nextElement) {
-    this.layerElement.insertBefore(newElement, nextElement);
-  } else {
-    this.layerElement.appendChild(newElement);
-  }
-};
-
-SVGRenderer.prototype.hide = function () {
-  this.layerElement.style.display = 'none';
-};
-
-SVGRenderer.prototype.show = function () {
-  this.layerElement.style.display = 'block';
-};
-
-/* global CVContextData, Matrix, extendPrototype, BaseRenderer, CVShapeElement, CVTextElement,
-CVImageElement, CVCompElement, CVSolidElement, SVGRenderer, createTag, createSizedArray */
-
-function CanvasRenderer(animationItem, config) {
-  this.animationItem = animationItem;
-  this.renderConfig = {
-    clearCanvas: (config && config.clearCanvas !== undefined) ? config.clearCanvas : true,
-    context: (config && config.context) || null,
-    progressiveLoad: (config && config.progressiveLoad) || false,
-    preserveAspectRatio: (config && config.preserveAspectRatio) || 'xMidYMid meet',
-    imagePreserveAspectRatio: (config && config.imagePreserveAspectRatio) || 'xMidYMid slice',
-    contentVisibility: (config && config.contentVisibility) || 'visible',
-    className: (config && config.className) || '',
-    id: (config && config.id) || '',
+    this.animationData.__complete = false;
+    dataManager.completeAnimation(this.animationData, this.onSegmentComplete);
   };
-  this.renderConfig.dpr = (config && config.dpr) || 1;
-  if (this.animationItem.wrapper) {
-    this.renderConfig.dpr = (config && config.dpr) || window.devicePixelRatio || 1;
-  }
-  this.renderedFrame = -1;
-  this.globalData = {
-    frameNum: -1,
-    _mdf: false,
-    renderConfig: this.renderConfig,
-    currentGlobalAlpha: -1,
+
+  AnimationItem.prototype.onSegmentComplete = function (data) {
+    this.animationData = data;
+    var expressionsPlugin = getExpressionsPlugin();
+
+    if (expressionsPlugin) {
+      expressionsPlugin.initExpressions(this);
+    }
+
+    this.loadNextSegment();
   };
-  this.contextData = new CVContextData();
-  this.elements = [];
-  this.pendingElements = [];
-  this.transformMat = new Matrix();
-  this.completeLayers = false;
-  this.rendererType = 'canvas';
-}
-extendPrototype([BaseRenderer], CanvasRenderer);
 
-CanvasRenderer.prototype.createShape = function (data) {
-  return new CVShapeElement(data, this.globalData, this);
-};
+  AnimationItem.prototype.loadNextSegment = function () {
+    var segments = this.animationData.segments;
 
-CanvasRenderer.prototype.createText = function (data) {
-  return new CVTextElement(data, this.globalData, this);
-};
-
-CanvasRenderer.prototype.createImage = function (data) {
-  return new CVImageElement(data, this.globalData, this);
-};
-
-CanvasRenderer.prototype.createComp = function (data) {
-  return new CVCompElement(data, this.globalData, this);
-};
-
-CanvasRenderer.prototype.createSolid = function (data) {
-  return new CVSolidElement(data, this.globalData, this);
-};
-
-CanvasRenderer.prototype.createNull = SVGRenderer.prototype.createNull;
-
-CanvasRenderer.prototype.ctxTransform = function (props) {
-  if (props[0] === 1 && props[1] === 0 && props[4] === 0 && props[5] === 1 && props[12] === 0 && props[13] === 0) {
-    return;
-  }
-  if (!this.renderConfig.clearCanvas) {
-    this.canvasContext.transform(props[0], props[1], props[4], props[5], props[12], props[13]);
-    return;
-  }
-  this.transformMat.cloneFromProps(props);
-  var cProps = this.contextData.cTr.props;
-  this.transformMat.transform(cProps[0], cProps[1], cProps[2], cProps[3], cProps[4], cProps[5], cProps[6], cProps[7], cProps[8], cProps[9], cProps[10], cProps[11], cProps[12], cProps[13], cProps[14], cProps[15]);
-  // this.contextData.cTr.transform(props[0],props[1],props[2],props[3],props[4],props[5],props[6],props[7],props[8],props[9],props[10],props[11],props[12],props[13],props[14],props[15]);
-  this.contextData.cTr.cloneFromProps(this.transformMat.props);
-  var trProps = this.contextData.cTr.props;
-  this.canvasContext.setTransform(trProps[0], trProps[1], trProps[4], trProps[5], trProps[12], trProps[13]);
-};
-
-CanvasRenderer.prototype.ctxOpacity = function (op) {
-  /* if(op === 1){
-        return;
-    } */
-  if (!this.renderConfig.clearCanvas) {
-    this.canvasContext.globalAlpha *= op < 0 ? 0 : op;
-    this.globalData.currentGlobalAlpha = this.contextData.cO;
-    return;
-  }
-  this.contextData.cO *= op < 0 ? 0 : op;
-  if (this.globalData.currentGlobalAlpha !== this.contextData.cO) {
-    this.canvasContext.globalAlpha = this.contextData.cO;
-    this.globalData.currentGlobalAlpha = this.contextData.cO;
-  }
-};
-
-CanvasRenderer.prototype.reset = function () {
-  if (!this.renderConfig.clearCanvas) {
-    this.canvasContext.restore();
-    return;
-  }
-  this.contextData.reset();
-};
-
-CanvasRenderer.prototype.save = function (actionFlag) {
-  if (!this.renderConfig.clearCanvas) {
-    this.canvasContext.save();
-    return;
-  }
-  if (actionFlag) {
-    this.canvasContext.save();
-  }
-  var props = this.contextData.cTr.props;
-  if (this.contextData._length <= this.contextData.cArrPos) {
-    this.contextData.duplicate();
-  }
-  var i;
-  var arr = this.contextData.saved[this.contextData.cArrPos];
-  for (i = 0; i < 16; i += 1) {
-    arr[i] = props[i];
-  }
-  this.contextData.savedOp[this.contextData.cArrPos] = this.contextData.cO;
-  this.contextData.cArrPos += 1;
-};
-
-CanvasRenderer.prototype.restore = function (actionFlag) {
-  if (!this.renderConfig.clearCanvas) {
-    this.canvasContext.restore();
-    return;
-  }
-  if (actionFlag) {
-    this.canvasContext.restore();
-    this.globalData.blendMode = 'source-over';
-  }
-  this.contextData.cArrPos -= 1;
-  var popped = this.contextData.saved[this.contextData.cArrPos];
-  var i;
-  var arr = this.contextData.cTr.props;
-  for (i = 0; i < 16; i += 1) {
-    arr[i] = popped[i];
-  }
-  this.canvasContext.setTransform(popped[0], popped[1], popped[4], popped[5], popped[12], popped[13]);
-  popped = this.contextData.savedOp[this.contextData.cArrPos];
-  this.contextData.cO = popped;
-  if (this.globalData.currentGlobalAlpha !== popped) {
-    this.canvasContext.globalAlpha = popped;
-    this.globalData.currentGlobalAlpha = popped;
-  }
-};
-
-CanvasRenderer.prototype.configAnimation = function (animData) {
-  if (this.animationItem.wrapper) {
-    this.animationItem.container = createTag('canvas');
-    var containerStyle = this.animationItem.container.style;
-    containerStyle.width = '100%';
-    containerStyle.height = '100%';
-    var origin = '0px 0px 0px';
-    containerStyle.transformOrigin = origin;
-    containerStyle.mozTransformOrigin = origin;
-    containerStyle.webkitTransformOrigin = origin;
-    containerStyle['-webkit-transform'] = origin;
-    containerStyle.contentVisibility = this.renderConfig.contentVisibility;
-    this.animationItem.wrapper.appendChild(this.animationItem.container);
-    this.canvasContext = this.animationItem.container.getContext('2d');
-    if (this.renderConfig.className) {
-      this.animationItem.container.setAttribute('class', this.renderConfig.className);
+    if (!segments || segments.length === 0 || !this.autoloadSegments) {
+      this.trigger('data_ready');
+      this.timeCompleted = this.totalFrames;
+      return;
     }
-    if (this.renderConfig.id) {
-      this.animationItem.container.setAttribute('id', this.renderConfig.id);
-    }
-  } else {
-    this.canvasContext = this.renderConfig.context;
-  }
-  this.data = animData;
-  this.layers = animData.layers;
-  this.transformCanvas = {
-    w: animData.w,
-    h: animData.h,
-    sx: 0,
-    sy: 0,
-    tx: 0,
-    ty: 0,
+
+    var segment = segments.shift();
+    this.timeCompleted = segment.time * this.frameRate;
+    var segmentPath = this.path + this.fileName + '_' + this.segmentPos + '.json';
+    this.segmentPos += 1;
+    dataManager.loadData(segmentPath, this.includeLayers.bind(this), function () {
+      this.trigger('data_failed');
+    }.bind(this));
   };
-  this.setupGlobalData(animData, document.body);
-  this.globalData.canvasContext = this.canvasContext;
-  this.globalData.renderer = this;
-  this.globalData.isDashed = false;
-  this.globalData.progressiveLoad = this.renderConfig.progressiveLoad;
-  this.globalData.transformCanvas = this.transformCanvas;
-  this.elements = createSizedArray(animData.layers.length);
 
-  this.updateContainerSize();
-};
+  AnimationItem.prototype.loadSegments = function () {
+    var segments = this.animationData.segments;
 
-CanvasRenderer.prototype.updateContainerSize = function () {
-  this.reset();
-  var elementWidth;
-  var elementHeight;
-  if (this.animationItem.wrapper && this.animationItem.container) {
-    elementWidth = this.animationItem.wrapper.offsetWidth;
-    elementHeight = this.animationItem.wrapper.offsetHeight;
-    this.animationItem.container.setAttribute('width', elementWidth * this.renderConfig.dpr);
-    this.animationItem.container.setAttribute('height', elementHeight * this.renderConfig.dpr);
-  } else {
-    elementWidth = this.canvasContext.canvas.width * this.renderConfig.dpr;
-    elementHeight = this.canvasContext.canvas.height * this.renderConfig.dpr;
-  }
-  var elementRel;
-  var animationRel;
-  if (this.renderConfig.preserveAspectRatio.indexOf('meet') !== -1 || this.renderConfig.preserveAspectRatio.indexOf('slice') !== -1) {
-    var par = this.renderConfig.preserveAspectRatio.split(' ');
-    var fillType = par[1] || 'meet';
-    var pos = par[0] || 'xMidYMid';
-    var xPos = pos.substr(0, 4);
-    var yPos = pos.substr(4);
-    elementRel = elementWidth / elementHeight;
-    animationRel = this.transformCanvas.w / this.transformCanvas.h;
-    if ((animationRel > elementRel && fillType === 'meet') || (animationRel < elementRel && fillType === 'slice')) {
-      this.transformCanvas.sx = elementWidth / (this.transformCanvas.w / this.renderConfig.dpr);
-      this.transformCanvas.sy = elementWidth / (this.transformCanvas.w / this.renderConfig.dpr);
-    } else {
-      this.transformCanvas.sx = elementHeight / (this.transformCanvas.h / this.renderConfig.dpr);
-      this.transformCanvas.sy = elementHeight / (this.transformCanvas.h / this.renderConfig.dpr);
+    if (!segments) {
+      this.timeCompleted = this.totalFrames;
     }
 
-    if (xPos === 'xMid' && ((animationRel < elementRel && fillType === 'meet') || (animationRel > elementRel && fillType === 'slice'))) {
-      this.transformCanvas.tx = ((elementWidth - this.transformCanvas.w * (elementHeight / this.transformCanvas.h)) / 2) * this.renderConfig.dpr;
-    } else if (xPos === 'xMax' && ((animationRel < elementRel && fillType === 'meet') || (animationRel > elementRel && fillType === 'slice'))) {
-      this.transformCanvas.tx = (elementWidth - this.transformCanvas.w * (elementHeight / this.transformCanvas.h)) * this.renderConfig.dpr;
-    } else {
-      this.transformCanvas.tx = 0;
-    }
-    if (yPos === 'YMid' && ((animationRel > elementRel && fillType === 'meet') || (animationRel < elementRel && fillType === 'slice'))) {
-      this.transformCanvas.ty = ((elementHeight - this.transformCanvas.h * (elementWidth / this.transformCanvas.w)) / 2) * this.renderConfig.dpr;
-    } else if (yPos === 'YMax' && ((animationRel > elementRel && fillType === 'meet') || (animationRel < elementRel && fillType === 'slice'))) {
-      this.transformCanvas.ty = ((elementHeight - this.transformCanvas.h * (elementWidth / this.transformCanvas.w))) * this.renderConfig.dpr;
-    } else {
-      this.transformCanvas.ty = 0;
-    }
-  } else if (this.renderConfig.preserveAspectRatio === 'none') {
-    this.transformCanvas.sx = elementWidth / (this.transformCanvas.w / this.renderConfig.dpr);
-    this.transformCanvas.sy = elementHeight / (this.transformCanvas.h / this.renderConfig.dpr);
-    this.transformCanvas.tx = 0;
-    this.transformCanvas.ty = 0;
-  } else {
-    this.transformCanvas.sx = this.renderConfig.dpr;
-    this.transformCanvas.sy = this.renderConfig.dpr;
-    this.transformCanvas.tx = 0;
-    this.transformCanvas.ty = 0;
-  }
-  this.transformCanvas.props = [this.transformCanvas.sx, 0, 0, 0, 0, this.transformCanvas.sy, 0, 0, 0, 0, 1, 0, this.transformCanvas.tx, this.transformCanvas.ty, 0, 1];
-  /* var i, len = this.elements.length;
-    for(i=0;i<len;i+=1){
-        if(this.elements[i] && this.elements[i].data.ty === 0){
-            this.elements[i].resize(this.globalData.transformCanvas);
-        }
-    } */
-  this.ctxTransform(this.transformCanvas.props);
-  this.canvasContext.beginPath();
-  this.canvasContext.rect(0, 0, this.transformCanvas.w, this.transformCanvas.h);
-  this.canvasContext.closePath();
-  this.canvasContext.clip();
-
-  this.renderFrame(this.renderedFrame, true);
-};
-
-CanvasRenderer.prototype.destroy = function () {
-  if (this.renderConfig.clearCanvas && this.animationItem.wrapper) {
-    this.animationItem.wrapper.innerText = '';
-  }
-  var i;
-  var len = this.layers ? this.layers.length : 0;
-  for (i = len - 1; i >= 0; i -= 1) {
-    if (this.elements[i]) {
-      this.elements[i].destroy();
-    }
-  }
-  this.elements.length = 0;
-  this.globalData.canvasContext = null;
-  this.animationItem.container = null;
-  this.destroyed = true;
-};
-
-CanvasRenderer.prototype.renderFrame = function (num, forceRender) {
-  if ((this.renderedFrame === num && this.renderConfig.clearCanvas === true && !forceRender) || this.destroyed || num === -1) {
-    return;
-  }
-  this.renderedFrame = num;
-  this.globalData.frameNum = num - this.animationItem._isFirstFrame;
-  this.globalData.frameId += 1;
-  this.globalData._mdf = !this.renderConfig.clearCanvas || forceRender;
-  this.globalData.projectInterface.currentFrame = num;
-
-  // console.log('--------');
-  // console.log('NEW: ',num);
-  var i;
-  var len = this.layers.length;
-  if (!this.completeLayers) {
-    this.checkLayers(num);
-  }
-
-  for (i = 0; i < len; i += 1) {
-    if (this.completeLayers || this.elements[i]) {
-      this.elements[i].prepareFrame(num - this.layers[i].st);
-    }
-  }
-  if (this.globalData._mdf) {
-    if (this.renderConfig.clearCanvas === true) {
-      this.canvasContext.clearRect(0, 0, this.transformCanvas.w, this.transformCanvas.h);
-    } else {
-      this.save();
-    }
-    for (i = len - 1; i >= 0; i -= 1) {
-      if (this.completeLayers || this.elements[i]) {
-        this.elements[i].renderFrame();
-      }
-    }
-    if (this.renderConfig.clearCanvas !== true) {
-      this.restore();
-    }
-  }
-};
-
-CanvasRenderer.prototype.buildItem = function (pos) {
-  var elements = this.elements;
-  if (elements[pos] || this.layers[pos].ty === 99) {
-    return;
-  }
-  var element = this.createItem(this.layers[pos], this, this.globalData);
-  elements[pos] = element;
-  element.initExpressions();
-  /* if(this.layers[pos].ty === 0){
-        element.resize(this.globalData.transformCanvas);
-    } */
-};
-
-CanvasRenderer.prototype.checkPendingElements = function () {
-  while (this.pendingElements.length) {
-    var element = this.pendingElements.pop();
-    element.checkParenting();
-  }
-};
-
-CanvasRenderer.prototype.hide = function () {
-  this.animationItem.container.style.display = 'none';
-};
-
-CanvasRenderer.prototype.show = function () {
-  this.animationItem.container.style.display = 'block';
-};
-
-/* global extendPrototype, BaseRenderer, SVGRenderer, SVGShapeElement, HShapeElement, SVGTextLottieElement,
-HTextElement, HCameraElement, IImageElement, HImageElement, SVGCompElement, HCompElement, ISolidElement,
-HSolidElement, styleDiv, createTag, createNS */
-
-function HybridRenderer(animationItem, config) {
-  this.animationItem = animationItem;
-  this.layers = null;
-  this.renderedFrame = -1;
-  this.renderConfig = {
-    className: (config && config.className) || '',
-    imagePreserveAspectRatio: (config && config.imagePreserveAspectRatio) || 'xMidYMid slice',
-    hideOnTransparent: !(config && config.hideOnTransparent === false),
-    filterSize: {
-      width: (config && config.filterSize && config.filterSize.width) || '400%',
-      height: (config && config.filterSize && config.filterSize.height) || '400%',
-      x: (config && config.filterSize && config.filterSize.x) || '-100%',
-      y: (config && config.filterSize && config.filterSize.y) || '-100%',
-    },
+    this.loadNextSegment();
   };
-  this.globalData = {
-    _mdf: false,
-    frameNum: -1,
-    renderConfig: this.renderConfig,
+
+  AnimationItem.prototype.imagesLoaded = function () {
+    this.trigger('loaded_images');
+    this.checkLoaded();
   };
-  this.pendingElements = [];
-  this.elements = [];
-  this.threeDElements = [];
-  this.destroyed = false;
-  this.camera = null;
-  this.supports3d = true;
-  this.rendererType = 'html';
-}
 
-extendPrototype([BaseRenderer], HybridRenderer);
-
-HybridRenderer.prototype.buildItem = SVGRenderer.prototype.buildItem;
-
-HybridRenderer.prototype.checkPendingElements = function () {
-  while (this.pendingElements.length) {
-    var element = this.pendingElements.pop();
-    element.checkParenting();
-  }
-};
-
-HybridRenderer.prototype.appendElementInPos = function (element, pos) {
-  var newDOMElement = element.getBaseElement();
-  if (!newDOMElement) {
-    return;
-  }
-  var layer = this.layers[pos];
-  if (!layer.ddd || !this.supports3d) {
-    if (this.threeDElements) {
-      this.addTo3dContainer(newDOMElement, pos);
-    } else {
-      var i = 0;
-      var nextDOMElement;
-      var nextLayer;
-      var tmpDOMElement;
-      while (i < pos) {
-        if (this.elements[i] && this.elements[i] !== true && this.elements[i].getBaseElement) {
-          nextLayer = this.elements[i];
-          tmpDOMElement = this.layers[i].ddd ? this.getThreeDContainerByPos(i) : nextLayer.getBaseElement();
-          nextDOMElement = tmpDOMElement || nextDOMElement;
-        }
-        i += 1;
-      }
-      if (nextDOMElement) {
-        if (!layer.ddd || !this.supports3d) {
-          this.layerElement.insertBefore(newDOMElement, nextDOMElement);
-        }
-      } else if (!layer.ddd || !this.supports3d) {
-        this.layerElement.appendChild(newDOMElement);
-      }
-    }
-  } else {
-    this.addTo3dContainer(newDOMElement, pos);
-  }
-};
-
-HybridRenderer.prototype.createShape = function (data) {
-  if (!this.supports3d) {
-    return new SVGShapeElement(data, this.globalData, this);
-  }
-  return new HShapeElement(data, this.globalData, this);
-};
-
-HybridRenderer.prototype.createText = function (data) {
-  if (!this.supports3d) {
-    return new SVGTextLottieElement(data, this.globalData, this);
-  }
-  return new HTextElement(data, this.globalData, this);
-};
-
-HybridRenderer.prototype.createCamera = function (data) {
-  this.camera = new HCameraElement(data, this.globalData, this);
-  return this.camera;
-};
-
-HybridRenderer.prototype.createImage = function (data) {
-  if (!this.supports3d) {
-    return new IImageElement(data, this.globalData, this);
-  }
-  return new HImageElement(data, this.globalData, this);
-};
-
-HybridRenderer.prototype.createComp = function (data) {
-  if (!this.supports3d) {
-    return new SVGCompElement(data, this.globalData, this);
-  }
-  return new HCompElement(data, this.globalData, this);
-};
-
-HybridRenderer.prototype.createSolid = function (data) {
-  if (!this.supports3d) {
-    return new ISolidElement(data, this.globalData, this);
-  }
-  return new HSolidElement(data, this.globalData, this);
-};
-
-HybridRenderer.prototype.createNull = SVGRenderer.prototype.createNull;
-
-HybridRenderer.prototype.getThreeDContainerByPos = function (pos) {
-  var i = 0;
-  var len = this.threeDElements.length;
-  while (i < len) {
-    if (this.threeDElements[i].startPos <= pos && this.threeDElements[i].endPos >= pos) {
-      return this.threeDElements[i].perspectiveElem;
-    }
-    i += 1;
-  }
-  return null;
-};
-
-HybridRenderer.prototype.createThreeDContainer = function (pos, type) {
-  var perspectiveElem = createTag('div');
-  var style;
-  var containerStyle;
-  styleDiv(perspectiveElem);
-  var container = createTag('div');
-  styleDiv(container);
-  if (type === '3d') {
-    style = perspectiveElem.style;
-    style.width = this.globalData.compSize.w + 'px';
-    style.height = this.globalData.compSize.h + 'px';
-    var center = '50% 50%';
-    style.webkitTransformOrigin = center;
-    style.mozTransformOrigin = center;
-    style.transformOrigin = center;
-    containerStyle = container.style;
-    var matrix = 'matrix3d(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1)';
-    containerStyle.transform = matrix;
-    containerStyle.webkitTransform = matrix;
-  }
-
-  perspectiveElem.appendChild(container);
-  // this.resizerElem.appendChild(perspectiveElem);
-  var threeDContainerData = {
-    container: container,
-    perspectiveElem: perspectiveElem,
-    startPos: pos,
-    endPos: pos,
-    type: type,
+  AnimationItem.prototype.preloadImages = function () {
+    this.imagePreloader.setAssetsPath(this.assetsPath);
+    this.imagePreloader.setPath(this.path);
+    this.imagePreloader.loadAssets(this.animationData.assets, this.imagesLoaded.bind(this));
   };
-  this.threeDElements.push(threeDContainerData);
-  return threeDContainerData;
-};
 
-HybridRenderer.prototype.build3dContainers = function () {
-  var i;
-  var len = this.layers.length;
-  var lastThreeDContainerData;
-  var currentContainer = '';
-  for (i = 0; i < len; i += 1) {
-    if (this.layers[i].ddd && this.layers[i].ty !== 3) {
-      if (currentContainer !== '3d') {
-        currentContainer = '3d';
-        lastThreeDContainerData = this.createThreeDContainer(i, '3d');
-      }
-      lastThreeDContainerData.endPos = Math.max(lastThreeDContainerData.endPos, i);
-    } else {
-      if (currentContainer !== '2d') {
-        currentContainer = '2d';
-        lastThreeDContainerData = this.createThreeDContainer(i, '2d');
-      }
-      lastThreeDContainerData.endPos = Math.max(lastThreeDContainerData.endPos, i);
+  AnimationItem.prototype.configAnimation = function (animData) {
+    if (!this.renderer) {
+      return;
     }
-  }
-  len = this.threeDElements.length;
-  for (i = len - 1; i >= 0; i -= 1) {
-    this.resizerElem.appendChild(this.threeDElements[i].perspectiveElem);
-  }
-};
 
-HybridRenderer.prototype.addTo3dContainer = function (elem, pos) {
-  var i = 0;
-  var len = this.threeDElements.length;
-  while (i < len) {
-    if (pos <= this.threeDElements[i].endPos) {
-      var j = this.threeDElements[i].startPos;
-      var nextElement;
-      while (j < pos) {
-        if (this.elements[j] && this.elements[j].getBaseElement) {
-          nextElement = this.elements[j].getBaseElement();
-        }
-        j += 1;
-      }
-      if (nextElement) {
-        this.threeDElements[i].container.insertBefore(elem, nextElement);
+    try {
+      this.animationData = animData;
+
+      if (this.initialSegment) {
+        this.totalFrames = Math.floor(this.initialSegment[1] - this.initialSegment[0]);
+        this.firstFrame = Math.round(this.initialSegment[0]);
       } else {
-        this.threeDElements[i].container.appendChild(elem);
+        this.totalFrames = Math.floor(this.animationData.op - this.animationData.ip);
+        this.firstFrame = Math.round(this.animationData.ip);
       }
-      break;
+
+      this.renderer.configAnimation(animData);
+
+      if (!animData.assets) {
+        animData.assets = [];
+      }
+
+      this.assets = this.animationData.assets;
+      this.frameRate = this.animationData.fr;
+      this.frameMult = this.animationData.fr / 1000;
+      this.renderer.searchExtraCompositions(animData.assets);
+      this.markers = markerParser(animData.markers || []);
+      this.trigger('config_ready');
+      this.preloadImages();
+      this.loadSegments();
+      this.updaFrameModifier();
+      this.waitForFontsLoaded();
+
+      if (this.isPaused) {
+        this.audioController.pause();
+      }
+    } catch (error) {
+      this.triggerConfigError(error);
     }
-    i += 1;
-  }
-};
+  };
 
-HybridRenderer.prototype.configAnimation = function (animData) {
-  var resizerElem = createTag('div');
-  var wrapper = this.animationItem.wrapper;
-  var style = resizerElem.style;
-  style.width = animData.w + 'px';
-  style.height = animData.h + 'px';
-  this.resizerElem = resizerElem;
-  styleDiv(resizerElem);
-  style.transformStyle = 'flat';
-  style.mozTransformStyle = 'flat';
-  style.webkitTransformStyle = 'flat';
-  if (this.renderConfig.className) {
-    resizerElem.setAttribute('class', this.renderConfig.className);
-  }
-  wrapper.appendChild(resizerElem);
-
-  style.overflow = 'hidden';
-  var svg = createNS('svg');
-  svg.setAttribute('width', '1');
-  svg.setAttribute('height', '1');
-  styleDiv(svg);
-  this.resizerElem.appendChild(svg);
-  var defs = createNS('defs');
-  svg.appendChild(defs);
-  this.data = animData;
-  // Mask animation
-  this.setupGlobalData(animData, svg);
-  this.globalData.defs = defs;
-  this.layers = animData.layers;
-  this.layerElement = this.resizerElem;
-  this.build3dContainers();
-  this.updateContainerSize();
-};
-
-HybridRenderer.prototype.destroy = function () {
-  if (this.animationItem.wrapper) {
-    this.animationItem.wrapper.innerText = '';
-  }
-  this.animationItem.container = null;
-  this.globalData.defs = null;
-  var i;
-  var len = this.layers ? this.layers.length : 0;
-  for (i = 0; i < len; i += 1) {
-    this.elements[i].destroy();
-  }
-  this.elements.length = 0;
-  this.destroyed = true;
-  this.animationItem = null;
-};
-
-HybridRenderer.prototype.updateContainerSize = function () {
-  var elementWidth = this.animationItem.wrapper.offsetWidth;
-  var elementHeight = this.animationItem.wrapper.offsetHeight;
-  var elementRel = elementWidth / elementHeight;
-  var animationRel = this.globalData.compSize.w / this.globalData.compSize.h;
-  var sx;
-  var sy;
-  var tx;
-  var ty;
-  if (animationRel > elementRel) {
-    sx = elementWidth / (this.globalData.compSize.w);
-    sy = elementWidth / (this.globalData.compSize.w);
-    tx = 0;
-    ty = ((elementHeight - this.globalData.compSize.h * (elementWidth / this.globalData.compSize.w)) / 2);
-  } else {
-    sx = elementHeight / (this.globalData.compSize.h);
-    sy = elementHeight / (this.globalData.compSize.h);
-    tx = (elementWidth - this.globalData.compSize.w * (elementHeight / this.globalData.compSize.h)) / 2;
-    ty = 0;
-  }
-  var style = this.resizerElem.style;
-  style.webkitTransform = 'matrix3d(' + sx + ',0,0,0,0,' + sy + ',0,0,0,0,1,0,' + tx + ',' + ty + ',0,1)';
-  style.transform = style.webkitTransform;
-};
-
-HybridRenderer.prototype.renderFrame = SVGRenderer.prototype.renderFrame;
-
-HybridRenderer.prototype.hide = function () {
-  this.resizerElem.style.display = 'none';
-};
-
-HybridRenderer.prototype.show = function () {
-  this.resizerElem.style.display = 'block';
-};
-
-HybridRenderer.prototype.initItems = function () {
-  this.buildAllItems();
-  if (this.camera) {
-    this.camera.setup();
-  } else {
-    var cWidth = this.globalData.compSize.w;
-    var cHeight = this.globalData.compSize.h;
-    var i;
-    var len = this.threeDElements.length;
-    for (i = 0; i < len; i += 1) {
-      var style = this.threeDElements[i].perspectiveElem.style;
-      style.webkitPerspective = Math.sqrt(Math.pow(cWidth, 2) + Math.pow(cHeight, 2)) + 'px';
-      style.perspective = style.webkitPerspective;
-    }
-  }
-};
-
-HybridRenderer.prototype.searchExtraCompositions = function (assets) {
-  var i;
-  var len = assets.length;
-  var floatingContainer = createTag('div');
-  for (i = 0; i < len; i += 1) {
-    if (assets[i].xt) {
-      var comp = this.createComp(assets[i], floatingContainer, this.globalData.comp, null);
-      comp.initExpressions();
-      this.globalData.projectInterface.registerComposition(comp);
-    }
-  }
-};
-
-/* global createSizedArray, createElementID, PropertyFactory, ShapePropertyFactory, createNS, locationHref */
-
-function MaskElement(data, element, globalData) {
-  this.data = data;
-  this.element = element;
-  this.globalData = globalData;
-  this.storedData = [];
-  this.masksProperties = this.data.masksProperties || [];
-  this.maskElement = null;
-  var defs = this.globalData.defs;
-  var i;
-  var len = this.masksProperties ? this.masksProperties.length : 0;
-  this.viewData = createSizedArray(len);
-  this.solidPath = '';
-
-  var path;
-  var properties = this.masksProperties;
-  var count = 0;
-  var currentMasks = [];
-  var j;
-  var jLen;
-  var layerId = createElementID();
-  var rect;
-  var expansor;
-  var feMorph;
-  var x;
-  var maskType = 'clipPath';
-  var maskRef = 'clip-path';
-  for (i = 0; i < len; i += 1) {
-    if ((properties[i].mode !== 'a' && properties[i].mode !== 'n') || properties[i].inv || properties[i].o.k !== 100 || properties[i].o.x) {
-      maskType = 'mask';
-      maskRef = 'mask';
+  AnimationItem.prototype.waitForFontsLoaded = function () {
+    if (!this.renderer) {
+      return;
     }
 
-    if ((properties[i].mode === 's' || properties[i].mode === 'i') && count === 0) {
-      rect = createNS('rect');
-      rect.setAttribute('fill', '#ffffff');
-      rect.setAttribute('width', this.element.comp.data.w || 0);
-      rect.setAttribute('height', this.element.comp.data.h || 0);
-      currentMasks.push(rect);
+    if (this.renderer.globalData.fontManager.isLoaded) {
+      this.checkLoaded();
     } else {
-      rect = null;
+      setTimeout(this.waitForFontsLoaded.bind(this), 20);
+    }
+  };
+
+  AnimationItem.prototype.checkLoaded = function () {
+    if (!this.isLoaded && this.renderer.globalData.fontManager.isLoaded && (this.imagePreloader.loadedImages() || this.renderer.rendererType !== 'canvas') && this.imagePreloader.loadedFootages()) {
+      this.isLoaded = true;
+      var expressionsPlugin = getExpressionsPlugin();
+
+      if (expressionsPlugin) {
+        expressionsPlugin.initExpressions(this);
+      }
+
+      this.renderer.initItems();
+      setTimeout(function () {
+        this.trigger('DOMLoaded');
+      }.bind(this), 0);
+      this.gotoFrame();
+
+      if (this.autoplay) {
+        this.play();
+      }
+    }
+  };
+
+  AnimationItem.prototype.resize = function () {
+    this.renderer.updateContainerSize();
+  };
+
+  AnimationItem.prototype.setSubframe = function (flag) {
+    this.isSubframeEnabled = !!flag;
+  };
+
+  AnimationItem.prototype.gotoFrame = function () {
+    this.currentFrame = this.isSubframeEnabled ? this.currentRawFrame : ~~this.currentRawFrame; // eslint-disable-line no-bitwise
+
+    if (this.timeCompleted !== this.totalFrames && this.currentFrame > this.timeCompleted) {
+      this.currentFrame = this.timeCompleted;
     }
 
-    path = createNS('path');
-    if (properties[i].mode === 'n') {
-      // TODO move this to a factory or to a constructor
-      this.viewData[i] = {
-        op: PropertyFactory.getProp(this.element, properties[i].o, 0, 0.01, this.element),
-        prop: ShapePropertyFactory.getShapeProp(this.element, properties[i], 3),
-        elem: path,
-        lastPath: '',
-      };
-      defs.appendChild(path);
+    this.trigger('enterFrame');
+    this.renderFrame();
+    this.trigger('drawnFrame');
+  };
+
+  AnimationItem.prototype.renderFrame = function () {
+    if (this.isLoaded === false || !this.renderer) {
+      return;
+    }
+
+    try {
+      this.renderer.renderFrame(this.currentFrame + this.firstFrame);
+    } catch (error) {
+      this.triggerRenderFrameError(error);
+    }
+  };
+
+  AnimationItem.prototype.play = function (name) {
+    if (name && this.name !== name) {
+      return;
+    }
+
+    if (this.isPaused === true) {
+      this.isPaused = false;
+      this.audioController.resume();
+
+      if (this._idle) {
+        this._idle = false;
+        this.trigger('_active');
+      }
+    }
+  };
+
+  AnimationItem.prototype.pause = function (name) {
+    if (name && this.name !== name) {
+      return;
+    }
+
+    if (this.isPaused === false) {
+      this.isPaused = true;
+      this._idle = true;
+      this.trigger('_idle');
+      this.audioController.pause();
+    }
+  };
+
+  AnimationItem.prototype.togglePause = function (name) {
+    if (name && this.name !== name) {
+      return;
+    }
+
+    if (this.isPaused === true) {
+      this.play();
     } else {
-      count += 1;
+      this.pause();
+    }
+  };
 
-      path.setAttribute('fill', properties[i].mode === 's' ? '#000000' : '#ffffff');
-      path.setAttribute('clip-rule', 'nonzero');
-      var filterID;
+  AnimationItem.prototype.stop = function (name) {
+    if (name && this.name !== name) {
+      return;
+    }
 
-      if (properties[i].x.k !== 0) {
-        maskType = 'mask';
-        maskRef = 'mask';
-        x = PropertyFactory.getProp(this.element, properties[i].x, 0, null, this.element);
-        filterID = createElementID();
-        expansor = createNS('filter');
-        expansor.setAttribute('id', filterID);
-        feMorph = createNS('feMorphology');
-        feMorph.setAttribute('operator', 'erode');
-        feMorph.setAttribute('in', 'SourceGraphic');
-        feMorph.setAttribute('radius', '0');
-        expansor.appendChild(feMorph);
-        defs.appendChild(expansor);
-        path.setAttribute('stroke', properties[i].mode === 's' ? '#000000' : '#ffffff');
-      } else {
-        feMorph = null;
-        x = null;
-      }
+    this.pause();
+    this.playCount = 0;
+    this._completedLoop = false;
+    this.setCurrentRawFrameValue(0);
+  };
 
-      // TODO move this to a factory or to a constructor
-      this.storedData[i] = {
-        elem: path,
-        x: x,
-        expan: feMorph,
-        lastPath: '',
-        lastOperator: '',
-        filterId: filterID,
-        lastRadius: 0,
-      };
-      if (properties[i].mode === 'i') {
-        jLen = currentMasks.length;
-        var g = createNS('g');
-        for (j = 0; j < jLen; j += 1) {
-          g.appendChild(currentMasks[j]);
-        }
-        var mask = createNS('mask');
-        mask.setAttribute('mask-type', 'alpha');
-        mask.setAttribute('id', layerId + '_' + count);
-        mask.appendChild(path);
-        defs.appendChild(mask);
-        g.setAttribute('mask', 'url(' + locationHref + '#' + layerId + '_' + count + ')');
+  AnimationItem.prototype.getMarkerData = function (markerName) {
+    var marker;
 
-        currentMasks.length = 0;
-        currentMasks.push(g);
-      } else {
-        currentMasks.push(path);
-      }
-      if (properties[i].inv && !this.solidPath) {
-        this.solidPath = this.createLayerSolidPath();
-      }
-      // TODO move this to a factory or to a constructor
-      this.viewData[i] = {
-        elem: path,
-        lastPath: '',
-        op: PropertyFactory.getProp(this.element, properties[i].o, 0, 0.01, this.element),
-        prop: ShapePropertyFactory.getShapeProp(this.element, properties[i], 3),
-        invRect: rect,
-      };
-      if (!this.viewData[i].prop.k) {
-        this.drawPath(properties[i], this.viewData[i].prop.v, this.viewData[i]);
+    for (var i = 0; i < this.markers.length; i += 1) {
+      marker = this.markers[i];
+
+      if (marker.payload && marker.payload.name === markerName) {
+        return marker;
       }
     }
-  }
 
-  this.maskElement = createNS(maskType);
+    return null;
+  };
 
-  len = currentMasks.length;
-  for (i = 0; i < len; i += 1) {
-    this.maskElement.appendChild(currentMasks[i]);
-  }
-
-  if (count > 0) {
-    this.maskElement.setAttribute('id', layerId);
-    this.element.maskedElement.setAttribute(maskRef, 'url(' + locationHref + '#' + layerId + ')');
-    defs.appendChild(this.maskElement);
-  }
-  if (this.viewData.length) {
-    this.element.addRenderableComponent(this);
-  }
-}
-
-MaskElement.prototype.getMaskProperty = function (pos) {
-  return this.viewData[pos].prop;
-};
-
-MaskElement.prototype.renderFrame = function (isFirstFrame) {
-  var finalMat = this.element.finalTransform.mat;
-  var i;
-  var len = this.masksProperties.length;
-  for (i = 0; i < len; i += 1) {
-    if (this.viewData[i].prop._mdf || isFirstFrame) {
-      this.drawPath(this.masksProperties[i], this.viewData[i].prop.v, this.viewData[i]);
+  AnimationItem.prototype.goToAndStop = function (value, isFrame, name) {
+    if (name && this.name !== name) {
+      return;
     }
-    if (this.viewData[i].op._mdf || isFirstFrame) {
-      this.viewData[i].elem.setAttribute('fill-opacity', this.viewData[i].op.v);
-    }
-    if (this.masksProperties[i].mode !== 'n') {
-      if (this.viewData[i].invRect && (this.element.finalTransform.mProp._mdf || isFirstFrame)) {
-        this.viewData[i].invRect.setAttribute('transform', finalMat.getInverseMatrix().to2dCSS());
+
+    var numValue = Number(value);
+
+    if (isNaN(numValue)) {
+      var marker = this.getMarkerData(value);
+
+      if (marker) {
+        this.goToAndStop(marker.time, true);
       }
-      if (this.storedData[i].x && (this.storedData[i].x._mdf || isFirstFrame)) {
-        var feMorph = this.storedData[i].expan;
-        if (this.storedData[i].x.v < 0) {
-          if (this.storedData[i].lastOperator !== 'erode') {
-            this.storedData[i].lastOperator = 'erode';
-            this.storedData[i].elem.setAttribute('filter', 'url(' + locationHref + '#' + this.storedData[i].filterId + ')');
-          }
-          feMorph.setAttribute('radius', -this.storedData[i].x.v);
+    } else if (isFrame) {
+      this.setCurrentRawFrameValue(value);
+    } else {
+      this.setCurrentRawFrameValue(value * this.frameModifier);
+    }
+
+    this.pause();
+  };
+
+  AnimationItem.prototype.goToAndPlay = function (value, isFrame, name) {
+    if (name && this.name !== name) {
+      return;
+    }
+
+    var numValue = Number(value);
+
+    if (isNaN(numValue)) {
+      var marker = this.getMarkerData(value);
+
+      if (marker) {
+        if (!marker.duration) {
+          this.goToAndStop(marker.time, true);
         } else {
-          if (this.storedData[i].lastOperator !== 'dilate') {
-            this.storedData[i].lastOperator = 'dilate';
-            this.storedData[i].elem.setAttribute('filter', null);
+          this.playSegments([marker.time, marker.time + marker.duration], true);
+        }
+      }
+    } else {
+      this.goToAndStop(numValue, isFrame, name);
+    }
+
+    this.play();
+  };
+
+  AnimationItem.prototype.advanceTime = function (value) {
+    if (this.isPaused === true || this.isLoaded === false) {
+      return;
+    }
+
+    var nextValue = this.currentRawFrame + value * this.frameModifier;
+    var _isComplete = false; // Checking if nextValue > totalFrames - 1 for addressing non looping and looping animations.
+    // If animation won't loop, it should stop at totalFrames - 1. If it will loop it should complete the last frame and then loop.
+
+    if (nextValue >= this.totalFrames - 1 && this.frameModifier > 0) {
+      if (!this.loop || this.playCount === this.loop) {
+        if (!this.checkSegments(nextValue > this.totalFrames ? nextValue % this.totalFrames : 0)) {
+          _isComplete = true;
+          nextValue = this.totalFrames - 1;
+        }
+      } else if (nextValue >= this.totalFrames) {
+        this.playCount += 1;
+
+        if (!this.checkSegments(nextValue % this.totalFrames)) {
+          this.setCurrentRawFrameValue(nextValue % this.totalFrames);
+          this._completedLoop = true;
+          this.trigger('loopComplete');
+        }
+      } else {
+        this.setCurrentRawFrameValue(nextValue);
+      }
+    } else if (nextValue < 0) {
+      if (!this.checkSegments(nextValue % this.totalFrames)) {
+        if (this.loop && !(this.playCount-- <= 0 && this.loop !== true)) {
+          // eslint-disable-line no-plusplus
+          this.setCurrentRawFrameValue(this.totalFrames + nextValue % this.totalFrames);
+
+          if (!this._completedLoop) {
+            this._completedLoop = true;
+          } else {
+            this.trigger('loopComplete');
           }
-          this.storedData[i].elem.setAttribute('stroke-width', this.storedData[i].x.v * 2);
+        } else {
+          _isComplete = true;
+          nextValue = 0;
+        }
+      }
+    } else {
+      this.setCurrentRawFrameValue(nextValue);
+    }
+
+    if (_isComplete) {
+      this.setCurrentRawFrameValue(nextValue);
+      this.pause();
+      this.trigger('complete');
+    }
+  };
+
+  AnimationItem.prototype.adjustSegment = function (arr, offset) {
+    this.playCount = 0;
+
+    if (arr[1] < arr[0]) {
+      if (this.frameModifier > 0) {
+        if (this.playSpeed < 0) {
+          this.setSpeed(-this.playSpeed);
+        } else {
+          this.setDirection(-1);
+        }
+      }
+
+      this.totalFrames = arr[0] - arr[1];
+      this.timeCompleted = this.totalFrames;
+      this.firstFrame = arr[1];
+      this.setCurrentRawFrameValue(this.totalFrames - 0.001 - offset);
+    } else if (arr[1] > arr[0]) {
+      if (this.frameModifier < 0) {
+        if (this.playSpeed < 0) {
+          this.setSpeed(-this.playSpeed);
+        } else {
+          this.setDirection(1);
+        }
+      }
+
+      this.totalFrames = arr[1] - arr[0];
+      this.timeCompleted = this.totalFrames;
+      this.firstFrame = arr[0];
+      this.setCurrentRawFrameValue(0.001 + offset);
+    }
+
+    this.trigger('segmentStart');
+  };
+
+  AnimationItem.prototype.setSegment = function (init, end) {
+    var pendingFrame = -1;
+
+    if (this.isPaused) {
+      if (this.currentRawFrame + this.firstFrame < init) {
+        pendingFrame = init;
+      } else if (this.currentRawFrame + this.firstFrame > end) {
+        pendingFrame = end - init;
+      }
+    }
+
+    this.firstFrame = init;
+    this.totalFrames = end - init;
+    this.timeCompleted = this.totalFrames;
+
+    if (pendingFrame !== -1) {
+      this.goToAndStop(pendingFrame, true);
+    }
+  };
+
+  AnimationItem.prototype.playSegments = function (arr, forceFlag) {
+    if (forceFlag) {
+      this.segments.length = 0;
+    }
+
+    if (_typeof$4(arr[0]) === 'object') {
+      var i;
+      var len = arr.length;
+
+      for (i = 0; i < len; i += 1) {
+        this.segments.push(arr[i]);
+      }
+    } else {
+      this.segments.push(arr);
+    }
+
+    if (this.segments.length && forceFlag) {
+      this.adjustSegment(this.segments.shift(), 0);
+    }
+
+    if (this.isPaused) {
+      this.play();
+    }
+  };
+
+  AnimationItem.prototype.resetSegments = function (forceFlag) {
+    this.segments.length = 0;
+    this.segments.push([this.animationData.ip, this.animationData.op]);
+
+    if (forceFlag) {
+      this.checkSegments(0);
+    }
+  };
+
+  AnimationItem.prototype.checkSegments = function (offset) {
+    if (this.segments.length) {
+      this.adjustSegment(this.segments.shift(), offset);
+      return true;
+    }
+
+    return false;
+  };
+
+  AnimationItem.prototype.destroy = function (name) {
+    if (name && this.name !== name || !this.renderer) {
+      return;
+    }
+
+    this.renderer.destroy();
+    this.imagePreloader.destroy();
+    this.trigger('destroy');
+    this._cbs = null;
+    this.onEnterFrame = null;
+    this.onLoopComplete = null;
+    this.onComplete = null;
+    this.onSegmentStart = null;
+    this.onDestroy = null;
+    this.renderer = null;
+    this.renderer = null;
+    this.imagePreloader = null;
+    this.projectInterface = null;
+  };
+
+  AnimationItem.prototype.setCurrentRawFrameValue = function (value) {
+    this.currentRawFrame = value;
+    this.gotoFrame();
+  };
+
+  AnimationItem.prototype.setSpeed = function (val) {
+    this.playSpeed = val;
+    this.updaFrameModifier();
+  };
+
+  AnimationItem.prototype.setDirection = function (val) {
+    this.playDirection = val < 0 ? -1 : 1;
+    this.updaFrameModifier();
+  };
+
+  AnimationItem.prototype.setVolume = function (val, name) {
+    if (name && this.name !== name) {
+      return;
+    }
+
+    this.audioController.setVolume(val);
+  };
+
+  AnimationItem.prototype.getVolume = function () {
+    return this.audioController.getVolume();
+  };
+
+  AnimationItem.prototype.mute = function (name) {
+    if (name && this.name !== name) {
+      return;
+    }
+
+    this.audioController.mute();
+  };
+
+  AnimationItem.prototype.unmute = function (name) {
+    if (name && this.name !== name) {
+      return;
+    }
+
+    this.audioController.unmute();
+  };
+
+  AnimationItem.prototype.updaFrameModifier = function () {
+    this.frameModifier = this.frameMult * this.playSpeed * this.playDirection;
+    this.audioController.setRate(this.playSpeed * this.playDirection);
+  };
+
+  AnimationItem.prototype.getPath = function () {
+    return this.path;
+  };
+
+  AnimationItem.prototype.getAssetsPath = function (assetData) {
+    var path = '';
+
+    if (assetData.e) {
+      path = assetData.p;
+    } else if (this.assetsPath) {
+      var imagePath = assetData.p;
+
+      if (imagePath.indexOf('images/') !== -1) {
+        imagePath = imagePath.split('/')[1];
+      }
+
+      path = this.assetsPath + imagePath;
+    } else {
+      path = this.path;
+      path += assetData.u ? assetData.u : '';
+      path += assetData.p;
+    }
+
+    return path;
+  };
+
+  AnimationItem.prototype.getAssetData = function (id) {
+    var i = 0;
+    var len = this.assets.length;
+
+    while (i < len) {
+      if (id === this.assets[i].id) {
+        return this.assets[i];
+      }
+
+      i += 1;
+    }
+
+    return null;
+  };
+
+  AnimationItem.prototype.hide = function () {
+    this.renderer.hide();
+  };
+
+  AnimationItem.prototype.show = function () {
+    this.renderer.show();
+  };
+
+  AnimationItem.prototype.getDuration = function (isFrame) {
+    return isFrame ? this.totalFrames : this.totalFrames / this.frameRate;
+  };
+
+  AnimationItem.prototype.trigger = function (name) {
+    if (this._cbs && this._cbs[name]) {
+      switch (name) {
+        case 'enterFrame':
+        case 'drawnFrame':
+          this.triggerEvent(name, new BMEnterFrameEvent(name, this.currentFrame, this.totalFrames, this.frameModifier));
+          break;
+
+        case 'loopComplete':
+          this.triggerEvent(name, new BMCompleteLoopEvent(name, this.loop, this.playCount, this.frameMult));
+          break;
+
+        case 'complete':
+          this.triggerEvent(name, new BMCompleteEvent(name, this.frameMult));
+          break;
+
+        case 'segmentStart':
+          this.triggerEvent(name, new BMSegmentStartEvent(name, this.firstFrame, this.totalFrames));
+          break;
+
+        case 'destroy':
+          this.triggerEvent(name, new BMDestroyEvent(name, this));
+          break;
+
+        default:
+          this.triggerEvent(name);
+      }
+    }
+
+    if (name === 'enterFrame' && this.onEnterFrame) {
+      this.onEnterFrame.call(this, new BMEnterFrameEvent(name, this.currentFrame, this.totalFrames, this.frameMult));
+    }
+
+    if (name === 'loopComplete' && this.onLoopComplete) {
+      this.onLoopComplete.call(this, new BMCompleteLoopEvent(name, this.loop, this.playCount, this.frameMult));
+    }
+
+    if (name === 'complete' && this.onComplete) {
+      this.onComplete.call(this, new BMCompleteEvent(name, this.frameMult));
+    }
+
+    if (name === 'segmentStart' && this.onSegmentStart) {
+      this.onSegmentStart.call(this, new BMSegmentStartEvent(name, this.firstFrame, this.totalFrames));
+    }
+
+    if (name === 'destroy' && this.onDestroy) {
+      this.onDestroy.call(this, new BMDestroyEvent(name, this));
+    }
+  };
+
+  AnimationItem.prototype.triggerRenderFrameError = function (nativeError) {
+    var error = new BMRenderFrameErrorEvent(nativeError, this.currentFrame);
+    this.triggerEvent('error', error);
+
+    if (this.onError) {
+      this.onError.call(this, error);
+    }
+  };
+
+  AnimationItem.prototype.triggerConfigError = function (nativeError) {
+    var error = new BMConfigErrorEvent(nativeError, this.currentFrame);
+    this.triggerEvent('error', error);
+
+    if (this.onError) {
+      this.onError.call(this, error);
+    }
+  };
+
+  var animationManager = function () {
+    var moduleOb = {};
+    var registeredAnimations = [];
+    var initTime = 0;
+    var len = 0;
+    var playingAnimationsNum = 0;
+    var _stopped = true;
+    var _isFrozen = false;
+
+    function removeElement(ev) {
+      var i = 0;
+      var animItem = ev.target;
+
+      while (i < len) {
+        if (registeredAnimations[i].animation === animItem) {
+          registeredAnimations.splice(i, 1);
+          i -= 1;
+          len -= 1;
+
+          if (!animItem.isPaused) {
+            subtractPlayingCount();
+          }
+        }
+
+        i += 1;
+      }
+    }
+
+    function registerAnimation(element, animationData) {
+      if (!element) {
+        return null;
+      }
+
+      var i = 0;
+
+      while (i < len) {
+        if (registeredAnimations[i].elem === element && registeredAnimations[i].elem !== null) {
+          return registeredAnimations[i].animation;
+        }
+
+        i += 1;
+      }
+
+      var animItem = new AnimationItem();
+      setupAnimation(animItem, element);
+      animItem.setData(element, animationData);
+      return animItem;
+    }
+
+    function getRegisteredAnimations() {
+      var i;
+      var lenAnims = registeredAnimations.length;
+      var animations = [];
+
+      for (i = 0; i < lenAnims; i += 1) {
+        animations.push(registeredAnimations[i].animation);
+      }
+
+      return animations;
+    }
+
+    function addPlayingCount() {
+      playingAnimationsNum += 1;
+      activate();
+    }
+
+    function subtractPlayingCount() {
+      playingAnimationsNum -= 1;
+    }
+
+    function setupAnimation(animItem, element) {
+      animItem.addEventListener('destroy', removeElement);
+      animItem.addEventListener('_active', addPlayingCount);
+      animItem.addEventListener('_idle', subtractPlayingCount);
+      registeredAnimations.push({
+        elem: element,
+        animation: animItem
+      });
+      len += 1;
+    }
+
+    function loadAnimation(params) {
+      var animItem = new AnimationItem();
+      setupAnimation(animItem, null);
+      animItem.setParams(params);
+      return animItem;
+    }
+
+    function setSpeed(val, animation) {
+      var i;
+
+      for (i = 0; i < len; i += 1) {
+        registeredAnimations[i].animation.setSpeed(val, animation);
+      }
+    }
+
+    function setDirection(val, animation) {
+      var i;
+
+      for (i = 0; i < len; i += 1) {
+        registeredAnimations[i].animation.setDirection(val, animation);
+      }
+    }
+
+    function play(animation) {
+      var i;
+
+      for (i = 0; i < len; i += 1) {
+        registeredAnimations[i].animation.play(animation);
+      }
+    }
+
+    function resume(nowTime) {
+      var elapsedTime = nowTime - initTime;
+      var i;
+
+      for (i = 0; i < len; i += 1) {
+        registeredAnimations[i].animation.advanceTime(elapsedTime);
+      }
+
+      initTime = nowTime;
+
+      if (playingAnimationsNum && !_isFrozen) {
+        window.requestAnimationFrame(resume);
+      } else {
+        _stopped = true;
+      }
+    }
+
+    function first(nowTime) {
+      initTime = nowTime;
+      window.requestAnimationFrame(resume);
+    }
+
+    function pause(animation) {
+      var i;
+
+      for (i = 0; i < len; i += 1) {
+        registeredAnimations[i].animation.pause(animation);
+      }
+    }
+
+    function goToAndStop(value, isFrame, animation) {
+      var i;
+
+      for (i = 0; i < len; i += 1) {
+        registeredAnimations[i].animation.goToAndStop(value, isFrame, animation);
+      }
+    }
+
+    function stop(animation) {
+      var i;
+
+      for (i = 0; i < len; i += 1) {
+        registeredAnimations[i].animation.stop(animation);
+      }
+    }
+
+    function togglePause(animation) {
+      var i;
+
+      for (i = 0; i < len; i += 1) {
+        registeredAnimations[i].animation.togglePause(animation);
+      }
+    }
+
+    function destroy(animation) {
+      var i;
+
+      for (i = len - 1; i >= 0; i -= 1) {
+        registeredAnimations[i].animation.destroy(animation);
+      }
+    }
+
+    function searchAnimations(animationData, standalone, renderer) {
+      var animElements = [].concat([].slice.call(document.getElementsByClassName('lottie')), [].slice.call(document.getElementsByClassName('bodymovin')));
+      var i;
+      var lenAnims = animElements.length;
+
+      for (i = 0; i < lenAnims; i += 1) {
+        if (renderer) {
+          animElements[i].setAttribute('data-bm-type', renderer);
+        }
+
+        registerAnimation(animElements[i], animationData);
+      }
+
+      if (standalone && lenAnims === 0) {
+        if (!renderer) {
+          renderer = 'svg';
+        }
+
+        var body = document.getElementsByTagName('body')[0];
+        body.innerText = '';
+        var div = createTag('div');
+        div.style.width = '100%';
+        div.style.height = '100%';
+        div.setAttribute('data-bm-type', renderer);
+        body.appendChild(div);
+        registerAnimation(div, animationData);
+      }
+    }
+
+    function resize() {
+      var i;
+
+      for (i = 0; i < len; i += 1) {
+        registeredAnimations[i].animation.resize();
+      }
+    }
+
+    function activate() {
+      if (!_isFrozen && playingAnimationsNum) {
+        if (_stopped) {
+          window.requestAnimationFrame(first);
+          _stopped = false;
         }
       }
     }
-  }
-};
 
-MaskElement.prototype.getMaskelement = function () {
-  return this.maskElement;
-};
+    function freeze() {
+      _isFrozen = true;
+    }
 
-MaskElement.prototype.createLayerSolidPath = function () {
-  var path = 'M0,0 ';
-  path += ' h' + this.globalData.compSize.w;
-  path += ' v' + this.globalData.compSize.h;
-  path += ' h-' + this.globalData.compSize.w;
-  path += ' v-' + this.globalData.compSize.h + ' ';
-  return path;
-};
+    function unfreeze() {
+      _isFrozen = false;
+      activate();
+    }
 
-MaskElement.prototype.drawPath = function (pathData, pathNodes, viewData) {
-  var pathString = ' M' + pathNodes.v[0][0] + ',' + pathNodes.v[0][1];
-  var i;
-  var len;
-  len = pathNodes._length;
-  for (i = 1; i < len; i += 1) {
-    // pathString += " C"+pathNodes.o[i-1][0]+','+pathNodes.o[i-1][1] + " "+pathNodes.i[i][0]+','+pathNodes.i[i][1] + " "+pathNodes.v[i][0]+','+pathNodes.v[i][1];
-    pathString += ' C' + pathNodes.o[i - 1][0] + ',' + pathNodes.o[i - 1][1] + ' ' + pathNodes.i[i][0] + ',' + pathNodes.i[i][1] + ' ' + pathNodes.v[i][0] + ',' + pathNodes.v[i][1];
-  }
-  // pathString += " C"+pathNodes.o[i-1][0]+','+pathNodes.o[i-1][1] + " "+pathNodes.i[0][0]+','+pathNodes.i[0][1] + " "+pathNodes.v[0][0]+','+pathNodes.v[0][1];
-  if (pathNodes.c && len > 1) {
-    pathString += ' C' + pathNodes.o[i - 1][0] + ',' + pathNodes.o[i - 1][1] + ' ' + pathNodes.i[0][0] + ',' + pathNodes.i[0][1] + ' ' + pathNodes.v[0][0] + ',' + pathNodes.v[0][1];
-  }
-  // pathNodes.__renderedString = pathString;
+    function setVolume(val, animation) {
+      var i;
 
-  if (viewData.lastPath !== pathString) {
-    var pathShapeValue = '';
-    if (viewData.elem) {
-      if (pathNodes.c) {
-        pathShapeValue = pathData.inv ? this.solidPath + pathString : pathString;
+      for (i = 0; i < len; i += 1) {
+        registeredAnimations[i].animation.setVolume(val, animation);
       }
-      viewData.elem.setAttribute('d', pathShapeValue);
     }
-    viewData.lastPath = pathString;
+
+    function mute(animation) {
+      var i;
+
+      for (i = 0; i < len; i += 1) {
+        registeredAnimations[i].animation.mute(animation);
+      }
+    }
+
+    function unmute(animation) {
+      var i;
+
+      for (i = 0; i < len; i += 1) {
+        registeredAnimations[i].animation.unmute(animation);
+      }
+    }
+
+    moduleOb.registerAnimation = registerAnimation;
+    moduleOb.loadAnimation = loadAnimation;
+    moduleOb.setSpeed = setSpeed;
+    moduleOb.setDirection = setDirection;
+    moduleOb.play = play;
+    moduleOb.pause = pause;
+    moduleOb.stop = stop;
+    moduleOb.togglePause = togglePause;
+    moduleOb.searchAnimations = searchAnimations;
+    moduleOb.resize = resize; // moduleOb.start = start;
+
+    moduleOb.goToAndStop = goToAndStop;
+    moduleOb.destroy = destroy;
+    moduleOb.freeze = freeze;
+    moduleOb.unfreeze = unfreeze;
+    moduleOb.setVolume = setVolume;
+    moduleOb.mute = mute;
+    moduleOb.unmute = unmute;
+    moduleOb.getRegisteredAnimations = getRegisteredAnimations;
+    return moduleOb;
+  }();
+
+  /* eslint-disable */
+  var BezierFactory = function () {
+    /**
+       * BezierEasing - use bezier curve for transition easing function
+       * by Gaëtan Renaudeau 2014 - 2015 – MIT License
+       *
+       * Credits: is based on Firefox's nsSMILKeySpline.cpp
+       * Usage:
+       * var spline = BezierEasing([ 0.25, 0.1, 0.25, 1.0 ])
+       * spline.get(x) => returns the easing value | x must be in [0, 1] range
+       *
+       */
+    var ob = {};
+    ob.getBezierEasing = getBezierEasing;
+    var beziers = {};
+
+    function getBezierEasing(a, b, c, d, nm) {
+      var str = nm || ('bez_' + a + '_' + b + '_' + c + '_' + d).replace(/\./g, 'p');
+
+      if (beziers[str]) {
+        return beziers[str];
+      }
+
+      var bezEasing = new BezierEasing([a, b, c, d]);
+      beziers[str] = bezEasing;
+      return bezEasing;
+    } // These values are established by empiricism with tests (tradeoff: performance VS precision)
+
+
+    var NEWTON_ITERATIONS = 4;
+    var NEWTON_MIN_SLOPE = 0.001;
+    var SUBDIVISION_PRECISION = 0.0000001;
+    var SUBDIVISION_MAX_ITERATIONS = 10;
+    var kSplineTableSize = 11;
+    var kSampleStepSize = 1.0 / (kSplineTableSize - 1.0);
+    var float32ArraySupported = typeof Float32Array === 'function';
+
+    function A(aA1, aA2) {
+      return 1.0 - 3.0 * aA2 + 3.0 * aA1;
+    }
+
+    function B(aA1, aA2) {
+      return 3.0 * aA2 - 6.0 * aA1;
+    }
+
+    function C(aA1) {
+      return 3.0 * aA1;
+    } // Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
+
+
+    function calcBezier(aT, aA1, aA2) {
+      return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT;
+    } // Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.
+
+
+    function getSlope(aT, aA1, aA2) {
+      return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1);
+    }
+
+    function binarySubdivide(aX, aA, aB, mX1, mX2) {
+      var currentX,
+          currentT,
+          i = 0;
+
+      do {
+        currentT = aA + (aB - aA) / 2.0;
+        currentX = calcBezier(currentT, mX1, mX2) - aX;
+
+        if (currentX > 0.0) {
+          aB = currentT;
+        } else {
+          aA = currentT;
+        }
+      } while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);
+
+      return currentT;
+    }
+
+    function newtonRaphsonIterate(aX, aGuessT, mX1, mX2) {
+      for (var i = 0; i < NEWTON_ITERATIONS; ++i) {
+        var currentSlope = getSlope(aGuessT, mX1, mX2);
+        if (currentSlope === 0.0) return aGuessT;
+        var currentX = calcBezier(aGuessT, mX1, mX2) - aX;
+        aGuessT -= currentX / currentSlope;
+      }
+
+      return aGuessT;
+    }
+    /**
+       * points is an array of [ mX1, mY1, mX2, mY2 ]
+       */
+
+
+    function BezierEasing(points) {
+      this._p = points;
+      this._mSampleValues = float32ArraySupported ? new Float32Array(kSplineTableSize) : new Array(kSplineTableSize);
+      this._precomputed = false;
+      this.get = this.get.bind(this);
+    }
+
+    BezierEasing.prototype = {
+      get: function get(x) {
+        var mX1 = this._p[0],
+            mY1 = this._p[1],
+            mX2 = this._p[2],
+            mY2 = this._p[3];
+        if (!this._precomputed) this._precompute();
+        if (mX1 === mY1 && mX2 === mY2) return x; // linear
+        // Because JavaScript number are imprecise, we should guarantee the extremes are right.
+
+        if (x === 0) return 0;
+        if (x === 1) return 1;
+        return calcBezier(this._getTForX(x), mY1, mY2);
+      },
+      // Private part
+      _precompute: function _precompute() {
+        var mX1 = this._p[0],
+            mY1 = this._p[1],
+            mX2 = this._p[2],
+            mY2 = this._p[3];
+        this._precomputed = true;
+
+        if (mX1 !== mY1 || mX2 !== mY2) {
+          this._calcSampleValues();
+        }
+      },
+      _calcSampleValues: function _calcSampleValues() {
+        var mX1 = this._p[0],
+            mX2 = this._p[2];
+
+        for (var i = 0; i < kSplineTableSize; ++i) {
+          this._mSampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2);
+        }
+      },
+
+      /**
+           * getTForX chose the fastest heuristic to determine the percentage value precisely from a given X projection.
+           */
+      _getTForX: function _getTForX(aX) {
+        var mX1 = this._p[0],
+            mX2 = this._p[2],
+            mSampleValues = this._mSampleValues;
+        var intervalStart = 0.0;
+        var currentSample = 1;
+        var lastSample = kSplineTableSize - 1;
+
+        for (; currentSample !== lastSample && mSampleValues[currentSample] <= aX; ++currentSample) {
+          intervalStart += kSampleStepSize;
+        }
+
+        --currentSample; // Interpolate to provide an initial guess for t
+
+        var dist = (aX - mSampleValues[currentSample]) / (mSampleValues[currentSample + 1] - mSampleValues[currentSample]);
+        var guessForT = intervalStart + dist * kSampleStepSize;
+        var initialSlope = getSlope(guessForT, mX1, mX2);
+
+        if (initialSlope >= NEWTON_MIN_SLOPE) {
+          return newtonRaphsonIterate(aX, guessForT, mX1, mX2);
+        }
+
+        if (initialSlope === 0.0) {
+          return guessForT;
+        }
+
+        return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize, mX1, mX2);
+      }
+    };
+    return ob;
+  }();
+
+  var pooling = function () {
+    function _double(arr) {
+      return arr.concat(createSizedArray(arr.length));
+    }
+
+    return {
+      "double": _double
+    };
+  }();
+
+  var poolFactory = function () {
+    return function (initialLength, _create, _release) {
+      var _length = 0;
+      var _maxLength = initialLength;
+      var pool = createSizedArray(_maxLength);
+      var ob = {
+        newElement: newElement,
+        release: release
+      };
+
+      function newElement() {
+        var element;
+
+        if (_length) {
+          _length -= 1;
+          element = pool[_length];
+        } else {
+          element = _create();
+        }
+
+        return element;
+      }
+
+      function release(element) {
+        if (_length === _maxLength) {
+          pool = pooling["double"](pool);
+          _maxLength *= 2;
+        }
+
+        if (_release) {
+          _release(element);
+        }
+
+        pool[_length] = element;
+        _length += 1;
+      }
+
+      return ob;
+    };
+  }();
+
+  var bezierLengthPool = function () {
+    function create() {
+      return {
+        addedLength: 0,
+        percents: createTypedArray('float32', getDefaultCurveSegments()),
+        lengths: createTypedArray('float32', getDefaultCurveSegments())
+      };
+    }
+
+    return poolFactory(8, create);
+  }();
+
+  var segmentsLengthPool = function () {
+    function create() {
+      return {
+        lengths: [],
+        totalLength: 0
+      };
+    }
+
+    function release(element) {
+      var i;
+      var len = element.lengths.length;
+
+      for (i = 0; i < len; i += 1) {
+        bezierLengthPool.release(element.lengths[i]);
+      }
+
+      element.lengths.length = 0;
+    }
+
+    return poolFactory(8, create, release);
+  }();
+
+  function bezFunction() {
+    var math = Math;
+
+    function pointOnLine2D(x1, y1, x2, y2, x3, y3) {
+      var det1 = x1 * y2 + y1 * x3 + x2 * y3 - x3 * y2 - y3 * x1 - x2 * y1;
+      return det1 > -0.001 && det1 < 0.001;
+    }
+
+    function pointOnLine3D(x1, y1, z1, x2, y2, z2, x3, y3, z3) {
+      if (z1 === 0 && z2 === 0 && z3 === 0) {
+        return pointOnLine2D(x1, y1, x2, y2, x3, y3);
+      }
+
+      var dist1 = math.sqrt(math.pow(x2 - x1, 2) + math.pow(y2 - y1, 2) + math.pow(z2 - z1, 2));
+      var dist2 = math.sqrt(math.pow(x3 - x1, 2) + math.pow(y3 - y1, 2) + math.pow(z3 - z1, 2));
+      var dist3 = math.sqrt(math.pow(x3 - x2, 2) + math.pow(y3 - y2, 2) + math.pow(z3 - z2, 2));
+      var diffDist;
+
+      if (dist1 > dist2) {
+        if (dist1 > dist3) {
+          diffDist = dist1 - dist2 - dist3;
+        } else {
+          diffDist = dist3 - dist2 - dist1;
+        }
+      } else if (dist3 > dist2) {
+        diffDist = dist3 - dist2 - dist1;
+      } else {
+        diffDist = dist2 - dist1 - dist3;
+      }
+
+      return diffDist > -0.0001 && diffDist < 0.0001;
+    }
+
+    var getBezierLength = function () {
+      return function (pt1, pt2, pt3, pt4) {
+        var curveSegments = getDefaultCurveSegments();
+        var k;
+        var i;
+        var len;
+        var ptCoord;
+        var perc;
+        var addedLength = 0;
+        var ptDistance;
+        var point = [];
+        var lastPoint = [];
+        var lengthData = bezierLengthPool.newElement();
+        len = pt3.length;
+
+        for (k = 0; k < curveSegments; k += 1) {
+          perc = k / (curveSegments - 1);
+          ptDistance = 0;
+
+          for (i = 0; i < len; i += 1) {
+            ptCoord = bmPow(1 - perc, 3) * pt1[i] + 3 * bmPow(1 - perc, 2) * perc * pt3[i] + 3 * (1 - perc) * bmPow(perc, 2) * pt4[i] + bmPow(perc, 3) * pt2[i];
+            point[i] = ptCoord;
+
+            if (lastPoint[i] !== null) {
+              ptDistance += bmPow(point[i] - lastPoint[i], 2);
+            }
+
+            lastPoint[i] = point[i];
+          }
+
+          if (ptDistance) {
+            ptDistance = bmSqrt(ptDistance);
+            addedLength += ptDistance;
+          }
+
+          lengthData.percents[k] = perc;
+          lengthData.lengths[k] = addedLength;
+        }
+
+        lengthData.addedLength = addedLength;
+        return lengthData;
+      };
+    }();
+
+    function getSegmentsLength(shapeData) {
+      var segmentsLength = segmentsLengthPool.newElement();
+      var closed = shapeData.c;
+      var pathV = shapeData.v;
+      var pathO = shapeData.o;
+      var pathI = shapeData.i;
+      var i;
+      var len = shapeData._length;
+      var lengths = segmentsLength.lengths;
+      var totalLength = 0;
+
+      for (i = 0; i < len - 1; i += 1) {
+        lengths[i] = getBezierLength(pathV[i], pathV[i + 1], pathO[i], pathI[i + 1]);
+        totalLength += lengths[i].addedLength;
+      }
+
+      if (closed && len) {
+        lengths[i] = getBezierLength(pathV[i], pathV[0], pathO[i], pathI[0]);
+        totalLength += lengths[i].addedLength;
+      }
+
+      segmentsLength.totalLength = totalLength;
+      return segmentsLength;
+    }
+
+    function BezierData(length) {
+      this.segmentLength = 0;
+      this.points = new Array(length);
+    }
+
+    function PointData(partial, point) {
+      this.partialLength = partial;
+      this.point = point;
+    }
+
+    var buildBezierData = function () {
+      var storedData = {};
+      return function (pt1, pt2, pt3, pt4) {
+        var bezierName = (pt1[0] + '_' + pt1[1] + '_' + pt2[0] + '_' + pt2[1] + '_' + pt3[0] + '_' + pt3[1] + '_' + pt4[0] + '_' + pt4[1]).replace(/\./g, 'p');
+
+        if (!storedData[bezierName]) {
+          var curveSegments = getDefaultCurveSegments();
+          var k;
+          var i;
+          var len;
+          var ptCoord;
+          var perc;
+          var addedLength = 0;
+          var ptDistance;
+          var point;
+          var lastPoint = null;
+
+          if (pt1.length === 2 && (pt1[0] !== pt2[0] || pt1[1] !== pt2[1]) && pointOnLine2D(pt1[0], pt1[1], pt2[0], pt2[1], pt1[0] + pt3[0], pt1[1] + pt3[1]) && pointOnLine2D(pt1[0], pt1[1], pt2[0], pt2[1], pt2[0] + pt4[0], pt2[1] + pt4[1])) {
+            curveSegments = 2;
+          }
+
+          var bezierData = new BezierData(curveSegments);
+          len = pt3.length;
+
+          for (k = 0; k < curveSegments; k += 1) {
+            point = createSizedArray(len);
+            perc = k / (curveSegments - 1);
+            ptDistance = 0;
+
+            for (i = 0; i < len; i += 1) {
+              ptCoord = bmPow(1 - perc, 3) * pt1[i] + 3 * bmPow(1 - perc, 2) * perc * (pt1[i] + pt3[i]) + 3 * (1 - perc) * bmPow(perc, 2) * (pt2[i] + pt4[i]) + bmPow(perc, 3) * pt2[i];
+              point[i] = ptCoord;
+
+              if (lastPoint !== null) {
+                ptDistance += bmPow(point[i] - lastPoint[i], 2);
+              }
+            }
+
+            ptDistance = bmSqrt(ptDistance);
+            addedLength += ptDistance;
+            bezierData.points[k] = new PointData(ptDistance, point);
+            lastPoint = point;
+          }
+
+          bezierData.segmentLength = addedLength;
+          storedData[bezierName] = bezierData;
+        }
+
+        return storedData[bezierName];
+      };
+    }();
+
+    function getDistancePerc(perc, bezierData) {
+      var percents = bezierData.percents;
+      var lengths = bezierData.lengths;
+      var len = percents.length;
+      var initPos = bmFloor((len - 1) * perc);
+      var lengthPos = perc * bezierData.addedLength;
+      var lPerc = 0;
+
+      if (initPos === len - 1 || initPos === 0 || lengthPos === lengths[initPos]) {
+        return percents[initPos];
+      }
+
+      var dir = lengths[initPos] > lengthPos ? -1 : 1;
+      var flag = true;
+
+      while (flag) {
+        if (lengths[initPos] <= lengthPos && lengths[initPos + 1] > lengthPos) {
+          lPerc = (lengthPos - lengths[initPos]) / (lengths[initPos + 1] - lengths[initPos]);
+          flag = false;
+        } else {
+          initPos += dir;
+        }
+
+        if (initPos < 0 || initPos >= len - 1) {
+          // FIX for TypedArrays that don't store floating point values with enough accuracy
+          if (initPos === len - 1) {
+            return percents[initPos];
+          }
+
+          flag = false;
+        }
+      }
+
+      return percents[initPos] + (percents[initPos + 1] - percents[initPos]) * lPerc;
+    }
+
+    function getPointInSegment(pt1, pt2, pt3, pt4, percent, bezierData) {
+      var t1 = getDistancePerc(percent, bezierData);
+      var u1 = 1 - t1;
+      var ptX = math.round((u1 * u1 * u1 * pt1[0] + (t1 * u1 * u1 + u1 * t1 * u1 + u1 * u1 * t1) * pt3[0] + (t1 * t1 * u1 + u1 * t1 * t1 + t1 * u1 * t1) * pt4[0] + t1 * t1 * t1 * pt2[0]) * 1000) / 1000;
+      var ptY = math.round((u1 * u1 * u1 * pt1[1] + (t1 * u1 * u1 + u1 * t1 * u1 + u1 * u1 * t1) * pt3[1] + (t1 * t1 * u1 + u1 * t1 * t1 + t1 * u1 * t1) * pt4[1] + t1 * t1 * t1 * pt2[1]) * 1000) / 1000;
+      return [ptX, ptY];
+    }
+
+    var bezierSegmentPoints = createTypedArray('float32', 8);
+
+    function getNewSegment(pt1, pt2, pt3, pt4, startPerc, endPerc, bezierData) {
+      if (startPerc < 0) {
+        startPerc = 0;
+      } else if (startPerc > 1) {
+        startPerc = 1;
+      }
+
+      var t0 = getDistancePerc(startPerc, bezierData);
+      endPerc = endPerc > 1 ? 1 : endPerc;
+      var t1 = getDistancePerc(endPerc, bezierData);
+      var i;
+      var len = pt1.length;
+      var u0 = 1 - t0;
+      var u1 = 1 - t1;
+      var u0u0u0 = u0 * u0 * u0;
+      var t0u0u0_3 = t0 * u0 * u0 * 3; // eslint-disable-line camelcase
+
+      var t0t0u0_3 = t0 * t0 * u0 * 3; // eslint-disable-line camelcase
+
+      var t0t0t0 = t0 * t0 * t0; //
+
+      var u0u0u1 = u0 * u0 * u1;
+      var t0u0u1_3 = t0 * u0 * u1 + u0 * t0 * u1 + u0 * u0 * t1; // eslint-disable-line camelcase
+
+      var t0t0u1_3 = t0 * t0 * u1 + u0 * t0 * t1 + t0 * u0 * t1; // eslint-disable-line camelcase
+
+      var t0t0t1 = t0 * t0 * t1; //
+
+      var u0u1u1 = u0 * u1 * u1;
+      var t0u1u1_3 = t0 * u1 * u1 + u0 * t1 * u1 + u0 * u1 * t1; // eslint-disable-line camelcase
+
+      var t0t1u1_3 = t0 * t1 * u1 + u0 * t1 * t1 + t0 * u1 * t1; // eslint-disable-line camelcase
+
+      var t0t1t1 = t0 * t1 * t1; //
+
+      var u1u1u1 = u1 * u1 * u1;
+      var t1u1u1_3 = t1 * u1 * u1 + u1 * t1 * u1 + u1 * u1 * t1; // eslint-disable-line camelcase
+
+      var t1t1u1_3 = t1 * t1 * u1 + u1 * t1 * t1 + t1 * u1 * t1; // eslint-disable-line camelcase
+
+      var t1t1t1 = t1 * t1 * t1;
+
+      for (i = 0; i < len; i += 1) {
+        bezierSegmentPoints[i * 4] = math.round((u0u0u0 * pt1[i] + t0u0u0_3 * pt3[i] + t0t0u0_3 * pt4[i] + t0t0t0 * pt2[i]) * 1000) / 1000; // eslint-disable-line camelcase
+
+        bezierSegmentPoints[i * 4 + 1] = math.round((u0u0u1 * pt1[i] + t0u0u1_3 * pt3[i] + t0t0u1_3 * pt4[i] + t0t0t1 * pt2[i]) * 1000) / 1000; // eslint-disable-line camelcase
+
+        bezierSegmentPoints[i * 4 + 2] = math.round((u0u1u1 * pt1[i] + t0u1u1_3 * pt3[i] + t0t1u1_3 * pt4[i] + t0t1t1 * pt2[i]) * 1000) / 1000; // eslint-disable-line camelcase
+
+        bezierSegmentPoints[i * 4 + 3] = math.round((u1u1u1 * pt1[i] + t1u1u1_3 * pt3[i] + t1t1u1_3 * pt4[i] + t1t1t1 * pt2[i]) * 1000) / 1000; // eslint-disable-line camelcase
+      }
+
+      return bezierSegmentPoints;
+    }
+
+    return {
+      getSegmentsLength: getSegmentsLength,
+      getNewSegment: getNewSegment,
+      getPointInSegment: getPointInSegment,
+      buildBezierData: buildBezierData,
+      pointOnLine2D: pointOnLine2D,
+      pointOnLine3D: pointOnLine3D
+    };
   }
-};
 
-MaskElement.prototype.destroy = function () {
-  this.element = null;
-  this.globalData = null;
-  this.maskElement = null;
-  this.data = null;
-  this.masksProperties = null;
-};
+  var bez = bezFunction();
 
-/**
- * @file
- * Handles AE's layer parenting property.
- *
- */
+  var PropertyFactory = function () {
+    var initFrame = initialDefaultFrame;
+    var mathAbs = Math.abs;
 
-function HierarchyElement() {}
+    function interpolateValue(frameNum, caching) {
+      var offsetTime = this.offsetTime;
+      var newValue;
 
-HierarchyElement.prototype = {
-  /**
-     * @function
-     * Initializes hierarchy properties
-     *
-     */
-  initHierarchy: function () {
-    // element's parent list
-    this.hierarchy = [];
-    // if element is parent of another layer _isParent will be true
-    this._isParent = false;
-    this.checkParenting();
-  },
-  /**
-     * @function
-     * Sets layer's hierarchy.
-     * @param {array} hierarch
-     * layer's parent list
-     *
-     */
-  setHierarchy: function (hierarchy) {
-    this.hierarchy = hierarchy;
-  },
-  /**
-     * @function
-     * Sets layer as parent.
-     *
-     */
-  setAsParent: function () {
-    this._isParent = true;
-  },
-  /**
-     * @function
-     * Searches layer's parenting chain
-     *
-     */
-  checkParenting: function () {
-    if (this.data.parent !== undefined) {
-      this.comp.buildElementParenting(this, this.data.parent, []);
+      if (this.propType === 'multidimensional') {
+        newValue = createTypedArray('float32', this.pv.length);
+      }
+
+      var iterationIndex = caching.lastIndex;
+      var i = iterationIndex;
+      var len = this.keyframes.length - 1;
+      var flag = true;
+      var keyData;
+      var nextKeyData;
+      var keyframeMetadata;
+
+      while (flag) {
+        keyData = this.keyframes[i];
+        nextKeyData = this.keyframes[i + 1];
+
+        if (i === len - 1 && frameNum >= nextKeyData.t - offsetTime) {
+          if (keyData.h) {
+            keyData = nextKeyData;
+          }
+
+          iterationIndex = 0;
+          break;
+        }
+
+        if (nextKeyData.t - offsetTime > frameNum) {
+          iterationIndex = i;
+          break;
+        }
+
+        if (i < len - 1) {
+          i += 1;
+        } else {
+          iterationIndex = 0;
+          flag = false;
+        }
+      }
+
+      keyframeMetadata = this.keyframesMetadata[i] || {};
+      var k;
+      var kLen;
+      var perc;
+      var jLen;
+      var j;
+      var fnc;
+      var nextKeyTime = nextKeyData.t - offsetTime;
+      var keyTime = keyData.t - offsetTime;
+      var endValue;
+
+      if (keyData.to) {
+        if (!keyframeMetadata.bezierData) {
+          keyframeMetadata.bezierData = bez.buildBezierData(keyData.s, nextKeyData.s || keyData.e, keyData.to, keyData.ti);
+        }
+
+        var bezierData = keyframeMetadata.bezierData;
+
+        if (frameNum >= nextKeyTime || frameNum < keyTime) {
+          var ind = frameNum >= nextKeyTime ? bezierData.points.length - 1 : 0;
+          kLen = bezierData.points[ind].point.length;
+
+          for (k = 0; k < kLen; k += 1) {
+            newValue[k] = bezierData.points[ind].point[k];
+          } // caching._lastKeyframeIndex = -1;
+
+        } else {
+          if (keyframeMetadata.__fnct) {
+            fnc = keyframeMetadata.__fnct;
+          } else {
+            fnc = BezierFactory.getBezierEasing(keyData.o.x, keyData.o.y, keyData.i.x, keyData.i.y, keyData.n).get;
+            keyframeMetadata.__fnct = fnc;
+          }
+
+          perc = fnc((frameNum - keyTime) / (nextKeyTime - keyTime));
+          var distanceInLine = bezierData.segmentLength * perc;
+          var segmentPerc;
+          var addedLength = caching.lastFrame < frameNum && caching._lastKeyframeIndex === i ? caching._lastAddedLength : 0;
+          j = caching.lastFrame < frameNum && caching._lastKeyframeIndex === i ? caching._lastPoint : 0;
+          flag = true;
+          jLen = bezierData.points.length;
+
+          while (flag) {
+            addedLength += bezierData.points[j].partialLength;
+
+            if (distanceInLine === 0 || perc === 0 || j === bezierData.points.length - 1) {
+              kLen = bezierData.points[j].point.length;
+
+              for (k = 0; k < kLen; k += 1) {
+                newValue[k] = bezierData.points[j].point[k];
+              }
+
+              break;
+            } else if (distanceInLine >= addedLength && distanceInLine < addedLength + bezierData.points[j + 1].partialLength) {
+              segmentPerc = (distanceInLine - addedLength) / bezierData.points[j + 1].partialLength;
+              kLen = bezierData.points[j].point.length;
+
+              for (k = 0; k < kLen; k += 1) {
+                newValue[k] = bezierData.points[j].point[k] + (bezierData.points[j + 1].point[k] - bezierData.points[j].point[k]) * segmentPerc;
+              }
+
+              break;
+            }
+
+            if (j < jLen - 1) {
+              j += 1;
+            } else {
+              flag = false;
+            }
+          }
+
+          caching._lastPoint = j;
+          caching._lastAddedLength = addedLength - bezierData.points[j].partialLength;
+          caching._lastKeyframeIndex = i;
+        }
+      } else {
+        var outX;
+        var outY;
+        var inX;
+        var inY;
+        var keyValue;
+        len = keyData.s.length;
+        endValue = nextKeyData.s || keyData.e;
+
+        if (this.sh && keyData.h !== 1) {
+          if (frameNum >= nextKeyTime) {
+            newValue[0] = endValue[0];
+            newValue[1] = endValue[1];
+            newValue[2] = endValue[2];
+          } else if (frameNum <= keyTime) {
+            newValue[0] = keyData.s[0];
+            newValue[1] = keyData.s[1];
+            newValue[2] = keyData.s[2];
+          } else {
+            var quatStart = createQuaternion(keyData.s);
+            var quatEnd = createQuaternion(endValue);
+            var time = (frameNum - keyTime) / (nextKeyTime - keyTime);
+            quaternionToEuler(newValue, slerp(quatStart, quatEnd, time));
+          }
+        } else {
+          for (i = 0; i < len; i += 1) {
+            if (keyData.h !== 1) {
+              if (frameNum >= nextKeyTime) {
+                perc = 1;
+              } else if (frameNum < keyTime) {
+                perc = 0;
+              } else {
+                if (keyData.o.x.constructor === Array) {
+                  if (!keyframeMetadata.__fnct) {
+                    keyframeMetadata.__fnct = [];
+                  }
+
+                  if (!keyframeMetadata.__fnct[i]) {
+                    outX = keyData.o.x[i] === undefined ? keyData.o.x[0] : keyData.o.x[i];
+                    outY = keyData.o.y[i] === undefined ? keyData.o.y[0] : keyData.o.y[i];
+                    inX = keyData.i.x[i] === undefined ? keyData.i.x[0] : keyData.i.x[i];
+                    inY = keyData.i.y[i] === undefined ? keyData.i.y[0] : keyData.i.y[i];
+                    fnc = BezierFactory.getBezierEasing(outX, outY, inX, inY).get;
+                    keyframeMetadata.__fnct[i] = fnc;
+                  } else {
+                    fnc = keyframeMetadata.__fnct[i];
+                  }
+                } else if (!keyframeMetadata.__fnct) {
+                  outX = keyData.o.x;
+                  outY = keyData.o.y;
+                  inX = keyData.i.x;
+                  inY = keyData.i.y;
+                  fnc = BezierFactory.getBezierEasing(outX, outY, inX, inY).get;
+                  keyData.keyframeMetadata = fnc;
+                } else {
+                  fnc = keyframeMetadata.__fnct;
+                }
+
+                perc = fnc((frameNum - keyTime) / (nextKeyTime - keyTime));
+              }
+            }
+
+            endValue = nextKeyData.s || keyData.e;
+            keyValue = keyData.h === 1 ? keyData.s[i] : keyData.s[i] + (endValue[i] - keyData.s[i]) * perc;
+
+            if (this.propType === 'multidimensional') {
+              newValue[i] = keyValue;
+            } else {
+              newValue = keyValue;
+            }
+          }
+        }
+      }
+
+      caching.lastIndex = iterationIndex;
+      return newValue;
+    } // based on @Toji's https://github.com/toji/gl-matrix/
+
+
+    function slerp(a, b, t) {
+      var out = [];
+      var ax = a[0];
+      var ay = a[1];
+      var az = a[2];
+      var aw = a[3];
+      var bx = b[0];
+      var by = b[1];
+      var bz = b[2];
+      var bw = b[3];
+      var omega;
+      var cosom;
+      var sinom;
+      var scale0;
+      var scale1;
+      cosom = ax * bx + ay * by + az * bz + aw * bw;
+
+      if (cosom < 0.0) {
+        cosom = -cosom;
+        bx = -bx;
+        by = -by;
+        bz = -bz;
+        bw = -bw;
+      }
+
+      if (1.0 - cosom > 0.000001) {
+        omega = Math.acos(cosom);
+        sinom = Math.sin(omega);
+        scale0 = Math.sin((1.0 - t) * omega) / sinom;
+        scale1 = Math.sin(t * omega) / sinom;
+      } else {
+        scale0 = 1.0 - t;
+        scale1 = t;
+      }
+
+      out[0] = scale0 * ax + scale1 * bx;
+      out[1] = scale0 * ay + scale1 * by;
+      out[2] = scale0 * az + scale1 * bz;
+      out[3] = scale0 * aw + scale1 * bw;
+      return out;
     }
-  },
-};
 
-/**
- * @file
- * Handles element's layer frame update.
- * Checks layer in point and out point
- *
- */
+    function quaternionToEuler(out, quat) {
+      var qx = quat[0];
+      var qy = quat[1];
+      var qz = quat[2];
+      var qw = quat[3];
+      var heading = Math.atan2(2 * qy * qw - 2 * qx * qz, 1 - 2 * qy * qy - 2 * qz * qz);
+      var attitude = Math.asin(2 * qx * qy + 2 * qz * qw);
+      var bank = Math.atan2(2 * qx * qw - 2 * qy * qz, 1 - 2 * qx * qx - 2 * qz * qz);
+      out[0] = heading / degToRads;
+      out[1] = attitude / degToRads;
+      out[2] = bank / degToRads;
+    }
 
-function FrameElement() {}
+    function createQuaternion(values) {
+      var heading = values[0] * degToRads;
+      var attitude = values[1] * degToRads;
+      var bank = values[2] * degToRads;
+      var c1 = Math.cos(heading / 2);
+      var c2 = Math.cos(attitude / 2);
+      var c3 = Math.cos(bank / 2);
+      var s1 = Math.sin(heading / 2);
+      var s2 = Math.sin(attitude / 2);
+      var s3 = Math.sin(bank / 2);
+      var w = c1 * c2 * c3 - s1 * s2 * s3;
+      var x = s1 * s2 * c3 + c1 * c2 * s3;
+      var y = s1 * c2 * c3 + c1 * s2 * s3;
+      var z = c1 * s2 * c3 - s1 * c2 * s3;
+      return [x, y, z, w];
+    }
 
-FrameElement.prototype = {
-  /**
-     * @function
-     * Initializes frame related properties.
-     *
-     */
-  initFrame: function () {
-    // set to true when inpoint is rendered
-    this._isFirstFrame = false;
-    // list of animated properties
-    this.dynamicProperties = [];
-    // If layer has been modified in current tick this will be true
-    this._mdf = false;
-  },
-  /**
-     * @function
-     * Calculates all dynamic values
-     *
-     * @param {number} num
-     * current frame number in Layer's time
-     * @param {boolean} isVisible
-     * if layers is currently in range
-     *
-     */
-  prepareProperties: function (num, isVisible) {
-    var i;
-    var len = this.dynamicProperties.length;
-    for (i = 0; i < len; i += 1) {
-      if (isVisible || (this._isParent && this.dynamicProperties[i].propType === 'transform')) {
-        this.dynamicProperties[i].getValue();
-        if (this.dynamicProperties[i]._mdf) {
-          this.globalData._mdf = true;
+    function getValueAtCurrentTime() {
+      var frameNum = this.comp.renderedFrame - this.offsetTime;
+      var initTime = this.keyframes[0].t - this.offsetTime;
+      var endTime = this.keyframes[this.keyframes.length - 1].t - this.offsetTime;
+
+      if (!(frameNum === this._caching.lastFrame || this._caching.lastFrame !== initFrame && (this._caching.lastFrame >= endTime && frameNum >= endTime || this._caching.lastFrame < initTime && frameNum < initTime))) {
+        if (this._caching.lastFrame >= frameNum) {
+          this._caching._lastKeyframeIndex = -1;
+          this._caching.lastIndex = 0;
+        }
+
+        var renderResult = this.interpolateValue(frameNum, this._caching);
+        this.pv = renderResult;
+      }
+
+      this._caching.lastFrame = frameNum;
+      return this.pv;
+    }
+
+    function setVValue(val) {
+      var multipliedValue;
+
+      if (this.propType === 'unidimensional') {
+        multipliedValue = val * this.mult;
+
+        if (mathAbs(this.v - multipliedValue) > 0.00001) {
+          this.v = multipliedValue;
           this._mdf = true;
         }
-      }
-    }
-  },
-  addDynamicProperty: function (prop) {
-    if (this.dynamicProperties.indexOf(prop) === -1) {
-      this.dynamicProperties.push(prop);
-    }
-  },
-};
+      } else {
+        var i = 0;
+        var len = this.v.length;
 
-/* global TransformPropertyFactory, Matrix */
-
-function TransformElement() {}
-
-TransformElement.prototype = {
-  initTransform: function () {
-    this.finalTransform = {
-      mProp: this.data.ks ? TransformPropertyFactory.getTransformProperty(this, this.data.ks, this) : { o: 0 },
-      _matMdf: false,
-      _opMdf: false,
-      mat: new Matrix(),
-    };
-    if (this.data.ao) {
-      this.finalTransform.mProp.autoOriented = true;
-    }
-
-    // TODO: check TYPE 11: Guided elements
-    if (this.data.ty !== 11) {
-      // this.createElements();
-    }
-  },
-  renderTransform: function () {
-    this.finalTransform._opMdf = this.finalTransform.mProp.o._mdf || this._isFirstFrame;
-    this.finalTransform._matMdf = this.finalTransform.mProp._mdf || this._isFirstFrame;
-
-    if (this.hierarchy) {
-      var mat;
-      var finalMat = this.finalTransform.mat;
-      var i = 0;
-      var len = this.hierarchy.length;
-      // Checking if any of the transformation matrices in the hierarchy chain has changed.
-      if (!this.finalTransform._matMdf) {
         while (i < len) {
-          if (this.hierarchy[i].finalTransform.mProp._mdf) {
-            this.finalTransform._matMdf = true;
-            break;
+          multipliedValue = val[i] * this.mult;
+
+          if (mathAbs(this.v[i] - multipliedValue) > 0.00001) {
+            this.v[i] = multipliedValue;
+            this._mdf = true;
           }
+
           i += 1;
         }
       }
+    }
 
-      if (this.finalTransform._matMdf) {
-        mat = this.finalTransform.mProp.v.props;
-        finalMat.cloneFromProps(mat);
-        for (i = 0; i < len; i += 1) {
-          mat = this.hierarchy[i].finalTransform.mProp.v.props;
-          finalMat.transform(mat[0], mat[1], mat[2], mat[3], mat[4], mat[5], mat[6], mat[7], mat[8], mat[9], mat[10], mat[11], mat[12], mat[13], mat[14], mat[15]);
-        }
-      }
-    }
-  },
-  globalToLocal: function (pt) {
-    var transforms = [];
-    transforms.push(this.finalTransform);
-    var flag = true;
-    var comp = this.comp;
-    while (flag) {
-      if (comp.finalTransform) {
-        if (comp.data.hasMask) {
-          transforms.splice(0, 0, comp.finalTransform);
-        }
-        comp = comp.comp;
-      } else {
-        flag = false;
-      }
-    }
-    var i;
-    var len = transforms.length;
-    var ptNew;
-    for (i = 0; i < len; i += 1) {
-      ptNew = transforms[i].mat.applyToPointArray(0, 0, 0);
-      // ptNew = transforms[i].mat.applyToPointArray(pt[0],pt[1],pt[2]);
-      pt = [pt[0] - ptNew[0], pt[1] - ptNew[1], 0];
-    }
-    return pt;
-  },
-  mHelper: new Matrix(),
-};
-
-function RenderableElement() {
-
-}
-
-RenderableElement.prototype = {
-  initRenderable: function () {
-    // layer's visibility related to inpoint and outpoint. Rename isVisible to isInRange
-    this.isInRange = false;
-    // layer's display state
-    this.hidden = false;
-    // If layer's transparency equals 0, it can be hidden
-    this.isTransparent = false;
-    // list of animated components
-    this.renderableComponents = [];
-  },
-  addRenderableComponent: function (component) {
-    if (this.renderableComponents.indexOf(component) === -1) {
-      this.renderableComponents.push(component);
-    }
-  },
-  removeRenderableComponent: function (component) {
-    if (this.renderableComponents.indexOf(component) !== -1) {
-      this.renderableComponents.splice(this.renderableComponents.indexOf(component), 1);
-    }
-  },
-  prepareRenderableFrame: function (num) {
-    this.checkLayerLimits(num);
-  },
-  checkTransparency: function () {
-    if (this.finalTransform.mProp.o.v <= 0) {
-      if (!this.isTransparent && this.globalData.renderConfig.hideOnTransparent) {
-        this.isTransparent = true;
-        this.hide();
-      }
-    } else if (this.isTransparent) {
-      this.isTransparent = false;
-      this.show();
-    }
-  },
-  /**
-     * @function
-     * Initializes frame related properties.
-     *
-     * @param {number} num
-     * current frame number in Layer's time
-     *
-     */
-  checkLayerLimits: function (num) {
-    if (this.data.ip - this.data.st <= num && this.data.op - this.data.st > num) {
-      if (this.isInRange !== true) {
-        this.globalData._mdf = true;
-        this._mdf = true;
-        this.isInRange = true;
-        this.show();
-      }
-    } else if (this.isInRange !== false) {
-      this.globalData._mdf = true;
-      this.isInRange = false;
-      this.hide();
-    }
-  },
-  renderRenderable: function () {
-    var i;
-    var len = this.renderableComponents.length;
-    for (i = 0; i < len; i += 1) {
-      this.renderableComponents[i].renderFrame(this._isFirstFrame);
-    }
-    /* this.maskManager.renderFrame(this.finalTransform.mat);
-        this.renderableEffectsManager.renderFrame(this._isFirstFrame); */
-  },
-  sourceRectAtTime: function () {
-    return {
-      top: 0,
-      left: 0,
-      width: 100,
-      height: 100,
-    };
-  },
-  getLayerSize: function () {
-    if (this.data.ty === 5) {
-      return { w: this.data.textData.width, h: this.data.textData.height };
-    }
-    return { w: this.data.width, h: this.data.height };
-  },
-};
-
-/* global extendPrototype, RenderableElement, createProxyFunction */
-
-function RenderableDOMElement() {}
-
-(function () {
-  var _prototype = {
-    initElement: function (data, globalData, comp) {
-      this.initFrame();
-      this.initBaseData(data, globalData, comp);
-      this.initTransform(data, globalData, comp);
-      this.initHierarchy();
-      this.initRenderable();
-      this.initRendererElement();
-      this.createContainerElements();
-      this.createRenderableComponents();
-      this.createContent();
-      this.hide();
-    },
-    hide: function () {
-      if (!this.hidden && (!this.isInRange || this.isTransparent)) {
-        var elem = this.baseElement || this.layerElement;
-        elem.style.display = 'none';
-        this.hidden = true;
-      }
-    },
-    show: function () {
-      if (this.isInRange && !this.isTransparent) {
-        if (!this.data.hd) {
-          var elem = this.baseElement || this.layerElement;
-          elem.style.display = 'block';
-        }
-        this.hidden = false;
-        this._isFirstFrame = true;
-      }
-    },
-    renderFrame: function () {
-      // If it is exported as hidden (data.hd === true) no need to render
-      // If it is not visible no need to render
-      if (this.data.hd || this.hidden) {
+    function processEffectsSequence() {
+      if (this.elem.globalData.frameId === this.frameId || !this.effectsSequence.length) {
         return;
       }
-      this.renderTransform();
-      this.renderRenderable();
-      this.renderElement();
-      this.renderInnerContent();
-      if (this._isFirstFrame) {
-        this._isFirstFrame = false;
+
+      if (this.lock) {
+        this.setVValue(this.pv);
+        return;
       }
-    },
-    renderInnerContent: function () {},
-    prepareFrame: function (num) {
+
+      this.lock = true;
+      this._mdf = this._isFirstFrame;
+      var i;
+      var len = this.effectsSequence.length;
+      var finalValue = this.kf ? this.pv : this.data.k;
+
+      for (i = 0; i < len; i += 1) {
+        finalValue = this.effectsSequence[i](finalValue);
+      }
+
+      this.setVValue(finalValue);
+      this._isFirstFrame = false;
+      this.lock = false;
+      this.frameId = this.elem.globalData.frameId;
+    }
+
+    function addEffect(effectFunction) {
+      this.effectsSequence.push(effectFunction);
+      this.container.addDynamicProperty(this);
+    }
+
+    function ValueProperty(elem, data, mult, container) {
+      this.propType = 'unidimensional';
+      this.mult = mult || 1;
+      this.data = data;
+      this.v = mult ? data.k * mult : data.k;
+      this.pv = data.k;
       this._mdf = false;
-      this.prepareRenderableFrame(num);
-      this.prepareProperties(num, this.isInRange);
-      this.checkTransparency();
-    },
-    destroy: function () {
-      this.innerElem = null;
-      this.destroyBaseElement();
-    },
-  };
-  extendPrototype([RenderableElement, createProxyFunction(_prototype)], RenderableDOMElement);
-}());
-
-/* exported ProcessedElement */
-
-function ProcessedElement(element, position) {
-  this.elem = element;
-  this.pos = position;
-}
-
-/* global createNS */
-
-function SVGStyleData(data, level) {
-  this.data = data;
-  this.type = data.ty;
-  this.d = '';
-  this.lvl = level;
-  this._mdf = false;
-  this.closed = data.hd === true;
-  this.pElem = createNS('path');
-  this.msElem = null;
-}
-
-SVGStyleData.prototype.reset = function () {
-  this.d = '';
-  this._mdf = false;
-};
-
-function SVGShapeData(transformers, level, shape) {
-  this.caches = [];
-  this.styles = [];
-  this.transformers = transformers;
-  this.lStr = '';
-  this.sh = shape;
-  this.lvl = level;
-  // TODO find if there are some cases where _isAnimated can be false.
-  // For now, since shapes add up with other shapes. They have to be calculated every time.
-  // One way of finding out is checking if all styles associated to this shape depend only of this shape
-  this._isAnimated = !!shape.k;
-  // TODO: commenting this for now since all shapes are animated
-  var i = 0;
-  var len = transformers.length;
-  while (i < len) {
-    if (transformers[i].mProps.dynamicProperties.length) {
-      this._isAnimated = true;
-      break;
+      this.elem = elem;
+      this.container = container;
+      this.comp = elem.comp;
+      this.k = false;
+      this.kf = false;
+      this.vel = 0;
+      this.effectsSequence = [];
+      this._isFirstFrame = true;
+      this.getValue = processEffectsSequence;
+      this.setVValue = setVValue;
+      this.addEffect = addEffect;
     }
-    i += 1;
-  }
-}
 
-SVGShapeData.prototype.setAsAnimated = function () {
-  this._isAnimated = true;
-};
+    function MultiDimensionalProperty(elem, data, mult, container) {
+      this.propType = 'multidimensional';
+      this.mult = mult || 1;
+      this.data = data;
+      this._mdf = false;
+      this.elem = elem;
+      this.container = container;
+      this.comp = elem.comp;
+      this.k = false;
+      this.kf = false;
+      this.frameId = -1;
+      var i;
+      var len = data.k.length;
+      this.v = createTypedArray('float32', len);
+      this.pv = createTypedArray('float32', len);
+      this.vel = createTypedArray('float32', len);
 
-/* exported SVGTransformData */
+      for (i = 0; i < len; i += 1) {
+        this.v[i] = data.k[i] * this.mult;
+        this.pv[i] = data.k[i];
+      }
 
-function SVGTransformData(mProps, op, container) {
-  this.transform = {
-    mProps: mProps,
-    op: op,
-    container: container,
-  };
-  this.elements = [];
-  this._isAnimated = this.transform.mProps.dynamicProperties.length || this.transform.op.effectsSequence.length;
-}
-
-/* global DashProperty, PropertyFactory, extendPrototype, DynamicPropertyContainer */
-
-function SVGStrokeStyleData(elem, data, styleOb) {
-  this.initDynamicPropertyContainer(elem);
-  this.getValue = this.iterateDynamicProperties;
-  this.o = PropertyFactory.getProp(elem, data.o, 0, 0.01, this);
-  this.w = PropertyFactory.getProp(elem, data.w, 0, null, this);
-  this.d = new DashProperty(elem, data.d || {}, 'svg', this);
-  this.c = PropertyFactory.getProp(elem, data.c, 1, 255, this);
-  this.style = styleOb;
-  this._isAnimated = !!this._isAnimated;
-}
-
-extendPrototype([DynamicPropertyContainer], SVGStrokeStyleData);
-
-/* global PropertyFactory, extendPrototype, DynamicPropertyContainer */
-
-function SVGFillStyleData(elem, data, styleOb) {
-  this.initDynamicPropertyContainer(elem);
-  this.getValue = this.iterateDynamicProperties;
-  this.o = PropertyFactory.getProp(elem, data.o, 0, 0.01, this);
-  this.c = PropertyFactory.getProp(elem, data.c, 1, 255, this);
-  this.style = styleOb;
-}
-
-extendPrototype([DynamicPropertyContainer], SVGFillStyleData);
-
-/* global PropertyFactory, degToRads, GradientProperty, createElementID, createNS, locationHref,
-extendPrototype, DynamicPropertyContainer, lineCapEnum, lineJoinEnum */
-
-function SVGGradientFillStyleData(elem, data, styleOb) {
-  this.initDynamicPropertyContainer(elem);
-  this.getValue = this.iterateDynamicProperties;
-  this.initGradientData(elem, data, styleOb);
-}
-
-SVGGradientFillStyleData.prototype.initGradientData = function (elem, data, styleOb) {
-  this.o = PropertyFactory.getProp(elem, data.o, 0, 0.01, this);
-  this.s = PropertyFactory.getProp(elem, data.s, 1, null, this);
-  this.e = PropertyFactory.getProp(elem, data.e, 1, null, this);
-  this.h = PropertyFactory.getProp(elem, data.h || { k: 0 }, 0, 0.01, this);
-  this.a = PropertyFactory.getProp(elem, data.a || { k: 0 }, 0, degToRads, this);
-  this.g = new GradientProperty(elem, data.g, this);
-  this.style = styleOb;
-  this.stops = [];
-  this.setGradientData(styleOb.pElem, data);
-  this.setGradientOpacity(data, styleOb);
-  this._isAnimated = !!this._isAnimated;
-};
-
-SVGGradientFillStyleData.prototype.setGradientData = function (pathElement, data) {
-  var gradientId = createElementID();
-  var gfill = createNS(data.t === 1 ? 'linearGradient' : 'radialGradient');
-  gfill.setAttribute('id', gradientId);
-  gfill.setAttribute('spreadMethod', 'pad');
-  gfill.setAttribute('gradientUnits', 'userSpaceOnUse');
-  var stops = [];
-  var stop;
-  var j;
-  var jLen;
-  jLen = data.g.p * 4;
-  for (j = 0; j < jLen; j += 4) {
-    stop = createNS('stop');
-    gfill.appendChild(stop);
-    stops.push(stop);
-  }
-  pathElement.setAttribute(data.ty === 'gf' ? 'fill' : 'stroke', 'url(' + locationHref + '#' + gradientId + ')');
-  this.gf = gfill;
-  this.cst = stops;
-};
-
-SVGGradientFillStyleData.prototype.setGradientOpacity = function (data, styleOb) {
-  if (this.g._hasOpacity && !this.g._collapsable) {
-    var stop;
-    var j;
-    var jLen;
-    var mask = createNS('mask');
-    var maskElement = createNS('path');
-    mask.appendChild(maskElement);
-    var opacityId = createElementID();
-    var maskId = createElementID();
-    mask.setAttribute('id', maskId);
-    var opFill = createNS(data.t === 1 ? 'linearGradient' : 'radialGradient');
-    opFill.setAttribute('id', opacityId);
-    opFill.setAttribute('spreadMethod', 'pad');
-    opFill.setAttribute('gradientUnits', 'userSpaceOnUse');
-    jLen = data.g.k.k[0].s ? data.g.k.k[0].s.length : data.g.k.k.length;
-    var stops = this.stops;
-    for (j = data.g.p * 4; j < jLen; j += 2) {
-      stop = createNS('stop');
-      stop.setAttribute('stop-color', 'rgb(255,255,255)');
-      opFill.appendChild(stop);
-      stops.push(stop);
+      this._isFirstFrame = true;
+      this.effectsSequence = [];
+      this.getValue = processEffectsSequence;
+      this.setVValue = setVValue;
+      this.addEffect = addEffect;
     }
-    maskElement.setAttribute(data.ty === 'gf' ? 'fill' : 'stroke', 'url(' + locationHref + '#' + opacityId + ')');
-    if (data.ty === 'gs') {
-      maskElement.setAttribute('stroke-linecap', lineCapEnum[data.lc || 2]);
-      maskElement.setAttribute('stroke-linejoin', lineJoinEnum[data.lj || 2]);
-      if (data.lj === 1) {
-        maskElement.setAttribute('stroke-miterlimit', data.ml);
+
+    function KeyframedValueProperty(elem, data, mult, container) {
+      this.propType = 'unidimensional';
+      this.keyframes = data.k;
+      this.keyframesMetadata = [];
+      this.offsetTime = elem.data.st;
+      this.frameId = -1;
+      this._caching = {
+        lastFrame: initFrame,
+        lastIndex: 0,
+        value: 0,
+        _lastKeyframeIndex: -1
+      };
+      this.k = true;
+      this.kf = true;
+      this.data = data;
+      this.mult = mult || 1;
+      this.elem = elem;
+      this.container = container;
+      this.comp = elem.comp;
+      this.v = initFrame;
+      this.pv = initFrame;
+      this._isFirstFrame = true;
+      this.getValue = processEffectsSequence;
+      this.setVValue = setVValue;
+      this.interpolateValue = interpolateValue;
+      this.effectsSequence = [getValueAtCurrentTime.bind(this)];
+      this.addEffect = addEffect;
+    }
+
+    function KeyframedMultidimensionalProperty(elem, data, mult, container) {
+      this.propType = 'multidimensional';
+      var i;
+      var len = data.k.length;
+      var s;
+      var e;
+      var to;
+      var ti;
+
+      for (i = 0; i < len - 1; i += 1) {
+        if (data.k[i].to && data.k[i].s && data.k[i + 1] && data.k[i + 1].s) {
+          s = data.k[i].s;
+          e = data.k[i + 1].s;
+          to = data.k[i].to;
+          ti = data.k[i].ti;
+
+          if (s.length === 2 && !(s[0] === e[0] && s[1] === e[1]) && bez.pointOnLine2D(s[0], s[1], e[0], e[1], s[0] + to[0], s[1] + to[1]) && bez.pointOnLine2D(s[0], s[1], e[0], e[1], e[0] + ti[0], e[1] + ti[1]) || s.length === 3 && !(s[0] === e[0] && s[1] === e[1] && s[2] === e[2]) && bez.pointOnLine3D(s[0], s[1], s[2], e[0], e[1], e[2], s[0] + to[0], s[1] + to[1], s[2] + to[2]) && bez.pointOnLine3D(s[0], s[1], s[2], e[0], e[1], e[2], e[0] + ti[0], e[1] + ti[1], e[2] + ti[2])) {
+            data.k[i].to = null;
+            data.k[i].ti = null;
+          }
+
+          if (s[0] === e[0] && s[1] === e[1] && to[0] === 0 && to[1] === 0 && ti[0] === 0 && ti[1] === 0) {
+            if (s.length === 2 || s[2] === e[2] && to[2] === 0 && ti[2] === 0) {
+              data.k[i].to = null;
+              data.k[i].ti = null;
+            }
+          }
+        }
+      }
+
+      this.effectsSequence = [getValueAtCurrentTime.bind(this)];
+      this.data = data;
+      this.keyframes = data.k;
+      this.keyframesMetadata = [];
+      this.offsetTime = elem.data.st;
+      this.k = true;
+      this.kf = true;
+      this._isFirstFrame = true;
+      this.mult = mult || 1;
+      this.elem = elem;
+      this.container = container;
+      this.comp = elem.comp;
+      this.getValue = processEffectsSequence;
+      this.setVValue = setVValue;
+      this.interpolateValue = interpolateValue;
+      this.frameId = -1;
+      var arrLen = data.k[0].s.length;
+      this.v = createTypedArray('float32', arrLen);
+      this.pv = createTypedArray('float32', arrLen);
+
+      for (i = 0; i < arrLen; i += 1) {
+        this.v[i] = initFrame;
+        this.pv[i] = initFrame;
+      }
+
+      this._caching = {
+        lastFrame: initFrame,
+        lastIndex: 0,
+        value: createTypedArray('float32', arrLen)
+      };
+      this.addEffect = addEffect;
+    }
+
+    function getProp(elem, data, type, mult, container) {
+      var p;
+
+      if (!data.k.length) {
+        p = new ValueProperty(elem, data, mult, container);
+      } else if (typeof data.k[0] === 'number') {
+        p = new MultiDimensionalProperty(elem, data, mult, container);
+      } else {
+        switch (type) {
+          case 0:
+            p = new KeyframedValueProperty(elem, data, mult, container);
+            break;
+
+          case 1:
+            p = new KeyframedMultidimensionalProperty(elem, data, mult, container);
+            break;
+
+          default:
+            break;
+        }
+      }
+
+      if (p.effectsSequence.length) {
+        container.addDynamicProperty(p);
+      }
+
+      return p;
+    }
+
+    var ob = {
+      getProp: getProp
+    };
+    return ob;
+  }();
+
+  function DynamicPropertyContainer() {}
+
+  DynamicPropertyContainer.prototype = {
+    addDynamicProperty: function addDynamicProperty(prop) {
+      if (this.dynamicProperties.indexOf(prop) === -1) {
+        this.dynamicProperties.push(prop);
+        this.container.addDynamicProperty(this);
+        this._isAnimated = true;
+      }
+    },
+    iterateDynamicProperties: function iterateDynamicProperties() {
+      this._mdf = false;
+      var i;
+      var len = this.dynamicProperties.length;
+
+      for (i = 0; i < len; i += 1) {
+        this.dynamicProperties[i].getValue();
+
+        if (this.dynamicProperties[i]._mdf) {
+          this._mdf = true;
+        }
+      }
+    },
+    initDynamicPropertyContainer: function initDynamicPropertyContainer(container) {
+      this.container = container;
+      this.dynamicProperties = [];
+      this._mdf = false;
+      this._isAnimated = false;
+    }
+  };
+
+  var pointPool = function () {
+    function create() {
+      return createTypedArray('float32', 2);
+    }
+
+    return poolFactory(8, create);
+  }();
+
+  function ShapePath() {
+    this.c = false;
+    this._length = 0;
+    this._maxLength = 8;
+    this.v = createSizedArray(this._maxLength);
+    this.o = createSizedArray(this._maxLength);
+    this.i = createSizedArray(this._maxLength);
+  }
+
+  ShapePath.prototype.setPathData = function (closed, len) {
+    this.c = closed;
+    this.setLength(len);
+    var i = 0;
+
+    while (i < len) {
+      this.v[i] = pointPool.newElement();
+      this.o[i] = pointPool.newElement();
+      this.i[i] = pointPool.newElement();
+      i += 1;
+    }
+  };
+
+  ShapePath.prototype.setLength = function (len) {
+    while (this._maxLength < len) {
+      this.doubleArrayLength();
+    }
+
+    this._length = len;
+  };
+
+  ShapePath.prototype.doubleArrayLength = function () {
+    this.v = this.v.concat(createSizedArray(this._maxLength));
+    this.i = this.i.concat(createSizedArray(this._maxLength));
+    this.o = this.o.concat(createSizedArray(this._maxLength));
+    this._maxLength *= 2;
+  };
+
+  ShapePath.prototype.setXYAt = function (x, y, type, pos, replace) {
+    var arr;
+    this._length = Math.max(this._length, pos + 1);
+
+    if (this._length >= this._maxLength) {
+      this.doubleArrayLength();
+    }
+
+    switch (type) {
+      case 'v':
+        arr = this.v;
+        break;
+
+      case 'i':
+        arr = this.i;
+        break;
+
+      case 'o':
+        arr = this.o;
+        break;
+
+      default:
+        arr = [];
+        break;
+    }
+
+    if (!arr[pos] || arr[pos] && !replace) {
+      arr[pos] = pointPool.newElement();
+    }
+
+    arr[pos][0] = x;
+    arr[pos][1] = y;
+  };
+
+  ShapePath.prototype.setTripleAt = function (vX, vY, oX, oY, iX, iY, pos, replace) {
+    this.setXYAt(vX, vY, 'v', pos, replace);
+    this.setXYAt(oX, oY, 'o', pos, replace);
+    this.setXYAt(iX, iY, 'i', pos, replace);
+  };
+
+  ShapePath.prototype.reverse = function () {
+    var newPath = new ShapePath();
+    newPath.setPathData(this.c, this._length);
+    var vertices = this.v;
+    var outPoints = this.o;
+    var inPoints = this.i;
+    var init = 0;
+
+    if (this.c) {
+      newPath.setTripleAt(vertices[0][0], vertices[0][1], inPoints[0][0], inPoints[0][1], outPoints[0][0], outPoints[0][1], 0, false);
+      init = 1;
+    }
+
+    var cnt = this._length - 1;
+    var len = this._length;
+    var i;
+
+    for (i = init; i < len; i += 1) {
+      newPath.setTripleAt(vertices[cnt][0], vertices[cnt][1], inPoints[cnt][0], inPoints[cnt][1], outPoints[cnt][0], outPoints[cnt][1], i, false);
+      cnt -= 1;
+    }
+
+    return newPath;
+  };
+
+  var shapePool = function () {
+    function create() {
+      return new ShapePath();
+    }
+
+    function release(shapePath) {
+      var len = shapePath._length;
+      var i;
+
+      for (i = 0; i < len; i += 1) {
+        pointPool.release(shapePath.v[i]);
+        pointPool.release(shapePath.i[i]);
+        pointPool.release(shapePath.o[i]);
+        shapePath.v[i] = null;
+        shapePath.i[i] = null;
+        shapePath.o[i] = null;
+      }
+
+      shapePath._length = 0;
+      shapePath.c = false;
+    }
+
+    function clone(shape) {
+      var cloned = factory.newElement();
+      var i;
+      var len = shape._length === undefined ? shape.v.length : shape._length;
+      cloned.setLength(len);
+      cloned.c = shape.c;
+
+      for (i = 0; i < len; i += 1) {
+        cloned.setTripleAt(shape.v[i][0], shape.v[i][1], shape.o[i][0], shape.o[i][1], shape.i[i][0], shape.i[i][1], i);
+      }
+
+      return cloned;
+    }
+
+    var factory = poolFactory(4, create, release);
+    factory.clone = clone;
+    return factory;
+  }();
+
+  function ShapeCollection() {
+    this._length = 0;
+    this._maxLength = 4;
+    this.shapes = createSizedArray(this._maxLength);
+  }
+
+  ShapeCollection.prototype.addShape = function (shapeData) {
+    if (this._length === this._maxLength) {
+      this.shapes = this.shapes.concat(createSizedArray(this._maxLength));
+      this._maxLength *= 2;
+    }
+
+    this.shapes[this._length] = shapeData;
+    this._length += 1;
+  };
+
+  ShapeCollection.prototype.releaseShapes = function () {
+    var i;
+
+    for (i = 0; i < this._length; i += 1) {
+      shapePool.release(this.shapes[i]);
+    }
+
+    this._length = 0;
+  };
+
+  var shapeCollectionPool = function () {
+    var ob = {
+      newShapeCollection: newShapeCollection,
+      release: release
+    };
+    var _length = 0;
+    var _maxLength = 4;
+    var pool = createSizedArray(_maxLength);
+
+    function newShapeCollection() {
+      var shapeCollection;
+
+      if (_length) {
+        _length -= 1;
+        shapeCollection = pool[_length];
+      } else {
+        shapeCollection = new ShapeCollection();
+      }
+
+      return shapeCollection;
+    }
+
+    function release(shapeCollection) {
+      var i;
+      var len = shapeCollection._length;
+
+      for (i = 0; i < len; i += 1) {
+        shapePool.release(shapeCollection.shapes[i]);
+      }
+
+      shapeCollection._length = 0;
+
+      if (_length === _maxLength) {
+        pool = pooling["double"](pool);
+        _maxLength *= 2;
+      }
+
+      pool[_length] = shapeCollection;
+      _length += 1;
+    }
+
+    return ob;
+  }();
+
+  var ShapePropertyFactory = function () {
+    var initFrame = -999999;
+
+    function interpolateShape(frameNum, previousValue, caching) {
+      var iterationIndex = caching.lastIndex;
+      var keyPropS;
+      var keyPropE;
+      var isHold;
+      var j;
+      var k;
+      var jLen;
+      var kLen;
+      var perc;
+      var vertexValue;
+      var kf = this.keyframes;
+
+      if (frameNum < kf[0].t - this.offsetTime) {
+        keyPropS = kf[0].s[0];
+        isHold = true;
+        iterationIndex = 0;
+      } else if (frameNum >= kf[kf.length - 1].t - this.offsetTime) {
+        keyPropS = kf[kf.length - 1].s ? kf[kf.length - 1].s[0] : kf[kf.length - 2].e[0];
+        /* if(kf[kf.length - 1].s){
+                  keyPropS = kf[kf.length - 1].s[0];
+              }else{
+                  keyPropS = kf[kf.length - 2].e[0];
+              } */
+
+        isHold = true;
+      } else {
+        var i = iterationIndex;
+        var len = kf.length - 1;
+        var flag = true;
+        var keyData;
+        var nextKeyData;
+        var keyframeMetadata;
+
+        while (flag) {
+          keyData = kf[i];
+          nextKeyData = kf[i + 1];
+
+          if (nextKeyData.t - this.offsetTime > frameNum) {
+            break;
+          }
+
+          if (i < len - 1) {
+            i += 1;
+          } else {
+            flag = false;
+          }
+        }
+
+        keyframeMetadata = this.keyframesMetadata[i] || {};
+        isHold = keyData.h === 1;
+        iterationIndex = i;
+
+        if (!isHold) {
+          if (frameNum >= nextKeyData.t - this.offsetTime) {
+            perc = 1;
+          } else if (frameNum < keyData.t - this.offsetTime) {
+            perc = 0;
+          } else {
+            var fnc;
+
+            if (keyframeMetadata.__fnct) {
+              fnc = keyframeMetadata.__fnct;
+            } else {
+              fnc = BezierFactory.getBezierEasing(keyData.o.x, keyData.o.y, keyData.i.x, keyData.i.y).get;
+              keyframeMetadata.__fnct = fnc;
+            }
+
+            perc = fnc((frameNum - (keyData.t - this.offsetTime)) / (nextKeyData.t - this.offsetTime - (keyData.t - this.offsetTime)));
+          }
+
+          keyPropE = nextKeyData.s ? nextKeyData.s[0] : keyData.e[0];
+        }
+
+        keyPropS = keyData.s[0];
+      }
+
+      jLen = previousValue._length;
+      kLen = keyPropS.i[0].length;
+      caching.lastIndex = iterationIndex;
+
+      for (j = 0; j < jLen; j += 1) {
+        for (k = 0; k < kLen; k += 1) {
+          vertexValue = isHold ? keyPropS.i[j][k] : keyPropS.i[j][k] + (keyPropE.i[j][k] - keyPropS.i[j][k]) * perc;
+          previousValue.i[j][k] = vertexValue;
+          vertexValue = isHold ? keyPropS.o[j][k] : keyPropS.o[j][k] + (keyPropE.o[j][k] - keyPropS.o[j][k]) * perc;
+          previousValue.o[j][k] = vertexValue;
+          vertexValue = isHold ? keyPropS.v[j][k] : keyPropS.v[j][k] + (keyPropE.v[j][k] - keyPropS.v[j][k]) * perc;
+          previousValue.v[j][k] = vertexValue;
+        }
       }
     }
-    this.of = opFill;
-    this.ms = mask;
-    this.ost = stops;
-    this.maskId = maskId;
-    styleOb.msElem = maskElement;
+
+    function interpolateShapeCurrentTime() {
+      var frameNum = this.comp.renderedFrame - this.offsetTime;
+      var initTime = this.keyframes[0].t - this.offsetTime;
+      var endTime = this.keyframes[this.keyframes.length - 1].t - this.offsetTime;
+      var lastFrame = this._caching.lastFrame;
+
+      if (!(lastFrame !== initFrame && (lastFrame < initTime && frameNum < initTime || lastFrame > endTime && frameNum > endTime))) {
+        /// /
+        this._caching.lastIndex = lastFrame < frameNum ? this._caching.lastIndex : 0;
+        this.interpolateShape(frameNum, this.pv, this._caching); /// /
+      }
+
+      this._caching.lastFrame = frameNum;
+      return this.pv;
+    }
+
+    function resetShape() {
+      this.paths = this.localShapeCollection;
+    }
+
+    function shapesEqual(shape1, shape2) {
+      if (shape1._length !== shape2._length || shape1.c !== shape2.c) {
+        return false;
+      }
+
+      var i;
+      var len = shape1._length;
+
+      for (i = 0; i < len; i += 1) {
+        if (shape1.v[i][0] !== shape2.v[i][0] || shape1.v[i][1] !== shape2.v[i][1] || shape1.o[i][0] !== shape2.o[i][0] || shape1.o[i][1] !== shape2.o[i][1] || shape1.i[i][0] !== shape2.i[i][0] || shape1.i[i][1] !== shape2.i[i][1]) {
+          return false;
+        }
+      }
+
+      return true;
+    }
+
+    function setVValue(newPath) {
+      if (!shapesEqual(this.v, newPath)) {
+        this.v = shapePool.clone(newPath);
+        this.localShapeCollection.releaseShapes();
+        this.localShapeCollection.addShape(this.v);
+        this._mdf = true;
+        this.paths = this.localShapeCollection;
+      }
+    }
+
+    function processEffectsSequence() {
+      if (this.elem.globalData.frameId === this.frameId) {
+        return;
+      }
+
+      if (!this.effectsSequence.length) {
+        this._mdf = false;
+        return;
+      }
+
+      if (this.lock) {
+        this.setVValue(this.pv);
+        return;
+      }
+
+      this.lock = true;
+      this._mdf = false;
+      var finalValue;
+
+      if (this.kf) {
+        finalValue = this.pv;
+      } else if (this.data.ks) {
+        finalValue = this.data.ks.k;
+      } else {
+        finalValue = this.data.pt.k;
+      }
+
+      var i;
+      var len = this.effectsSequence.length;
+
+      for (i = 0; i < len; i += 1) {
+        finalValue = this.effectsSequence[i](finalValue);
+      }
+
+      this.setVValue(finalValue);
+      this.lock = false;
+      this.frameId = this.elem.globalData.frameId;
+    }
+
+    function ShapeProperty(elem, data, type) {
+      this.propType = 'shape';
+      this.comp = elem.comp;
+      this.container = elem;
+      this.elem = elem;
+      this.data = data;
+      this.k = false;
+      this.kf = false;
+      this._mdf = false;
+      var pathData = type === 3 ? data.pt.k : data.ks.k;
+      this.v = shapePool.clone(pathData);
+      this.pv = shapePool.clone(this.v);
+      this.localShapeCollection = shapeCollectionPool.newShapeCollection();
+      this.paths = this.localShapeCollection;
+      this.paths.addShape(this.v);
+      this.reset = resetShape;
+      this.effectsSequence = [];
+    }
+
+    function addEffect(effectFunction) {
+      this.effectsSequence.push(effectFunction);
+      this.container.addDynamicProperty(this);
+    }
+
+    ShapeProperty.prototype.interpolateShape = interpolateShape;
+    ShapeProperty.prototype.getValue = processEffectsSequence;
+    ShapeProperty.prototype.setVValue = setVValue;
+    ShapeProperty.prototype.addEffect = addEffect;
+
+    function KeyframedShapeProperty(elem, data, type) {
+      this.propType = 'shape';
+      this.comp = elem.comp;
+      this.elem = elem;
+      this.container = elem;
+      this.offsetTime = elem.data.st;
+      this.keyframes = type === 3 ? data.pt.k : data.ks.k;
+      this.keyframesMetadata = [];
+      this.k = true;
+      this.kf = true;
+      var len = this.keyframes[0].s[0].i.length;
+      this.v = shapePool.newElement();
+      this.v.setPathData(this.keyframes[0].s[0].c, len);
+      this.pv = shapePool.clone(this.v);
+      this.localShapeCollection = shapeCollectionPool.newShapeCollection();
+      this.paths = this.localShapeCollection;
+      this.paths.addShape(this.v);
+      this.lastFrame = initFrame;
+      this.reset = resetShape;
+      this._caching = {
+        lastFrame: initFrame,
+        lastIndex: 0
+      };
+      this.effectsSequence = [interpolateShapeCurrentTime.bind(this)];
+    }
+
+    KeyframedShapeProperty.prototype.getValue = processEffectsSequence;
+    KeyframedShapeProperty.prototype.interpolateShape = interpolateShape;
+    KeyframedShapeProperty.prototype.setVValue = setVValue;
+    KeyframedShapeProperty.prototype.addEffect = addEffect;
+
+    var EllShapeProperty = function () {
+      var cPoint = roundCorner;
+
+      function EllShapePropertyFactory(elem, data) {
+        this.v = shapePool.newElement();
+        this.v.setPathData(true, 4);
+        this.localShapeCollection = shapeCollectionPool.newShapeCollection();
+        this.paths = this.localShapeCollection;
+        this.localShapeCollection.addShape(this.v);
+        this.d = data.d;
+        this.elem = elem;
+        this.comp = elem.comp;
+        this.frameId = -1;
+        this.initDynamicPropertyContainer(elem);
+        this.p = PropertyFactory.getProp(elem, data.p, 1, 0, this);
+        this.s = PropertyFactory.getProp(elem, data.s, 1, 0, this);
+
+        if (this.dynamicProperties.length) {
+          this.k = true;
+        } else {
+          this.k = false;
+          this.convertEllToPath();
+        }
+      }
+
+      EllShapePropertyFactory.prototype = {
+        reset: resetShape,
+        getValue: function getValue() {
+          if (this.elem.globalData.frameId === this.frameId) {
+            return;
+          }
+
+          this.frameId = this.elem.globalData.frameId;
+          this.iterateDynamicProperties();
+
+          if (this._mdf) {
+            this.convertEllToPath();
+          }
+        },
+        convertEllToPath: function convertEllToPath() {
+          var p0 = this.p.v[0];
+          var p1 = this.p.v[1];
+          var s0 = this.s.v[0] / 2;
+          var s1 = this.s.v[1] / 2;
+
+          var _cw = this.d !== 3;
+
+          var _v = this.v;
+          _v.v[0][0] = p0;
+          _v.v[0][1] = p1 - s1;
+          _v.v[1][0] = _cw ? p0 + s0 : p0 - s0;
+          _v.v[1][1] = p1;
+          _v.v[2][0] = p0;
+          _v.v[2][1] = p1 + s1;
+          _v.v[3][0] = _cw ? p0 - s0 : p0 + s0;
+          _v.v[3][1] = p1;
+          _v.i[0][0] = _cw ? p0 - s0 * cPoint : p0 + s0 * cPoint;
+          _v.i[0][1] = p1 - s1;
+          _v.i[1][0] = _cw ? p0 + s0 : p0 - s0;
+          _v.i[1][1] = p1 - s1 * cPoint;
+          _v.i[2][0] = _cw ? p0 + s0 * cPoint : p0 - s0 * cPoint;
+          _v.i[2][1] = p1 + s1;
+          _v.i[3][0] = _cw ? p0 - s0 : p0 + s0;
+          _v.i[3][1] = p1 + s1 * cPoint;
+          _v.o[0][0] = _cw ? p0 + s0 * cPoint : p0 - s0 * cPoint;
+          _v.o[0][1] = p1 - s1;
+          _v.o[1][0] = _cw ? p0 + s0 : p0 - s0;
+          _v.o[1][1] = p1 + s1 * cPoint;
+          _v.o[2][0] = _cw ? p0 - s0 * cPoint : p0 + s0 * cPoint;
+          _v.o[2][1] = p1 + s1;
+          _v.o[3][0] = _cw ? p0 - s0 : p0 + s0;
+          _v.o[3][1] = p1 - s1 * cPoint;
+        }
+      };
+      extendPrototype([DynamicPropertyContainer], EllShapePropertyFactory);
+      return EllShapePropertyFactory;
+    }();
+
+    var StarShapeProperty = function () {
+      function StarShapePropertyFactory(elem, data) {
+        this.v = shapePool.newElement();
+        this.v.setPathData(true, 0);
+        this.elem = elem;
+        this.comp = elem.comp;
+        this.data = data;
+        this.frameId = -1;
+        this.d = data.d;
+        this.initDynamicPropertyContainer(elem);
+
+        if (data.sy === 1) {
+          this.ir = PropertyFactory.getProp(elem, data.ir, 0, 0, this);
+          this.is = PropertyFactory.getProp(elem, data.is, 0, 0.01, this);
+          this.convertToPath = this.convertStarToPath;
+        } else {
+          this.convertToPath = this.convertPolygonToPath;
+        }
+
+        this.pt = PropertyFactory.getProp(elem, data.pt, 0, 0, this);
+        this.p = PropertyFactory.getProp(elem, data.p, 1, 0, this);
+        this.r = PropertyFactory.getProp(elem, data.r, 0, degToRads, this);
+        this.or = PropertyFactory.getProp(elem, data.or, 0, 0, this);
+        this.os = PropertyFactory.getProp(elem, data.os, 0, 0.01, this);
+        this.localShapeCollection = shapeCollectionPool.newShapeCollection();
+        this.localShapeCollection.addShape(this.v);
+        this.paths = this.localShapeCollection;
+
+        if (this.dynamicProperties.length) {
+          this.k = true;
+        } else {
+          this.k = false;
+          this.convertToPath();
+        }
+      }
+
+      StarShapePropertyFactory.prototype = {
+        reset: resetShape,
+        getValue: function getValue() {
+          if (this.elem.globalData.frameId === this.frameId) {
+            return;
+          }
+
+          this.frameId = this.elem.globalData.frameId;
+          this.iterateDynamicProperties();
+
+          if (this._mdf) {
+            this.convertToPath();
+          }
+        },
+        convertStarToPath: function convertStarToPath() {
+          var numPts = Math.floor(this.pt.v) * 2;
+          var angle = Math.PI * 2 / numPts;
+          /* this.v.v.length = numPts;
+                  this.v.i.length = numPts;
+                  this.v.o.length = numPts; */
+
+          var longFlag = true;
+          var longRad = this.or.v;
+          var shortRad = this.ir.v;
+          var longRound = this.os.v;
+          var shortRound = this.is.v;
+          var longPerimSegment = 2 * Math.PI * longRad / (numPts * 2);
+          var shortPerimSegment = 2 * Math.PI * shortRad / (numPts * 2);
+          var i;
+          var rad;
+          var roundness;
+          var perimSegment;
+          var currentAng = -Math.PI / 2;
+          currentAng += this.r.v;
+          var dir = this.data.d === 3 ? -1 : 1;
+          this.v._length = 0;
+
+          for (i = 0; i < numPts; i += 1) {
+            rad = longFlag ? longRad : shortRad;
+            roundness = longFlag ? longRound : shortRound;
+            perimSegment = longFlag ? longPerimSegment : shortPerimSegment;
+            var x = rad * Math.cos(currentAng);
+            var y = rad * Math.sin(currentAng);
+            var ox = x === 0 && y === 0 ? 0 : y / Math.sqrt(x * x + y * y);
+            var oy = x === 0 && y === 0 ? 0 : -x / Math.sqrt(x * x + y * y);
+            x += +this.p.v[0];
+            y += +this.p.v[1];
+            this.v.setTripleAt(x, y, x - ox * perimSegment * roundness * dir, y - oy * perimSegment * roundness * dir, x + ox * perimSegment * roundness * dir, y + oy * perimSegment * roundness * dir, i, true);
+            /* this.v.v[i] = [x,y];
+                      this.v.i[i] = [x+ox*perimSegment*roundness*dir,y+oy*perimSegment*roundness*dir];
+                      this.v.o[i] = [x-ox*perimSegment*roundness*dir,y-oy*perimSegment*roundness*dir];
+                      this.v._length = numPts; */
+
+            longFlag = !longFlag;
+            currentAng += angle * dir;
+          }
+        },
+        convertPolygonToPath: function convertPolygonToPath() {
+          var numPts = Math.floor(this.pt.v);
+          var angle = Math.PI * 2 / numPts;
+          var rad = this.or.v;
+          var roundness = this.os.v;
+          var perimSegment = 2 * Math.PI * rad / (numPts * 4);
+          var i;
+          var currentAng = -Math.PI * 0.5;
+          var dir = this.data.d === 3 ? -1 : 1;
+          currentAng += this.r.v;
+          this.v._length = 0;
+
+          for (i = 0; i < numPts; i += 1) {
+            var x = rad * Math.cos(currentAng);
+            var y = rad * Math.sin(currentAng);
+            var ox = x === 0 && y === 0 ? 0 : y / Math.sqrt(x * x + y * y);
+            var oy = x === 0 && y === 0 ? 0 : -x / Math.sqrt(x * x + y * y);
+            x += +this.p.v[0];
+            y += +this.p.v[1];
+            this.v.setTripleAt(x, y, x - ox * perimSegment * roundness * dir, y - oy * perimSegment * roundness * dir, x + ox * perimSegment * roundness * dir, y + oy * perimSegment * roundness * dir, i, true);
+            currentAng += angle * dir;
+          }
+
+          this.paths.length = 0;
+          this.paths[0] = this.v;
+        }
+      };
+      extendPrototype([DynamicPropertyContainer], StarShapePropertyFactory);
+      return StarShapePropertyFactory;
+    }();
+
+    var RectShapeProperty = function () {
+      function RectShapePropertyFactory(elem, data) {
+        this.v = shapePool.newElement();
+        this.v.c = true;
+        this.localShapeCollection = shapeCollectionPool.newShapeCollection();
+        this.localShapeCollection.addShape(this.v);
+        this.paths = this.localShapeCollection;
+        this.elem = elem;
+        this.comp = elem.comp;
+        this.frameId = -1;
+        this.d = data.d;
+        this.initDynamicPropertyContainer(elem);
+        this.p = PropertyFactory.getProp(elem, data.p, 1, 0, this);
+        this.s = PropertyFactory.getProp(elem, data.s, 1, 0, this);
+        this.r = PropertyFactory.getProp(elem, data.r, 0, 0, this);
+
+        if (this.dynamicProperties.length) {
+          this.k = true;
+        } else {
+          this.k = false;
+          this.convertRectToPath();
+        }
+      }
+
+      RectShapePropertyFactory.prototype = {
+        convertRectToPath: function convertRectToPath() {
+          var p0 = this.p.v[0];
+          var p1 = this.p.v[1];
+          var v0 = this.s.v[0] / 2;
+          var v1 = this.s.v[1] / 2;
+          var round = bmMin(v0, v1, this.r.v);
+          var cPoint = round * (1 - roundCorner);
+          this.v._length = 0;
+
+          if (this.d === 2 || this.d === 1) {
+            this.v.setTripleAt(p0 + v0, p1 - v1 + round, p0 + v0, p1 - v1 + round, p0 + v0, p1 - v1 + cPoint, 0, true);
+            this.v.setTripleAt(p0 + v0, p1 + v1 - round, p0 + v0, p1 + v1 - cPoint, p0 + v0, p1 + v1 - round, 1, true);
+
+            if (round !== 0) {
+              this.v.setTripleAt(p0 + v0 - round, p1 + v1, p0 + v0 - round, p1 + v1, p0 + v0 - cPoint, p1 + v1, 2, true);
+              this.v.setTripleAt(p0 - v0 + round, p1 + v1, p0 - v0 + cPoint, p1 + v1, p0 - v0 + round, p1 + v1, 3, true);
+              this.v.setTripleAt(p0 - v0, p1 + v1 - round, p0 - v0, p1 + v1 - round, p0 - v0, p1 + v1 - cPoint, 4, true);
+              this.v.setTripleAt(p0 - v0, p1 - v1 + round, p0 - v0, p1 - v1 + cPoint, p0 - v0, p1 - v1 + round, 5, true);
+              this.v.setTripleAt(p0 - v0 + round, p1 - v1, p0 - v0 + round, p1 - v1, p0 - v0 + cPoint, p1 - v1, 6, true);
+              this.v.setTripleAt(p0 + v0 - round, p1 - v1, p0 + v0 - cPoint, p1 - v1, p0 + v0 - round, p1 - v1, 7, true);
+            } else {
+              this.v.setTripleAt(p0 - v0, p1 + v1, p0 - v0 + cPoint, p1 + v1, p0 - v0, p1 + v1, 2);
+              this.v.setTripleAt(p0 - v0, p1 - v1, p0 - v0, p1 - v1 + cPoint, p0 - v0, p1 - v1, 3);
+            }
+          } else {
+            this.v.setTripleAt(p0 + v0, p1 - v1 + round, p0 + v0, p1 - v1 + cPoint, p0 + v0, p1 - v1 + round, 0, true);
+
+            if (round !== 0) {
+              this.v.setTripleAt(p0 + v0 - round, p1 - v1, p0 + v0 - round, p1 - v1, p0 + v0 - cPoint, p1 - v1, 1, true);
+              this.v.setTripleAt(p0 - v0 + round, p1 - v1, p0 - v0 + cPoint, p1 - v1, p0 - v0 + round, p1 - v1, 2, true);
+              this.v.setTripleAt(p0 - v0, p1 - v1 + round, p0 - v0, p1 - v1 + round, p0 - v0, p1 - v1 + cPoint, 3, true);
+              this.v.setTripleAt(p0 - v0, p1 + v1 - round, p0 - v0, p1 + v1 - cPoint, p0 - v0, p1 + v1 - round, 4, true);
+              this.v.setTripleAt(p0 - v0 + round, p1 + v1, p0 - v0 + round, p1 + v1, p0 - v0 + cPoint, p1 + v1, 5, true);
+              this.v.setTripleAt(p0 + v0 - round, p1 + v1, p0 + v0 - cPoint, p1 + v1, p0 + v0 - round, p1 + v1, 6, true);
+              this.v.setTripleAt(p0 + v0, p1 + v1 - round, p0 + v0, p1 + v1 - round, p0 + v0, p1 + v1 - cPoint, 7, true);
+            } else {
+              this.v.setTripleAt(p0 - v0, p1 - v1, p0 - v0 + cPoint, p1 - v1, p0 - v0, p1 - v1, 1, true);
+              this.v.setTripleAt(p0 - v0, p1 + v1, p0 - v0, p1 + v1 - cPoint, p0 - v0, p1 + v1, 2, true);
+              this.v.setTripleAt(p0 + v0, p1 + v1, p0 + v0 - cPoint, p1 + v1, p0 + v0, p1 + v1, 3, true);
+            }
+          }
+        },
+        getValue: function getValue() {
+          if (this.elem.globalData.frameId === this.frameId) {
+            return;
+          }
+
+          this.frameId = this.elem.globalData.frameId;
+          this.iterateDynamicProperties();
+
+          if (this._mdf) {
+            this.convertRectToPath();
+          }
+        },
+        reset: resetShape
+      };
+      extendPrototype([DynamicPropertyContainer], RectShapePropertyFactory);
+      return RectShapePropertyFactory;
+    }();
+
+    function getShapeProp(elem, data, type) {
+      var prop;
+
+      if (type === 3 || type === 4) {
+        var dataProp = type === 3 ? data.pt : data.ks;
+        var keys = dataProp.k;
+
+        if (keys.length) {
+          prop = new KeyframedShapeProperty(elem, data, type);
+        } else {
+          prop = new ShapeProperty(elem, data, type);
+        }
+      } else if (type === 5) {
+        prop = new RectShapeProperty(elem, data);
+      } else if (type === 6) {
+        prop = new EllShapeProperty(elem, data);
+      } else if (type === 7) {
+        prop = new StarShapeProperty(elem, data);
+      }
+
+      if (prop.k) {
+        elem.addDynamicProperty(prop);
+      }
+
+      return prop;
+    }
+
+    function getConstructorFunction() {
+      return ShapeProperty;
+    }
+
+    function getKeyframedConstructorFunction() {
+      return KeyframedShapeProperty;
+    }
+
+    var ob = {};
+    ob.getShapeProp = getShapeProp;
+    ob.getConstructorFunction = getConstructorFunction;
+    ob.getKeyframedConstructorFunction = getKeyframedConstructorFunction;
+    return ob;
+  }();
+
+  /*!
+   Transformation Matrix v2.0
+   (c) Epistemex 2014-2015
+   www.epistemex.com
+   By Ken Fyrstenberg
+   Contributions by leeoniya.
+   License: MIT, header required.
+   */
+
+  /**
+   * 2D transformation matrix object initialized with identity matrix.
+   *
+   * The matrix can synchronize a canvas context by supplying the context
+   * as an argument, or later apply current absolute transform to an
+   * existing context.
+   *
+   * All values are handled as floating point values.
+   *
+   * @param {CanvasRenderingContext2D} [context] - Optional context to sync with Matrix
+   * @prop {number} a - scale x
+   * @prop {number} b - shear y
+   * @prop {number} c - shear x
+   * @prop {number} d - scale y
+   * @prop {number} e - translate x
+   * @prop {number} f - translate y
+   * @prop {CanvasRenderingContext2D|null} [context=null] - set or get current canvas context
+   * @constructor
+   */
+
+  var Matrix = function () {
+    var _cos = Math.cos;
+    var _sin = Math.sin;
+    var _tan = Math.tan;
+    var _rnd = Math.round;
+
+    function reset() {
+      this.props[0] = 1;
+      this.props[1] = 0;
+      this.props[2] = 0;
+      this.props[3] = 0;
+      this.props[4] = 0;
+      this.props[5] = 1;
+      this.props[6] = 0;
+      this.props[7] = 0;
+      this.props[8] = 0;
+      this.props[9] = 0;
+      this.props[10] = 1;
+      this.props[11] = 0;
+      this.props[12] = 0;
+      this.props[13] = 0;
+      this.props[14] = 0;
+      this.props[15] = 1;
+      return this;
+    }
+
+    function rotate(angle) {
+      if (angle === 0) {
+        return this;
+      }
+
+      var mCos = _cos(angle);
+
+      var mSin = _sin(angle);
+
+      return this._t(mCos, -mSin, 0, 0, mSin, mCos, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
+    }
+
+    function rotateX(angle) {
+      if (angle === 0) {
+        return this;
+      }
+
+      var mCos = _cos(angle);
+
+      var mSin = _sin(angle);
+
+      return this._t(1, 0, 0, 0, 0, mCos, -mSin, 0, 0, mSin, mCos, 0, 0, 0, 0, 1);
+    }
+
+    function rotateY(angle) {
+      if (angle === 0) {
+        return this;
+      }
+
+      var mCos = _cos(angle);
+
+      var mSin = _sin(angle);
+
+      return this._t(mCos, 0, mSin, 0, 0, 1, 0, 0, -mSin, 0, mCos, 0, 0, 0, 0, 1);
+    }
+
+    function rotateZ(angle) {
+      if (angle === 0) {
+        return this;
+      }
+
+      var mCos = _cos(angle);
+
+      var mSin = _sin(angle);
+
+      return this._t(mCos, -mSin, 0, 0, mSin, mCos, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
+    }
+
+    function shear(sx, sy) {
+      return this._t(1, sy, sx, 1, 0, 0);
+    }
+
+    function skew(ax, ay) {
+      return this.shear(_tan(ax), _tan(ay));
+    }
+
+    function skewFromAxis(ax, angle) {
+      var mCos = _cos(angle);
+
+      var mSin = _sin(angle);
+
+      return this._t(mCos, mSin, 0, 0, -mSin, mCos, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)._t(1, 0, 0, 0, _tan(ax), 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)._t(mCos, -mSin, 0, 0, mSin, mCos, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); // return this._t(mCos, mSin, -mSin, mCos, 0, 0)._t(1, 0, _tan(ax), 1, 0, 0)._t(mCos, -mSin, mSin, mCos, 0, 0);
+    }
+
+    function scale(sx, sy, sz) {
+      if (!sz && sz !== 0) {
+        sz = 1;
+      }
+
+      if (sx === 1 && sy === 1 && sz === 1) {
+        return this;
+      }
+
+      return this._t(sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, sz, 0, 0, 0, 0, 1);
+    }
+
+    function setTransform(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {
+      this.props[0] = a;
+      this.props[1] = b;
+      this.props[2] = c;
+      this.props[3] = d;
+      this.props[4] = e;
+      this.props[5] = f;
+      this.props[6] = g;
+      this.props[7] = h;
+      this.props[8] = i;
+      this.props[9] = j;
+      this.props[10] = k;
+      this.props[11] = l;
+      this.props[12] = m;
+      this.props[13] = n;
+      this.props[14] = o;
+      this.props[15] = p;
+      return this;
+    }
+
+    function translate(tx, ty, tz) {
+      tz = tz || 0;
+
+      if (tx !== 0 || ty !== 0 || tz !== 0) {
+        return this._t(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, tx, ty, tz, 1);
+      }
+
+      return this;
+    }
+
+    function transform(a2, b2, c2, d2, e2, f2, g2, h2, i2, j2, k2, l2, m2, n2, o2, p2) {
+      var _p = this.props;
+
+      if (a2 === 1 && b2 === 0 && c2 === 0 && d2 === 0 && e2 === 0 && f2 === 1 && g2 === 0 && h2 === 0 && i2 === 0 && j2 === 0 && k2 === 1 && l2 === 0) {
+        // NOTE: commenting this condition because TurboFan deoptimizes code when present
+        // if(m2 !== 0 || n2 !== 0 || o2 !== 0){
+        _p[12] = _p[12] * a2 + _p[15] * m2;
+        _p[13] = _p[13] * f2 + _p[15] * n2;
+        _p[14] = _p[14] * k2 + _p[15] * o2;
+        _p[15] *= p2; // }
+
+        this._identityCalculated = false;
+        return this;
+      }
+
+      var a1 = _p[0];
+      var b1 = _p[1];
+      var c1 = _p[2];
+      var d1 = _p[3];
+      var e1 = _p[4];
+      var f1 = _p[5];
+      var g1 = _p[6];
+      var h1 = _p[7];
+      var i1 = _p[8];
+      var j1 = _p[9];
+      var k1 = _p[10];
+      var l1 = _p[11];
+      var m1 = _p[12];
+      var n1 = _p[13];
+      var o1 = _p[14];
+      var p1 = _p[15];
+      /* matrix order (canvas compatible):
+           * ace
+           * bdf
+           * 001
+           */
+
+      _p[0] = a1 * a2 + b1 * e2 + c1 * i2 + d1 * m2;
+      _p[1] = a1 * b2 + b1 * f2 + c1 * j2 + d1 * n2;
+      _p[2] = a1 * c2 + b1 * g2 + c1 * k2 + d1 * o2;
+      _p[3] = a1 * d2 + b1 * h2 + c1 * l2 + d1 * p2;
+      _p[4] = e1 * a2 + f1 * e2 + g1 * i2 + h1 * m2;
+      _p[5] = e1 * b2 + f1 * f2 + g1 * j2 + h1 * n2;
+      _p[6] = e1 * c2 + f1 * g2 + g1 * k2 + h1 * o2;
+      _p[7] = e1 * d2 + f1 * h2 + g1 * l2 + h1 * p2;
+      _p[8] = i1 * a2 + j1 * e2 + k1 * i2 + l1 * m2;
+      _p[9] = i1 * b2 + j1 * f2 + k1 * j2 + l1 * n2;
+      _p[10] = i1 * c2 + j1 * g2 + k1 * k2 + l1 * o2;
+      _p[11] = i1 * d2 + j1 * h2 + k1 * l2 + l1 * p2;
+      _p[12] = m1 * a2 + n1 * e2 + o1 * i2 + p1 * m2;
+      _p[13] = m1 * b2 + n1 * f2 + o1 * j2 + p1 * n2;
+      _p[14] = m1 * c2 + n1 * g2 + o1 * k2 + p1 * o2;
+      _p[15] = m1 * d2 + n1 * h2 + o1 * l2 + p1 * p2;
+      this._identityCalculated = false;
+      return this;
+    }
+
+    function isIdentity() {
+      if (!this._identityCalculated) {
+        this._identity = !(this.props[0] !== 1 || this.props[1] !== 0 || this.props[2] !== 0 || this.props[3] !== 0 || this.props[4] !== 0 || this.props[5] !== 1 || this.props[6] !== 0 || this.props[7] !== 0 || this.props[8] !== 0 || this.props[9] !== 0 || this.props[10] !== 1 || this.props[11] !== 0 || this.props[12] !== 0 || this.props[13] !== 0 || this.props[14] !== 0 || this.props[15] !== 1);
+        this._identityCalculated = true;
+      }
+
+      return this._identity;
+    }
+
+    function equals(matr) {
+      var i = 0;
+
+      while (i < 16) {
+        if (matr.props[i] !== this.props[i]) {
+          return false;
+        }
+
+        i += 1;
+      }
+
+      return true;
+    }
+
+    function clone(matr) {
+      var i;
+
+      for (i = 0; i < 16; i += 1) {
+        matr.props[i] = this.props[i];
+      }
+
+      return matr;
+    }
+
+    function cloneFromProps(props) {
+      var i;
+
+      for (i = 0; i < 16; i += 1) {
+        this.props[i] = props[i];
+      }
+    }
+
+    function applyToPoint(x, y, z) {
+      return {
+        x: x * this.props[0] + y * this.props[4] + z * this.props[8] + this.props[12],
+        y: x * this.props[1] + y * this.props[5] + z * this.props[9] + this.props[13],
+        z: x * this.props[2] + y * this.props[6] + z * this.props[10] + this.props[14]
+      };
+      /* return {
+           x: x * me.a + y * me.c + me.e,
+           y: x * me.b + y * me.d + me.f
+           }; */
+    }
+
+    function applyToX(x, y, z) {
+      return x * this.props[0] + y * this.props[4] + z * this.props[8] + this.props[12];
+    }
+
+    function applyToY(x, y, z) {
+      return x * this.props[1] + y * this.props[5] + z * this.props[9] + this.props[13];
+    }
+
+    function applyToZ(x, y, z) {
+      return x * this.props[2] + y * this.props[6] + z * this.props[10] + this.props[14];
+    }
+
+    function getInverseMatrix() {
+      var determinant = this.props[0] * this.props[5] - this.props[1] * this.props[4];
+      var a = this.props[5] / determinant;
+      var b = -this.props[1] / determinant;
+      var c = -this.props[4] / determinant;
+      var d = this.props[0] / determinant;
+      var e = (this.props[4] * this.props[13] - this.props[5] * this.props[12]) / determinant;
+      var f = -(this.props[0] * this.props[13] - this.props[1] * this.props[12]) / determinant;
+      var inverseMatrix = new Matrix();
+      inverseMatrix.props[0] = a;
+      inverseMatrix.props[1] = b;
+      inverseMatrix.props[4] = c;
+      inverseMatrix.props[5] = d;
+      inverseMatrix.props[12] = e;
+      inverseMatrix.props[13] = f;
+      return inverseMatrix;
+    }
+
+    function inversePoint(pt) {
+      var inverseMatrix = this.getInverseMatrix();
+      return inverseMatrix.applyToPointArray(pt[0], pt[1], pt[2] || 0);
+    }
+
+    function inversePoints(pts) {
+      var i;
+      var len = pts.length;
+      var retPts = [];
+
+      for (i = 0; i < len; i += 1) {
+        retPts[i] = inversePoint(pts[i]);
+      }
+
+      return retPts;
+    }
+
+    function applyToTriplePoints(pt1, pt2, pt3) {
+      var arr = createTypedArray('float32', 6);
+
+      if (this.isIdentity()) {
+        arr[0] = pt1[0];
+        arr[1] = pt1[1];
+        arr[2] = pt2[0];
+        arr[3] = pt2[1];
+        arr[4] = pt3[0];
+        arr[5] = pt3[1];
+      } else {
+        var p0 = this.props[0];
+        var p1 = this.props[1];
+        var p4 = this.props[4];
+        var p5 = this.props[5];
+        var p12 = this.props[12];
+        var p13 = this.props[13];
+        arr[0] = pt1[0] * p0 + pt1[1] * p4 + p12;
+        arr[1] = pt1[0] * p1 + pt1[1] * p5 + p13;
+        arr[2] = pt2[0] * p0 + pt2[1] * p4 + p12;
+        arr[3] = pt2[0] * p1 + pt2[1] * p5 + p13;
+        arr[4] = pt3[0] * p0 + pt3[1] * p4 + p12;
+        arr[5] = pt3[0] * p1 + pt3[1] * p5 + p13;
+      }
+
+      return arr;
+    }
+
+    function applyToPointArray(x, y, z) {
+      var arr;
+
+      if (this.isIdentity()) {
+        arr = [x, y, z];
+      } else {
+        arr = [x * this.props[0] + y * this.props[4] + z * this.props[8] + this.props[12], x * this.props[1] + y * this.props[5] + z * this.props[9] + this.props[13], x * this.props[2] + y * this.props[6] + z * this.props[10] + this.props[14]];
+      }
+
+      return arr;
+    }
+
+    function applyToPointStringified(x, y) {
+      if (this.isIdentity()) {
+        return x + ',' + y;
+      }
+
+      var _p = this.props;
+      return Math.round((x * _p[0] + y * _p[4] + _p[12]) * 100) / 100 + ',' + Math.round((x * _p[1] + y * _p[5] + _p[13]) * 100) / 100;
+    }
+
+    function toCSS() {
+      // Doesn't make much sense to add this optimization. If it is an identity matrix, it's very likely this will get called only once since it won't be keyframed.
+
+      /* if(this.isIdentity()) {
+              return '';
+          } */
+      var i = 0;
+      var props = this.props;
+      var cssValue = 'matrix3d(';
+      var v = 10000;
+
+      while (i < 16) {
+        cssValue += _rnd(props[i] * v) / v;
+        cssValue += i === 15 ? ')' : ',';
+        i += 1;
+      }
+
+      return cssValue;
+    }
+
+    function roundMatrixProperty(val) {
+      var v = 10000;
+
+      if (val < 0.000001 && val > 0 || val > -0.000001 && val < 0) {
+        return _rnd(val * v) / v;
+      }
+
+      return val;
+    }
+
+    function to2dCSS() {
+      // Doesn't make much sense to add this optimization. If it is an identity matrix, it's very likely this will get called only once since it won't be keyframed.
+
+      /* if(this.isIdentity()) {
+              return '';
+          } */
+      var props = this.props;
+
+      var _a = roundMatrixProperty(props[0]);
+
+      var _b = roundMatrixProperty(props[1]);
+
+      var _c = roundMatrixProperty(props[4]);
+
+      var _d = roundMatrixProperty(props[5]);
+
+      var _e = roundMatrixProperty(props[12]);
+
+      var _f = roundMatrixProperty(props[13]);
+
+      return 'matrix(' + _a + ',' + _b + ',' + _c + ',' + _d + ',' + _e + ',' + _f + ')';
+    }
+
+    return function () {
+      this.reset = reset;
+      this.rotate = rotate;
+      this.rotateX = rotateX;
+      this.rotateY = rotateY;
+      this.rotateZ = rotateZ;
+      this.skew = skew;
+      this.skewFromAxis = skewFromAxis;
+      this.shear = shear;
+      this.scale = scale;
+      this.setTransform = setTransform;
+      this.translate = translate;
+      this.transform = transform;
+      this.applyToPoint = applyToPoint;
+      this.applyToX = applyToX;
+      this.applyToY = applyToY;
+      this.applyToZ = applyToZ;
+      this.applyToPointArray = applyToPointArray;
+      this.applyToTriplePoints = applyToTriplePoints;
+      this.applyToPointStringified = applyToPointStringified;
+      this.toCSS = toCSS;
+      this.to2dCSS = to2dCSS;
+      this.clone = clone;
+      this.cloneFromProps = cloneFromProps;
+      this.equals = equals;
+      this.inversePoints = inversePoints;
+      this.inversePoint = inversePoint;
+      this.getInverseMatrix = getInverseMatrix;
+      this._t = this.transform;
+      this.isIdentity = isIdentity;
+      this._identity = true;
+      this._identityCalculated = false;
+      this.props = createTypedArray('float32', 16);
+      this.reset();
+    };
+  }();
+
+  function _typeof$3(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof$3 = function _typeof(obj) { return typeof obj; }; } else { _typeof$3 = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof$3(obj); }
+  var lottie = {};
+  var standalone = '__[STANDALONE]__';
+  var animationData = '__[ANIMATIONDATA]__';
+  var renderer = '';
+
+  function setLocation(href) {
+    setLocationHref(href);
   }
-};
 
-extendPrototype([DynamicPropertyContainer], SVGGradientFillStyleData);
+  function searchAnimations() {
+    if (standalone === true) {
+      animationManager.searchAnimations(animationData, standalone, renderer);
+    } else {
+      animationManager.searchAnimations();
+    }
+  }
 
-/* global PropertyFactory, DashProperty, extendPrototype, SVGGradientFillStyleData, DynamicPropertyContainer */
+  function setSubframeRendering(flag) {
+    setSubframeEnabled(flag);
+  }
 
-function SVGGradientStrokeStyleData(elem, data, styleOb) {
-  this.initDynamicPropertyContainer(elem);
-  this.getValue = this.iterateDynamicProperties;
-  this.w = PropertyFactory.getProp(elem, data.w, 0, null, this);
-  this.d = new DashProperty(elem, data.d || {}, 'svg', this);
-  this.initGradientData(elem, data, styleOb);
-  this._isAnimated = !!this._isAnimated;
-}
+  function setPrefix(prefix) {
+    setIdPrefix(prefix);
+  }
 
-extendPrototype([SVGGradientFillStyleData, DynamicPropertyContainer], SVGGradientStrokeStyleData);
+  function loadAnimation(params) {
+    if (standalone === true) {
+      params.animationData = JSON.parse(animationData);
+    }
 
-/* global createNS */
-/* exported ShapeGroupData */
+    return animationManager.loadAnimation(params);
+  }
 
-function ShapeGroupData() {
-  this.it = [];
-  this.prevViewData = [];
-  this.gr = createNS('g');
-}
+  function setQuality(value) {
+    if (typeof value === 'string') {
+      switch (value) {
+        case 'high':
+          setDefaultCurveSegments(200);
+          break;
 
-/* global Matrix, buildShapeString, bmFloor */
-/* exported SVGElementsRenderer */
+        default:
+        case 'medium':
+          setDefaultCurveSegments(50);
+          break;
 
-var SVGElementsRenderer = (function () {
-  var _identityMatrix = new Matrix();
-  var _matrixHelper = new Matrix();
+        case 'low':
+          setDefaultCurveSegments(10);
+          break;
+      }
+    } else if (!isNaN(value) && value > 1) {
+      setDefaultCurveSegments(value);
+    }
 
-  var ob = {
-    createRenderFunction: createRenderFunction,
-  };
+    if (getDefaultCurveSegments() >= 50) {
+      roundValues(false);
+    } else {
+      roundValues(true);
+    }
+  }
 
-  function createRenderFunction(data) {
-    switch (data.ty) {
-      case 'fl':
-        return renderFill;
-      case 'gf':
-        return renderGradient;
-      case 'gs':
-        return renderGradientStroke;
-      case 'st':
-        return renderStroke;
-      case 'sh':
-      case 'el':
-      case 'rc':
-      case 'sr':
-        return renderPath;
-      case 'tr':
-        return renderContentTransform;
+  function inBrowser() {
+    return typeof navigator !== 'undefined';
+  }
+
+  function installPlugin(type, plugin) {
+    if (type === 'expressions') {
+      setExpressionsPlugin(plugin);
+    }
+  }
+
+  function getFactory(name) {
+    switch (name) {
+      case 'propertyFactory':
+        return PropertyFactory;
+
+      case 'shapePropertyFactory':
+        return ShapePropertyFactory;
+
+      case 'matrix':
+        return Matrix;
+
       default:
         return null;
     }
   }
 
-  function renderContentTransform(styleData, itemData, isFirstFrame) {
-    if (isFirstFrame || itemData.transform.op._mdf) {
-      itemData.transform.container.setAttribute('opacity', itemData.transform.op.v);
-    }
-    if (isFirstFrame || itemData.transform.mProps._mdf) {
-      itemData.transform.container.setAttribute('transform', itemData.transform.mProps.v.to2dCSS());
-    }
-  }
+  lottie.play = animationManager.play;
+  lottie.pause = animationManager.pause;
+  lottie.setLocationHref = setLocation;
+  lottie.togglePause = animationManager.togglePause;
+  lottie.setSpeed = animationManager.setSpeed;
+  lottie.setDirection = animationManager.setDirection;
+  lottie.stop = animationManager.stop;
+  lottie.searchAnimations = searchAnimations;
+  lottie.registerAnimation = animationManager.registerAnimation;
+  lottie.loadAnimation = loadAnimation;
+  lottie.setSubframeRendering = setSubframeRendering;
+  lottie.resize = animationManager.resize; // lottie.start = start;
 
-  function renderPath(styleData, itemData, isFirstFrame) {
-    var j;
-    var jLen;
-    var pathStringTransformed;
-    var redraw;
-    var pathNodes;
-    var l;
-    var lLen = itemData.styles.length;
-    var lvl = itemData.lvl;
-    var paths;
-    var mat;
-    var props;
-    var iterations;
-    var k;
-    for (l = 0; l < lLen; l += 1) {
-      redraw = itemData.sh._mdf || isFirstFrame;
-      if (itemData.styles[l].lvl < lvl) {
-        mat = _matrixHelper.reset();
-        iterations = lvl - itemData.styles[l].lvl;
-        k = itemData.transformers.length - 1;
-        while (!redraw && iterations > 0) {
-          redraw = itemData.transformers[k].mProps._mdf || redraw;
-          iterations -= 1;
-          k -= 1;
-        }
-        if (redraw) {
-          iterations = lvl - itemData.styles[l].lvl;
-          k = itemData.transformers.length - 1;
-          while (iterations > 0) {
-            props = itemData.transformers[k].mProps.v.props;
-            mat.transform(props[0], props[1], props[2], props[3], props[4], props[5], props[6], props[7], props[8], props[9], props[10], props[11], props[12], props[13], props[14], props[15]);
-            iterations -= 1;
-            k -= 1;
-          }
-        }
-      } else {
-        mat = _identityMatrix;
-      }
-      paths = itemData.sh.paths;
-      jLen = paths._length;
-      if (redraw) {
-        pathStringTransformed = '';
-        for (j = 0; j < jLen; j += 1) {
-          pathNodes = paths.shapes[j];
-          if (pathNodes && pathNodes._length) {
-            pathStringTransformed += buildShapeString(pathNodes, pathNodes._length, pathNodes.c, mat);
-          }
-        }
-        itemData.caches[l] = pathStringTransformed;
-      } else {
-        pathStringTransformed = itemData.caches[l];
-      }
-      itemData.styles[l].d += styleData.hd === true ? '' : pathStringTransformed;
-      itemData.styles[l]._mdf = redraw || itemData.styles[l]._mdf;
-    }
-  }
-
-  function renderFill(styleData, itemData, isFirstFrame) {
-    var styleElem = itemData.style;
+  lottie.goToAndStop = animationManager.goToAndStop;
+  lottie.destroy = animationManager.destroy;
+  lottie.setQuality = setQuality;
+  lottie.inBrowser = inBrowser;
+  lottie.installPlugin = installPlugin;
+  lottie.freeze = animationManager.freeze;
+  lottie.unfreeze = animationManager.unfreeze;
+  lottie.setVolume = animationManager.setVolume;
+  lottie.mute = animationManager.mute;
+  lottie.unmute = animationManager.unmute;
+  lottie.getRegisteredAnimations = animationManager.getRegisteredAnimations;
+  lottie.useWebWorker = setWebWorker;
+  lottie.setIDPrefix = setPrefix;
+  lottie.__getFactory = getFactory;
+  lottie.version = '5.9.0';
 
-    if (itemData.c._mdf || isFirstFrame) {
-      styleElem.pElem.setAttribute('fill', 'rgb(' + bmFloor(itemData.c.v[0]) + ',' + bmFloor(itemData.c.v[1]) + ',' + bmFloor(itemData.c.v[2]) + ')');
-    }
-    if (itemData.o._mdf || isFirstFrame) {
-      styleElem.pElem.setAttribute('fill-opacity', itemData.o.v);
+  function checkReady() {
+    if (document.readyState === 'complete') {
+      clearInterval(readyStateCheckInterval);
+      searchAnimations();
     }
   }
 
-  function renderGradientStroke(styleData, itemData, isFirstFrame) {
-    renderGradient(styleData, itemData, isFirstFrame);
-    renderStroke(styleData, itemData, isFirstFrame);
-  }
+  function getQueryVariable(variable) {
+    var vars = queryString.split('&');
 
-  function renderGradient(styleData, itemData, isFirstFrame) {
-    var gfill = itemData.gf;
-    var hasOpacity = itemData.g._hasOpacity;
-    var pt1 = itemData.s.v;
-    var pt2 = itemData.e.v;
+    for (var i = 0; i < vars.length; i += 1) {
+      var pair = vars[i].split('=');
 
-    if (itemData.o._mdf || isFirstFrame) {
-      var attr = styleData.ty === 'gf' ? 'fill-opacity' : 'stroke-opacity';
-      itemData.style.pElem.setAttribute(attr, itemData.o.v);
-    }
-    if (itemData.s._mdf || isFirstFrame) {
-      var attr1 = styleData.t === 1 ? 'x1' : 'cx';
-      var attr2 = attr1 === 'x1' ? 'y1' : 'cy';
-      gfill.setAttribute(attr1, pt1[0]);
-      gfill.setAttribute(attr2, pt1[1]);
-      if (hasOpacity && !itemData.g._collapsable) {
-        itemData.of.setAttribute(attr1, pt1[0]);
-        itemData.of.setAttribute(attr2, pt1[1]);
-      }
-    }
-    var stops;
-    var i;
-    var len;
-    var stop;
-    if (itemData.g._cmdf || isFirstFrame) {
-      stops = itemData.cst;
-      var cValues = itemData.g.c;
-      len = stops.length;
-      for (i = 0; i < len; i += 1) {
-        stop = stops[i];
-        stop.setAttribute('offset', cValues[i * 4] + '%');
-        stop.setAttribute('stop-color', 'rgb(' + cValues[i * 4 + 1] + ',' + cValues[i * 4 + 2] + ',' + cValues[i * 4 + 3] + ')');
-      }
-    }
-    if (hasOpacity && (itemData.g._omdf || isFirstFrame)) {
-      var oValues = itemData.g.o;
-      if (itemData.g._collapsable) {
-        stops = itemData.cst;
-      } else {
-        stops = itemData.ost;
-      }
-      len = stops.length;
-      for (i = 0; i < len; i += 1) {
-        stop = stops[i];
-        if (!itemData.g._collapsable) {
-          stop.setAttribute('offset', oValues[i * 2] + '%');
-        }
-        stop.setAttribute('stop-opacity', oValues[i * 2 + 1]);
-      }
-    }
-    if (styleData.t === 1) {
-      if (itemData.e._mdf || isFirstFrame) {
-        gfill.setAttribute('x2', pt2[0]);
-        gfill.setAttribute('y2', pt2[1]);
-        if (hasOpacity && !itemData.g._collapsable) {
-          itemData.of.setAttribute('x2', pt2[0]);
-          itemData.of.setAttribute('y2', pt2[1]);
-        }
-      }
-    } else {
-      var rad;
-      if (itemData.s._mdf || itemData.e._mdf || isFirstFrame) {
-        rad = Math.sqrt(Math.pow(pt1[0] - pt2[0], 2) + Math.pow(pt1[1] - pt2[1], 2));
-        gfill.setAttribute('r', rad);
-        if (hasOpacity && !itemData.g._collapsable) {
-          itemData.of.setAttribute('r', rad);
-        }
-      }
-      if (itemData.e._mdf || itemData.h._mdf || itemData.a._mdf || isFirstFrame) {
-        if (!rad) {
-          rad = Math.sqrt(Math.pow(pt1[0] - pt2[0], 2) + Math.pow(pt1[1] - pt2[1], 2));
-        }
-        var ang = Math.atan2(pt2[1] - pt1[1], pt2[0] - pt1[0]);
-
-        var percent = itemData.h.v;
-        if (percent >= 1) {
-          percent = 0.99;
-        } else if (percent <= -1) {
-          percent = -0.99;
-        }
-        var dist = rad * percent;
-        var x = Math.cos(ang + itemData.a.v) * dist + pt1[0];
-        var y = Math.sin(ang + itemData.a.v) * dist + pt1[1];
-        gfill.setAttribute('fx', x);
-        gfill.setAttribute('fy', y);
-        if (hasOpacity && !itemData.g._collapsable) {
-          itemData.of.setAttribute('fx', x);
-          itemData.of.setAttribute('fy', y);
-        }
-      }
-      // gfill.setAttribute('fy','200');
-    }
-  }
-
-  function renderStroke(styleData, itemData, isFirstFrame) {
-    var styleElem = itemData.style;
-    var d = itemData.d;
-    if (d && (d._mdf || isFirstFrame) && d.dashStr) {
-      styleElem.pElem.setAttribute('stroke-dasharray', d.dashStr);
-      styleElem.pElem.setAttribute('stroke-dashoffset', d.dashoffset[0]);
-    }
-    if (itemData.c && (itemData.c._mdf || isFirstFrame)) {
-      styleElem.pElem.setAttribute('stroke', 'rgb(' + bmFloor(itemData.c.v[0]) + ',' + bmFloor(itemData.c.v[1]) + ',' + bmFloor(itemData.c.v[2]) + ')');
-    }
-    if (itemData.o._mdf || isFirstFrame) {
-      styleElem.pElem.setAttribute('stroke-opacity', itemData.o.v);
-    }
-    if (itemData.w._mdf || isFirstFrame) {
-      styleElem.pElem.setAttribute('stroke-width', itemData.w.v);
-      if (styleElem.msElem) {
-        styleElem.msElem.setAttribute('stroke-width', itemData.w.v);
-      }
-    }
-  }
-
-  return ob;
-}());
-
-/* global Matrix */
-
-function ShapeTransformManager() {
-  this.sequences = {};
-  this.sequenceList = [];
-  this.transform_key_count = 0;
-}
-
-ShapeTransformManager.prototype = {
-  addTransformSequence: function (transforms) {
-    var i;
-    var len = transforms.length;
-    var key = '_';
-    for (i = 0; i < len; i += 1) {
-      key += transforms[i].transform.key + '_';
-    }
-    var sequence = this.sequences[key];
-    if (!sequence) {
-      sequence = {
-        transforms: [].concat(transforms),
-        finalTransform: new Matrix(),
-        _mdf: false,
-      };
-      this.sequences[key] = sequence;
-      this.sequenceList.push(sequence);
-    }
-    return sequence;
-  },
-  processSequence: function (sequence, isFirstFrame) {
-    var i = 0;
-    var len = sequence.transforms.length;
-    var _mdf = isFirstFrame;
-    while (i < len && !isFirstFrame) {
-      if (sequence.transforms[i].transform.mProps._mdf) {
-        _mdf = true;
-        break;
-      }
-      i += 1;
-    }
-    if (_mdf) {
-      var props;
-      sequence.finalTransform.reset();
-      for (i = len - 1; i >= 0; i -= 1) {
-        props = sequence.transforms[i].transform.mProps.v.props;
-        sequence.finalTransform.transform(props[0], props[1], props[2], props[3], props[4], props[5], props[6], props[7], props[8], props[9], props[10], props[11], props[12], props[13], props[14], props[15]);
-      }
-    }
-    sequence._mdf = _mdf;
-  },
-  processSequences: function (isFirstFrame) {
-    var i;
-    var len = this.sequenceList.length;
-    for (i = 0; i < len; i += 1) {
-      this.processSequence(this.sequenceList[i], isFirstFrame);
-    }
-  },
-  getNewKey: function () {
-    this.transform_key_count += 1;
-    return '_' + this.transform_key_count;
-  },
-};
-
-/* global ShapePropertyFactory, SVGShapeData */
-
-function CVShapeData(element, data, styles, transformsManager) {
-  this.styledShapes = [];
-  this.tr = [0, 0, 0, 0, 0, 0];
-  var ty = 4;
-  if (data.ty === 'rc') {
-    ty = 5;
-  } else if (data.ty === 'el') {
-    ty = 6;
-  } else if (data.ty === 'sr') {
-    ty = 7;
-  }
-  this.sh = ShapePropertyFactory.getShapeProp(element, data, ty, element);
-  var i;
-  var len = styles.length;
-  var styledShape;
-  for (i = 0; i < len; i += 1) {
-    if (!styles[i].closed) {
-      styledShape = {
-        transforms: transformsManager.addTransformSequence(styles[i].transforms),
-        trNodes: [],
-      };
-      this.styledShapes.push(styledShape);
-      styles[i].elements.push(styledShape);
-    }
-  }
-}
-
-CVShapeData.prototype.setAsAnimated = SVGShapeData.prototype.setAsAnimated;
-
-/* global LayerExpressionInterface, EffectsExpressionInterface, CompExpressionInterface, ShapeExpressionInterface,
-TextExpressionInterface, getBlendMode,createElementID, EffectsManager */
-
-function BaseElement() {
-}
-
-BaseElement.prototype = {
-  checkMasks: function () {
-    if (!this.data.hasMask) {
-      return false;
-    }
-    var i = 0;
-    var len = this.data.masksProperties.length;
-    while (i < len) {
-      if ((this.data.masksProperties[i].mode !== 'n' && this.data.masksProperties[i].cl !== false)) {
-        return true;
-      }
-      i += 1;
-    }
-    return false;
-  },
-  initExpressions: function () {
-    this.layerInterface = LayerExpressionInterface(this);
-    if (this.data.hasMask && this.maskManager) {
-      this.layerInterface.registerMaskInterface(this.maskManager);
-    }
-    var effectsInterface = EffectsExpressionInterface.createEffectsInterface(this, this.layerInterface);
-    this.layerInterface.registerEffectsInterface(effectsInterface);
-
-    if (this.data.ty === 0 || this.data.xt) {
-      this.compInterface = CompExpressionInterface(this);
-    } else if (this.data.ty === 4) {
-      this.layerInterface.shapeInterface = ShapeExpressionInterface(this.shapesData, this.itemsData, this.layerInterface);
-      this.layerInterface.content = this.layerInterface.shapeInterface;
-    } else if (this.data.ty === 5) {
-      this.layerInterface.textInterface = TextExpressionInterface(this);
-      this.layerInterface.text = this.layerInterface.textInterface;
-    }
-  },
-  setBlendMode: function () {
-    var blendModeValue = getBlendMode(this.data.bm);
-    var elem = this.baseElement || this.layerElement;
-
-    elem.style['mix-blend-mode'] = blendModeValue;
-  },
-  initBaseData: function (data, globalData, comp) {
-    this.globalData = globalData;
-    this.comp = comp;
-    this.data = data;
-    this.layerId = createElementID();
-
-    // Stretch factor for old animations missing this property.
-    if (!this.data.sr) {
-      this.data.sr = 1;
-    }
-    // effects manager
-    this.effectsManager = new EffectsManager(this.data, this, this.dynamicProperties);
-  },
-  getType: function () {
-    return this.type;
-  },
-  sourceRectAtTime: function () {},
-};
-
-/* global extendPrototype, BaseElement, TransformElement, HierarchyElement, FrameElement */
-
-function NullElement(data, globalData, comp) {
-  this.initFrame();
-  this.initBaseData(data, globalData, comp);
-  this.initFrame();
-  this.initTransform(data, globalData, comp);
-  this.initHierarchy();
-}
-
-NullElement.prototype.prepareFrame = function (num) {
-  this.prepareProperties(num, true);
-};
-
-NullElement.prototype.renderFrame = function () {
-};
-
-NullElement.prototype.getBaseElement = function () {
-  return null;
-};
-
-NullElement.prototype.destroy = function () {
-};
-
-NullElement.prototype.sourceRectAtTime = function () {
-};
-
-NullElement.prototype.hide = function () {
-};
-
-extendPrototype([BaseElement, TransformElement, HierarchyElement, FrameElement], NullElement);
-
-/* global filtersFactory, featureSupport, filtersFactory, createElementID, createNS, MaskElement, SVGEffects, locationHref */
-
-function SVGBaseElement() {
-}
-
-SVGBaseElement.prototype = {
-  initRendererElement: function () {
-    this.layerElement = createNS('g');
-  },
-  createContainerElements: function () {
-    this.matteElement = createNS('g');
-    this.transformedElement = this.layerElement;
-    this.maskedElement = this.layerElement;
-    this._sizeChanged = false;
-    var layerElementParent = null;
-    // If this layer acts as a mask for the following layer
-    var filId;
-    var fil;
-    var gg;
-    if (this.data.td) {
-      if (this.data.td == 3 || this.data.td == 1) { // eslint-disable-line eqeqeq
-        var masker = createNS('mask');
-        masker.setAttribute('id', this.layerId);
-        masker.setAttribute('mask-type', this.data.td == 3 ? 'luminance' : 'alpha'); // eslint-disable-line eqeqeq
-        masker.appendChild(this.layerElement);
-        layerElementParent = masker;
-        this.globalData.defs.appendChild(masker);
-        // This is only for IE and Edge when mask if of type alpha
-        if (!featureSupport.maskType && this.data.td == 1) { // eslint-disable-line eqeqeq
-          masker.setAttribute('mask-type', 'luminance');
-          filId = createElementID();
-          fil = filtersFactory.createFilter(filId);
-          this.globalData.defs.appendChild(fil);
-          fil.appendChild(filtersFactory.createAlphaToLuminanceFilter());
-          gg = createNS('g');
-          gg.appendChild(this.layerElement);
-          layerElementParent = gg;
-          masker.appendChild(gg);
-          gg.setAttribute('filter', 'url(' + locationHref + '#' + filId + ')');
-        }
-      } else if (this.data.td == 2) { // eslint-disable-line eqeqeq
-        var maskGroup = createNS('mask');
-        maskGroup.setAttribute('id', this.layerId);
-        maskGroup.setAttribute('mask-type', 'alpha');
-        var maskGrouper = createNS('g');
-        maskGroup.appendChild(maskGrouper);
-        filId = createElementID();
-        fil = filtersFactory.createFilter(filId);
-        /// /
-
-        // This solution doesn't work on Android when meta tag with viewport attribute is set
-        /* var feColorMatrix = createNS('feColorMatrix');
-                feColorMatrix.setAttribute('type', 'matrix');
-                feColorMatrix.setAttribute('color-interpolation-filters', 'sRGB');
-                feColorMatrix.setAttribute('values','1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 -1 1');
-                fil.appendChild(feColorMatrix); */
-        /// /
-        var feCTr = createNS('feComponentTransfer');
-        feCTr.setAttribute('in', 'SourceGraphic');
-        fil.appendChild(feCTr);
-        var feFunc = createNS('feFuncA');
-        feFunc.setAttribute('type', 'table');
-        feFunc.setAttribute('tableValues', '1.0 0.0');
-        feCTr.appendChild(feFunc);
-        /// /
-        this.globalData.defs.appendChild(fil);
-        var alphaRect = createNS('rect');
-        alphaRect.setAttribute('width', this.comp.data.w);
-        alphaRect.setAttribute('height', this.comp.data.h);
-        alphaRect.setAttribute('x', '0');
-        alphaRect.setAttribute('y', '0');
-        alphaRect.setAttribute('fill', '#ffffff');
-        alphaRect.setAttribute('opacity', '0');
-        maskGrouper.setAttribute('filter', 'url(' + locationHref + '#' + filId + ')');
-        maskGrouper.appendChild(alphaRect);
-        maskGrouper.appendChild(this.layerElement);
-        layerElementParent = maskGrouper;
-        if (!featureSupport.maskType) {
-          maskGroup.setAttribute('mask-type', 'luminance');
-          fil.appendChild(filtersFactory.createAlphaToLuminanceFilter());
-          gg = createNS('g');
-          maskGrouper.appendChild(alphaRect);
-          gg.appendChild(this.layerElement);
-          layerElementParent = gg;
-          maskGrouper.appendChild(gg);
-        }
-        this.globalData.defs.appendChild(maskGroup);
-      }
-    } else if (this.data.tt) {
-      this.matteElement.appendChild(this.layerElement);
-      layerElementParent = this.matteElement;
-      this.baseElement = this.matteElement;
-    } else {
-      this.baseElement = this.layerElement;
-    }
-    if (this.data.ln) {
-      this.layerElement.setAttribute('id', this.data.ln);
-    }
-    if (this.data.cl) {
-      this.layerElement.setAttribute('class', this.data.cl);
-    }
-    // Clipping compositions to hide content that exceeds boundaries. If collapsed transformations is on, component should not be clipped
-    if (this.data.ty === 0 && !this.data.hd) {
-      var cp = createNS('clipPath');
-      var pt = createNS('path');
-      pt.setAttribute('d', 'M0,0 L' + this.data.w + ',0 L' + this.data.w + ',' + this.data.h + ' L0,' + this.data.h + 'z');
-      var clipId = createElementID();
-      cp.setAttribute('id', clipId);
-      cp.appendChild(pt);
-      this.globalData.defs.appendChild(cp);
-
-      if (this.checkMasks()) {
-        var cpGroup = createNS('g');
-        cpGroup.setAttribute('clip-path', 'url(' + locationHref + '#' + clipId + ')');
-        cpGroup.appendChild(this.layerElement);
-        this.transformedElement = cpGroup;
-        if (layerElementParent) {
-          layerElementParent.appendChild(this.transformedElement);
-        } else {
-          this.baseElement = this.transformedElement;
-        }
-      } else {
-        this.layerElement.setAttribute('clip-path', 'url(' + locationHref + '#' + clipId + ')');
-      }
-    }
-    if (this.data.bm !== 0) {
-      this.setBlendMode();
-    }
-  },
-  renderElement: function () {
-    if (this.finalTransform._matMdf) {
-      this.transformedElement.setAttribute('transform', this.finalTransform.mat.to2dCSS());
-    }
-    if (this.finalTransform._opMdf) {
-      this.transformedElement.setAttribute('opacity', this.finalTransform.mProp.o.v);
-    }
-  },
-  destroyBaseElement: function () {
-    this.layerElement = null;
-    this.matteElement = null;
-    this.maskManager.destroy();
-  },
-  getBaseElement: function () {
-    if (this.data.hd) {
-      return null;
-    }
-    return this.baseElement;
-  },
-  createRenderableComponents: function () {
-    this.maskManager = new MaskElement(this.data, this, this.globalData);
-    this.renderableEffectsManager = new SVGEffects(this);
-  },
-  setMatte: function (id) {
-    if (!this.matteElement) {
-      return;
-    }
-    this.matteElement.setAttribute('mask', 'url(' + locationHref + '#' + id + ')');
-  },
-};
-
-/* global ProcessedElement */
-
-function IShapeElement() {
-}
-
-IShapeElement.prototype = {
-  addShapeToModifiers: function (data) {
-    var i;
-    var len = this.shapeModifiers.length;
-    for (i = 0; i < len; i += 1) {
-      this.shapeModifiers[i].addShape(data);
-    }
-  },
-  isShapeInAnimatedModifiers: function (data) {
-    var i = 0;
-    var len = this.shapeModifiers.length;
-    while (i < len) {
-      if (this.shapeModifiers[i].isAnimatedWithShape(data)) {
-        return true;
-      }
-    }
-    return false;
-  },
-  renderModifiers: function () {
-    if (!this.shapeModifiers.length) {
-      return;
-    }
-    var i;
-    var len = this.shapes.length;
-    for (i = 0; i < len; i += 1) {
-      this.shapes[i].sh.reset();
-    }
-
-    len = this.shapeModifiers.length;
-    var shouldBreakProcess;
-    for (i = len - 1; i >= 0; i -= 1) {
-      shouldBreakProcess = this.shapeModifiers[i].processShapes(this._isFirstFrame);
-      // workaround to fix cases where a repeater resets the shape so the following processes get called twice
-      // TODO: find a better solution for this
-      if (shouldBreakProcess) {
-        break;
-      }
-    }
-  },
-
-  searchProcessedElement: function (elem) {
-    var elements = this.processedElements;
-    var i = 0;
-    var len = elements.length;
-    while (i < len) {
-      if (elements[i].elem === elem) {
-        return elements[i].pos;
-      }
-      i += 1;
-    }
-    return 0;
-  },
-  addProcessedElement: function (elem, pos) {
-    var elements = this.processedElements;
-    var i = elements.length;
-    while (i) {
-      i -= 1;
-      if (elements[i].elem === elem) {
-        elements[i].pos = pos;
-        return;
-      }
-    }
-    elements.push(new ProcessedElement(elem, pos));
-  },
-  prepareFrame: function (num) {
-    this.prepareRenderableFrame(num);
-    this.prepareProperties(num, this.isInRange);
-  },
-};
-
-/* global TextProperty, TextAnimatorProperty, buildShapeString, LetterProps */
-
-function ITextElement() {
-}
-
-ITextElement.prototype.initElement = function (data, globalData, comp) {
-  this.lettersChangedFlag = true;
-  this.initFrame();
-  this.initBaseData(data, globalData, comp);
-  this.textProperty = new TextProperty(this, data.t, this.dynamicProperties);
-  this.textAnimator = new TextAnimatorProperty(data.t, this.renderType, this);
-  this.initTransform(data, globalData, comp);
-  this.initHierarchy();
-  this.initRenderable();
-  this.initRendererElement();
-  this.createContainerElements();
-  this.createRenderableComponents();
-  this.createContent();
-  this.hide();
-  this.textAnimator.searchProperties(this.dynamicProperties);
-};
-
-ITextElement.prototype.prepareFrame = function (num) {
-  this._mdf = false;
-  this.prepareRenderableFrame(num);
-  this.prepareProperties(num, this.isInRange);
-  if (this.textProperty._mdf || this.textProperty._isFirstFrame) {
-    this.buildNewText();
-    this.textProperty._isFirstFrame = false;
-    this.textProperty._mdf = false;
-  }
-};
-
-ITextElement.prototype.createPathShape = function (matrixHelper, shapes) {
-  var j;
-  var jLen = shapes.length;
-  var pathNodes;
-  var shapeStr = '';
-  for (j = 0; j < jLen; j += 1) {
-    pathNodes = shapes[j].ks.k;
-    shapeStr += buildShapeString(pathNodes, pathNodes.i.length, true, matrixHelper);
-  }
-  return shapeStr;
-};
-
-ITextElement.prototype.updateDocumentData = function (newData, index) {
-  this.textProperty.updateDocumentData(newData, index);
-};
-
-ITextElement.prototype.canResizeFont = function (_canResize) {
-  this.textProperty.canResizeFont(_canResize);
-};
-
-ITextElement.prototype.setMinimumFontSize = function (_fontSize) {
-  this.textProperty.setMinimumFontSize(_fontSize);
-};
-
-ITextElement.prototype.applyTextPropertiesToMatrix = function (documentData, matrixHelper, lineNumber, xPos, yPos) {
-  if (documentData.ps) {
-    matrixHelper.translate(documentData.ps[0], documentData.ps[1] + documentData.ascent, 0);
-  }
-  matrixHelper.translate(0, -documentData.ls, 0);
-  switch (documentData.j) {
-    case 1:
-      matrixHelper.translate(documentData.justifyOffset + (documentData.boxWidth - documentData.lineWidths[lineNumber]), 0, 0);
-      break;
-    case 2:
-      matrixHelper.translate(documentData.justifyOffset + (documentData.boxWidth - documentData.lineWidths[lineNumber]) / 2, 0, 0);
-      break;
-    default:
-      break;
-  }
-  matrixHelper.translate(xPos, yPos, 0);
-};
-
-ITextElement.prototype.buildColor = function (colorData) {
-  return 'rgb(' + Math.round(colorData[0] * 255) + ',' + Math.round(colorData[1] * 255) + ',' + Math.round(colorData[2] * 255) + ')';
-};
-
-ITextElement.prototype.emptyProp = new LetterProps();
-
-ITextElement.prototype.destroy = function () {
-
-};
-
-/* global extendPrototype, BaseElement, TransformElement, HierarchyElement, FrameElement, RenderableDOMElement */
-
-function ICompElement() {}
-
-extendPrototype([BaseElement, TransformElement, HierarchyElement, FrameElement, RenderableDOMElement], ICompElement);
-
-ICompElement.prototype.initElement = function (data, globalData, comp) {
-  this.initFrame();
-  this.initBaseData(data, globalData, comp);
-  this.initTransform(data, globalData, comp);
-  this.initRenderable();
-  this.initHierarchy();
-  this.initRendererElement();
-  this.createContainerElements();
-  this.createRenderableComponents();
-  if (this.data.xt || !globalData.progressiveLoad) {
-    this.buildAllItems();
-  }
-  this.hide();
-};
-
-/* ICompElement.prototype.hide = function(){
-    if(!this.hidden){
-        this.hideElement();
-        var i,len = this.elements.length;
-        for( i = 0; i < len; i+=1 ){
-            if(this.elements[i]){
-                this.elements[i].hide();
-            }
-        }
-    }
-}; */
-
-ICompElement.prototype.prepareFrame = function (num) {
-  this._mdf = false;
-  this.prepareRenderableFrame(num);
-  this.prepareProperties(num, this.isInRange);
-  if (!this.isInRange && !this.data.xt) {
-    return;
-  }
-
-  if (!this.tm._placeholder) {
-    var timeRemapped = this.tm.v;
-    if (timeRemapped === this.data.op) {
-      timeRemapped = this.data.op - 1;
-    }
-    this.renderedFrame = timeRemapped;
-  } else {
-    this.renderedFrame = num / this.data.sr;
-  }
-  var i;
-  var len = this.elements.length;
-  if (!this.completeLayers) {
-    this.checkLayers(this.renderedFrame);
-  }
-  // This iteration needs to be backwards because of how expressions connect between each other
-  for (i = len - 1; i >= 0; i -= 1) {
-    if (this.completeLayers || this.elements[i]) {
-      this.elements[i].prepareFrame(this.renderedFrame - this.layers[i].st);
-      if (this.elements[i]._mdf) {
-        this._mdf = true;
-      }
-    }
-  }
-};
-
-ICompElement.prototype.renderInnerContent = function () {
-  var i;
-  var len = this.layers.length;
-  for (i = 0; i < len; i += 1) {
-    if (this.completeLayers || this.elements[i]) {
-      this.elements[i].renderFrame();
-    }
-  }
-};
-
-ICompElement.prototype.setElements = function (elems) {
-  this.elements = elems;
-};
-
-ICompElement.prototype.getElements = function () {
-  return this.elements;
-};
-
-ICompElement.prototype.destroyElements = function () {
-  var i;
-  var len = this.layers.length;
-  for (i = 0; i < len; i += 1) {
-    if (this.elements[i]) {
-      this.elements[i].destroy();
-    }
-  }
-};
-
-ICompElement.prototype.destroy = function () {
-  this.destroyElements();
-  this.destroyBaseElement();
-};
-
-/* global extendPrototype, BaseElement, TransformElement, SVGBaseElement, HierarchyElement, FrameElement, RenderableDOMElement, createNS */
-
-function IImageElement(data, globalData, comp) {
-  this.assetData = globalData.getAssetData(data.refId);
-  this.initElement(data, globalData, comp);
-  this.sourceRect = {
-    top: 0, left: 0, width: this.assetData.w, height: this.assetData.h,
-  };
-}
-
-extendPrototype([BaseElement, TransformElement, SVGBaseElement, HierarchyElement, FrameElement, RenderableDOMElement], IImageElement);
-
-IImageElement.prototype.createContent = function () {
-  var assetPath = this.globalData.getAssetsPath(this.assetData);
-
-  this.innerElem = createNS('image');
-  this.innerElem.setAttribute('width', this.assetData.w + 'px');
-  this.innerElem.setAttribute('height', this.assetData.h + 'px');
-  this.innerElem.setAttribute('preserveAspectRatio', this.assetData.pr || this.globalData.renderConfig.imagePreserveAspectRatio);
-  this.innerElem.setAttributeNS('http://www.w3.org/1999/xlink', 'href', assetPath);
-
-  this.layerElement.appendChild(this.innerElem);
-};
-
-IImageElement.prototype.sourceRectAtTime = function () {
-  return this.sourceRect;
-};
-
-/* global extendPrototype, IImageElement, createNS */
-
-function ISolidElement(data, globalData, comp) {
-  this.initElement(data, globalData, comp);
-}
-extendPrototype([IImageElement], ISolidElement);
-
-ISolidElement.prototype.createContent = function () {
-  var rect = createNS('rect');
-  /// /rect.style.width = this.data.sw;
-  /// /rect.style.height = this.data.sh;
-  /// /rect.style.fill = this.data.sc;
-  rect.setAttribute('width', this.data.sw);
-  rect.setAttribute('height', this.data.sh);
-  rect.setAttribute('fill', this.data.sc);
-  this.layerElement.appendChild(rect);
-};
-
-/* global PropertyFactory, extendPrototype, RenderableElement, BaseElement, FrameElement */
-
-function AudioElement(data, globalData, comp) {
-  this.initFrame();
-  this.initRenderable();
-  this.assetData = globalData.getAssetData(data.refId);
-  this.initBaseData(data, globalData, comp);
-  this._isPlaying = false;
-  this._canPlay = false;
-  var assetPath = this.globalData.getAssetsPath(this.assetData);
-  this.audio = this.globalData.audioController.createAudio(assetPath);
-  this._currentTime = 0;
-  this.globalData.audioController.addAudio(this);
-  this.tm = data.tm ? PropertyFactory.getProp(this, data.tm, 0, globalData.frameRate, this) : { _placeholder: true };
-}
-
-AudioElement.prototype.prepareFrame = function (num) {
-  this.prepareRenderableFrame(num, true);
-  this.prepareProperties(num, true);
-  if (!this.tm._placeholder) {
-    var timeRemapped = this.tm.v;
-    this._currentTime = timeRemapped;
-  } else {
-    this._currentTime = num / this.data.sr;
-  }
-};
-
-extendPrototype([RenderableElement, BaseElement, FrameElement], AudioElement);
-
-AudioElement.prototype.renderFrame = function () {
-  if (this.isInRange && this._canPlay) {
-    if (!this._isPlaying) {
-      this.audio.play();
-      this.audio.seek(this._currentTime / this.globalData.frameRate);
-      this._isPlaying = true;
-    } else if (!this.audio.playing()
-      || Math.abs(this._currentTime / this.globalData.frameRate - this.audio.seek()) > 0.1
-    ) {
-      this.audio.seek(this._currentTime / this.globalData.frameRate);
-    }
-  }
-};
-
-AudioElement.prototype.show = function () {
-  // this.audio.play()
-};
-
-AudioElement.prototype.hide = function () {
-  this.audio.pause();
-  this._isPlaying = false;
-};
-
-AudioElement.prototype.pause = function () {
-  this.audio.pause();
-  this._isPlaying = false;
-  this._canPlay = false;
-};
-
-AudioElement.prototype.resume = function () {
-  this._canPlay = true;
-};
-
-AudioElement.prototype.setRate = function (rateValue) {
-  this.audio.rate(rateValue);
-};
-
-AudioElement.prototype.volume = function (volumeValue) {
-  this.audio.volume(volumeValue);
-};
-
-AudioElement.prototype.getBaseElement = function () {
-  return null;
-};
-
-AudioElement.prototype.destroy = function () {
-};
-
-AudioElement.prototype.sourceRectAtTime = function () {
-};
-
-AudioElement.prototype.initExpressions = function () {
-};
-
-/* global extendPrototype, RenderableElement, BaseElement, FrameElement, FootageInterface */
-
-function FootageElement(data, globalData, comp) {
-  this.initFrame();
-  this.initRenderable();
-  this.assetData = globalData.getAssetData(data.refId);
-  this.footageData = globalData.imageLoader.getAsset(this.assetData);
-  this.initBaseData(data, globalData, comp);
-}
-
-FootageElement.prototype.prepareFrame = function () {
-};
-
-extendPrototype([RenderableElement, BaseElement, FrameElement], FootageElement);
-
-FootageElement.prototype.getBaseElement = function () {
-  return null;
-};
-
-FootageElement.prototype.renderFrame = function () {
-};
-
-FootageElement.prototype.destroy = function () {
-};
-
-FootageElement.prototype.initExpressions = function () {
-  this.layerInterface = FootageInterface(this);
-};
-
-FootageElement.prototype.getFootageData = function () {
-  return this.footageData;
-};
-
-/* global createSizedArray, PropertyFactory, extendPrototype, SVGRenderer, ICompElement, SVGBaseElement */
-
-function SVGCompElement(data, globalData, comp) {
-  this.layers = data.layers;
-  this.supports3d = true;
-  this.completeLayers = false;
-  this.pendingElements = [];
-  this.elements = this.layers ? createSizedArray(this.layers.length) : [];
-  // this.layerElement = createNS('g');
-  this.initElement(data, globalData, comp);
-  this.tm = data.tm ? PropertyFactory.getProp(this, data.tm, 0, globalData.frameRate, this) : { _placeholder: true };
-}
-
-extendPrototype([SVGRenderer, ICompElement, SVGBaseElement], SVGCompElement);
-
-/* global extendPrototype, BaseElement, TransformElement, SVGBaseElement, HierarchyElement, FrameElement,
-RenderableDOMElement, ITextElement, createSizedArray, createNS */
-
-function SVGTextLottieElement(data, globalData, comp) {
-  this.textSpans = [];
-  this.renderType = 'svg';
-  this.initElement(data, globalData, comp);
-}
-
-extendPrototype([BaseElement, TransformElement, SVGBaseElement, HierarchyElement, FrameElement, RenderableDOMElement, ITextElement], SVGTextLottieElement);
-
-SVGTextLottieElement.prototype.createContent = function () {
-  if (this.data.singleShape && !this.globalData.fontManager.chars) {
-    this.textContainer = createNS('text');
-  }
-};
-
-SVGTextLottieElement.prototype.buildTextContents = function (textArray) {
-  var i = 0;
-  var len = textArray.length;
-  var textContents = [];
-  var currentTextContent = '';
-  while (i < len) {
-    if (textArray[i] === String.fromCharCode(13) || textArray[i] === String.fromCharCode(3)) {
-      textContents.push(currentTextContent);
-      currentTextContent = '';
-    } else {
-      currentTextContent += textArray[i];
-    }
-    i += 1;
-  }
-  textContents.push(currentTextContent);
-  return textContents;
-};
-
-SVGTextLottieElement.prototype.buildNewText = function () {
-  var i;
-  var len;
-
-  var documentData = this.textProperty.currentData;
-  this.renderedLetters = createSizedArray(documentData ? documentData.l.length : 0);
-  if (documentData.fc) {
-    this.layerElement.setAttribute('fill', this.buildColor(documentData.fc));
-  } else {
-    this.layerElement.setAttribute('fill', 'rgba(0,0,0,0)');
-  }
-  if (documentData.sc) {
-    this.layerElement.setAttribute('stroke', this.buildColor(documentData.sc));
-    this.layerElement.setAttribute('stroke-width', documentData.sw);
-  }
-  this.layerElement.setAttribute('font-size', documentData.finalSize);
-  var fontData = this.globalData.fontManager.getFontByName(documentData.f);
-  if (fontData.fClass) {
-    this.layerElement.setAttribute('class', fontData.fClass);
-  } else {
-    this.layerElement.setAttribute('font-family', fontData.fFamily);
-    var fWeight = documentData.fWeight;
-    var fStyle = documentData.fStyle;
-    this.layerElement.setAttribute('font-style', fStyle);
-    this.layerElement.setAttribute('font-weight', fWeight);
-  }
-  this.layerElement.setAttribute('aria-label', documentData.t);
-
-  var letters = documentData.l || [];
-  var usesGlyphs = !!this.globalData.fontManager.chars;
-  len = letters.length;
-
-  var tSpan;
-  var matrixHelper = this.mHelper;
-  var shapes;
-  var shapeStr = '';
-  var singleShape = this.data.singleShape;
-  var xPos = 0;
-  var yPos = 0;
-  var firstLine = true;
-  var trackingOffset = documentData.tr * 0.001 * documentData.finalSize;
-  if (singleShape && !usesGlyphs && !documentData.sz) {
-    var tElement = this.textContainer;
-    var justify = 'start';
-    switch (documentData.j) {
-      case 1:
-        justify = 'end';
-        break;
-      case 2:
-        justify = 'middle';
-        break;
-      default:
-        justify = 'start';
-        break;
-    }
-    tElement.setAttribute('text-anchor', justify);
-    tElement.setAttribute('letter-spacing', trackingOffset);
-    var textContent = this.buildTextContents(documentData.finalText);
-    len = textContent.length;
-    yPos = documentData.ps ? documentData.ps[1] + documentData.ascent : 0;
-    for (i = 0; i < len; i += 1) {
-      tSpan = this.textSpans[i] || createNS('tspan');
-      tSpan.textContent = textContent[i];
-      tSpan.setAttribute('x', 0);
-      tSpan.setAttribute('y', yPos);
-      tSpan.style.display = 'inherit';
-      tElement.appendChild(tSpan);
-      this.textSpans[i] = tSpan;
-      yPos += documentData.finalLineHeight;
-    }
-
-    this.layerElement.appendChild(tElement);
-  } else {
-    var cachedSpansLength = this.textSpans.length;
-    var shapeData;
-    var charData;
-    for (i = 0; i < len; i += 1) {
-      if (!usesGlyphs || !singleShape || i === 0) {
-        tSpan = cachedSpansLength > i ? this.textSpans[i] : createNS(usesGlyphs ? 'path' : 'text');
-        if (cachedSpansLength <= i) {
-          tSpan.setAttribute('stroke-linecap', 'butt');
-          tSpan.setAttribute('stroke-linejoin', 'round');
-          tSpan.setAttribute('stroke-miterlimit', '4');
-          this.textSpans[i] = tSpan;
-          this.layerElement.appendChild(tSpan);
-        }
-        tSpan.style.display = 'inherit';
-      }
-
-      matrixHelper.reset();
-      matrixHelper.scale(documentData.finalSize / 100, documentData.finalSize / 100);
-      if (singleShape) {
-        if (letters[i].n) {
-          xPos = -trackingOffset;
-          yPos += documentData.yOffset;
-          yPos += firstLine ? 1 : 0;
-          firstLine = false;
-        }
-        this.applyTextPropertiesToMatrix(documentData, matrixHelper, letters[i].line, xPos, yPos);
-        xPos += letters[i].l || 0;
-        // xPos += letters[i].val === ' ' ? 0 : trackingOffset;
-        xPos += trackingOffset;
-      }
-      if (usesGlyphs) {
-        charData = this.globalData.fontManager.getCharData(documentData.finalText[i], fontData.fStyle, this.globalData.fontManager.getFontByName(documentData.f).fFamily);
-        shapeData = (charData && charData.data) || {};
-        shapes = shapeData.shapes ? shapeData.shapes[0].it : [];
-        if (!singleShape) {
-          tSpan.setAttribute('d', this.createPathShape(matrixHelper, shapes));
-        } else {
-          shapeStr += this.createPathShape(matrixHelper, shapes);
-        }
-      } else {
-        if (singleShape) {
-          tSpan.setAttribute('transform', 'translate(' + matrixHelper.props[12] + ',' + matrixHelper.props[13] + ')');
-        }
-        tSpan.textContent = letters[i].val;
-        tSpan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve');
-      }
-      //
-    }
-    if (singleShape && tSpan) {
-      tSpan.setAttribute('d', shapeStr);
-    }
-  }
-  while (i < this.textSpans.length) {
-    this.textSpans[i].style.display = 'none';
-    i += 1;
-  }
-
-  this._sizeChanged = true;
-};
-
-SVGTextLottieElement.prototype.sourceRectAtTime = function () {
-  this.prepareFrame(this.comp.renderedFrame - this.data.st);
-  this.renderInnerContent();
-  if (this._sizeChanged) {
-    this._sizeChanged = false;
-    var textBox = this.layerElement.getBBox();
-    this.bbox = {
-      top: textBox.y,
-      left: textBox.x,
-      width: textBox.width,
-      height: textBox.height,
-    };
-  }
-  return this.bbox;
-};
-
-SVGTextLottieElement.prototype.renderInnerContent = function () {
-  if (!this.data.singleShape) {
-    this.textAnimator.getMeasures(this.textProperty.currentData, this.lettersChangedFlag);
-    if (this.lettersChangedFlag || this.textAnimator.lettersChangedFlag) {
-      this._sizeChanged = true;
-      var i;
-      var len;
-      var renderedLetters = this.textAnimator.renderedLetters;
-
-      var letters = this.textProperty.currentData.l;
-
-      len = letters.length;
-      var renderedLetter;
-      var textSpan;
-      for (i = 0; i < len; i += 1) {
-        if (!letters[i].n) {
-          renderedLetter = renderedLetters[i];
-          textSpan = this.textSpans[i];
-          if (renderedLetter._mdf.m) {
-            textSpan.setAttribute('transform', renderedLetter.m);
-          }
-          if (renderedLetter._mdf.o) {
-            textSpan.setAttribute('opacity', renderedLetter.o);
-          }
-          if (renderedLetter._mdf.sw) {
-            textSpan.setAttribute('stroke-width', renderedLetter.sw);
-          }
-          if (renderedLetter._mdf.sc) {
-            textSpan.setAttribute('stroke', renderedLetter.sc);
-          }
-          if (renderedLetter._mdf.fc) {
-            textSpan.setAttribute('fill', renderedLetter.fc);
-          }
-        }
-      }
-    }
-  }
-};
-
-/* global extendPrototype, BaseElement, TransformElement, SVGBaseElement, IShapeElement, HierarchyElement,
-FrameElement, RenderableDOMElement, Matrix, SVGStyleData, SVGStrokeStyleData, SVGFillStyleData,
-SVGGradientFillStyleData, SVGGradientStrokeStyleData, locationHref, getBlendMode, ShapeGroupData,
-TransformPropertyFactory, SVGTransformData, ShapePropertyFactory, SVGShapeData, SVGElementsRenderer, ShapeModifiers,
-lineCapEnum, lineJoinEnum */
-
-function SVGShapeElement(data, globalData, comp) {
-  // List of drawable elements
-  this.shapes = [];
-  // Full shape data
-  this.shapesData = data.shapes;
-  // List of styles that will be applied to shapes
-  this.stylesList = [];
-  // List of modifiers that will be applied to shapes
-  this.shapeModifiers = [];
-  // List of items in shape tree
-  this.itemsData = [];
-  // List of items in previous shape tree
-  this.processedElements = [];
-  // List of animated components
-  this.animatedContents = [];
-  this.initElement(data, globalData, comp);
-  // Moving any property that doesn't get too much access after initialization because of v8 way of handling more than 10 properties.
-  // List of elements that have been created
-  this.prevViewData = [];
-  // Moving any property that doesn't get too much access after initialization because of v8 way of handling more than 10 properties.
-}
-
-extendPrototype([BaseElement, TransformElement, SVGBaseElement, IShapeElement, HierarchyElement, FrameElement, RenderableDOMElement], SVGShapeElement);
-
-SVGShapeElement.prototype.initSecondaryElement = function () {
-};
-
-SVGShapeElement.prototype.identityMatrix = new Matrix();
-
-SVGShapeElement.prototype.buildExpressionInterface = function () {};
-
-SVGShapeElement.prototype.createContent = function () {
-  this.searchShapes(this.shapesData, this.itemsData, this.prevViewData, this.layerElement, 0, [], true);
-  this.filterUniqueShapes();
-};
-
-/*
-This method searches for multiple shapes that affect a single element and one of them is animated
-*/
-SVGShapeElement.prototype.filterUniqueShapes = function () {
-  var i;
-  var len = this.shapes.length;
-  var shape;
-  var j;
-  var jLen = this.stylesList.length;
-  var style;
-  var tempShapes = [];
-  var areAnimated = false;
-  for (j = 0; j < jLen; j += 1) {
-    style = this.stylesList[j];
-    areAnimated = false;
-    tempShapes.length = 0;
-    for (i = 0; i < len; i += 1) {
-      shape = this.shapes[i];
-      if (shape.styles.indexOf(style) !== -1) {
-        tempShapes.push(shape);
-        areAnimated = shape._isAnimated || areAnimated;
-      }
-    }
-    if (tempShapes.length > 1 && areAnimated) {
-      this.setShapesAsAnimated(tempShapes);
-    }
-  }
-};
-
-SVGShapeElement.prototype.setShapesAsAnimated = function (shapes) {
-  var i;
-  var len = shapes.length;
-  for (i = 0; i < len; i += 1) {
-    shapes[i].setAsAnimated();
-  }
-};
-
-SVGShapeElement.prototype.createStyleElement = function (data, level) {
-  // TODO: prevent drawing of hidden styles
-  var elementData;
-  var styleOb = new SVGStyleData(data, level);
-
-  var pathElement = styleOb.pElem;
-  if (data.ty === 'st') {
-    elementData = new SVGStrokeStyleData(this, data, styleOb);
-  } else if (data.ty === 'fl') {
-    elementData = new SVGFillStyleData(this, data, styleOb);
-  } else if (data.ty === 'gf' || data.ty === 'gs') {
-    var GradientConstructor = data.ty === 'gf' ? SVGGradientFillStyleData : SVGGradientStrokeStyleData;
-    elementData = new GradientConstructor(this, data, styleOb);
-    this.globalData.defs.appendChild(elementData.gf);
-    if (elementData.maskId) {
-      this.globalData.defs.appendChild(elementData.ms);
-      this.globalData.defs.appendChild(elementData.of);
-      pathElement.setAttribute('mask', 'url(' + locationHref + '#' + elementData.maskId + ')');
-    }
-  }
-
-  if (data.ty === 'st' || data.ty === 'gs') {
-    pathElement.setAttribute('stroke-linecap', lineCapEnum[data.lc || 2]);
-    pathElement.setAttribute('stroke-linejoin', lineJoinEnum[data.lj || 2]);
-    pathElement.setAttribute('fill-opacity', '0');
-    if (data.lj === 1) {
-      pathElement.setAttribute('stroke-miterlimit', data.ml);
-    }
-  }
-
-  if (data.r === 2) {
-    pathElement.setAttribute('fill-rule', 'evenodd');
-  }
-
-  if (data.ln) {
-    pathElement.setAttribute('id', data.ln);
-  }
-  if (data.cl) {
-    pathElement.setAttribute('class', data.cl);
-  }
-  if (data.bm) {
-    pathElement.style['mix-blend-mode'] = getBlendMode(data.bm);
-  }
-  this.stylesList.push(styleOb);
-  this.addToAnimatedContents(data, elementData);
-  return elementData;
-};
-
-SVGShapeElement.prototype.createGroupElement = function (data) {
-  var elementData = new ShapeGroupData();
-  if (data.ln) {
-    elementData.gr.setAttribute('id', data.ln);
-  }
-  if (data.cl) {
-    elementData.gr.setAttribute('class', data.cl);
-  }
-  if (data.bm) {
-    elementData.gr.style['mix-blend-mode'] = getBlendMode(data.bm);
-  }
-  return elementData;
-};
-
-SVGShapeElement.prototype.createTransformElement = function (data, container) {
-  var transformProperty = TransformPropertyFactory.getTransformProperty(this, data, this);
-  var elementData = new SVGTransformData(transformProperty, transformProperty.o, container);
-  this.addToAnimatedContents(data, elementData);
-  return elementData;
-};
-
-SVGShapeElement.prototype.createShapeElement = function (data, ownTransformers, level) {
-  var ty = 4;
-  if (data.ty === 'rc') {
-    ty = 5;
-  } else if (data.ty === 'el') {
-    ty = 6;
-  } else if (data.ty === 'sr') {
-    ty = 7;
-  }
-  var shapeProperty = ShapePropertyFactory.getShapeProp(this, data, ty, this);
-  var elementData = new SVGShapeData(ownTransformers, level, shapeProperty);
-  this.shapes.push(elementData);
-  this.addShapeToModifiers(elementData);
-  this.addToAnimatedContents(data, elementData);
-  return elementData;
-};
-
-SVGShapeElement.prototype.addToAnimatedContents = function (data, element) {
-  var i = 0;
-  var len = this.animatedContents.length;
-  while (i < len) {
-    if (this.animatedContents[i].element === element) {
-      return;
-    }
-    i += 1;
-  }
-  this.animatedContents.push({
-    fn: SVGElementsRenderer.createRenderFunction(data),
-    element: element,
-    data: data,
-  });
-};
-
-SVGShapeElement.prototype.setElementStyles = function (elementData) {
-  var arr = elementData.styles;
-  var j;
-  var jLen = this.stylesList.length;
-  for (j = 0; j < jLen; j += 1) {
-    if (!this.stylesList[j].closed) {
-      arr.push(this.stylesList[j]);
-    }
-  }
-};
-
-SVGShapeElement.prototype.reloadShapes = function () {
-  this._isFirstFrame = true;
-  var i;
-  var len = this.itemsData.length;
-  for (i = 0; i < len; i += 1) {
-    this.prevViewData[i] = this.itemsData[i];
-  }
-  this.searchShapes(this.shapesData, this.itemsData, this.prevViewData, this.layerElement, 0, [], true);
-  this.filterUniqueShapes();
-  len = this.dynamicProperties.length;
-  for (i = 0; i < len; i += 1) {
-    this.dynamicProperties[i].getValue();
-  }
-  this.renderModifiers();
-};
-
-SVGShapeElement.prototype.searchShapes = function (arr, itemsData, prevViewData, container, level, transformers, render) {
-  var ownTransformers = [].concat(transformers);
-  var i;
-  var len = arr.length - 1;
-  var j;
-  var jLen;
-  var ownStyles = [];
-  var ownModifiers = [];
-  var currentTransform;
-  var modifier;
-  var processedPos;
-  for (i = len; i >= 0; i -= 1) {
-    processedPos = this.searchProcessedElement(arr[i]);
-    if (!processedPos) {
-      arr[i]._render = render;
-    } else {
-      itemsData[i] = prevViewData[processedPos - 1];
-    }
-    if (arr[i].ty === 'fl' || arr[i].ty === 'st' || arr[i].ty === 'gf' || arr[i].ty === 'gs') {
-      if (!processedPos) {
-        itemsData[i] = this.createStyleElement(arr[i], level);
-      } else {
-        itemsData[i].style.closed = false;
-      }
-      if (arr[i]._render) {
-        if (itemsData[i].style.pElem.parentNode !== container) {
-          container.appendChild(itemsData[i].style.pElem);
-        }
-      }
-      ownStyles.push(itemsData[i].style);
-    } else if (arr[i].ty === 'gr') {
-      if (!processedPos) {
-        itemsData[i] = this.createGroupElement(arr[i]);
-      } else {
-        jLen = itemsData[i].it.length;
-        for (j = 0; j < jLen; j += 1) {
-          itemsData[i].prevViewData[j] = itemsData[i].it[j];
-        }
-      }
-      this.searchShapes(arr[i].it, itemsData[i].it, itemsData[i].prevViewData, itemsData[i].gr, level + 1, ownTransformers, render);
-      if (arr[i]._render) {
-        if (itemsData[i].gr.parentNode !== container) {
-          container.appendChild(itemsData[i].gr);
-        }
-      }
-    } else if (arr[i].ty === 'tr') {
-      if (!processedPos) {
-        itemsData[i] = this.createTransformElement(arr[i], container);
-      }
-      currentTransform = itemsData[i].transform;
-      ownTransformers.push(currentTransform);
-    } else if (arr[i].ty === 'sh' || arr[i].ty === 'rc' || arr[i].ty === 'el' || arr[i].ty === 'sr') {
-      if (!processedPos) {
-        itemsData[i] = this.createShapeElement(arr[i], ownTransformers, level);
-      }
-      this.setElementStyles(itemsData[i]);
-    } else if (arr[i].ty === 'tm' || arr[i].ty === 'rd' || arr[i].ty === 'ms' || arr[i].ty === 'pb') {
-      if (!processedPos) {
-        modifier = ShapeModifiers.getModifier(arr[i].ty);
-        modifier.init(this, arr[i]);
-        itemsData[i] = modifier;
-        this.shapeModifiers.push(modifier);
-      } else {
-        modifier = itemsData[i];
-        modifier.closed = false;
-      }
-      ownModifiers.push(modifier);
-    } else if (arr[i].ty === 'rp') {
-      if (!processedPos) {
-        modifier = ShapeModifiers.getModifier(arr[i].ty);
-        itemsData[i] = modifier;
-        modifier.init(this, arr, i, itemsData);
-        this.shapeModifiers.push(modifier);
-        render = false;
-      } else {
-        modifier = itemsData[i];
-        modifier.closed = true;
-      }
-      ownModifiers.push(modifier);
-    }
-    this.addProcessedElement(arr[i], i + 1);
-  }
-  len = ownStyles.length;
-  for (i = 0; i < len; i += 1) {
-    ownStyles[i].closed = true;
-  }
-  len = ownModifiers.length;
-  for (i = 0; i < len; i += 1) {
-    ownModifiers[i].closed = true;
-  }
-};
-
-SVGShapeElement.prototype.renderInnerContent = function () {
-  this.renderModifiers();
-  var i;
-  var len = this.stylesList.length;
-  for (i = 0; i < len; i += 1) {
-    this.stylesList[i].reset();
-  }
-  this.renderShape();
-
-  for (i = 0; i < len; i += 1) {
-    if (this.stylesList[i]._mdf || this._isFirstFrame) {
-      if (this.stylesList[i].msElem) {
-        this.stylesList[i].msElem.setAttribute('d', this.stylesList[i].d);
-        // Adding M0 0 fixes same mask bug on all browsers
-        this.stylesList[i].d = 'M0 0' + this.stylesList[i].d;
-      }
-      this.stylesList[i].pElem.setAttribute('d', this.stylesList[i].d || 'M0 0');
-    }
-  }
-};
-
-SVGShapeElement.prototype.renderShape = function () {
-  var i;
-  var len = this.animatedContents.length;
-  var animatedContent;
-  for (i = 0; i < len; i += 1) {
-    animatedContent = this.animatedContents[i];
-    if ((this._isFirstFrame || animatedContent.element._isAnimated) && animatedContent.data !== true) {
-      animatedContent.fn(animatedContent.data, animatedContent.element, this._isFirstFrame);
-    }
-  }
-};
-
-SVGShapeElement.prototype.destroy = function () {
-  this.destroyBaseElement();
-  this.shapesData = null;
-  this.itemsData = null;
-};
-
-/* global createNS */
-
-function SVGTintFilter(filter, filterManager) {
-  this.filterManager = filterManager;
-  var feColorMatrix = createNS('feColorMatrix');
-  feColorMatrix.setAttribute('type', 'matrix');
-  feColorMatrix.setAttribute('color-interpolation-filters', 'linearRGB');
-  feColorMatrix.setAttribute('values', '0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0');
-  feColorMatrix.setAttribute('result', 'f1');
-  filter.appendChild(feColorMatrix);
-  feColorMatrix = createNS('feColorMatrix');
-  feColorMatrix.setAttribute('type', 'matrix');
-  feColorMatrix.setAttribute('color-interpolation-filters', 'sRGB');
-  feColorMatrix.setAttribute('values', '1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0');
-  feColorMatrix.setAttribute('result', 'f2');
-  filter.appendChild(feColorMatrix);
-  this.matrixFilter = feColorMatrix;
-  if (filterManager.effectElements[2].p.v !== 100 || filterManager.effectElements[2].p.k) {
-    var feMerge = createNS('feMerge');
-    filter.appendChild(feMerge);
-    var feMergeNode;
-    feMergeNode = createNS('feMergeNode');
-    feMergeNode.setAttribute('in', 'SourceGraphic');
-    feMerge.appendChild(feMergeNode);
-    feMergeNode = createNS('feMergeNode');
-    feMergeNode.setAttribute('in', 'f2');
-    feMerge.appendChild(feMergeNode);
-  }
-}
-
-SVGTintFilter.prototype.renderFrame = function (forceRender) {
-  if (forceRender || this.filterManager._mdf) {
-    var colorBlack = this.filterManager.effectElements[0].p.v;
-    var colorWhite = this.filterManager.effectElements[1].p.v;
-    var opacity = this.filterManager.effectElements[2].p.v / 100;
-    this.matrixFilter.setAttribute('values', (colorWhite[0] - colorBlack[0]) + ' 0 0 0 ' + colorBlack[0] + ' ' + (colorWhite[1] - colorBlack[1]) + ' 0 0 0 ' + colorBlack[1] + ' ' + (colorWhite[2] - colorBlack[2]) + ' 0 0 0 ' + colorBlack[2] + ' 0 0 0 ' + opacity + ' 0');
-  }
-};
-
-/* global createNS */
-
-function SVGFillFilter(filter, filterManager) {
-  this.filterManager = filterManager;
-  var feColorMatrix = createNS('feColorMatrix');
-  feColorMatrix.setAttribute('type', 'matrix');
-  feColorMatrix.setAttribute('color-interpolation-filters', 'sRGB');
-  feColorMatrix.setAttribute('values', '1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0');
-  filter.appendChild(feColorMatrix);
-  this.matrixFilter = feColorMatrix;
-}
-SVGFillFilter.prototype.renderFrame = function (forceRender) {
-  if (forceRender || this.filterManager._mdf) {
-    var color = this.filterManager.effectElements[2].p.v;
-    var opacity = this.filterManager.effectElements[6].p.v;
-    this.matrixFilter.setAttribute('values', '0 0 0 0 ' + color[0] + ' 0 0 0 0 ' + color[1] + ' 0 0 0 0 ' + color[2] + ' 0 0 0 ' + opacity + ' 0');
-  }
-};
-
-/* global createNS */
-
-function SVGGaussianBlurEffect(filter, filterManager) {
-  // Outset the filter region by 100% on all sides to accommodate blur expansion.
-  filter.setAttribute('x', '-100%');
-  filter.setAttribute('y', '-100%');
-  filter.setAttribute('width', '300%');
-  filter.setAttribute('height', '300%');
-
-  this.filterManager = filterManager;
-  var feGaussianBlur = createNS('feGaussianBlur');
-  filter.appendChild(feGaussianBlur);
-  this.feGaussianBlur = feGaussianBlur;
-}
-
-SVGGaussianBlurEffect.prototype.renderFrame = function (forceRender) {
-  if (forceRender || this.filterManager._mdf) {
-    // Empirical value, matching AE's blur appearance.
-    var kBlurrinessToSigma = 0.3;
-    var sigma = this.filterManager.effectElements[0].p.v * kBlurrinessToSigma;
-
-    // Dimensions mapping:
-    //
-    //   1 -> horizontal & vertical
-    //   2 -> horizontal only
-    //   3 -> vertical only
-    //
-    var dimensions = this.filterManager.effectElements[1].p.v;
-    var sigmaX = (dimensions == 3) ? 0 : sigma; // eslint-disable-line eqeqeq
-    var sigmaY = (dimensions == 2) ? 0 : sigma; // eslint-disable-line eqeqeq
-
-    this.feGaussianBlur.setAttribute('stdDeviation', sigmaX + ' ' + sigmaY);
-
-    // Repeat edges mapping:
-    //
-    //   0 -> off -> duplicate
-    //   1 -> on  -> wrap
-    var edgeMode = (this.filterManager.effectElements[2].p.v == 1) ? 'wrap' : 'duplicate'; // eslint-disable-line eqeqeq
-    this.feGaussianBlur.setAttribute('edgeMode', edgeMode);
-  }
-};
-
-/* global createNS, createElementID, locationHref, bmFloor */
-
-function SVGStrokeEffect(elem, filterManager) {
-  this.initialized = false;
-  this.filterManager = filterManager;
-  this.elem = elem;
-  this.paths = [];
-}
-
-SVGStrokeEffect.prototype.initialize = function () {
-  var elemChildren = this.elem.layerElement.children || this.elem.layerElement.childNodes;
-  var path;
-  var groupPath;
-  var i;
-  var len;
-  if (this.filterManager.effectElements[1].p.v === 1) {
-    len = this.elem.maskManager.masksProperties.length;
-    i = 0;
-  } else {
-    i = this.filterManager.effectElements[0].p.v - 1;
-    len = i + 1;
-  }
-  groupPath = createNS('g');
-  groupPath.setAttribute('fill', 'none');
-  groupPath.setAttribute('stroke-linecap', 'round');
-  groupPath.setAttribute('stroke-dashoffset', 1);
-  for (i; i < len; i += 1) {
-    path = createNS('path');
-    groupPath.appendChild(path);
-    this.paths.push({ p: path, m: i });
-  }
-  if (this.filterManager.effectElements[10].p.v === 3) {
-    var mask = createNS('mask');
-    var id = createElementID();
-    mask.setAttribute('id', id);
-    mask.setAttribute('mask-type', 'alpha');
-    mask.appendChild(groupPath);
-    this.elem.globalData.defs.appendChild(mask);
-    var g = createNS('g');
-    g.setAttribute('mask', 'url(' + locationHref + '#' + id + ')');
-    while (elemChildren[0]) {
-      g.appendChild(elemChildren[0]);
-    }
-    this.elem.layerElement.appendChild(g);
-    this.masker = mask;
-    groupPath.setAttribute('stroke', '#fff');
-  } else if (this.filterManager.effectElements[10].p.v === 1 || this.filterManager.effectElements[10].p.v === 2) {
-    if (this.filterManager.effectElements[10].p.v === 2) {
-      elemChildren = this.elem.layerElement.children || this.elem.layerElement.childNodes;
-      while (elemChildren.length) {
-        this.elem.layerElement.removeChild(elemChildren[0]);
-      }
-    }
-    this.elem.layerElement.appendChild(groupPath);
-    this.elem.layerElement.removeAttribute('mask');
-    groupPath.setAttribute('stroke', '#fff');
-  }
-  this.initialized = true;
-  this.pathMasker = groupPath;
-};
-
-SVGStrokeEffect.prototype.renderFrame = function (forceRender) {
-  if (!this.initialized) {
-    this.initialize();
-  }
-  var i;
-  var len = this.paths.length;
-  var mask;
-  var path;
-  for (i = 0; i < len; i += 1) {
-    if (this.paths[i].m !== -1) {
-      mask = this.elem.maskManager.viewData[this.paths[i].m];
-      path = this.paths[i].p;
-      if (forceRender || this.filterManager._mdf || mask.prop._mdf) {
-        path.setAttribute('d', mask.lastPath);
-      }
-      if (forceRender || this.filterManager.effectElements[9].p._mdf || this.filterManager.effectElements[4].p._mdf || this.filterManager.effectElements[7].p._mdf || this.filterManager.effectElements[8].p._mdf || mask.prop._mdf) {
-        var dasharrayValue;
-        if (this.filterManager.effectElements[7].p.v !== 0 || this.filterManager.effectElements[8].p.v !== 100) {
-          var s = Math.min(this.filterManager.effectElements[7].p.v, this.filterManager.effectElements[8].p.v) * 0.01;
-          var e = Math.max(this.filterManager.effectElements[7].p.v, this.filterManager.effectElements[8].p.v) * 0.01;
-          var l = path.getTotalLength();
-          dasharrayValue = '0 0 0 ' + l * s + ' ';
-          var lineLength = l * (e - s);
-          var segment = 1 + this.filterManager.effectElements[4].p.v * 2 * this.filterManager.effectElements[9].p.v * 0.01;
-          var units = Math.floor(lineLength / segment);
-          var j;
-          for (j = 0; j < units; j += 1) {
-            dasharrayValue += '1 ' + this.filterManager.effectElements[4].p.v * 2 * this.filterManager.effectElements[9].p.v * 0.01 + ' ';
-          }
-          dasharrayValue += '0 ' + l * 10 + ' 0 0';
-        } else {
-          dasharrayValue = '1 ' + this.filterManager.effectElements[4].p.v * 2 * this.filterManager.effectElements[9].p.v * 0.01;
-        }
-        path.setAttribute('stroke-dasharray', dasharrayValue);
-      }
-    }
-  }
-  if (forceRender || this.filterManager.effectElements[4].p._mdf) {
-    this.pathMasker.setAttribute('stroke-width', this.filterManager.effectElements[4].p.v * 2);
-  }
-
-  if (forceRender || this.filterManager.effectElements[6].p._mdf) {
-    this.pathMasker.setAttribute('opacity', this.filterManager.effectElements[6].p.v);
-  }
-  if (this.filterManager.effectElements[10].p.v === 1 || this.filterManager.effectElements[10].p.v === 2) {
-    if (forceRender || this.filterManager.effectElements[3].p._mdf) {
-      var color = this.filterManager.effectElements[3].p.v;
-      this.pathMasker.setAttribute('stroke', 'rgb(' + bmFloor(color[0] * 255) + ',' + bmFloor(color[1] * 255) + ',' + bmFloor(color[2] * 255) + ')');
-    }
-  }
-};
-
-/* global createNS */
-
-function SVGTritoneFilter(filter, filterManager) {
-  this.filterManager = filterManager;
-  var feColorMatrix = createNS('feColorMatrix');
-  feColorMatrix.setAttribute('type', 'matrix');
-  feColorMatrix.setAttribute('color-interpolation-filters', 'linearRGB');
-  feColorMatrix.setAttribute('values', '0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0');
-  feColorMatrix.setAttribute('result', 'f1');
-  filter.appendChild(feColorMatrix);
-  var feComponentTransfer = createNS('feComponentTransfer');
-  feComponentTransfer.setAttribute('color-interpolation-filters', 'sRGB');
-  filter.appendChild(feComponentTransfer);
-  this.matrixFilter = feComponentTransfer;
-  var feFuncR = createNS('feFuncR');
-  feFuncR.setAttribute('type', 'table');
-  feComponentTransfer.appendChild(feFuncR);
-  this.feFuncR = feFuncR;
-  var feFuncG = createNS('feFuncG');
-  feFuncG.setAttribute('type', 'table');
-  feComponentTransfer.appendChild(feFuncG);
-  this.feFuncG = feFuncG;
-  var feFuncB = createNS('feFuncB');
-  feFuncB.setAttribute('type', 'table');
-  feComponentTransfer.appendChild(feFuncB);
-  this.feFuncB = feFuncB;
-}
-
-SVGTritoneFilter.prototype.renderFrame = function (forceRender) {
-  if (forceRender || this.filterManager._mdf) {
-    var color1 = this.filterManager.effectElements[0].p.v;
-    var color2 = this.filterManager.effectElements[1].p.v;
-    var color3 = this.filterManager.effectElements[2].p.v;
-    var tableR = color3[0] + ' ' + color2[0] + ' ' + color1[0];
-    var tableG = color3[1] + ' ' + color2[1] + ' ' + color1[1];
-    var tableB = color3[2] + ' ' + color2[2] + ' ' + color1[2];
-    this.feFuncR.setAttribute('tableValues', tableR);
-    this.feFuncG.setAttribute('tableValues', tableG);
-    this.feFuncB.setAttribute('tableValues', tableB);
-    // var opacity = this.filterManager.effectElements[2].p.v/100;
-    // this.matrixFilter.setAttribute('values',(colorWhite[0]- colorBlack[0])+' 0 0 0 '+ colorBlack[0] +' '+ (colorWhite[1]- colorBlack[1]) +' 0 0 0 '+ colorBlack[1] +' '+ (colorWhite[2]- colorBlack[2]) +' 0 0 0 '+ colorBlack[2] +' 0 0 0 ' + opacity + ' 0');
-  }
-};
-
-/* global createNS */
-
-function SVGProLevelsFilter(filter, filterManager) {
-  this.filterManager = filterManager;
-  var effectElements = this.filterManager.effectElements;
-  var feComponentTransfer = createNS('feComponentTransfer');
-
-  if (effectElements[10].p.k || effectElements[10].p.v !== 0 || effectElements[11].p.k || effectElements[11].p.v !== 1 || effectElements[12].p.k || effectElements[12].p.v !== 1 || effectElements[13].p.k || effectElements[13].p.v !== 0 || effectElements[14].p.k || effectElements[14].p.v !== 1) {
-    this.feFuncR = this.createFeFunc('feFuncR', feComponentTransfer);
-  }
-  if (effectElements[17].p.k || effectElements[17].p.v !== 0 || effectElements[18].p.k || effectElements[18].p.v !== 1 || effectElements[19].p.k || effectElements[19].p.v !== 1 || effectElements[20].p.k || effectElements[20].p.v !== 0 || effectElements[21].p.k || effectElements[21].p.v !== 1) {
-    this.feFuncG = this.createFeFunc('feFuncG', feComponentTransfer);
-  }
-  if (effectElements[24].p.k || effectElements[24].p.v !== 0 || effectElements[25].p.k || effectElements[25].p.v !== 1 || effectElements[26].p.k || effectElements[26].p.v !== 1 || effectElements[27].p.k || effectElements[27].p.v !== 0 || effectElements[28].p.k || effectElements[28].p.v !== 1) {
-    this.feFuncB = this.createFeFunc('feFuncB', feComponentTransfer);
-  }
-  if (effectElements[31].p.k || effectElements[31].p.v !== 0 || effectElements[32].p.k || effectElements[32].p.v !== 1 || effectElements[33].p.k || effectElements[33].p.v !== 1 || effectElements[34].p.k || effectElements[34].p.v !== 0 || effectElements[35].p.k || effectElements[35].p.v !== 1) {
-    this.feFuncA = this.createFeFunc('feFuncA', feComponentTransfer);
-  }
-
-  if (this.feFuncR || this.feFuncG || this.feFuncB || this.feFuncA) {
-    feComponentTransfer.setAttribute('color-interpolation-filters', 'sRGB');
-    filter.appendChild(feComponentTransfer);
-    feComponentTransfer = createNS('feComponentTransfer');
-  }
-
-  if (effectElements[3].p.k || effectElements[3].p.v !== 0 || effectElements[4].p.k || effectElements[4].p.v !== 1 || effectElements[5].p.k || effectElements[5].p.v !== 1 || effectElements[6].p.k || effectElements[6].p.v !== 0 || effectElements[7].p.k || effectElements[7].p.v !== 1) {
-    feComponentTransfer.setAttribute('color-interpolation-filters', 'sRGB');
-    filter.appendChild(feComponentTransfer);
-    this.feFuncRComposed = this.createFeFunc('feFuncR', feComponentTransfer);
-    this.feFuncGComposed = this.createFeFunc('feFuncG', feComponentTransfer);
-    this.feFuncBComposed = this.createFeFunc('feFuncB', feComponentTransfer);
-  }
-}
-
-SVGProLevelsFilter.prototype.createFeFunc = function (type, feComponentTransfer) {
-  var feFunc = createNS(type);
-  feFunc.setAttribute('type', 'table');
-  feComponentTransfer.appendChild(feFunc);
-  return feFunc;
-};
-
-SVGProLevelsFilter.prototype.getTableValue = function (inputBlack, inputWhite, gamma, outputBlack, outputWhite) {
-  var cnt = 0;
-  var segments = 256;
-  var perc;
-  var min = Math.min(inputBlack, inputWhite);
-  var max = Math.max(inputBlack, inputWhite);
-  var table = Array.call(null, { length: segments });
-  var colorValue;
-  var pos = 0;
-  var outputDelta = outputWhite - outputBlack;
-  var inputDelta = inputWhite - inputBlack;
-  while (cnt <= 256) {
-    perc = cnt / 256;
-    if (perc <= min) {
-      colorValue = inputDelta < 0 ? outputWhite : outputBlack;
-    } else if (perc >= max) {
-      colorValue = inputDelta < 0 ? outputBlack : outputWhite;
-    } else {
-      colorValue = (outputBlack + outputDelta * Math.pow((perc - inputBlack) / inputDelta, 1 / gamma));
-    }
-    table[pos] = colorValue;
-    pos += 1;
-    cnt += 256 / (segments - 1);
-  }
-  return table.join(' ');
-};
-
-SVGProLevelsFilter.prototype.renderFrame = function (forceRender) {
-  if (forceRender || this.filterManager._mdf) {
-    var val;
-    var effectElements = this.filterManager.effectElements;
-    if (this.feFuncRComposed && (forceRender || effectElements[3].p._mdf || effectElements[4].p._mdf || effectElements[5].p._mdf || effectElements[6].p._mdf || effectElements[7].p._mdf)) {
-      val = this.getTableValue(effectElements[3].p.v, effectElements[4].p.v, effectElements[5].p.v, effectElements[6].p.v, effectElements[7].p.v);
-      this.feFuncRComposed.setAttribute('tableValues', val);
-      this.feFuncGComposed.setAttribute('tableValues', val);
-      this.feFuncBComposed.setAttribute('tableValues', val);
-    }
-
-    if (this.feFuncR && (forceRender || effectElements[10].p._mdf || effectElements[11].p._mdf || effectElements[12].p._mdf || effectElements[13].p._mdf || effectElements[14].p._mdf)) {
-      val = this.getTableValue(effectElements[10].p.v, effectElements[11].p.v, effectElements[12].p.v, effectElements[13].p.v, effectElements[14].p.v);
-      this.feFuncR.setAttribute('tableValues', val);
-    }
-
-    if (this.feFuncG && (forceRender || effectElements[17].p._mdf || effectElements[18].p._mdf || effectElements[19].p._mdf || effectElements[20].p._mdf || effectElements[21].p._mdf)) {
-      val = this.getTableValue(effectElements[17].p.v, effectElements[18].p.v, effectElements[19].p.v, effectElements[20].p.v, effectElements[21].p.v);
-      this.feFuncG.setAttribute('tableValues', val);
-    }
-
-    if (this.feFuncB && (forceRender || effectElements[24].p._mdf || effectElements[25].p._mdf || effectElements[26].p._mdf || effectElements[27].p._mdf || effectElements[28].p._mdf)) {
-      val = this.getTableValue(effectElements[24].p.v, effectElements[25].p.v, effectElements[26].p.v, effectElements[27].p.v, effectElements[28].p.v);
-      this.feFuncB.setAttribute('tableValues', val);
-    }
-
-    if (this.feFuncA && (forceRender || effectElements[31].p._mdf || effectElements[32].p._mdf || effectElements[33].p._mdf || effectElements[34].p._mdf || effectElements[35].p._mdf)) {
-      val = this.getTableValue(effectElements[31].p.v, effectElements[32].p.v, effectElements[33].p.v, effectElements[34].p.v, effectElements[35].p.v);
-      this.feFuncA.setAttribute('tableValues', val);
-    }
-  }
-};
-
-/* global createNS, rgbToHex, degToRads */
-
-function SVGDropShadowEffect(filter, filterManager) {
-  var filterSize = filterManager.container.globalData.renderConfig.filterSize;
-  filter.setAttribute('x', filterSize.x);
-  filter.setAttribute('y', filterSize.y);
-  filter.setAttribute('width', filterSize.width);
-  filter.setAttribute('height', filterSize.height);
-  this.filterManager = filterManager;
-
-  var feGaussianBlur = createNS('feGaussianBlur');
-  feGaussianBlur.setAttribute('in', 'SourceAlpha');
-  feGaussianBlur.setAttribute('result', 'drop_shadow_1');
-  feGaussianBlur.setAttribute('stdDeviation', '0');
-  this.feGaussianBlur = feGaussianBlur;
-  filter.appendChild(feGaussianBlur);
-
-  var feOffset = createNS('feOffset');
-  feOffset.setAttribute('dx', '25');
-  feOffset.setAttribute('dy', '0');
-  feOffset.setAttribute('in', 'drop_shadow_1');
-  feOffset.setAttribute('result', 'drop_shadow_2');
-  this.feOffset = feOffset;
-  filter.appendChild(feOffset);
-  var feFlood = createNS('feFlood');
-  feFlood.setAttribute('flood-color', '#00ff00');
-  feFlood.setAttribute('flood-opacity', '1');
-  feFlood.setAttribute('result', 'drop_shadow_3');
-  this.feFlood = feFlood;
-  filter.appendChild(feFlood);
-
-  var feComposite = createNS('feComposite');
-  feComposite.setAttribute('in', 'drop_shadow_3');
-  feComposite.setAttribute('in2', 'drop_shadow_2');
-  feComposite.setAttribute('operator', 'in');
-  feComposite.setAttribute('result', 'drop_shadow_4');
-  filter.appendChild(feComposite);
-
-  var feMerge = createNS('feMerge');
-  filter.appendChild(feMerge);
-  var feMergeNode;
-  feMergeNode = createNS('feMergeNode');
-  feMerge.appendChild(feMergeNode);
-  feMergeNode = createNS('feMergeNode');
-  feMergeNode.setAttribute('in', 'SourceGraphic');
-  this.feMergeNode = feMergeNode;
-  this.feMerge = feMerge;
-  this.originalNodeAdded = false;
-  feMerge.appendChild(feMergeNode);
-}
-
-SVGDropShadowEffect.prototype.renderFrame = function (forceRender) {
-  if (forceRender || this.filterManager._mdf) {
-    if (forceRender || this.filterManager.effectElements[4].p._mdf) {
-      this.feGaussianBlur.setAttribute('stdDeviation', this.filterManager.effectElements[4].p.v / 4);
-    }
-    if (forceRender || this.filterManager.effectElements[0].p._mdf) {
-      var col = this.filterManager.effectElements[0].p.v;
-      this.feFlood.setAttribute('flood-color', rgbToHex(Math.round(col[0] * 255), Math.round(col[1] * 255), Math.round(col[2] * 255)));
-    }
-    if (forceRender || this.filterManager.effectElements[1].p._mdf) {
-      this.feFlood.setAttribute('flood-opacity', this.filterManager.effectElements[1].p.v / 255);
-    }
-    if (forceRender || this.filterManager.effectElements[2].p._mdf || this.filterManager.effectElements[3].p._mdf) {
-      var distance = this.filterManager.effectElements[3].p.v;
-      var angle = (this.filterManager.effectElements[2].p.v - 90) * degToRads;
-      var x = distance * Math.cos(angle);
-      var y = distance * Math.sin(angle);
-      this.feOffset.setAttribute('dx', x);
-      this.feOffset.setAttribute('dy', y);
-    }
-    /* if(forceRender || this.filterManager.effectElements[5].p._mdf){
-            if(this.filterManager.effectElements[5].p.v === 1 && this.originalNodeAdded) {
-                this.feMerge.removeChild(this.feMergeNode);
-                this.originalNodeAdded = false;
-            } else if(this.filterManager.effectElements[5].p.v === 0 && !this.originalNodeAdded) {
-                this.feMerge.appendChild(this.feMergeNode);
-                this.originalNodeAdded = true;
-            }
-        } */
-  }
-};
-
-/* global createElementID, createNS */
-
-var _svgMatteSymbols = [];
-
-function SVGMatte3Effect(filterElem, filterManager, elem) {
-  this.initialized = false;
-  this.filterManager = filterManager;
-  this.filterElem = filterElem;
-  this.elem = elem;
-  elem.matteElement = createNS('g');
-  elem.matteElement.appendChild(elem.layerElement);
-  elem.matteElement.appendChild(elem.transformedElement);
-  elem.baseElement = elem.matteElement;
-}
-
-SVGMatte3Effect.prototype.findSymbol = function (mask) {
-  var i = 0;
-  var len = _svgMatteSymbols.length;
-  while (i < len) {
-    if (_svgMatteSymbols[i] === mask) {
-      return _svgMatteSymbols[i];
-    }
-    i += 1;
-  }
-  return null;
-};
-
-SVGMatte3Effect.prototype.replaceInParent = function (mask, symbolId) {
-  var parentNode = mask.layerElement.parentNode;
-  if (!parentNode) {
-    return;
-  }
-  var children = parentNode.children;
-  var i = 0;
-  var len = children.length;
-  while (i < len) {
-    if (children[i] === mask.layerElement) {
-      break;
-    }
-    i += 1;
-  }
-  var nextChild;
-  if (i <= len - 2) {
-    nextChild = children[i + 1];
-  }
-  var useElem = createNS('use');
-  useElem.setAttribute('href', '#' + symbolId);
-  if (nextChild) {
-    parentNode.insertBefore(useElem, nextChild);
-  } else {
-    parentNode.appendChild(useElem);
-  }
-};
-
-SVGMatte3Effect.prototype.setElementAsMask = function (elem, mask) {
-  if (!this.findSymbol(mask)) {
-    var symbolId = createElementID();
-    var masker = createNS('mask');
-    masker.setAttribute('id', mask.layerId);
-    masker.setAttribute('mask-type', 'alpha');
-    _svgMatteSymbols.push(mask);
-    var defs = elem.globalData.defs;
-    defs.appendChild(masker);
-    var symbol = createNS('symbol');