UNPKG

458 kBJavaScriptView Raw
1(typeof navigator !== "undefined") && (function(root, factory) {
2 if (typeof define === "function" && define.amd) {
3 define(function() {
4 return factory(root);
5 });
6 } else if (typeof module === "object" && module.exports) {
7 module.exports = factory(root);
8 } else {
9 root.lottie = factory(root);
10 root.bodymovin = root.lottie;
11 }
12}((window || {}), function(window) {
13 "use strict";
14var svgNS = "http://www.w3.org/2000/svg";
15
16var locationHref = '';
17
18var initialDefaultFrame = -999999;
19
20var subframeEnabled = true;
21var expressionsPlugin;
22var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
23var cachedColors = {};
24var bm_rounder = Math.round;
25var bm_rnd;
26var bm_pow = Math.pow;
27var bm_sqrt = Math.sqrt;
28var bm_abs = Math.abs;
29var bm_floor = Math.floor;
30var bm_max = Math.max;
31var bm_min = Math.min;
32var blitter = 10;
33
34var BMMath = {};
35(function(){
36 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"];
37 var i, len = propertyNames.length;
38 for(i=0;i<len;i+=1){
39 BMMath[propertyNames[i]] = Math[propertyNames[i]];
40 }
41}());
42
43function ProjectInterface(){return {};}
44
45BMMath.random = Math.random;
46BMMath.abs = function(val){
47 var tOfVal = typeof val;
48 if(tOfVal === 'object' && val.length){
49 var absArr = createSizedArray(val.length);
50 var i, len = val.length;
51 for(i=0;i<len;i+=1){
52 absArr[i] = Math.abs(val[i]);
53 }
54 return absArr;
55 }
56 return Math.abs(val);
57
58};
59var defaultCurveSegments = 150;
60var degToRads = Math.PI/180;
61var roundCorner = 0.5519;
62
63function roundValues(flag){
64 if(flag){
65 bm_rnd = Math.round;
66 }else{
67 bm_rnd = function(val){
68 return val;
69 };
70 }
71}
72roundValues(false);
73
74function styleDiv(element){
75 element.style.position = 'absolute';
76 element.style.top = 0;
77 element.style.left = 0;
78 element.style.display = 'block';
79 element.style.transformOrigin = element.style.webkitTransformOrigin = '0 0';
80 element.style.backfaceVisibility = element.style.webkitBackfaceVisibility = 'visible';
81 element.style.transformStyle = element.style.webkitTransformStyle = element.style.mozTransformStyle = "preserve-3d";
82}
83
84function BMEnterFrameEvent(type, currentTime, totalTime, frameMultiplier){
85 this.type = type;
86 this.currentTime = currentTime;
87 this.totalTime = totalTime;
88 this.direction = frameMultiplier < 0 ? -1 : 1;
89}
90
91function BMCompleteEvent(type, frameMultiplier){
92 this.type = type;
93 this.direction = frameMultiplier < 0 ? -1 : 1;
94}
95
96function BMCompleteLoopEvent(type, totalLoops, currentLoop, frameMultiplier){
97 this.type = type;
98 this.currentLoop = currentLoop;
99 this.totalLoops = totalLoops;
100 this.direction = frameMultiplier < 0 ? -1 : 1;
101}
102
103function BMSegmentStartEvent(type, firstFrame, totalFrames){
104 this.type = type;
105 this.firstFrame = firstFrame;
106 this.totalFrames = totalFrames;
107}
108
109function BMDestroyEvent(type, target){
110 this.type = type;
111 this.target = target;
112}
113
114function BMRenderFrameErrorEvent(nativeError, currentTime) {
115 this.type = 'renderFrameError';
116 this.nativeError = nativeError;
117 this.currentTime = currentTime;
118}
119
120function BMConfigErrorEvent(nativeError) {
121 this.type = 'configError';
122 this.nativeError = nativeError;
123}
124
125function BMAnimationConfigErrorEvent(type, nativeError) {
126 this.type = type;
127 this.nativeError = nativeError;
128 this.currentTime = currentTime;
129}
130
131var createElementID = (function(){
132 var _count = 0;
133 return function createID() {
134 return '__lottie_element_' + ++_count
135 }
136}())
137
138function HSVtoRGB(h, s, v) {
139 var r, g, b, i, f, p, q, t;
140 i = Math.floor(h * 6);
141 f = h * 6 - i;
142 p = v * (1 - s);
143 q = v * (1 - f * s);
144 t = v * (1 - (1 - f) * s);
145 switch (i % 6) {
146 case 0: r = v; g = t; b = p; break;
147 case 1: r = q; g = v; b = p; break;
148 case 2: r = p; g = v; b = t; break;
149 case 3: r = p; g = q; b = v; break;
150 case 4: r = t; g = p; b = v; break;
151 case 5: r = v; g = p; b = q; break;
152 }
153 return [ r,
154 g,
155 b ];
156}
157
158function RGBtoHSV(r, g, b) {
159 var max = Math.max(r, g, b), min = Math.min(r, g, b),
160 d = max - min,
161 h,
162 s = (max === 0 ? 0 : d / max),
163 v = max / 255;
164
165 switch (max) {
166 case min: h = 0; break;
167 case r: h = (g - b) + d * (g < b ? 6: 0); h /= 6 * d; break;
168 case g: h = (b - r) + d * 2; h /= 6 * d; break;
169 case b: h = (r - g) + d * 4; h /= 6 * d; break;
170 }
171
172 return [
173 h,
174 s,
175 v
176 ];
177}
178
179function addSaturationToRGB(color,offset){
180 var hsv = RGBtoHSV(color[0]*255,color[1]*255,color[2]*255);
181 hsv[1] += offset;
182 if (hsv[1] > 1) {
183 hsv[1] = 1;
184 }
185 else if (hsv[1] <= 0) {
186 hsv[1] = 0;
187 }
188 return HSVtoRGB(hsv[0],hsv[1],hsv[2]);
189}
190
191function addBrightnessToRGB(color,offset){
192 var hsv = RGBtoHSV(color[0]*255,color[1]*255,color[2]*255);
193 hsv[2] += offset;
194 if (hsv[2] > 1) {
195 hsv[2] = 1;
196 }
197 else if (hsv[2] < 0) {
198 hsv[2] = 0;
199 }
200 return HSVtoRGB(hsv[0],hsv[1],hsv[2]);
201}
202
203function addHueToRGB(color,offset) {
204 var hsv = RGBtoHSV(color[0]*255,color[1]*255,color[2]*255);
205 hsv[0] += offset/360;
206 if (hsv[0] > 1) {
207 hsv[0] -= 1;
208 }
209 else if (hsv[0] < 0) {
210 hsv[0] += 1;
211 }
212 return HSVtoRGB(hsv[0],hsv[1],hsv[2]);
213}
214
215var rgbToHex = (function(){
216 var colorMap = [];
217 var i;
218 var hex;
219 for(i=0;i<256;i+=1){
220 hex = i.toString(16);
221 colorMap[i] = hex.length == 1 ? '0' + hex : hex;
222 }
223
224 return function(r, g, b) {
225 if(r<0){
226 r = 0;
227 }
228 if(g<0){
229 g = 0;
230 }
231 if(b<0){
232 b = 0;
233 }
234 return '#' + colorMap[r] + colorMap[g] + colorMap[b];
235 };
236}());
237function BaseEvent(){}
238BaseEvent.prototype = {
239 triggerEvent: function (eventName, args) {
240 if (this._cbs[eventName]) {
241 var len = this._cbs[eventName].length;
242 for (var i = 0; i < len; i++){
243 this._cbs[eventName][i](args);
244 }
245 }
246 },
247 addEventListener: function (eventName, callback) {
248 if (!this._cbs[eventName]){
249 this._cbs[eventName] = [];
250 }
251 this._cbs[eventName].push(callback);
252
253 return function() {
254 this.removeEventListener(eventName, callback);
255 }.bind(this);
256 },
257 removeEventListener: function (eventName,callback){
258 if (!callback){
259 this._cbs[eventName] = null;
260 }else if(this._cbs[eventName]){
261 var i = 0, len = this._cbs[eventName].length;
262 while(i<len){
263 if(this._cbs[eventName][i] === callback){
264 this._cbs[eventName].splice(i,1);
265 i -=1;
266 len -= 1;
267 }
268 i += 1;
269 }
270 if(!this._cbs[eventName].length){
271 this._cbs[eventName] = null;
272 }
273 }
274 }
275};
276var createTypedArray = (function(){
277 function createRegularArray(type, len){
278 var i = 0, arr = [], value;
279 switch(type) {
280 case 'int16':
281 case 'uint8c':
282 value = 1;
283 break;
284 default:
285 value = 1.1;
286 break;
287 }
288 for(i = 0; i < len; i += 1) {
289 arr.push(value);
290 }
291 return arr;
292 }
293 function createTypedArray(type, len){
294 if(type === 'float32') {
295 return new Float32Array(len);
296 } else if(type === 'int16') {
297 return new Int16Array(len);
298 } else if(type === 'uint8c') {
299 return new Uint8ClampedArray(len);
300 }
301 }
302 if(typeof Uint8ClampedArray === 'function' && typeof Float32Array === 'function') {
303 return createTypedArray;
304 } else {
305 return createRegularArray;
306 }
307}());
308
309function createSizedArray(len) {
310 return Array.apply(null,{length:len});
311}
312function createTag(type) {
313 //return {appendChild:function(){},setAttribute:function(){},style:{}}
314 return document.createElement(type);
315}
316function DynamicPropertyContainer(){};
317DynamicPropertyContainer.prototype = {
318 addDynamicProperty: function(prop) {
319 if(this.dynamicProperties.indexOf(prop) === -1) {
320 this.dynamicProperties.push(prop);
321 this.container.addDynamicProperty(this);
322 this._isAnimated = true;
323 }
324 },
325 iterateDynamicProperties: function(){
326 this._mdf = false;
327 var i, len = this.dynamicProperties.length;
328 for(i=0;i<len;i+=1){
329 this.dynamicProperties[i].getValue();
330 if(this.dynamicProperties[i]._mdf) {
331 this._mdf = true;
332 }
333 }
334 },
335 initDynamicPropertyContainer: function(container){
336 this.container = container;
337 this.dynamicProperties = [];
338 this._mdf = false;
339 this._isAnimated = false;
340 }
341}
342var getBlendMode = (function() {
343
344 var blendModeEnums = {
345 0:'source-over',
346 1:'multiply',
347 2:'screen',
348 3:'overlay',
349 4:'darken',
350 5:'lighten',
351 6:'color-dodge',
352 7:'color-burn',
353 8:'hard-light',
354 9:'soft-light',
355 10:'difference',
356 11:'exclusion',
357 12:'hue',
358 13:'saturation',
359 14:'color',
360 15:'luminosity'
361 }
362
363 return function(mode) {
364 return blendModeEnums[mode] || '';
365 }
366}())
367/*!
368 Transformation Matrix v2.0
369 (c) Epistemex 2014-2015
370 www.epistemex.com
371 By Ken Fyrstenberg
372 Contributions by leeoniya.
373 License: MIT, header required.
374 */
375
376/**
377 * 2D transformation matrix object initialized with identity matrix.
378 *
379 * The matrix can synchronize a canvas context by supplying the context
380 * as an argument, or later apply current absolute transform to an
381 * existing context.
382 *
383 * All values are handled as floating point values.
384 *
385 * @param {CanvasRenderingContext2D} [context] - Optional context to sync with Matrix
386 * @prop {number} a - scale x
387 * @prop {number} b - shear y
388 * @prop {number} c - shear x
389 * @prop {number} d - scale y
390 * @prop {number} e - translate x
391 * @prop {number} f - translate y
392 * @prop {CanvasRenderingContext2D|null} [context=null] - set or get current canvas context
393 * @constructor
394 */
395
396var Matrix = (function(){
397
398 var _cos = Math.cos;
399 var _sin = Math.sin;
400 var _tan = Math.tan;
401 var _rnd = Math.round;
402
403 function reset(){
404 this.props[0] = 1;
405 this.props[1] = 0;
406 this.props[2] = 0;
407 this.props[3] = 0;
408 this.props[4] = 0;
409 this.props[5] = 1;
410 this.props[6] = 0;
411 this.props[7] = 0;
412 this.props[8] = 0;
413 this.props[9] = 0;
414 this.props[10] = 1;
415 this.props[11] = 0;
416 this.props[12] = 0;
417 this.props[13] = 0;
418 this.props[14] = 0;
419 this.props[15] = 1;
420 return this;
421 }
422
423 function rotate(angle) {
424 if(angle === 0){
425 return this;
426 }
427 var mCos = _cos(angle);
428 var mSin = _sin(angle);
429 return this._t(mCos, -mSin, 0, 0, mSin, mCos, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
430 }
431
432 function rotateX(angle){
433 if(angle === 0){
434 return this;
435 }
436 var mCos = _cos(angle);
437 var mSin = _sin(angle);
438 return this._t(1, 0, 0, 0, 0, mCos, -mSin, 0, 0, mSin, mCos, 0, 0, 0, 0, 1);
439 }
440
441 function rotateY(angle){
442 if(angle === 0){
443 return this;
444 }
445 var mCos = _cos(angle);
446 var mSin = _sin(angle);
447 return this._t(mCos, 0, mSin, 0, 0, 1, 0, 0, -mSin, 0, mCos, 0, 0, 0, 0, 1);
448 }
449
450 function rotateZ(angle){
451 if(angle === 0){
452 return this;
453 }
454 var mCos = _cos(angle);
455 var mSin = _sin(angle);
456 return this._t(mCos, -mSin, 0, 0, mSin, mCos, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
457 }
458
459 function shear(sx,sy){
460 return this._t(1, sy, sx, 1, 0, 0);
461 }
462
463 function skew(ax, ay){
464 return this.shear(_tan(ax), _tan(ay));
465 }
466
467 function skewFromAxis(ax, angle){
468 var mCos = _cos(angle);
469 var mSin = _sin(angle);
470 return this._t(mCos, mSin, 0, 0, -mSin, mCos, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)
471 ._t(1, 0, 0, 0, _tan(ax), 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)
472 ._t(mCos, -mSin, 0, 0, mSin, mCos, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
473 //return this._t(mCos, mSin, -mSin, mCos, 0, 0)._t(1, 0, _tan(ax), 1, 0, 0)._t(mCos, -mSin, mSin, mCos, 0, 0);
474 }
475
476 function scale(sx, sy, sz) {
477 if(!sz && sz !== 0) {
478 sz = 1;
479 }
480 if(sx === 1 && sy === 1 && sz === 1){
481 return this;
482 }
483 return this._t(sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, sz, 0, 0, 0, 0, 1);
484 }
485
486 function setTransform(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {
487 this.props[0] = a;
488 this.props[1] = b;
489 this.props[2] = c;
490 this.props[3] = d;
491 this.props[4] = e;
492 this.props[5] = f;
493 this.props[6] = g;
494 this.props[7] = h;
495 this.props[8] = i;
496 this.props[9] = j;
497 this.props[10] = k;
498 this.props[11] = l;
499 this.props[12] = m;
500 this.props[13] = n;
501 this.props[14] = o;
502 this.props[15] = p;
503 return this;
504 }
505
506 function translate(tx, ty, tz) {
507 tz = tz || 0;
508 if(tx !== 0 || ty !== 0 || tz !== 0){
509 return this._t(1,0,0,0,0,1,0,0,0,0,1,0,tx,ty,tz,1);
510 }
511 return this;
512 }
513
514 function transform(a2, b2, c2, d2, e2, f2, g2, h2, i2, j2, k2, l2, m2, n2, o2, p2) {
515
516 var _p = this.props;
517
518 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){
519 //NOTE: commenting this condition because TurboFan deoptimizes code when present
520 //if(m2 !== 0 || n2 !== 0 || o2 !== 0){
521 _p[12] = _p[12] * a2 + _p[15] * m2;
522 _p[13] = _p[13] * f2 + _p[15] * n2;
523 _p[14] = _p[14] * k2 + _p[15] * o2;
524 _p[15] = _p[15] * p2;
525 //}
526 this._identityCalculated = false;
527 return this;
528 }
529
530 var a1 = _p[0];
531 var b1 = _p[1];
532 var c1 = _p[2];
533 var d1 = _p[3];
534 var e1 = _p[4];
535 var f1 = _p[5];
536 var g1 = _p[6];
537 var h1 = _p[7];
538 var i1 = _p[8];
539 var j1 = _p[9];
540 var k1 = _p[10];
541 var l1 = _p[11];
542 var m1 = _p[12];
543 var n1 = _p[13];
544 var o1 = _p[14];
545 var p1 = _p[15];
546
547 /* matrix order (canvas compatible):
548 * ace
549 * bdf
550 * 001
551 */
552 _p[0] = a1 * a2 + b1 * e2 + c1 * i2 + d1 * m2;
553 _p[1] = a1 * b2 + b1 * f2 + c1 * j2 + d1 * n2 ;
554 _p[2] = a1 * c2 + b1 * g2 + c1 * k2 + d1 * o2 ;
555 _p[3] = a1 * d2 + b1 * h2 + c1 * l2 + d1 * p2 ;
556
557 _p[4] = e1 * a2 + f1 * e2 + g1 * i2 + h1 * m2 ;
558 _p[5] = e1 * b2 + f1 * f2 + g1 * j2 + h1 * n2 ;
559 _p[6] = e1 * c2 + f1 * g2 + g1 * k2 + h1 * o2 ;
560 _p[7] = e1 * d2 + f1 * h2 + g1 * l2 + h1 * p2 ;
561
562 _p[8] = i1 * a2 + j1 * e2 + k1 * i2 + l1 * m2 ;
563 _p[9] = i1 * b2 + j1 * f2 + k1 * j2 + l1 * n2 ;
564 _p[10] = i1 * c2 + j1 * g2 + k1 * k2 + l1 * o2 ;
565 _p[11] = i1 * d2 + j1 * h2 + k1 * l2 + l1 * p2 ;
566
567 _p[12] = m1 * a2 + n1 * e2 + o1 * i2 + p1 * m2 ;
568 _p[13] = m1 * b2 + n1 * f2 + o1 * j2 + p1 * n2 ;
569 _p[14] = m1 * c2 + n1 * g2 + o1 * k2 + p1 * o2 ;
570 _p[15] = m1 * d2 + n1 * h2 + o1 * l2 + p1 * p2 ;
571
572 this._identityCalculated = false;
573 return this;
574 }
575
576 function isIdentity() {
577 if(!this._identityCalculated){
578 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);
579 this._identityCalculated = true;
580 }
581 return this._identity;
582 }
583
584 function equals(matr){
585 var i = 0;
586 while (i < 16) {
587 if(matr.props[i] !== this.props[i]) {
588 return false;
589 }
590 i+=1;
591 }
592 return true;
593 }
594
595 function clone(matr){
596 var i;
597 for(i=0;i<16;i+=1){
598 matr.props[i] = this.props[i];
599 }
600 }
601
602 function cloneFromProps(props){
603 var i;
604 for(i=0;i<16;i+=1){
605 this.props[i] = props[i];
606 }
607 }
608
609 function applyToPoint(x, y, z) {
610
611 return {
612 x: x * this.props[0] + y * this.props[4] + z * this.props[8] + this.props[12],
613 y: x * this.props[1] + y * this.props[5] + z * this.props[9] + this.props[13],
614 z: x * this.props[2] + y * this.props[6] + z * this.props[10] + this.props[14]
615 };
616 /*return {
617 x: x * me.a + y * me.c + me.e,
618 y: x * me.b + y * me.d + me.f
619 };*/
620 }
621 function applyToX(x, y, z) {
622 return x * this.props[0] + y * this.props[4] + z * this.props[8] + this.props[12];
623 }
624 function applyToY(x, y, z) {
625 return x * this.props[1] + y * this.props[5] + z * this.props[9] + this.props[13];
626 }
627 function applyToZ(x, y, z) {
628 return x * this.props[2] + y * this.props[6] + z * this.props[10] + this.props[14];
629 }
630
631 function getInverseMatrix() {
632 var determinant = this.props[0] * this.props[5] - this.props[1] * this.props[4];
633 var a = this.props[5]/determinant;
634 var b = - this.props[1]/determinant;
635 var c = - this.props[4]/determinant;
636 var d = this.props[0]/determinant;
637 var e = (this.props[4] * this.props[13] - this.props[5] * this.props[12])/determinant;
638 var f = - (this.props[0] * this.props[13] - this.props[1] * this.props[12])/determinant;
639 var inverseMatrix = new Matrix();
640 inverseMatrix.props[0] = a;
641 inverseMatrix.props[1] = b;
642 inverseMatrix.props[4] = c;
643 inverseMatrix.props[5] = d;
644 inverseMatrix.props[12] = e;
645 inverseMatrix.props[13] = f;
646 return inverseMatrix;
647 }
648
649 function inversePoint(pt) {
650 var inverseMatrix = this.getInverseMatrix();
651 return inverseMatrix.applyToPointArray(pt[0], pt[1], pt[2] || 0)
652 }
653
654 function inversePoints(pts){
655 var i, len = pts.length, retPts = [];
656 for(i=0;i<len;i+=1){
657 retPts[i] = inversePoint(pts[i]);
658 }
659 return retPts;
660 }
661
662 function applyToTriplePoints(pt1, pt2, pt3) {
663 var arr = createTypedArray('float32', 6);
664 if(this.isIdentity()) {
665 arr[0] = pt1[0];
666 arr[1] = pt1[1];
667 arr[2] = pt2[0];
668 arr[3] = pt2[1];
669 arr[4] = pt3[0];
670 arr[5] = pt3[1];
671 } else {
672 var p0 = this.props[0], p1 = this.props[1], p4 = this.props[4], p5 = this.props[5], p12 = this.props[12], p13 = this.props[13];
673 arr[0] = pt1[0] * p0 + pt1[1] * p4 + p12;
674 arr[1] = pt1[0] * p1 + pt1[1] * p5 + p13;
675 arr[2] = pt2[0] * p0 + pt2[1] * p4 + p12;
676 arr[3] = pt2[0] * p1 + pt2[1] * p5 + p13;
677 arr[4] = pt3[0] * p0 + pt3[1] * p4 + p12;
678 arr[5] = pt3[0] * p1 + pt3[1] * p5 + p13;
679 }
680 return arr;
681 }
682
683 function applyToPointArray(x,y,z){
684 var arr;
685 if(this.isIdentity()) {
686 arr = [x,y,z];
687 } else {
688 arr = [
689 x * this.props[0] + y * this.props[4] + z * this.props[8] + this.props[12],
690 x * this.props[1] + y * this.props[5] + z * this.props[9] + this.props[13],
691 x * this.props[2] + y * this.props[6] + z * this.props[10] + this.props[14]
692 ];
693 }
694 return arr;
695 }
696
697 function applyToPointStringified(x, y) {
698 if(this.isIdentity()) {
699 return x + ',' + y;
700 }
701 var _p = this.props;
702 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;
703 }
704
705 function toCSS() {
706 //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.
707 /*if(this.isIdentity()) {
708 return '';
709 }*/
710 var i = 0;
711 var props = this.props;
712 var cssValue = 'matrix3d(';
713 var v = 10000;
714 while(i<16){
715 cssValue += _rnd(props[i]*v)/v;
716 cssValue += i === 15 ? ')':',';
717 i += 1;
718 }
719 return cssValue;
720 }
721
722 function roundMatrixProperty(val) {
723 var v = 10000;
724 if((val < 0.000001 && val > 0) || (val > -0.000001 && val < 0)) {
725 return _rnd(val * v) / v;
726 }
727 return val;
728 }
729
730 function to2dCSS() {
731 //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.
732 /*if(this.isIdentity()) {
733 return '';
734 }*/
735 var props = this.props;
736 var _a = roundMatrixProperty(props[0]);
737 var _b = roundMatrixProperty(props[1]);
738 var _c = roundMatrixProperty(props[4]);
739 var _d = roundMatrixProperty(props[5]);
740 var _e = roundMatrixProperty(props[12]);
741 var _f = roundMatrixProperty(props[13]);
742 return "matrix(" + _a + ',' + _b + ',' + _c + ',' + _d + ',' + _e + ',' + _f + ")";
743 }
744
745 return function(){
746 this.reset = reset;
747 this.rotate = rotate;
748 this.rotateX = rotateX;
749 this.rotateY = rotateY;
750 this.rotateZ = rotateZ;
751 this.skew = skew;
752 this.skewFromAxis = skewFromAxis;
753 this.shear = shear;
754 this.scale = scale;
755 this.setTransform = setTransform;
756 this.translate = translate;
757 this.transform = transform;
758 this.applyToPoint = applyToPoint;
759 this.applyToX = applyToX;
760 this.applyToY = applyToY;
761 this.applyToZ = applyToZ;
762 this.applyToPointArray = applyToPointArray;
763 this.applyToTriplePoints = applyToTriplePoints;
764 this.applyToPointStringified = applyToPointStringified;
765 this.toCSS = toCSS;
766 this.to2dCSS = to2dCSS;
767 this.clone = clone;
768 this.cloneFromProps = cloneFromProps;
769 this.equals = equals;
770 this.inversePoints = inversePoints;
771 this.inversePoint = inversePoint;
772 this.getInverseMatrix = getInverseMatrix;
773 this._t = this.transform;
774 this.isIdentity = isIdentity;
775 this._identity = true;
776 this._identityCalculated = false;
777
778 this.props = createTypedArray('float32', 16);
779 this.reset();
780 };
781}());
782
783/*
784 Copyright 2014 David Bau.
785
786 Permission is hereby granted, free of charge, to any person obtaining
787 a copy of this software and associated documentation files (the
788 "Software"), to deal in the Software without restriction, including
789 without limitation the rights to use, copy, modify, merge, publish,
790 distribute, sublicense, and/or sell copies of the Software, and to
791 permit persons to whom the Software is furnished to do so, subject to
792 the following conditions:
793
794 The above copyright notice and this permission notice shall be
795 included in all copies or substantial portions of the Software.
796
797 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
798 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
799 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
800 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
801 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
802 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
803 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
804
805 */
806
807(function (pool, math) {
808//
809// The following constants are related to IEEE 754 limits.
810//
811 var global = this,
812 width = 256, // each RC4 output is 0 <= x < 256
813 chunks = 6, // at least six RC4 outputs for each double
814 digits = 52, // there are 52 significant digits in a double
815 rngname = 'random', // rngname: name for Math.random and Math.seedrandom
816 startdenom = math.pow(width, chunks),
817 significance = math.pow(2, digits),
818 overflow = significance * 2,
819 mask = width - 1,
820 nodecrypto; // node.js crypto module, initialized at the bottom.
821
822//
823// seedrandom()
824// This is the seedrandom function described above.
825//
826 function seedrandom(seed, options, callback) {
827 var key = [];
828 options = (options === true) ? { entropy: true } : (options || {});
829
830 // Flatten the seed string or build one from local entropy if needed.
831 var shortseed = mixkey(flatten(
832 options.entropy ? [seed, tostring(pool)] :
833 (seed === null) ? autoseed() : seed, 3), key);
834
835 // Use the seed to initialize an ARC4 generator.
836 var arc4 = new ARC4(key);
837
838 // This function returns a random double in [0, 1) that contains
839 // randomness in every bit of the mantissa of the IEEE 754 value.
840 var prng = function() {
841 var n = arc4.g(chunks), // Start with a numerator n < 2 ^ 48
842 d = startdenom, // and denominator d = 2 ^ 48.
843 x = 0; // and no 'extra last byte'.
844 while (n < significance) { // Fill up all significant digits by
845 n = (n + x) * width; // shifting numerator and
846 d *= width; // denominator and generating a
847 x = arc4.g(1); // new least-significant-byte.
848 }
849 while (n >= overflow) { // To avoid rounding up, before adding
850 n /= 2; // last byte, shift everything
851 d /= 2; // right using integer math until
852 x >>>= 1; // we have exactly the desired bits.
853 }
854 return (n + x) / d; // Form the number within [0, 1).
855 };
856
857 prng.int32 = function() { return arc4.g(4) | 0; };
858 prng.quick = function() { return arc4.g(4) / 0x100000000; };
859 prng.double = prng;
860
861 // Mix the randomness into accumulated entropy.
862 mixkey(tostring(arc4.S), pool);
863
864 // Calling convention: what to return as a function of prng, seed, is_math.
865 return (options.pass || callback ||
866 function(prng, seed, is_math_call, state) {
867 if (state) {
868 // Load the arc4 state from the given state if it has an S array.
869 if (state.S) { copy(state, arc4); }
870 // Only provide the .state method if requested via options.state.
871 prng.state = function() { return copy(arc4, {}); };
872 }
873
874 // If called as a method of Math (Math.seedrandom()), mutate
875 // Math.random because that is how seedrandom.js has worked since v1.0.
876 if (is_math_call) { math[rngname] = prng; return seed; }
877
878 // Otherwise, it is a newer calling convention, so return the
879 // prng directly.
880 else return prng;
881 })(
882 prng,
883 shortseed,
884 'global' in options ? options.global : (this == math),
885 options.state);
886 }
887 math['seed' + rngname] = seedrandom;
888
889//
890// ARC4
891//
892// An ARC4 implementation. The constructor takes a key in the form of
893// an array of at most (width) integers that should be 0 <= x < (width).
894//
895// The g(count) method returns a pseudorandom integer that concatenates
896// the next (count) outputs from ARC4. Its return value is a number x
897// that is in the range 0 <= x < (width ^ count).
898//
899 function ARC4(key) {
900 var t, keylen = key.length,
901 me = this, i = 0, j = me.i = me.j = 0, s = me.S = [];
902
903 // The empty key [] is treated as [0].
904 if (!keylen) { key = [keylen++]; }
905
906 // Set up S using the standard key scheduling algorithm.
907 while (i < width) {
908 s[i] = i++;
909 }
910 for (i = 0; i < width; i++) {
911 s[i] = s[j = mask & (j + key[i % keylen] + (t = s[i]))];
912 s[j] = t;
913 }
914
915 // The "g" method returns the next (count) outputs as one number.
916 me.g = function(count) {
917 // Using instance members instead of closure state nearly doubles speed.
918 var t, r = 0,
919 i = me.i, j = me.j, s = me.S;
920 while (count--) {
921 t = s[i = mask & (i + 1)];
922 r = r * width + s[mask & ((s[i] = s[j = mask & (j + t)]) + (s[j] = t))];
923 }
924 me.i = i; me.j = j;
925 return r;
926 // For robust unpredictability, the function call below automatically
927 // discards an initial batch of values. This is called RC4-drop[256].
928 // See http://google.com/search?q=rsa+fluhrer+response&btnI
929 };
930 }
931
932//
933// copy()
934// Copies internal state of ARC4 to or from a plain object.
935//
936 function copy(f, t) {
937 t.i = f.i;
938 t.j = f.j;
939 t.S = f.S.slice();
940 return t;
941 }
942
943//
944// flatten()
945// Converts an object tree to nested arrays of strings.
946//
947 function flatten(obj, depth) {
948 var result = [], typ = (typeof obj), prop;
949 if (depth && typ == 'object') {
950 for (prop in obj) {
951 try { result.push(flatten(obj[prop], depth - 1)); } catch (e) {}
952 }
953 }
954 return (result.length ? result : typ == 'string' ? obj : obj + '\0');
955 }
956
957//
958// mixkey()
959// Mixes a string seed into a key that is an array of integers, and
960// returns a shortened string seed that is equivalent to the result key.
961//
962 function mixkey(seed, key) {
963 var stringseed = seed + '', smear, j = 0;
964 while (j < stringseed.length) {
965 key[mask & j] =
966 mask & ((smear ^= key[mask & j] * 19) + stringseed.charCodeAt(j++));
967 }
968 return tostring(key);
969 }
970
971//
972// autoseed()
973// Returns an object for autoseeding, using window.crypto and Node crypto
974// module if available.
975//
976 function autoseed() {
977 try {
978 if (nodecrypto) { return tostring(nodecrypto.randomBytes(width)); }
979 var out = new Uint8Array(width);
980 (global.crypto || global.msCrypto).getRandomValues(out);
981 return tostring(out);
982 } catch (e) {
983 var browser = global.navigator,
984 plugins = browser && browser.plugins;
985 return [+new Date(), global, plugins, global.screen, tostring(pool)];
986 }
987 }
988
989//
990// tostring()
991// Converts an array of charcodes to a string
992//
993 function tostring(a) {
994 return String.fromCharCode.apply(0, a);
995 }
996
997//
998// When seedrandom.js is loaded, we immediately mix a few bits
999// from the built-in RNG into the entropy pool. Because we do
1000// not want to interfere with deterministic PRNG state later,
1001// seedrandom will not call math.random on its own again after
1002// initialization.
1003//
1004 mixkey(math.random(), pool);
1005
1006//
1007// Nodejs and AMD support: export the implementation as a module using
1008// either convention.
1009//
1010
1011// End anonymous scope, and pass initial values.
1012})(
1013 [], // pool: entropy pool starts empty
1014 BMMath // math: package containing random, pow, and seedrandom
1015);
1016var BezierFactory = (function(){
1017 /**
1018 * BezierEasing - use bezier curve for transition easing function
1019 * by Gaëtan Renaudeau 2014 - 2015 – MIT License
1020 *
1021 * Credits: is based on Firefox's nsSMILKeySpline.cpp
1022 * Usage:
1023 * var spline = BezierEasing([ 0.25, 0.1, 0.25, 1.0 ])
1024 * spline.get(x) => returns the easing value | x must be in [0, 1] range
1025 *
1026 */
1027
1028 var ob = {};
1029 ob.getBezierEasing = getBezierEasing;
1030 var beziers = {};
1031
1032 function getBezierEasing(a,b,c,d,nm){
1033 var str = nm || ('bez_' + a+'_'+b+'_'+c+'_'+d).replace(/\./g, 'p');
1034 if(beziers[str]){
1035 return beziers[str];
1036 }
1037 var bezEasing = new BezierEasing([a,b,c,d]);
1038 beziers[str] = bezEasing;
1039 return bezEasing;
1040 }
1041
1042// These values are established by empiricism with tests (tradeoff: performance VS precision)
1043 var NEWTON_ITERATIONS = 4;
1044 var NEWTON_MIN_SLOPE = 0.001;
1045 var SUBDIVISION_PRECISION = 0.0000001;
1046 var SUBDIVISION_MAX_ITERATIONS = 10;
1047
1048 var kSplineTableSize = 11;
1049 var kSampleStepSize = 1.0 / (kSplineTableSize - 1.0);
1050
1051 var float32ArraySupported = typeof Float32Array === "function";
1052
1053 function A (aA1, aA2) { return 1.0 - 3.0 * aA2 + 3.0 * aA1; }
1054 function B (aA1, aA2) { return 3.0 * aA2 - 6.0 * aA1; }
1055 function C (aA1) { return 3.0 * aA1; }
1056
1057// Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
1058 function calcBezier (aT, aA1, aA2) {
1059 return ((A(aA1, aA2)*aT + B(aA1, aA2))*aT + C(aA1))*aT;
1060 }
1061
1062// Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.
1063 function getSlope (aT, aA1, aA2) {
1064 return 3.0 * A(aA1, aA2)*aT*aT + 2.0 * B(aA1, aA2) * aT + C(aA1);
1065 }
1066
1067 function binarySubdivide (aX, aA, aB, mX1, mX2) {
1068 var currentX, currentT, i = 0;
1069 do {
1070 currentT = aA + (aB - aA) / 2.0;
1071 currentX = calcBezier(currentT, mX1, mX2) - aX;
1072 if (currentX > 0.0) {
1073 aB = currentT;
1074 } else {
1075 aA = currentT;
1076 }
1077 } while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);
1078 return currentT;
1079 }
1080
1081 function newtonRaphsonIterate (aX, aGuessT, mX1, mX2) {
1082 for (var i = 0; i < NEWTON_ITERATIONS; ++i) {
1083 var currentSlope = getSlope(aGuessT, mX1, mX2);
1084 if (currentSlope === 0.0) return aGuessT;
1085 var currentX = calcBezier(aGuessT, mX1, mX2) - aX;
1086 aGuessT -= currentX / currentSlope;
1087 }
1088 return aGuessT;
1089 }
1090
1091 /**
1092 * points is an array of [ mX1, mY1, mX2, mY2 ]
1093 */
1094 function BezierEasing (points) {
1095 this._p = points;
1096 this._mSampleValues = float32ArraySupported ? new Float32Array(kSplineTableSize) : new Array(kSplineTableSize);
1097 this._precomputed = false;
1098
1099 this.get = this.get.bind(this);
1100 }
1101
1102 BezierEasing.prototype = {
1103
1104 get: function (x) {
1105 var mX1 = this._p[0],
1106 mY1 = this._p[1],
1107 mX2 = this._p[2],
1108 mY2 = this._p[3];
1109 if (!this._precomputed) this._precompute();
1110 if (mX1 === mY1 && mX2 === mY2) return x; // linear
1111 // Because JavaScript number are imprecise, we should guarantee the extremes are right.
1112 if (x === 0) return 0;
1113 if (x === 1) return 1;
1114 return calcBezier(this._getTForX(x), mY1, mY2);
1115 },
1116
1117 // Private part
1118
1119 _precompute: function () {
1120 var mX1 = this._p[0],
1121 mY1 = this._p[1],
1122 mX2 = this._p[2],
1123 mY2 = this._p[3];
1124 this._precomputed = true;
1125 if (mX1 !== mY1 || mX2 !== mY2)
1126 this._calcSampleValues();
1127 },
1128
1129 _calcSampleValues: function () {
1130 var mX1 = this._p[0],
1131 mX2 = this._p[2];
1132 for (var i = 0; i < kSplineTableSize; ++i) {
1133 this._mSampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2);
1134 }
1135 },
1136
1137 /**
1138 * getTForX chose the fastest heuristic to determine the percentage value precisely from a given X projection.
1139 */
1140 _getTForX: function (aX) {
1141 var mX1 = this._p[0],
1142 mX2 = this._p[2],
1143 mSampleValues = this._mSampleValues;
1144
1145 var intervalStart = 0.0;
1146 var currentSample = 1;
1147 var lastSample = kSplineTableSize - 1;
1148
1149 for (; currentSample !== lastSample && mSampleValues[currentSample] <= aX; ++currentSample) {
1150 intervalStart += kSampleStepSize;
1151 }
1152 --currentSample;
1153
1154 // Interpolate to provide an initial guess for t
1155 var dist = (aX - mSampleValues[currentSample]) / (mSampleValues[currentSample+1] - mSampleValues[currentSample]);
1156 var guessForT = intervalStart + dist * kSampleStepSize;
1157
1158 var initialSlope = getSlope(guessForT, mX1, mX2);
1159 if (initialSlope >= NEWTON_MIN_SLOPE) {
1160 return newtonRaphsonIterate(aX, guessForT, mX1, mX2);
1161 } else if (initialSlope === 0.0) {
1162 return guessForT;
1163 } else {
1164 return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize, mX1, mX2);
1165 }
1166 }
1167 };
1168
1169 return ob;
1170
1171}());
1172(function () {
1173 var lastTime = 0;
1174 var vendors = ['ms', 'moz', 'webkit', 'o'];
1175 for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
1176 window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
1177 window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame'];
1178 }
1179 if(!window.requestAnimationFrame)
1180 window.requestAnimationFrame = function (callback, element) {
1181 var currTime = new Date().getTime();
1182 var timeToCall = Math.max(0, 16 - (currTime - lastTime));
1183 var id = setTimeout(function () {
1184 callback(currTime + timeToCall);
1185 },
1186 timeToCall);
1187 lastTime = currTime + timeToCall;
1188 return id;
1189 };
1190 if(!window.cancelAnimationFrame)
1191 window.cancelAnimationFrame = function (id) {
1192 clearTimeout(id);
1193 };
1194}());
1195
1196function extendPrototype(sources,destination){
1197 var i, len = sources.length, sourcePrototype;
1198 for (i = 0;i < len;i += 1) {
1199 sourcePrototype = sources[i].prototype;
1200 for (var attr in sourcePrototype) {
1201 if (sourcePrototype.hasOwnProperty(attr)) destination.prototype[attr] = sourcePrototype[attr];
1202 }
1203 }
1204}
1205
1206function getDescriptor(object, prop) {
1207 return Object.getOwnPropertyDescriptor(object, prop);
1208}
1209
1210function createProxyFunction(prototype) {
1211 function ProxyFunction(){}
1212 ProxyFunction.prototype = prototype;
1213 return ProxyFunction;
1214}
1215function bezFunction(){
1216
1217 var easingFunctions = [];
1218 var math = Math;
1219
1220 function pointOnLine2D(x1,y1, x2,y2, x3,y3){
1221 var det1 = (x1*y2) + (y1*x3) + (x2*y3) - (x3*y2) - (y3*x1) - (x2*y1);
1222 return det1 > -0.001 && det1 < 0.001;
1223 }
1224
1225 function pointOnLine3D(x1,y1,z1, x2,y2,z2, x3,y3,z3){
1226 if(z1 === 0 && z2 === 0 && z3 === 0) {
1227 return pointOnLine2D(x1,y1, x2,y2, x3,y3);
1228 }
1229 var dist1 = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2) + Math.pow(z2 - z1, 2));
1230 var dist2 = Math.sqrt(Math.pow(x3 - x1, 2) + Math.pow(y3 - y1, 2) + Math.pow(z3 - z1, 2));
1231 var dist3 = Math.sqrt(Math.pow(x3 - x2, 2) + Math.pow(y3 - y2, 2) + Math.pow(z3 - z2, 2));
1232 var diffDist;
1233 if(dist1 > dist2){
1234 if(dist1 > dist3){
1235 diffDist = dist1 - dist2 - dist3;
1236 } else {
1237 diffDist = dist3 - dist2 - dist1;
1238 }
1239 } else if(dist3 > dist2){
1240 diffDist = dist3 - dist2 - dist1;
1241 } else {
1242 diffDist = dist2 - dist1 - dist3;
1243 }
1244 return diffDist > -0.0001 && diffDist < 0.0001;
1245 }
1246
1247 var getBezierLength = (function(){
1248
1249 return function(pt1,pt2,pt3,pt4){
1250 var curveSegments = defaultCurveSegments;
1251 var k;
1252 var i, len;
1253 var ptCoord,perc,addedLength = 0;
1254 var ptDistance;
1255 var point = [],lastPoint = [];
1256 var lengthData = bezier_length_pool.newElement();
1257 len = pt3.length;
1258 for(k=0;k<curveSegments;k+=1){
1259 perc = k/(curveSegments-1);
1260 ptDistance = 0;
1261 for(i=0;i<len;i+=1){
1262 ptCoord = bm_pow(1-perc,3)*pt1[i]+3*bm_pow(1-perc,2)*perc*pt3[i]+3*(1-perc)*bm_pow(perc,2)*pt4[i]+bm_pow(perc,3)*pt2[i];
1263 point[i] = ptCoord;
1264 if(lastPoint[i] !== null){
1265 ptDistance += bm_pow(point[i] - lastPoint[i],2);
1266 }
1267 lastPoint[i] = point[i];
1268 }
1269 if(ptDistance){
1270 ptDistance = bm_sqrt(ptDistance);
1271 addedLength += ptDistance;
1272 }
1273 lengthData.percents[k] = perc;
1274 lengthData.lengths[k] = addedLength;
1275 }
1276 lengthData.addedLength = addedLength;
1277 return lengthData;
1278 };
1279 }());
1280
1281 function getSegmentsLength(shapeData) {
1282 var segmentsLength = segments_length_pool.newElement();
1283 var closed = shapeData.c;
1284 var pathV = shapeData.v;
1285 var pathO = shapeData.o;
1286 var pathI = shapeData.i;
1287 var i, len = shapeData._length;
1288 var lengths = segmentsLength.lengths;
1289 var totalLength = 0;
1290 for(i=0;i<len-1;i+=1){
1291 lengths[i] = getBezierLength(pathV[i],pathV[i+1],pathO[i],pathI[i+1]);
1292 totalLength += lengths[i].addedLength;
1293 }
1294 if(closed && len){
1295 lengths[i] = getBezierLength(pathV[i],pathV[0],pathO[i],pathI[0]);
1296 totalLength += lengths[i].addedLength;
1297 }
1298 segmentsLength.totalLength = totalLength;
1299 return segmentsLength;
1300 }
1301
1302 function BezierData(length){
1303 this.segmentLength = 0;
1304 this.points = new Array(length);
1305 }
1306
1307 function PointData(partial,point){
1308 this.partialLength = partial;
1309 this.point = point;
1310 }
1311
1312 var buildBezierData = (function(){
1313
1314 var storedData = {};
1315
1316 return function (pt1, pt2, pt3, pt4){
1317 var bezierName = (pt1[0]+'_'+pt1[1]+'_'+pt2[0]+'_'+pt2[1]+'_'+pt3[0]+'_'+pt3[1]+'_'+pt4[0]+'_'+pt4[1]).replace(/\./g, 'p');
1318 if(!storedData[bezierName]){
1319 var curveSegments = defaultCurveSegments;
1320 var k, i, len;
1321 var ptCoord,perc,addedLength = 0;
1322 var ptDistance;
1323 var point,lastPoint = null;
1324 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])){
1325 curveSegments = 2;
1326 }
1327 var bezierData = new BezierData(curveSegments);
1328 len = pt3.length;
1329 for (k = 0; k < curveSegments; k += 1) {
1330 point = createSizedArray(len);
1331 perc = k / (curveSegments - 1);
1332 ptDistance = 0;
1333 for (i = 0; i < len; i += 1){
1334 ptCoord = bm_pow(1-perc,3)*pt1[i]+3*bm_pow(1-perc,2)*perc*(pt1[i] + pt3[i])+3*(1-perc)*bm_pow(perc,2)*(pt2[i] + pt4[i])+bm_pow(perc,3)*pt2[i];
1335 point[i] = ptCoord;
1336 if(lastPoint !== null){
1337 ptDistance += bm_pow(point[i] - lastPoint[i],2);
1338 }
1339 }
1340 ptDistance = bm_sqrt(ptDistance);
1341 addedLength += ptDistance;
1342 bezierData.points[k] = new PointData(ptDistance, point);
1343 lastPoint = point;
1344 }
1345 bezierData.segmentLength = addedLength;
1346 storedData[bezierName] = bezierData;
1347 }
1348 return storedData[bezierName];
1349 };
1350 }());
1351
1352 function getDistancePerc(perc,bezierData){
1353 var percents = bezierData.percents;
1354 var lengths = bezierData.lengths;
1355 var len = percents.length;
1356 var initPos = bm_floor((len-1)*perc);
1357 var lengthPos = perc*bezierData.addedLength;
1358 var lPerc = 0;
1359 if(initPos === len - 1 || initPos === 0 || lengthPos === lengths[initPos]){
1360 return percents[initPos];
1361 }else{
1362 var dir = lengths[initPos] > lengthPos ? -1 : 1;
1363 var flag = true;
1364 while(flag){
1365 if(lengths[initPos] <= lengthPos && lengths[initPos+1] > lengthPos){
1366 lPerc = (lengthPos - lengths[initPos]) / (lengths[initPos+1] - lengths[initPos]);
1367 flag = false;
1368 }else{
1369 initPos += dir;
1370 }
1371 if(initPos < 0 || initPos >= len - 1){
1372 //FIX for TypedArrays that don't store floating point values with enough accuracy
1373 if(initPos === len - 1) {
1374 return percents[initPos];
1375 }
1376 flag = false;
1377 }
1378 }
1379 return percents[initPos] + (percents[initPos+1] - percents[initPos])*lPerc;
1380 }
1381 }
1382
1383 function getPointInSegment(pt1, pt2, pt3, pt4, percent, bezierData) {
1384 var t1 = getDistancePerc(percent,bezierData);
1385 var u0 = 1;
1386 var u1 = 1 - t1;
1387 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;
1388 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;
1389 return [ptX, ptY];
1390 }
1391
1392 function getSegmentArray() {
1393
1394 }
1395
1396 var bezier_segment_points = createTypedArray('float32', 8);
1397
1398 function getNewSegment(pt1,pt2,pt3,pt4,startPerc,endPerc, bezierData){
1399
1400 startPerc = startPerc < 0 ? 0 : startPerc > 1 ? 1 : startPerc;
1401 var t0 = getDistancePerc(startPerc,bezierData);
1402 endPerc = endPerc > 1 ? 1 : endPerc;
1403 var t1 = getDistancePerc(endPerc,bezierData);
1404 var i, len = pt1.length;
1405 var u0 = 1 - t0;
1406 var u1 = 1 - t1;
1407 var u0u0u0 = u0*u0*u0;
1408 var t0u0u0_3 = t0*u0*u0*3;
1409 var t0t0u0_3 = t0*t0*u0*3;
1410 var t0t0t0 = t0*t0*t0;
1411 //
1412 var u0u0u1 = u0*u0*u1;
1413 var t0u0u1_3 = t0*u0*u1 + u0*t0*u1 + u0*u0*t1;
1414 var t0t0u1_3 = t0*t0*u1 + u0*t0*t1 + t0*u0*t1;
1415 var t0t0t1 = t0*t0*t1;
1416 //
1417 var u0u1u1 = u0*u1*u1;
1418 var t0u1u1_3 = t0*u1*u1 + u0*t1*u1 + u0*u1*t1;
1419 var t0t1u1_3 = t0*t1*u1 + u0*t1*t1 + t0*u1*t1;
1420 var t0t1t1 = t0*t1*t1;
1421 //
1422 var u1u1u1 = u1*u1*u1;
1423 var t1u1u1_3 = t1*u1*u1 + u1*t1*u1 + u1*u1*t1;
1424 var t1t1u1_3 = t1*t1*u1 + u1*t1*t1 + t1*u1*t1;
1425 var t1t1t1 = t1*t1*t1;
1426 for(i=0;i<len;i+=1){
1427 bezier_segment_points[i * 4] = Math.round((u0u0u0 * pt1[i] + t0u0u0_3 * pt3[i] + t0t0u0_3 * pt4[i] + t0t0t0 * pt2[i]) * 1000) / 1000;
1428 bezier_segment_points[i * 4 + 1] = Math.round((u0u0u1 * pt1[i] + t0u0u1_3 * pt3[i] + t0t0u1_3 * pt4[i] + t0t0t1 * pt2[i]) * 1000) / 1000;
1429 bezier_segment_points[i * 4 + 2] = Math.round((u0u1u1 * pt1[i] + t0u1u1_3 * pt3[i] + t0t1u1_3 * pt4[i] + t0t1t1 * pt2[i]) * 1000) / 1000;
1430 bezier_segment_points[i * 4 + 3] = Math.round((u1u1u1 * pt1[i] + t1u1u1_3 * pt3[i] + t1t1u1_3 * pt4[i] + t1t1t1 * pt2[i]) * 1000) / 1000;
1431 }
1432
1433 return bezier_segment_points;
1434 }
1435
1436 return {
1437 getSegmentsLength : getSegmentsLength,
1438 getNewSegment : getNewSegment,
1439 getPointInSegment : getPointInSegment,
1440 buildBezierData : buildBezierData,
1441 pointOnLine2D : pointOnLine2D,
1442 pointOnLine3D : pointOnLine3D
1443 };
1444}
1445
1446var bez = bezFunction();
1447function dataFunctionManager(){
1448
1449 //var tCanvasHelper = createTag('canvas').getContext('2d');
1450
1451 function completeLayers(layers, comps, fontManager){
1452 var layerData;
1453 var animArray, lastFrame;
1454 var i, len = layers.length;
1455 var j, jLen, k, kLen;
1456 for(i=0;i<len;i+=1){
1457 layerData = layers[i];
1458 if(!('ks' in layerData) || layerData.completed){
1459 continue;
1460 }
1461 layerData.completed = true;
1462 if(layerData.tt){
1463 layers[i-1].td = layerData.tt;
1464 }
1465 animArray = [];
1466 lastFrame = -1;
1467 if(layerData.hasMask){
1468 var maskProps = layerData.masksProperties;
1469 jLen = maskProps.length;
1470 for(j=0;j<jLen;j+=1){
1471 if(maskProps[j].pt.k.i){
1472 convertPathsToAbsoluteValues(maskProps[j].pt.k);
1473 }else{
1474 kLen = maskProps[j].pt.k.length;
1475 for(k=0;k<kLen;k+=1){
1476 if(maskProps[j].pt.k[k].s){
1477 convertPathsToAbsoluteValues(maskProps[j].pt.k[k].s[0]);
1478 }
1479 if(maskProps[j].pt.k[k].e){
1480 convertPathsToAbsoluteValues(maskProps[j].pt.k[k].e[0]);
1481 }
1482 }
1483 }
1484 }
1485 }
1486 if(layerData.ty===0){
1487 layerData.layers = findCompLayers(layerData.refId, comps);
1488 completeLayers(layerData.layers,comps, fontManager);
1489 }else if(layerData.ty === 4){
1490 completeShapes(layerData.shapes);
1491 }else if(layerData.ty == 5){
1492 completeText(layerData, fontManager);
1493 }
1494 }
1495 }
1496
1497 function findCompLayers(id,comps){
1498 var i = 0, len = comps.length;
1499 while(i<len){
1500 if(comps[i].id === id){
1501 if(!comps[i].layers.__used) {
1502 comps[i].layers.__used = true;
1503 return comps[i].layers;
1504 }
1505 return JSON.parse(JSON.stringify(comps[i].layers));
1506 }
1507 i += 1;
1508 }
1509 }
1510
1511 function completeShapes(arr){
1512 var i, len = arr.length;
1513 var j, jLen;
1514 var hasPaths = false;
1515 for(i=len-1;i>=0;i-=1){
1516 if(arr[i].ty == 'sh'){
1517 if(arr[i].ks.k.i){
1518 convertPathsToAbsoluteValues(arr[i].ks.k);
1519 }else{
1520 jLen = arr[i].ks.k.length;
1521 for(j=0;j<jLen;j+=1){
1522 if(arr[i].ks.k[j].s){
1523 convertPathsToAbsoluteValues(arr[i].ks.k[j].s[0]);
1524 }
1525 if(arr[i].ks.k[j].e){
1526 convertPathsToAbsoluteValues(arr[i].ks.k[j].e[0]);
1527 }
1528 }
1529 }
1530 hasPaths = true;
1531 }else if(arr[i].ty == 'gr'){
1532 completeShapes(arr[i].it);
1533 }
1534 }
1535 /*if(hasPaths){
1536 //mx: distance
1537 //ss: sensitivity
1538 //dc: decay
1539 arr.splice(arr.length-1,0,{
1540 "ty": "ms",
1541 "mx":20,
1542 "ss":10,
1543 "dc":0.001,
1544 "maxDist":200
1545 });
1546 }*/
1547 }
1548
1549 function convertPathsToAbsoluteValues(path){
1550 var i, len = path.i.length;
1551 for(i=0;i<len;i+=1){
1552 path.i[i][0] += path.v[i][0];
1553 path.i[i][1] += path.v[i][1];
1554 path.o[i][0] += path.v[i][0];
1555 path.o[i][1] += path.v[i][1];
1556 }
1557 }
1558
1559 function checkVersion(minimum,animVersionString){
1560 var animVersion = animVersionString ? animVersionString.split('.') : [100,100,100];
1561 if(minimum[0]>animVersion[0]){
1562 return true;
1563 } else if(animVersion[0] > minimum[0]){
1564 return false;
1565 }
1566 if(minimum[1]>animVersion[1]){
1567 return true;
1568 } else if(animVersion[1] > minimum[1]){
1569 return false;
1570 }
1571 if(minimum[2]>animVersion[2]){
1572 return true;
1573 } else if(animVersion[2] > minimum[2]){
1574 return false;
1575 }
1576 }
1577
1578 var checkText = (function(){
1579 var minimumVersion = [4,4,14];
1580
1581 function updateTextLayer(textLayer){
1582 var documentData = textLayer.t.d;
1583 textLayer.t.d = {
1584 k: [
1585 {
1586 s:documentData,
1587 t:0
1588 }
1589 ]
1590 };
1591 }
1592
1593 function iterateLayers(layers){
1594 var i, len = layers.length;
1595 for(i=0;i<len;i+=1){
1596 if(layers[i].ty === 5){
1597 updateTextLayer(layers[i]);
1598 }
1599 }
1600 }
1601
1602 return function (animationData){
1603 if(checkVersion(minimumVersion,animationData.v)){
1604 iterateLayers(animationData.layers);
1605 if(animationData.assets){
1606 var i, len = animationData.assets.length;
1607 for(i=0;i<len;i+=1){
1608 if(animationData.assets[i].layers){
1609 iterateLayers(animationData.assets[i].layers);
1610
1611 }
1612 }
1613 }
1614 }
1615 };
1616 }());
1617
1618 var checkChars = (function() {
1619 var minimumVersion = [4,7,99];
1620 return function (animationData){
1621 if(animationData.chars && !checkVersion(minimumVersion,animationData.v)){
1622 var i, len = animationData.chars.length, j, jLen, k, kLen;
1623 var pathData, paths;
1624 for(i = 0; i < len; i += 1) {
1625 if(animationData.chars[i].data && animationData.chars[i].data.shapes) {
1626 paths = animationData.chars[i].data.shapes[0].it;
1627 jLen = paths.length;
1628
1629 for(j = 0; j < jLen; j += 1) {
1630 pathData = paths[j].ks.k;
1631 if(!pathData.__converted) {
1632 convertPathsToAbsoluteValues(paths[j].ks.k);
1633 pathData.__converted = true;
1634 }
1635 }
1636 }
1637 }
1638 }
1639 };
1640 }());
1641
1642 var checkColors = (function(){
1643 var minimumVersion = [4,1,9];
1644
1645 function iterateShapes(shapes){
1646 var i, len = shapes.length;
1647 var j, jLen;
1648 for(i=0;i<len;i+=1){
1649 if(shapes[i].ty === 'gr'){
1650 iterateShapes(shapes[i].it);
1651 }else if(shapes[i].ty === 'fl' || shapes[i].ty === 'st'){
1652 if(shapes[i].c.k && shapes[i].c.k[0].i){
1653 jLen = shapes[i].c.k.length;
1654 for(j=0;j<jLen;j+=1){
1655 if(shapes[i].c.k[j].s){
1656 shapes[i].c.k[j].s[0] /= 255;
1657 shapes[i].c.k[j].s[1] /= 255;
1658 shapes[i].c.k[j].s[2] /= 255;
1659 shapes[i].c.k[j].s[3] /= 255;
1660 }
1661 if(shapes[i].c.k[j].e){
1662 shapes[i].c.k[j].e[0] /= 255;
1663 shapes[i].c.k[j].e[1] /= 255;
1664 shapes[i].c.k[j].e[2] /= 255;
1665 shapes[i].c.k[j].e[3] /= 255;
1666 }
1667 }
1668 } else {
1669 shapes[i].c.k[0] /= 255;
1670 shapes[i].c.k[1] /= 255;
1671 shapes[i].c.k[2] /= 255;
1672 shapes[i].c.k[3] /= 255;
1673 }
1674 }
1675 }
1676 }
1677
1678 function iterateLayers(layers){
1679 var i, len = layers.length;
1680 for(i=0;i<len;i+=1){
1681 if(layers[i].ty === 4){
1682 iterateShapes(layers[i].shapes);
1683 }
1684 }
1685 }
1686
1687 return function (animationData){
1688 if(checkVersion(minimumVersion,animationData.v)){
1689 iterateLayers(animationData.layers);
1690 if(animationData.assets){
1691 var i, len = animationData.assets.length;
1692 for(i=0;i<len;i+=1){
1693 if(animationData.assets[i].layers){
1694 iterateLayers(animationData.assets[i].layers);
1695
1696 }
1697 }
1698 }
1699 }
1700 };
1701 }());
1702
1703 var checkShapes = (function(){
1704 var minimumVersion = [4,4,18];
1705
1706
1707
1708 function completeShapes(arr){
1709 var i, len = arr.length;
1710 var j, jLen;
1711 var hasPaths = false;
1712 for(i=len-1;i>=0;i-=1){
1713 if(arr[i].ty == 'sh'){
1714 if(arr[i].ks.k.i){
1715 arr[i].ks.k.c = arr[i].closed;
1716 }else{
1717 jLen = arr[i].ks.k.length;
1718 for(j=0;j<jLen;j+=1){
1719 if(arr[i].ks.k[j].s){
1720 arr[i].ks.k[j].s[0].c = arr[i].closed;
1721 }
1722 if(arr[i].ks.k[j].e){
1723 arr[i].ks.k[j].e[0].c = arr[i].closed;
1724 }
1725 }
1726 }
1727 hasPaths = true;
1728 }else if(arr[i].ty == 'gr'){
1729 completeShapes(arr[i].it);
1730 }
1731 }
1732 }
1733
1734 function iterateLayers(layers){
1735 var layerData;
1736 var i, len = layers.length;
1737 var j, jLen, k, kLen;
1738 for(i=0;i<len;i+=1){
1739 layerData = layers[i];
1740 if(layerData.hasMask){
1741 var maskProps = layerData.masksProperties;
1742 jLen = maskProps.length;
1743 for(j=0;j<jLen;j+=1){
1744 if(maskProps[j].pt.k.i){
1745 maskProps[j].pt.k.c = maskProps[j].cl;
1746 }else{
1747 kLen = maskProps[j].pt.k.length;
1748 for(k=0;k<kLen;k+=1){
1749 if(maskProps[j].pt.k[k].s){
1750 maskProps[j].pt.k[k].s[0].c = maskProps[j].cl;
1751 }
1752 if(maskProps[j].pt.k[k].e){
1753 maskProps[j].pt.k[k].e[0].c = maskProps[j].cl;
1754 }
1755 }
1756 }
1757 }
1758 }
1759 if(layerData.ty === 4){
1760 completeShapes(layerData.shapes);
1761 }
1762 }
1763 }
1764
1765 return function (animationData){
1766 if(checkVersion(minimumVersion,animationData.v)){
1767 iterateLayers(animationData.layers);
1768 if(animationData.assets){
1769 var i, len = animationData.assets.length;
1770 for(i=0;i<len;i+=1){
1771 if(animationData.assets[i].layers){
1772 iterateLayers(animationData.assets[i].layers);
1773
1774 }
1775 }
1776 }
1777 }
1778 };
1779 }());
1780
1781 function completeData(animationData, fontManager){
1782 if(animationData.__complete){
1783 return;
1784 }
1785 checkColors(animationData);
1786 checkText(animationData);
1787 checkChars(animationData);
1788 checkShapes(animationData);
1789 completeLayers(animationData.layers, animationData.assets, fontManager);
1790 animationData.__complete = true;
1791 //blitAnimation(animationData, animationData.assets, fontManager);
1792 }
1793
1794 function completeText(data, fontManager){
1795 if(data.t.a.length === 0 && !('m' in data.t.p)){
1796 data.singleShape = true;
1797 }
1798 }
1799
1800 var moduleOb = {};
1801 moduleOb.completeData = completeData;
1802 moduleOb.checkColors = checkColors;
1803 moduleOb.checkChars = checkChars;
1804 moduleOb.checkShapes = checkShapes;
1805 moduleOb.completeLayers = completeLayers;
1806
1807 return moduleOb;
1808}
1809
1810var dataManager = dataFunctionManager();
1811
1812var FontManager = (function(){
1813
1814 var maxWaitingTime = 5000;
1815 var emptyChar = {
1816 w: 0,
1817 size:0,
1818 shapes:[]
1819 };
1820 var combinedCharacters = [];
1821 //Hindi characters
1822 combinedCharacters = combinedCharacters.concat([2304, 2305, 2306, 2307, 2362, 2363, 2364, 2364, 2366
1823 , 2367, 2368, 2369, 2370, 2371, 2372, 2373, 2374, 2375, 2376, 2377, 2378, 2379
1824 , 2380, 2381, 2382, 2383, 2387, 2388, 2389, 2390, 2391, 2402, 2403]);
1825
1826 function trimFontOptions(font) {
1827 var familyArray = font.split(',');
1828 var i, len = familyArray.length;
1829 var enabledFamilies = [];
1830 for (i = 0; i < len; i += 1) {
1831 if (familyArray[i] !== 'sans-serif' && familyArray[i] !== 'monospace') {
1832 enabledFamilies.push(familyArray[i]);
1833 }
1834 }
1835 return enabledFamilies.join(',');
1836 }
1837
1838 function setUpNode(font, family){
1839 var parentNode = createTag('span');
1840 parentNode.style.fontFamily = family;
1841 var node = createTag('span');
1842 // Characters that vary significantly among different fonts
1843 node.innerText = 'giItT1WQy@!-/#';
1844 // Visible - so we can measure it - but not on the screen
1845 parentNode.style.position = 'absolute';
1846 parentNode.style.left = '-10000px';
1847 parentNode.style.top = '-10000px';
1848 // Large font size makes even subtle changes obvious
1849 parentNode.style.fontSize = '300px';
1850 // Reset any font properties
1851 parentNode.style.fontVariant = 'normal';
1852 parentNode.style.fontStyle = 'normal';
1853 parentNode.style.fontWeight = 'normal';
1854 parentNode.style.letterSpacing = '0';
1855 parentNode.appendChild(node);
1856 document.body.appendChild(parentNode);
1857
1858 // Remember width with no applied web font
1859 var width = node.offsetWidth;
1860 node.style.fontFamily = trimFontOptions(font) + ', ' + family;
1861 return {node:node, w:width, parent:parentNode};
1862 }
1863
1864 function checkLoadedFonts() {
1865 var i, len = this.fonts.length;
1866 var node, w;
1867 var loadedCount = len;
1868 for(i=0;i<len; i+= 1){
1869 if(this.fonts[i].loaded){
1870 loadedCount -= 1;
1871 continue;
1872 }
1873 if(this.fonts[i].fOrigin === 'n' || this.fonts[i].origin === 0){
1874 this.fonts[i].loaded = true;
1875 } else{
1876 node = this.fonts[i].monoCase.node;
1877 w = this.fonts[i].monoCase.w;
1878 if(node.offsetWidth !== w){
1879 loadedCount -= 1;
1880 this.fonts[i].loaded = true;
1881 }else{
1882 node = this.fonts[i].sansCase.node;
1883 w = this.fonts[i].sansCase.w;
1884 if(node.offsetWidth !== w){
1885 loadedCount -= 1;
1886 this.fonts[i].loaded = true;
1887 }
1888 }
1889 if(this.fonts[i].loaded){
1890 this.fonts[i].sansCase.parent.parentNode.removeChild(this.fonts[i].sansCase.parent);
1891 this.fonts[i].monoCase.parent.parentNode.removeChild(this.fonts[i].monoCase.parent);
1892 }
1893 }
1894 }
1895
1896 if(loadedCount !== 0 && Date.now() - this.initTime < maxWaitingTime){
1897 setTimeout(this.checkLoadedFontsBinded, 20);
1898 }else{
1899 setTimeout(this.setIsLoadedBinded, 10);
1900
1901 }
1902 }
1903
1904 function createHelper(def, fontData){
1905 var tHelper = createNS('text');
1906 tHelper.style.fontSize = '100px';
1907 //tHelper.style.fontFamily = fontData.fFamily;
1908 tHelper.setAttribute('font-family', fontData.fFamily);
1909 tHelper.setAttribute('font-style', fontData.fStyle);
1910 tHelper.setAttribute('font-weight', fontData.fWeight);
1911 tHelper.textContent = '1';
1912 if(fontData.fClass){
1913 tHelper.style.fontFamily = 'inherit';
1914 tHelper.setAttribute('class', fontData.fClass);
1915 } else {
1916 tHelper.style.fontFamily = fontData.fFamily;
1917 }
1918 def.appendChild(tHelper);
1919 var tCanvasHelper = createTag('canvas').getContext('2d');
1920 tCanvasHelper.font = fontData.fWeight + ' ' + fontData.fStyle + ' 100px '+ fontData.fFamily;
1921 //tCanvasHelper.font = ' 100px '+ fontData.fFamily;
1922 return tHelper;
1923 }
1924
1925 function addFonts(fontData, defs){
1926 if(!fontData){
1927 this.isLoaded = true;
1928 return;
1929 }
1930 if(this.chars){
1931 this.isLoaded = true;
1932 this.fonts = fontData.list;
1933 return;
1934 }
1935
1936
1937 var fontArr = fontData.list;
1938 var i, len = fontArr.length;
1939 var _pendingFonts = len;
1940 for(i=0; i<len; i+= 1){
1941 var shouldLoadFont = true;
1942 var loadedSelector;
1943 var j;
1944 fontArr[i].loaded = false;
1945 fontArr[i].monoCase = setUpNode(fontArr[i].fFamily,'monospace');
1946 fontArr[i].sansCase = setUpNode(fontArr[i].fFamily,'sans-serif');
1947 if(!fontArr[i].fPath) {
1948 fontArr[i].loaded = true;
1949 _pendingFonts -= 1;
1950 }else if(fontArr[i].fOrigin === 'p' || fontArr[i].origin === 3){
1951 loadedSelector = document.querySelectorAll('style[f-forigin="p"][f-family="'+ fontArr[i].fFamily +'"], style[f-origin="3"][f-family="'+ fontArr[i].fFamily +'"]');
1952
1953 if (loadedSelector.length > 0) {
1954 shouldLoadFont = false;
1955 }
1956
1957 if (shouldLoadFont) {
1958 var s = createTag('style');
1959 s.setAttribute('f-forigin', fontArr[i].fOrigin);
1960 s.setAttribute('f-origin', fontArr[i].origin);
1961 s.setAttribute('f-family', fontArr[i].fFamily);
1962 s.type = "text/css";
1963 s.innerText = "@font-face {" + "font-family: "+fontArr[i].fFamily+"; font-style: normal; src: url('"+fontArr[i].fPath+"');}";
1964 defs.appendChild(s);
1965 }
1966 } else if(fontArr[i].fOrigin === 'g' || fontArr[i].origin === 1){
1967 loadedSelector = document.querySelectorAll('link[f-forigin="g"], link[f-origin="1"]');
1968
1969 for (j = 0; j < loadedSelector.length; j++) {
1970 if (loadedSelector[j].href.indexOf(fontArr[i].fPath) !== -1) {
1971 // Font is already loaded
1972 shouldLoadFont = false;
1973 }
1974 }
1975
1976 if (shouldLoadFont) {
1977 var l = createTag('link');
1978 l.setAttribute('f-forigin', fontArr[i].fOrigin);
1979 l.setAttribute('f-origin', fontArr[i].origin);
1980 l.type = "text/css";
1981 l.rel = "stylesheet";
1982 l.href = fontArr[i].fPath;
1983 document.body.appendChild(l);
1984 }
1985 } else if(fontArr[i].fOrigin === 't' || fontArr[i].origin === 2){
1986 loadedSelector = document.querySelectorAll('script[f-forigin="t"], script[f-origin="2"]');
1987
1988 for (j = 0; j < loadedSelector.length; j++) {
1989 if (fontArr[i].fPath === loadedSelector[j].src) {
1990 // Font is already loaded
1991 shouldLoadFont = false;
1992 }
1993 }
1994
1995 if (shouldLoadFont) {
1996 var sc = createTag('link');
1997 sc.setAttribute('f-forigin', fontArr[i].fOrigin);
1998 sc.setAttribute('f-origin', fontArr[i].origin);
1999 sc.setAttribute('rel','stylesheet');
2000 sc.setAttribute('href',fontArr[i].fPath);
2001 defs.appendChild(sc);
2002 }
2003 }
2004 fontArr[i].helper = createHelper(defs,fontArr[i]);
2005 fontArr[i].cache = {};
2006 this.fonts.push(fontArr[i]);
2007 }
2008 if (_pendingFonts === 0) {
2009 this.isLoaded = true;
2010 } else {
2011 //On some cases even if the font is loaded, it won't load correctly when measuring text on canvas.
2012 //Adding this timeout seems to fix it
2013 setTimeout(this.checkLoadedFonts.bind(this), 100);
2014 }
2015 }
2016
2017 function addChars(chars){
2018 if(!chars){
2019 return;
2020 }
2021 if(!this.chars){
2022 this.chars = [];
2023 }
2024 var i, len = chars.length;
2025 var j, jLen = this.chars.length, found;
2026 for(i=0;i<len;i+=1){
2027 j = 0;
2028 found = false;
2029 while(j<jLen){
2030 if(this.chars[j].style === chars[i].style && this.chars[j].fFamily === chars[i].fFamily && this.chars[j].ch === chars[i].ch){
2031 found = true;
2032 }
2033 j += 1;
2034 }
2035 if(!found){
2036 this.chars.push(chars[i]);
2037 jLen += 1;
2038 }
2039 }
2040 }
2041
2042 function getCharData(char, style, font){
2043 var i = 0, len = this.chars.length;
2044 while( i < len) {
2045 if(this.chars[i].ch === char && this.chars[i].style === style && this.chars[i].fFamily === font){
2046
2047 return this.chars[i];
2048 }
2049 i+= 1;
2050 }
2051 if((typeof char === 'string' && char.charCodeAt(0) !== 13 || !char) && console && console.warn) {
2052 console.warn('Missing character from exported characters list: ', char, style, font);
2053 }
2054 return emptyChar;
2055 }
2056
2057 function measureText(char, fontName, size) {
2058 var fontData = this.getFontByName(fontName);
2059 var index = char.charCodeAt(0);
2060 if(!fontData.cache[index + 1]) {
2061 var tHelper = fontData.helper;
2062 //Canvas version
2063 //fontData.cache[index] = tHelper.measureText(char).width / 100;
2064 //SVG version
2065 //console.log(tHelper.getBBox().width)
2066 if (char === ' ') {
2067 tHelper.textContent = '|' + char + '|';
2068 var doubleSize = tHelper.getComputedTextLength();
2069 tHelper.textContent = '||';
2070 var singleSize = tHelper.getComputedTextLength();
2071 fontData.cache[index + 1] = (doubleSize - singleSize)/100;
2072 } else {
2073 tHelper.textContent = char;
2074 fontData.cache[index + 1] = (tHelper.getComputedTextLength())/100;
2075 }
2076 }
2077 return fontData.cache[index + 1] * size;
2078 }
2079
2080 function getFontByName(name){
2081 var i = 0, len = this.fonts.length;
2082 while(i<len){
2083 if(this.fonts[i].fName === name) {
2084 return this.fonts[i];
2085 }
2086 i += 1;
2087 }
2088 return this.fonts[0];
2089 }
2090
2091 function getCombinedCharacterCodes() {
2092 return combinedCharacters;
2093 }
2094
2095 function setIsLoaded() {
2096 this.isLoaded = true
2097 }
2098
2099 var Font = function(){
2100 this.fonts = [];
2101 this.chars = null;
2102 this.typekitLoaded = 0;
2103 this.isLoaded = false;
2104 this.initTime = Date.now();
2105 this.setIsLoadedBinded = this.setIsLoaded.bind(this)
2106 this.checkLoadedFontsBinded = this.checkLoadedFonts.bind(this)
2107 };
2108 //TODO: for now I'm adding these methods to the Class and not the prototype. Think of a better way to implement it.
2109 Font.getCombinedCharacterCodes = getCombinedCharacterCodes;
2110
2111 var fontPrototype = {
2112 addChars: addChars,
2113 addFonts: addFonts,
2114 getCharData: getCharData,
2115 getFontByName: getFontByName,
2116 measureText: measureText,
2117 checkLoadedFonts: checkLoadedFonts,
2118 setIsLoaded: setIsLoaded,
2119 }
2120
2121 Font.prototype = fontPrototype;
2122
2123 return Font;
2124
2125}());
2126
2127var PropertyFactory = (function(){
2128
2129 var initFrame = initialDefaultFrame;
2130 var math_abs = Math.abs;
2131
2132 function interpolateValue(frameNum, caching) {
2133 var offsetTime = this.offsetTime;
2134 var newValue;
2135 if (this.propType === 'multidimensional') {
2136 newValue = createTypedArray('float32', this.pv.length);
2137 }
2138 var iterationIndex = caching.lastIndex;
2139 var i = iterationIndex;
2140 var len = this.keyframes.length - 1, flag = true;
2141 var keyData, nextKeyData;
2142
2143 while (flag) {
2144 keyData = this.keyframes[i];
2145 nextKeyData = this.keyframes[i + 1];
2146 if (i === len - 1 && frameNum >= nextKeyData.t - offsetTime){
2147 if(keyData.h){
2148 keyData = nextKeyData;
2149 }
2150 iterationIndex = 0;
2151 break;
2152 }
2153 if ((nextKeyData.t - offsetTime) > frameNum){
2154 iterationIndex = i;
2155 break;
2156 }
2157 if (i < len - 1){
2158 i += 1;
2159 } else {
2160 iterationIndex = 0;
2161 flag = false;
2162 }
2163 }
2164
2165 var k, kLen, perc, jLen, j, fnc;
2166 var nextKeyTime = nextKeyData.t - offsetTime;
2167 var keyTime = keyData.t - offsetTime;
2168 var endValue;
2169 if (keyData.to) {
2170 if (!keyData.bezierData) {
2171 keyData.bezierData = bez.buildBezierData(keyData.s, nextKeyData.s || keyData.e, keyData.to, keyData.ti);
2172 }
2173 var bezierData = keyData.bezierData;
2174 if (frameNum >= nextKeyTime || frameNum < keyTime) {
2175 var ind = frameNum >= nextKeyTime ? bezierData.points.length - 1 : 0;
2176 kLen = bezierData.points[ind].point.length;
2177 for (k = 0; k < kLen; k += 1) {
2178 newValue[k] = bezierData.points[ind].point[k];
2179 }
2180 // caching._lastKeyframeIndex = -1;
2181 } else {
2182 if (keyData.__fnct) {
2183 fnc = keyData.__fnct;
2184 } else {
2185 fnc = BezierFactory.getBezierEasing(keyData.o.x, keyData.o.y, keyData.i.x, keyData.i.y, keyData.n).get;
2186 keyData.__fnct = fnc;
2187 }
2188 perc = fnc((frameNum - keyTime) / (nextKeyTime - keyTime));
2189 var distanceInLine = bezierData.segmentLength*perc;
2190
2191 var segmentPerc;
2192 var addedLength = (caching.lastFrame < frameNum && caching._lastKeyframeIndex === i) ? caching._lastAddedLength : 0;
2193 j = (caching.lastFrame < frameNum && caching._lastKeyframeIndex === i) ? caching._lastPoint : 0;
2194 flag = true;
2195 jLen = bezierData.points.length;
2196 while (flag) {
2197 addedLength += bezierData.points[j].partialLength;
2198 if (distanceInLine === 0 || perc === 0 || j === bezierData.points.length - 1) {
2199 kLen = bezierData.points[j].point.length;
2200 for (k = 0; k < kLen; k += 1) {
2201 newValue[k] = bezierData.points[j].point[k];
2202 }
2203 break;
2204 } else if (distanceInLine >= addedLength && distanceInLine < addedLength + bezierData.points[j + 1].partialLength) {
2205 segmentPerc = (distanceInLine - addedLength) / bezierData.points[j + 1].partialLength;
2206 kLen = bezierData.points[j].point.length;
2207 for (k = 0; k < kLen; k += 1) {
2208 newValue[k] = bezierData.points[j].point[k] + (bezierData.points[j + 1].point[k] - bezierData.points[j].point[k]) * segmentPerc;
2209 }
2210 break;
2211 }
2212 if (j < jLen - 1){
2213 j += 1;
2214 } else {
2215 flag = false;
2216 }
2217 }
2218 caching._lastPoint = j;
2219 caching._lastAddedLength = addedLength - bezierData.points[j].partialLength;
2220 caching._lastKeyframeIndex = i;
2221 }
2222 } else {
2223 var outX, outY, inX, inY, keyValue;
2224 len = keyData.s.length;
2225 endValue = nextKeyData.s || keyData.e;
2226 if (this.sh && keyData.h !== 1) {
2227 if (frameNum >= nextKeyTime) {
2228 newValue[0] = endValue[0];
2229 newValue[1] = endValue[1];
2230 newValue[2] = endValue[2];
2231 } else if (frameNum <= keyTime) {
2232 newValue[0] = keyData.s[0];
2233 newValue[1] = keyData.s[1];
2234 newValue[2] = keyData.s[2];
2235 } else {
2236 var quatStart = createQuaternion(keyData.s);
2237 var quatEnd = createQuaternion(endValue);
2238 var time = (frameNum - keyTime) / (nextKeyTime - keyTime);
2239 quaternionToEuler(newValue, slerp(quatStart, quatEnd, time));
2240 }
2241
2242 } else {
2243 for(i = 0; i < len; i += 1) {
2244 if (keyData.h !== 1) {
2245 if (frameNum >= nextKeyTime) {
2246 perc = 1;
2247 } else if(frameNum < keyTime) {
2248 perc = 0;
2249 } else {
2250 if(keyData.o.x.constructor === Array) {
2251 if (!keyData.__fnct) {
2252 keyData.__fnct = [];
2253 }
2254 if (!keyData.__fnct[i]) {
2255 outX = (typeof keyData.o.x[i] === 'undefined') ? keyData.o.x[0] : keyData.o.x[i];
2256 outY = (typeof keyData.o.y[i] === 'undefined') ? keyData.o.y[0] : keyData.o.y[i];
2257 inX = (typeof keyData.i.x[i] === 'undefined') ? keyData.i.x[0] : keyData.i.x[i];
2258 inY = (typeof keyData.i.y[i] === 'undefined') ? keyData.i.y[0] : keyData.i.y[i];
2259 fnc = BezierFactory.getBezierEasing(outX, outY, inX, inY).get;
2260 keyData.__fnct[i] = fnc;
2261 } else {
2262 fnc = keyData.__fnct[i];
2263 }
2264 } else {
2265 if (!keyData.__fnct) {
2266 outX = keyData.o.x;
2267 outY = keyData.o.y;
2268 inX = keyData.i.x;
2269 inY = keyData.i.y;
2270 fnc = BezierFactory.getBezierEasing(outX, outY, inX, inY).get;
2271 keyData.__fnct = fnc;
2272 } else {
2273 fnc = keyData.__fnct;
2274 }
2275 }
2276 perc = fnc((frameNum - keyTime) / (nextKeyTime - keyTime ));
2277 }
2278 }
2279
2280 endValue = nextKeyData.s || keyData.e;
2281 keyValue = keyData.h === 1 ? keyData.s[i] : keyData.s[i] + (endValue[i] - keyData.s[i]) * perc;
2282
2283 if (this.propType === 'multidimensional') {
2284 newValue[i] = keyValue;
2285 } else {
2286 newValue = keyValue;
2287 }
2288 }
2289 }
2290 }
2291 caching.lastIndex = iterationIndex;
2292 return newValue;
2293 }
2294
2295 //based on @Toji's https://github.com/toji/gl-matrix/
2296 function slerp(a, b, t) {
2297 var out = [];
2298 var ax = a[0], ay = a[1], az = a[2], aw = a[3],
2299 bx = b[0], by = b[1], bz = b[2], bw = b[3]
2300
2301 var omega, cosom, sinom, scale0, scale1;
2302
2303 cosom = ax * bx + ay * by + az * bz + aw * bw;
2304 if (cosom < 0.0) {
2305 cosom = -cosom;
2306 bx = -bx;
2307 by = -by;
2308 bz = -bz;
2309 bw = -bw;
2310 }
2311 if ((1.0 - cosom) > 0.000001) {
2312 omega = Math.acos(cosom);
2313 sinom = Math.sin(omega);
2314 scale0 = Math.sin((1.0 - t) * omega) / sinom;
2315 scale1 = Math.sin(t * omega) / sinom;
2316 } else {
2317 scale0 = 1.0 - t;
2318 scale1 = t;
2319 }
2320 out[0] = scale0 * ax + scale1 * bx;
2321 out[1] = scale0 * ay + scale1 * by;
2322 out[2] = scale0 * az + scale1 * bz;
2323 out[3] = scale0 * aw + scale1 * bw;
2324
2325 return out;
2326 }
2327
2328 function quaternionToEuler(out, quat) {
2329 var qx = quat[0];
2330 var qy = quat[1];
2331 var qz = quat[2];
2332 var qw = quat[3];
2333 var heading = Math.atan2(2*qy*qw-2*qx*qz , 1 - 2*qy*qy - 2*qz*qz)
2334 var attitude = Math.asin(2*qx*qy + 2*qz*qw)
2335 var bank = Math.atan2(2*qx*qw-2*qy*qz , 1 - 2*qx*qx - 2*qz*qz);
2336 out[0] = heading/degToRads;
2337 out[1] = attitude/degToRads;
2338 out[2] = bank/degToRads;
2339 }
2340
2341 function createQuaternion(values) {
2342 var heading = values[0] * degToRads;
2343 var attitude = values[1] * degToRads;
2344 var bank = values[2] * degToRads;
2345 var c1 = Math.cos(heading / 2);
2346 var c2 = Math.cos(attitude / 2);
2347 var c3 = Math.cos(bank / 2);
2348 var s1 = Math.sin(heading / 2);
2349 var s2 = Math.sin(attitude / 2);
2350 var s3 = Math.sin(bank / 2);
2351 var w = c1 * c2 * c3 - s1 * s2 * s3;
2352 var x = s1 * s2 * c3 + c1 * c2 * s3;
2353 var y = s1 * c2 * c3 + c1 * s2 * s3;
2354 var z = c1 * s2 * c3 - s1 * c2 * s3;
2355
2356 return [x,y,z,w];
2357 }
2358
2359 function getValueAtCurrentTime(){
2360 var frameNum = this.comp.renderedFrame - this.offsetTime;
2361 var initTime = this.keyframes[0].t - this.offsetTime;
2362 var endTime = this.keyframes[this.keyframes.length- 1].t-this.offsetTime;
2363 if(!(frameNum === this._caching.lastFrame || (this._caching.lastFrame !== initFrame && ((this._caching.lastFrame >= endTime && frameNum >= endTime) || (this._caching.lastFrame < initTime && frameNum < initTime))))){
2364 if(this._caching.lastFrame >= frameNum) {
2365 this._caching._lastKeyframeIndex = -1;
2366 this._caching.lastIndex = 0;
2367 }
2368
2369 var renderResult = this.interpolateValue(frameNum, this._caching);
2370 this.pv = renderResult;
2371 }
2372 this._caching.lastFrame = frameNum;
2373 return this.pv;
2374 }
2375
2376 function setVValue(val) {
2377 var multipliedValue;
2378 if(this.propType === 'unidimensional') {
2379 multipliedValue = val * this.mult;
2380 if(math_abs(this.v - multipliedValue) > 0.00001) {
2381 this.v = multipliedValue;
2382 this._mdf = true;
2383 }
2384 } else {
2385 var i = 0, len = this.v.length;
2386 while (i < len) {
2387 multipliedValue = val[i] * this.mult;
2388 if (math_abs(this.v[i] - multipliedValue) > 0.00001) {
2389 this.v[i] = multipliedValue;
2390 this._mdf = true;
2391 }
2392 i += 1;
2393 }
2394 }
2395 }
2396
2397 function processEffectsSequence() {
2398 if (this.elem.globalData.frameId === this.frameId || !this.effectsSequence.length) {
2399 return;
2400 }
2401 if(this.lock) {
2402 this.setVValue(this.pv);
2403 return;
2404 }
2405 this.lock = true;
2406 this._mdf = this._isFirstFrame;
2407 var multipliedValue;
2408 var i, len = this.effectsSequence.length;
2409 var finalValue = this.kf ? this.pv : this.data.k;
2410 for(i = 0; i < len; i += 1) {
2411 finalValue = this.effectsSequence[i](finalValue);
2412 }
2413 this.setVValue(finalValue);
2414 this._isFirstFrame = false;
2415 this.lock = false;
2416 this.frameId = this.elem.globalData.frameId;
2417 }
2418
2419 function addEffect(effectFunction) {
2420 this.effectsSequence.push(effectFunction);
2421 this.container.addDynamicProperty(this);
2422 }
2423
2424 function ValueProperty(elem, data, mult, container){
2425 this.propType = 'unidimensional';
2426 this.mult = mult || 1;
2427 this.data = data;
2428 this.v = mult ? data.k * mult : data.k;
2429 this.pv = data.k;
2430 this._mdf = false;
2431 this.elem = elem;
2432 this.container = container;
2433 this.comp = elem.comp;
2434 this.k = false;
2435 this.kf = false;
2436 this.vel = 0;
2437 this.effectsSequence = [];
2438 this._isFirstFrame = true;
2439 this.getValue = processEffectsSequence;
2440 this.setVValue = setVValue;
2441 this.addEffect = addEffect;
2442 }
2443
2444 function MultiDimensionalProperty(elem, data, mult, container) {
2445 this.propType = 'multidimensional';
2446 this.mult = mult || 1;
2447 this.data = data;
2448 this._mdf = false;
2449 this.elem = elem;
2450 this.container = container;
2451 this.comp = elem.comp;
2452 this.k = false;
2453 this.kf = false;
2454 this.frameId = -1;
2455 var i, len = data.k.length;
2456 this.v = createTypedArray('float32', len);
2457 this.pv = createTypedArray('float32', len);
2458 var arr = createTypedArray('float32', len);
2459 this.vel = createTypedArray('float32', len);
2460 for (i = 0; i < len; i += 1) {
2461 this.v[i] = data.k[i] * this.mult;
2462 this.pv[i] = data.k[i];
2463 }
2464 this._isFirstFrame = true;
2465 this.effectsSequence = [];
2466 this.getValue = processEffectsSequence;
2467 this.setVValue = setVValue;
2468 this.addEffect = addEffect;
2469 }
2470
2471 function KeyframedValueProperty(elem, data, mult, container) {
2472 this.propType = 'unidimensional';
2473 this.keyframes = data.k;
2474 this.offsetTime = elem.data.st;
2475 this.frameId = -1;
2476 this._caching = {lastFrame: initFrame, lastIndex: 0, value: 0, _lastKeyframeIndex: -1};
2477 this.k = true;
2478 this.kf = true;
2479 this.data = data;
2480 this.mult = mult || 1;
2481 this.elem = elem;
2482 this.container = container;
2483 this.comp = elem.comp;
2484 this.v = initFrame;
2485 this.pv = initFrame;
2486 this._isFirstFrame = true;
2487 this.getValue = processEffectsSequence;
2488 this.setVValue = setVValue;
2489 this.interpolateValue = interpolateValue;
2490 this.effectsSequence = [getValueAtCurrentTime.bind(this)];
2491 this.addEffect = addEffect;
2492 }
2493
2494 function KeyframedMultidimensionalProperty(elem, data, mult, container){
2495 this.propType = 'multidimensional';
2496 var i, len = data.k.length;
2497 var s, e,to,ti;
2498 for (i = 0; i < len - 1; i += 1) {
2499 if (data.k[i].to && data.k[i].s && data.k[i + 1] && data.k[i + 1].s) {
2500 s = data.k[i].s;
2501 e = data.k[i + 1].s;
2502 to = data.k[i].to;
2503 ti = data.k[i].ti;
2504 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]))){
2505 data.k[i].to = null;
2506 data.k[i].ti = null;
2507 }
2508 if(s[0] === e[0] && s[1] === e[1] && to[0] === 0 && to[1] === 0 && ti[0] === 0 && ti[1] === 0) {
2509 if(s.length === 2 || (s[2] === e[2] && to[2] === 0 && ti[2] === 0)) {
2510 data.k[i].to = null;
2511 data.k[i].ti = null;
2512 }
2513 }
2514 }
2515 }
2516 this.effectsSequence = [getValueAtCurrentTime.bind(this)];
2517 this.keyframes = data.k;
2518 this.offsetTime = elem.data.st;
2519 this.k = true;
2520 this.kf = true;
2521 this._isFirstFrame = true;
2522 this.mult = mult || 1;
2523 this.elem = elem;
2524 this.container = container;
2525 this.comp = elem.comp;
2526 this.getValue = processEffectsSequence;
2527 this.setVValue = setVValue;
2528 this.interpolateValue = interpolateValue;
2529 this.frameId = -1;
2530 var arrLen = data.k[0].s.length;
2531 this.v = createTypedArray('float32', arrLen);
2532 this.pv = createTypedArray('float32', arrLen);
2533 for (i = 0; i < arrLen; i += 1) {
2534 this.v[i] = initFrame;
2535 this.pv[i] = initFrame;
2536 }
2537 this._caching={lastFrame:initFrame,lastIndex:0,value:createTypedArray('float32', arrLen)};
2538 this.addEffect = addEffect;
2539 }
2540
2541 function getProp(elem,data,type, mult, container) {
2542 var p;
2543 if(!data.k.length){
2544 p = new ValueProperty(elem,data, mult, container);
2545 }else if(typeof(data.k[0]) === 'number'){
2546 p = new MultiDimensionalProperty(elem,data, mult, container);
2547 }else{
2548 switch(type){
2549 case 0:
2550 p = new KeyframedValueProperty(elem,data,mult, container);
2551 break;
2552 case 1:
2553 p = new KeyframedMultidimensionalProperty(elem,data,mult, container);
2554 break;
2555 }
2556 }
2557 if(p.effectsSequence.length){
2558 container.addDynamicProperty(p);
2559 }
2560 return p;
2561 }
2562
2563 var ob = {
2564 getProp: getProp
2565 };
2566 return ob;
2567}());
2568var TransformPropertyFactory = (function() {
2569
2570 var defaultVector = [0,0]
2571
2572 function applyToMatrix(mat) {
2573 var _mdf = this._mdf;
2574 this.iterateDynamicProperties();
2575 this._mdf = this._mdf || _mdf;
2576 if (this.a) {
2577 mat.translate(-this.a.v[0], -this.a.v[1], this.a.v[2]);
2578 }
2579 if (this.s) {
2580 mat.scale(this.s.v[0], this.s.v[1], this.s.v[2]);
2581 }
2582 if (this.sk) {
2583 mat.skewFromAxis(-this.sk.v, this.sa.v);
2584 }
2585 if (this.r) {
2586 mat.rotate(-this.r.v);
2587 } else {
2588 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]);
2589 }
2590 if (this.data.p.s) {
2591 if (this.data.p.z) {
2592 mat.translate(this.px.v, this.py.v, -this.pz.v);
2593 } else {
2594 mat.translate(this.px.v, this.py.v, 0);
2595 }
2596 } else {
2597 mat.translate(this.p.v[0], this.p.v[1], -this.p.v[2]);
2598 }
2599 }
2600 function processKeys(forceRender){
2601 if (this.elem.globalData.frameId === this.frameId) {
2602 return;
2603 }
2604 if(this._isDirty) {
2605 this.precalculateMatrix();
2606 this._isDirty = false;
2607 }
2608
2609 this.iterateDynamicProperties();
2610
2611 if (this._mdf || forceRender) {
2612 this.v.cloneFromProps(this.pre.props);
2613 if (this.appliedTransformations < 1) {
2614 this.v.translate(-this.a.v[0], -this.a.v[1], this.a.v[2]);
2615 }
2616 if(this.appliedTransformations < 2) {
2617 this.v.scale(this.s.v[0], this.s.v[1], this.s.v[2]);
2618 }
2619 if (this.sk && this.appliedTransformations < 3) {
2620 this.v.skewFromAxis(-this.sk.v, this.sa.v);
2621 }
2622 if (this.r && this.appliedTransformations < 4) {
2623 this.v.rotate(-this.r.v);
2624 } else if (!this.r && this.appliedTransformations < 4){
2625 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]);
2626 }
2627 if (this.autoOriented) {
2628 var v1,v2, frameRate = this.elem.globalData.frameRate;
2629 if(this.p && this.p.keyframes && this.p.getValueAtTime) {
2630 if (this.p._caching.lastFrame+this.p.offsetTime <= this.p.keyframes[0].t) {
2631 v1 = this.p.getValueAtTime((this.p.keyframes[0].t + 0.01) / frameRate,0);
2632 v2 = this.p.getValueAtTime(this.p.keyframes[0].t / frameRate, 0);
2633 } else if(this.p._caching.lastFrame+this.p.offsetTime >= this.p.keyframes[this.p.keyframes.length - 1].t) {
2634 v1 = this.p.getValueAtTime((this.p.keyframes[this.p.keyframes.length - 1].t / frameRate), 0);
2635 v2 = this.p.getValueAtTime((this.p.keyframes[this.p.keyframes.length - 1].t - 0.05) / frameRate, 0);
2636 } else {
2637 v1 = this.p.pv;
2638 v2 = this.p.getValueAtTime((this.p._caching.lastFrame+this.p.offsetTime - 0.01) / frameRate, this.p.offsetTime);
2639 }
2640 } else if(this.px && this.px.keyframes && this.py.keyframes && this.px.getValueAtTime && this.py.getValueAtTime) {
2641 v1 = [];
2642 v2 = [];
2643 var px = this.px, py = this.py, frameRate;
2644 if (px._caching.lastFrame+px.offsetTime <= px.keyframes[0].t) {
2645 v1[0] = px.getValueAtTime((px.keyframes[0].t + 0.01) / frameRate,0);
2646 v1[1] = py.getValueAtTime((py.keyframes[0].t + 0.01) / frameRate,0);
2647 v2[0] = px.getValueAtTime((px.keyframes[0].t) / frameRate,0);
2648 v2[1] = py.getValueAtTime((py.keyframes[0].t) / frameRate,0);
2649 } else if(px._caching.lastFrame+px.offsetTime >= px.keyframes[px.keyframes.length - 1].t) {
2650 v1[0] = px.getValueAtTime((px.keyframes[px.keyframes.length - 1].t / frameRate),0);
2651 v1[1] = py.getValueAtTime((py.keyframes[py.keyframes.length - 1].t / frameRate),0);
2652 v2[0] = px.getValueAtTime((px.keyframes[px.keyframes.length - 1].t - 0.01) / frameRate,0);
2653 v2[1] = py.getValueAtTime((py.keyframes[py.keyframes.length - 1].t - 0.01) / frameRate,0);
2654 } else {
2655 v1 = [px.pv, py.pv];
2656 v2[0] = px.getValueAtTime((px._caching.lastFrame+px.offsetTime - 0.01) / frameRate,px.offsetTime);
2657 v2[1] = py.getValueAtTime((py._caching.lastFrame+py.offsetTime - 0.01) / frameRate,py.offsetTime);
2658 }
2659 } else {
2660 v1 = v2 = defaultVector
2661 }
2662 this.v.rotate(-Math.atan2(v1[1] - v2[1], v1[0] - v2[0]));
2663 }
2664 if(this.data.p && this.data.p.s){
2665 if(this.data.p.z) {
2666 this.v.translate(this.px.v, this.py.v, -this.pz.v);
2667 } else {
2668 this.v.translate(this.px.v, this.py.v, 0);
2669 }
2670 }else{
2671 this.v.translate(this.p.v[0],this.p.v[1],-this.p.v[2]);
2672 }
2673 }
2674 this.frameId = this.elem.globalData.frameId;
2675 }
2676
2677 function precalculateMatrix() {
2678 if(!this.a.k) {
2679 this.pre.translate(-this.a.v[0], -this.a.v[1], this.a.v[2]);
2680 this.appliedTransformations = 1;
2681 } else {
2682 return;
2683 }
2684 if(!this.s.effectsSequence.length) {
2685 this.pre.scale(this.s.v[0], this.s.v[1], this.s.v[2]);
2686 this.appliedTransformations = 2;
2687 } else {
2688 return;
2689 }
2690 if(this.sk) {
2691 if(!this.sk.effectsSequence.length && !this.sa.effectsSequence.length) {
2692 this.pre.skewFromAxis(-this.sk.v, this.sa.v);
2693 this.appliedTransformations = 3;
2694 } else {
2695 return;
2696 }
2697 }
2698 if (this.r) {
2699 if(!this.r.effectsSequence.length) {
2700 this.pre.rotate(-this.r.v);
2701 this.appliedTransformations = 4;
2702 } else {
2703 return;
2704 }
2705 } else if(!this.rz.effectsSequence.length && !this.ry.effectsSequence.length && !this.rx.effectsSequence.length && !this.or.effectsSequence.length) {
2706 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]);
2707 this.appliedTransformations = 4;
2708 }
2709 }
2710
2711 function autoOrient(){
2712 //
2713 //var prevP = this.getValueAtTime();
2714 }
2715
2716 function addDynamicProperty(prop) {
2717 this._addDynamicProperty(prop);
2718 this.elem.addDynamicProperty(prop);
2719 this._isDirty = true;
2720 }
2721
2722 function TransformProperty(elem,data,container){
2723 this.elem = elem;
2724 this.frameId = -1;
2725 this.propType = 'transform';
2726 this.data = data;
2727 this.v = new Matrix();
2728 //Precalculated matrix with non animated properties
2729 this.pre = new Matrix();
2730 this.appliedTransformations = 0;
2731 this.initDynamicPropertyContainer(container || elem);
2732 if(data.p && data.p.s){
2733 this.px = PropertyFactory.getProp(elem,data.p.x,0,0,this);
2734 this.py = PropertyFactory.getProp(elem,data.p.y,0,0,this);
2735 if(data.p.z){
2736 this.pz = PropertyFactory.getProp(elem,data.p.z,0,0,this);
2737 }
2738 }else{
2739 this.p = PropertyFactory.getProp(elem,data.p || {k:[0,0,0]},1,0,this);
2740 }
2741 if(data.rx) {
2742 this.rx = PropertyFactory.getProp(elem, data.rx, 0, degToRads, this);
2743 this.ry = PropertyFactory.getProp(elem, data.ry, 0, degToRads, this);
2744 this.rz = PropertyFactory.getProp(elem, data.rz, 0, degToRads, this);
2745 if(data.or.k[0].ti) {
2746 var i, len = data.or.k.length;
2747 for(i=0;i<len;i+=1) {
2748 data.or.k[i].to = data.or.k[i].ti = null;
2749 }
2750 }
2751 this.or = PropertyFactory.getProp(elem, data.or, 1, degToRads, this);
2752 //sh Indicates it needs to be capped between -180 and 180
2753 this.or.sh = true;
2754 } else {
2755 this.r = PropertyFactory.getProp(elem, data.r || {k: 0}, 0, degToRads, this);
2756 }
2757 if(data.sk){
2758 this.sk = PropertyFactory.getProp(elem, data.sk, 0, degToRads, this);
2759 this.sa = PropertyFactory.getProp(elem, data.sa, 0, degToRads, this);
2760 }
2761 this.a = PropertyFactory.getProp(elem,data.a || {k:[0,0,0]},1,0,this);
2762 this.s = PropertyFactory.getProp(elem,data.s || {k:[100,100,100]},1,0.01,this);
2763 // 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.
2764 if(data.o){
2765 this.o = PropertyFactory.getProp(elem,data.o,0,0.01,elem);
2766 } else {
2767 this.o = {_mdf:false,v:1};
2768 }
2769 this._isDirty = true;
2770 if(!this.dynamicProperties.length){
2771 this.getValue(true);
2772 }
2773 }
2774
2775 TransformProperty.prototype = {
2776 applyToMatrix: applyToMatrix,
2777 getValue: processKeys,
2778 precalculateMatrix: precalculateMatrix,
2779 autoOrient: autoOrient
2780 }
2781
2782 extendPrototype([DynamicPropertyContainer], TransformProperty);
2783 TransformProperty.prototype.addDynamicProperty = addDynamicProperty;
2784 TransformProperty.prototype._addDynamicProperty = DynamicPropertyContainer.prototype.addDynamicProperty;
2785
2786 function getTransformProperty(elem,data,container){
2787 return new TransformProperty(elem,data,container);
2788 }
2789
2790 return {
2791 getTransformProperty: getTransformProperty
2792 };
2793
2794}());
2795function ShapePath(){
2796 this.c = false;
2797 this._length = 0;
2798 this._maxLength = 8;
2799 this.v = createSizedArray(this._maxLength);
2800 this.o = createSizedArray(this._maxLength);
2801 this.i = createSizedArray(this._maxLength);
2802}
2803
2804ShapePath.prototype.setPathData = function(closed, len) {
2805 this.c = closed;
2806 this.setLength(len);
2807 var i = 0;
2808 while(i < len){
2809 this.v[i] = point_pool.newElement();
2810 this.o[i] = point_pool.newElement();
2811 this.i[i] = point_pool.newElement();
2812 i += 1;
2813 }
2814};
2815
2816ShapePath.prototype.setLength = function(len) {
2817 while(this._maxLength < len) {
2818 this.doubleArrayLength();
2819 }
2820 this._length = len;
2821};
2822
2823ShapePath.prototype.doubleArrayLength = function() {
2824 this.v = this.v.concat(createSizedArray(this._maxLength));
2825 this.i = this.i.concat(createSizedArray(this._maxLength));
2826 this.o = this.o.concat(createSizedArray(this._maxLength));
2827 this._maxLength *= 2;
2828};
2829
2830ShapePath.prototype.setXYAt = function(x, y, type, pos, replace) {
2831 var arr;
2832 this._length = Math.max(this._length, pos + 1);
2833 if(this._length >= this._maxLength) {
2834 this.doubleArrayLength();
2835 }
2836 switch(type){
2837 case 'v':
2838 arr = this.v;
2839 break;
2840 case 'i':
2841 arr = this.i;
2842 break;
2843 case 'o':
2844 arr = this.o;
2845 break;
2846 }
2847 if(!arr[pos] || (arr[pos] && !replace)){
2848 arr[pos] = point_pool.newElement();
2849 }
2850 arr[pos][0] = x;
2851 arr[pos][1] = y;
2852};
2853
2854ShapePath.prototype.setTripleAt = function(vX,vY,oX,oY,iX,iY,pos, replace) {
2855 this.setXYAt(vX,vY,'v',pos, replace);
2856 this.setXYAt(oX,oY,'o',pos, replace);
2857 this.setXYAt(iX,iY,'i',pos, replace);
2858};
2859
2860ShapePath.prototype.reverse = function() {
2861 var newPath = new ShapePath();
2862 newPath.setPathData(this.c, this._length);
2863 var vertices = this.v, outPoints = this.o, inPoints = this.i;
2864 var init = 0;
2865 if (this.c) {
2866 newPath.setTripleAt(vertices[0][0], vertices[0][1], inPoints[0][0], inPoints[0][1], outPoints[0][0], outPoints[0][1], 0, false);
2867 init = 1;
2868 }
2869 var cnt = this._length - 1;
2870 var len = this._length;
2871
2872 var i;
2873 for (i = init; i < len; i += 1) {
2874 newPath.setTripleAt(vertices[cnt][0], vertices[cnt][1], inPoints[cnt][0], inPoints[cnt][1], outPoints[cnt][0], outPoints[cnt][1], i, false);
2875 cnt -= 1;
2876 }
2877 return newPath;
2878};
2879var ShapePropertyFactory = (function(){
2880
2881 var initFrame = -999999;
2882
2883 function interpolateShape(frameNum, previousValue, caching) {
2884 var iterationIndex = caching.lastIndex;
2885 var keyPropS,keyPropE,isHold, j, k, jLen, kLen, perc, vertexValue;
2886 var kf = this.keyframes;
2887 if(frameNum < kf[0].t-this.offsetTime){
2888 keyPropS = kf[0].s[0];
2889 isHold = true;
2890 iterationIndex = 0;
2891 }else if(frameNum >= kf[kf.length - 1].t-this.offsetTime){
2892 keyPropS = kf[kf.length - 1].s ? kf[kf.length - 1].s[0] : kf[kf.length - 2].e[0];
2893 /*if(kf[kf.length - 1].s){
2894 keyPropS = kf[kf.length - 1].s[0];
2895 }else{
2896 keyPropS = kf[kf.length - 2].e[0];
2897 }*/
2898 isHold = true;
2899 }else{
2900 var i = iterationIndex;
2901 var len = kf.length- 1,flag = true,keyData,nextKeyData;
2902 while(flag){
2903 keyData = kf[i];
2904 nextKeyData = kf[i+1];
2905 if((nextKeyData.t - this.offsetTime) > frameNum){
2906 break;
2907 }
2908 if(i < len - 1){
2909 i += 1;
2910 }else{
2911 flag = false;
2912 }
2913 }
2914 isHold = keyData.h === 1;
2915 iterationIndex = i;
2916 if(!isHold){
2917 if(frameNum >= nextKeyData.t-this.offsetTime){
2918 perc = 1;
2919 }else if(frameNum < keyData.t-this.offsetTime){
2920 perc = 0;
2921 }else{
2922 var fnc;
2923 if(keyData.__fnct){
2924 fnc = keyData.__fnct;
2925 }else{
2926 fnc = BezierFactory.getBezierEasing(keyData.o.x,keyData.o.y,keyData.i.x,keyData.i.y).get;
2927 keyData.__fnct = fnc;
2928 }
2929 perc = fnc((frameNum-(keyData.t-this.offsetTime))/((nextKeyData.t-this.offsetTime)-(keyData.t-this.offsetTime)));
2930 }
2931 keyPropE = nextKeyData.s ? nextKeyData.s[0] : keyData.e[0];
2932 }
2933 keyPropS = keyData.s[0];
2934 }
2935 jLen = previousValue._length;
2936 kLen = keyPropS.i[0].length;
2937 caching.lastIndex = iterationIndex;
2938
2939 for(j=0;j<jLen;j+=1){
2940 for(k=0;k<kLen;k+=1){
2941 vertexValue = isHold ? keyPropS.i[j][k] : keyPropS.i[j][k]+(keyPropE.i[j][k]-keyPropS.i[j][k])*perc;
2942 previousValue.i[j][k] = vertexValue;
2943 vertexValue = isHold ? keyPropS.o[j][k] : keyPropS.o[j][k]+(keyPropE.o[j][k]-keyPropS.o[j][k])*perc;
2944 previousValue.o[j][k] = vertexValue;
2945 vertexValue = isHold ? keyPropS.v[j][k] : keyPropS.v[j][k]+(keyPropE.v[j][k]-keyPropS.v[j][k])*perc;
2946 previousValue.v[j][k] = vertexValue;
2947 }
2948 }
2949 }
2950
2951 function interpolateShapeCurrentTime(){
2952 var frameNum = this.comp.renderedFrame - this.offsetTime;
2953 var initTime = this.keyframes[0].t - this.offsetTime;
2954 var endTime = this.keyframes[this.keyframes.length - 1].t - this.offsetTime;
2955 var lastFrame = this._caching.lastFrame;
2956 if(!(lastFrame !== initFrame && ((lastFrame < initTime && frameNum < initTime) || (lastFrame > endTime && frameNum > endTime)))){
2957 ////
2958 this._caching.lastIndex = lastFrame < frameNum ? this._caching.lastIndex : 0;
2959 this.interpolateShape(frameNum, this.pv, this._caching);
2960 ////
2961 }
2962 this._caching.lastFrame = frameNum;
2963 return this.pv;
2964 }
2965
2966 function resetShape(){
2967 this.paths = this.localShapeCollection;
2968 }
2969
2970 function shapesEqual(shape1, shape2) {
2971 if(shape1._length !== shape2._length || shape1.c !== shape2.c){
2972 return false;
2973 }
2974 var i, len = shape1._length;
2975 for(i = 0; i < len; i += 1) {
2976 if(shape1.v[i][0] !== shape2.v[i][0]
2977 || shape1.v[i][1] !== shape2.v[i][1]
2978 || shape1.o[i][0] !== shape2.o[i][0]
2979 || shape1.o[i][1] !== shape2.o[i][1]
2980 || shape1.i[i][0] !== shape2.i[i][0]
2981 || shape1.i[i][1] !== shape2.i[i][1]) {
2982 return false;
2983 }
2984 }
2985 return true;
2986 }
2987
2988 function setVValue(newPath) {
2989 if(!shapesEqual(this.v, newPath)) {
2990 this.v = shape_pool.clone(newPath);
2991 this.localShapeCollection.releaseShapes();
2992 this.localShapeCollection.addShape(this.v);
2993 this._mdf = true;
2994 this.paths = this.localShapeCollection;
2995 }
2996 }
2997
2998 function processEffectsSequence() {
2999 if (this.elem.globalData.frameId === this.frameId) {
3000 return;
3001 } else if (!this.effectsSequence.length) {
3002 this._mdf = false;
3003 return;
3004 }
3005 if (this.lock) {
3006 this.setVValue(this.pv);
3007 return;
3008 }
3009 this.lock = true;
3010 this._mdf = false;
3011 var finalValue = this.kf ? this.pv : this.data.ks ? this.data.ks.k : this.data.pt.k;
3012 var i, len = this.effectsSequence.length;
3013 for(i = 0; i < len; i += 1) {
3014 finalValue = this.effectsSequence[i](finalValue);
3015 }
3016 this.setVValue(finalValue);
3017 this.lock = false;
3018 this.frameId = this.elem.globalData.frameId;
3019 };
3020
3021 function ShapeProperty(elem, data, type){
3022 this.propType = 'shape';
3023 this.comp = elem.comp;
3024 this.container = elem;
3025 this.elem = elem;
3026 this.data = data;
3027 this.k = false;
3028 this.kf = false;
3029 this._mdf = false;
3030 var pathData = type === 3 ? data.pt.k : data.ks.k;
3031 this.v = shape_pool.clone(pathData);
3032 this.pv = shape_pool.clone(this.v);
3033 this.localShapeCollection = shapeCollection_pool.newShapeCollection();
3034 this.paths = this.localShapeCollection;
3035 this.paths.addShape(this.v);
3036 this.reset = resetShape;
3037 this.effectsSequence = [];
3038 }
3039
3040 function addEffect(effectFunction) {
3041 this.effectsSequence.push(effectFunction);
3042 this.container.addDynamicProperty(this);
3043 }
3044
3045 ShapeProperty.prototype.interpolateShape = interpolateShape;
3046 ShapeProperty.prototype.getValue = processEffectsSequence;
3047 ShapeProperty.prototype.setVValue = setVValue;
3048 ShapeProperty.prototype.addEffect = addEffect;
3049
3050 function KeyframedShapeProperty(elem,data,type){
3051 this.propType = 'shape';
3052 this.comp = elem.comp;
3053 this.elem = elem;
3054 this.container = elem;
3055 this.offsetTime = elem.data.st;
3056 this.keyframes = type === 3 ? data.pt.k : data.ks.k;
3057 this.k = true;
3058 this.kf = true;
3059 var i, len = this.keyframes[0].s[0].i.length;
3060 var jLen = this.keyframes[0].s[0].i[0].length;
3061 this.v = shape_pool.newElement();
3062 this.v.setPathData(this.keyframes[0].s[0].c, len);
3063 this.pv = shape_pool.clone(this.v);
3064 this.localShapeCollection = shapeCollection_pool.newShapeCollection();
3065 this.paths = this.localShapeCollection;
3066 this.paths.addShape(this.v);
3067 this.lastFrame = initFrame;
3068 this.reset = resetShape;
3069 this._caching = {lastFrame: initFrame, lastIndex: 0};
3070 this.effectsSequence = [interpolateShapeCurrentTime.bind(this)];
3071 }
3072 KeyframedShapeProperty.prototype.getValue = processEffectsSequence;
3073 KeyframedShapeProperty.prototype.interpolateShape = interpolateShape;
3074 KeyframedShapeProperty.prototype.setVValue = setVValue;
3075 KeyframedShapeProperty.prototype.addEffect = addEffect;
3076
3077 var EllShapeProperty = (function(){
3078
3079 var cPoint = roundCorner;
3080
3081 function EllShapeProperty(elem,data) {
3082 /*this.v = {
3083 v: createSizedArray(4),
3084 i: createSizedArray(4),
3085 o: createSizedArray(4),
3086 c: true
3087 };*/
3088 this.v = shape_pool.newElement();
3089 this.v.setPathData(true, 4);
3090 this.localShapeCollection = shapeCollection_pool.newShapeCollection();
3091 this.paths = this.localShapeCollection;
3092 this.localShapeCollection.addShape(this.v);
3093 this.d = data.d;
3094 this.elem = elem;
3095 this.comp = elem.comp;
3096 this.frameId = -1;
3097 this.initDynamicPropertyContainer(elem);
3098 this.p = PropertyFactory.getProp(elem,data.p,1,0,this);
3099 this.s = PropertyFactory.getProp(elem,data.s,1,0,this);
3100 if(this.dynamicProperties.length){
3101 this.k = true;
3102 }else{
3103 this.k = false;
3104 this.convertEllToPath();
3105 }
3106 };
3107
3108 EllShapeProperty.prototype = {
3109 reset: resetShape,
3110 getValue: function (){
3111 if(this.elem.globalData.frameId === this.frameId){
3112 return;
3113 }
3114 this.frameId = this.elem.globalData.frameId;
3115 this.iterateDynamicProperties();
3116
3117 if(this._mdf){
3118 this.convertEllToPath();
3119 }
3120 },
3121 convertEllToPath: function() {
3122 var p0 = this.p.v[0], p1 = this.p.v[1], s0 = this.s.v[0]/2, s1 = this.s.v[1]/2;
3123 var _cw = this.d !== 3;
3124 var _v = this.v;
3125 _v.v[0][0] = p0;
3126 _v.v[0][1] = p1 - s1;
3127 _v.v[1][0] = _cw ? p0 + s0 : p0 - s0;
3128 _v.v[1][1] = p1;
3129 _v.v[2][0] = p0;
3130 _v.v[2][1] = p1 + s1;
3131 _v.v[3][0] = _cw ? p0 - s0 : p0 + s0;
3132 _v.v[3][1] = p1;
3133 _v.i[0][0] = _cw ? p0 - s0 * cPoint : p0 + s0 * cPoint;
3134 _v.i[0][1] = p1 - s1;
3135 _v.i[1][0] = _cw ? p0 + s0 : p0 - s0;
3136 _v.i[1][1] = p1 - s1 * cPoint;
3137 _v.i[2][0] = _cw ? p0 + s0 * cPoint : p0 - s0 * cPoint;
3138 _v.i[2][1] = p1 + s1;
3139 _v.i[3][0] = _cw ? p0 - s0 : p0 + s0;
3140 _v.i[3][1] = p1 + s1 * cPoint;
3141 _v.o[0][0] = _cw ? p0 + s0 * cPoint : p0 - s0 * cPoint;
3142 _v.o[0][1] = p1 - s1;
3143 _v.o[1][0] = _cw ? p0 + s0 : p0 - s0;
3144 _v.o[1][1] = p1 + s1 * cPoint;
3145 _v.o[2][0] = _cw ? p0 - s0 * cPoint : p0 + s0 * cPoint;
3146 _v.o[2][1] = p1 + s1;
3147 _v.o[3][0] = _cw ? p0 - s0 : p0 + s0;
3148 _v.o[3][1] = p1 - s1 * cPoint;
3149 }
3150 }
3151
3152 extendPrototype([DynamicPropertyContainer], EllShapeProperty);
3153
3154 return EllShapeProperty;
3155 }());
3156
3157 var StarShapeProperty = (function() {
3158
3159 function StarShapeProperty(elem,data) {
3160 this.v = shape_pool.newElement();
3161 this.v.setPathData(true, 0);
3162 this.elem = elem;
3163 this.comp = elem.comp;
3164 this.data = data;
3165 this.frameId = -1;
3166 this.d = data.d;
3167 this.initDynamicPropertyContainer(elem);
3168 if(data.sy === 1){
3169 this.ir = PropertyFactory.getProp(elem,data.ir,0,0,this);
3170 this.is = PropertyFactory.getProp(elem,data.is,0,0.01,this);
3171 this.convertToPath = this.convertStarToPath;
3172 } else {
3173 this.convertToPath = this.convertPolygonToPath;
3174 }
3175 this.pt = PropertyFactory.getProp(elem,data.pt,0,0,this);
3176 this.p = PropertyFactory.getProp(elem,data.p,1,0,this);
3177 this.r = PropertyFactory.getProp(elem,data.r,0,degToRads,this);
3178 this.or = PropertyFactory.getProp(elem,data.or,0,0,this);
3179 this.os = PropertyFactory.getProp(elem,data.os,0,0.01,this);
3180 this.localShapeCollection = shapeCollection_pool.newShapeCollection();
3181 this.localShapeCollection.addShape(this.v);
3182 this.paths = this.localShapeCollection;
3183 if(this.dynamicProperties.length){
3184 this.k = true;
3185 }else{
3186 this.k = false;
3187 this.convertToPath();
3188 }
3189 };
3190
3191 StarShapeProperty.prototype = {
3192 reset: resetShape,
3193 getValue: function() {
3194 if(this.elem.globalData.frameId === this.frameId){
3195 return;
3196 }
3197 this.frameId = this.elem.globalData.frameId;
3198 this.iterateDynamicProperties();
3199 if(this._mdf){
3200 this.convertToPath();
3201 }
3202 },
3203 convertStarToPath: function() {
3204 var numPts = Math.floor(this.pt.v)*2;
3205 var angle = Math.PI*2/numPts;
3206 /*this.v.v.length = numPts;
3207 this.v.i.length = numPts;
3208 this.v.o.length = numPts;*/
3209 var longFlag = true;
3210 var longRad = this.or.v;
3211 var shortRad = this.ir.v;
3212 var longRound = this.os.v;
3213 var shortRound = this.is.v;
3214 var longPerimSegment = 2*Math.PI*longRad/(numPts*2);
3215 var shortPerimSegment = 2*Math.PI*shortRad/(numPts*2);
3216 var i, rad,roundness,perimSegment, currentAng = -Math.PI/ 2;
3217 currentAng += this.r.v;
3218 var dir = this.data.d === 3 ? -1 : 1;
3219 this.v._length = 0;
3220 for(i=0;i<numPts;i+=1){
3221 rad = longFlag ? longRad : shortRad;
3222 roundness = longFlag ? longRound : shortRound;
3223 perimSegment = longFlag ? longPerimSegment : shortPerimSegment;
3224 var x = rad * Math.cos(currentAng);
3225 var y = rad * Math.sin(currentAng);
3226 var ox = x === 0 && y === 0 ? 0 : y/Math.sqrt(x*x + y*y);
3227 var oy = x === 0 && y === 0 ? 0 : -x/Math.sqrt(x*x + y*y);
3228 x += + this.p.v[0];
3229 y += + this.p.v[1];
3230 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);
3231
3232 /*this.v.v[i] = [x,y];
3233 this.v.i[i] = [x+ox*perimSegment*roundness*dir,y+oy*perimSegment*roundness*dir];
3234 this.v.o[i] = [x-ox*perimSegment*roundness*dir,y-oy*perimSegment*roundness*dir];
3235 this.v._length = numPts;*/
3236 longFlag = !longFlag;
3237 currentAng += angle*dir;
3238 }
3239 },
3240 convertPolygonToPath: function() {
3241 var numPts = Math.floor(this.pt.v);
3242 var angle = Math.PI*2/numPts;
3243 var rad = this.or.v;
3244 var roundness = this.os.v;
3245 var perimSegment = 2*Math.PI*rad/(numPts*4);
3246 var i, currentAng = -Math.PI/ 2;
3247 var dir = this.data.d === 3 ? -1 : 1;
3248 currentAng += this.r.v;
3249 this.v._length = 0;
3250 for(i=0;i<numPts;i+=1){
3251 var x = rad * Math.cos(currentAng);
3252 var y = rad * Math.sin(currentAng);
3253 var ox = x === 0 && y === 0 ? 0 : y/Math.sqrt(x*x + y*y);
3254 var oy = x === 0 && y === 0 ? 0 : -x/Math.sqrt(x*x + y*y);
3255 x += + this.p.v[0];
3256 y += + this.p.v[1];
3257 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);
3258 currentAng += angle*dir;
3259 }
3260 this.paths.length = 0;
3261 this.paths[0] = this.v;
3262 }
3263
3264 }
3265 extendPrototype([DynamicPropertyContainer], StarShapeProperty);
3266
3267 return StarShapeProperty;
3268 }());
3269
3270 var RectShapeProperty = (function() {
3271
3272 function RectShapeProperty(elem,data) {
3273 this.v = shape_pool.newElement();
3274 this.v.c = true;
3275 this.localShapeCollection = shapeCollection_pool.newShapeCollection();
3276 this.localShapeCollection.addShape(this.v);
3277 this.paths = this.localShapeCollection;
3278 this.elem = elem;
3279 this.comp = elem.comp;
3280 this.frameId = -1;
3281 this.d = data.d;
3282 this.initDynamicPropertyContainer(elem);
3283 this.p = PropertyFactory.getProp(elem,data.p,1,0,this);
3284 this.s = PropertyFactory.getProp(elem,data.s,1,0,this);
3285 this.r = PropertyFactory.getProp(elem,data.r,0,0,this);
3286 if(this.dynamicProperties.length){
3287 this.k = true;
3288 }else{
3289 this.k = false;
3290 this.convertRectToPath();
3291 }
3292 };
3293
3294 RectShapeProperty.prototype = {
3295 convertRectToPath: function (){
3296 var p0 = this.p.v[0], p1 = this.p.v[1], v0 = this.s.v[0]/2, v1 = this.s.v[1]/2;
3297 var round = bm_min(v0,v1,this.r.v);
3298 var cPoint = round*(1-roundCorner);
3299 this.v._length = 0;
3300
3301 if(this.d === 2 || this.d === 1) {
3302 this.v.setTripleAt(p0+v0, p1-v1+round,p0+v0, p1-v1+round,p0+v0,p1-v1+cPoint,0, true);
3303 this.v.setTripleAt(p0+v0, p1+v1-round,p0+v0, p1+v1-cPoint,p0+v0, p1+v1-round,1, true);
3304 if(round!== 0){
3305 this.v.setTripleAt(p0+v0-round, p1+v1,p0+v0-round,p1+v1,p0+v0-cPoint,p1+v1,2, true);
3306 this.v.setTripleAt(p0-v0+round,p1+v1,p0-v0+cPoint,p1+v1,p0-v0+round,p1+v1,3, true);
3307 this.v.setTripleAt(p0-v0,p1+v1-round,p0-v0,p1+v1-round,p0-v0,p1+v1-cPoint,4, true);
3308 this.v.setTripleAt(p0-v0,p1-v1+round,p0-v0,p1-v1+cPoint,p0-v0,p1-v1+round,5, true);
3309 this.v.setTripleAt(p0-v0+round,p1-v1,p0-v0+round,p1-v1,p0-v0+cPoint,p1-v1,6, true);
3310 this.v.setTripleAt(p0+v0-round,p1-v1,p0+v0-cPoint,p1-v1,p0+v0-round,p1-v1,7, true);
3311 } else {
3312 this.v.setTripleAt(p0-v0,p1+v1,p0-v0+cPoint,p1+v1,p0-v0,p1+v1,2);
3313 this.v.setTripleAt(p0-v0,p1-v1,p0-v0,p1-v1+cPoint,p0-v0,p1-v1,3);
3314 }
3315 }else{
3316 this.v.setTripleAt(p0+v0,p1-v1+round,p0+v0,p1-v1+cPoint,p0+v0,p1-v1+round,0, true);
3317 if(round!== 0){
3318 this.v.setTripleAt(p0+v0-round,p1-v1,p0+v0-round,p1-v1,p0+v0-cPoint,p1-v1,1, true);
3319 this.v.setTripleAt(p0-v0+round,p1-v1,p0-v0+cPoint,p1-v1,p0-v0+round,p1-v1,2, true);
3320 this.v.setTripleAt(p0-v0,p1-v1+round,p0-v0,p1-v1+round,p0-v0,p1-v1+cPoint,3, true);
3321 this.v.setTripleAt(p0-v0,p1+v1-round,p0-v0,p1+v1-cPoint,p0-v0,p1+v1-round,4, true);
3322 this.v.setTripleAt(p0-v0+round,p1+v1,p0-v0+round,p1+v1,p0-v0+cPoint,p1+v1,5, true);
3323 this.v.setTripleAt(p0+v0-round,p1+v1,p0+v0-cPoint,p1+v1,p0+v0-round,p1+v1,6, true);
3324 this.v.setTripleAt(p0+v0,p1+v1-round,p0+v0,p1+v1-round,p0+v0,p1+v1-cPoint,7, true);
3325 } else {
3326 this.v.setTripleAt(p0-v0,p1-v1,p0-v0+cPoint,p1-v1,p0-v0,p1-v1,1, true);
3327 this.v.setTripleAt(p0-v0,p1+v1,p0-v0,p1+v1-cPoint,p0-v0,p1+v1,2, true);
3328 this.v.setTripleAt(p0+v0,p1+v1,p0+v0-cPoint,p1+v1,p0+v0,p1+v1,3, true);
3329
3330 }
3331 }
3332 },
3333 getValue: function(frameNum){
3334 if(this.elem.globalData.frameId === this.frameId){
3335 return;
3336 }
3337 this.frameId = this.elem.globalData.frameId;
3338 this.iterateDynamicProperties();
3339 if(this._mdf){
3340 this.convertRectToPath();
3341 }
3342
3343 },
3344 reset: resetShape
3345 }
3346 extendPrototype([DynamicPropertyContainer], RectShapeProperty);
3347
3348 return RectShapeProperty;
3349 }());
3350
3351 function getShapeProp(elem,data,type){
3352 var prop;
3353 if(type === 3 || type === 4){
3354 var dataProp = type === 3 ? data.pt : data.ks;
3355 var keys = dataProp.k;
3356 if(keys.length){
3357 prop = new KeyframedShapeProperty(elem, data, type);
3358 }else{
3359 prop = new ShapeProperty(elem, data, type);
3360 }
3361 }else if(type === 5){
3362 prop = new RectShapeProperty(elem, data);
3363 }else if(type === 6){
3364 prop = new EllShapeProperty(elem, data);
3365 }else if(type === 7){
3366 prop = new StarShapeProperty(elem, data);
3367 }
3368 if(prop.k){
3369 elem.addDynamicProperty(prop);
3370 }
3371 return prop;
3372 }
3373
3374 function getConstructorFunction() {
3375 return ShapeProperty;
3376 }
3377
3378 function getKeyframedConstructorFunction() {
3379 return KeyframedShapeProperty;
3380 }
3381
3382 var ob = {};
3383 ob.getShapeProp = getShapeProp;
3384 ob.getConstructorFunction = getConstructorFunction;
3385 ob.getKeyframedConstructorFunction = getKeyframedConstructorFunction;
3386 return ob;
3387}());
3388var ShapeModifiers = (function(){
3389 var ob = {};
3390 var modifiers = {};
3391 ob.registerModifier = registerModifier;
3392 ob.getModifier = getModifier;
3393
3394 function registerModifier(nm,factory){
3395 if(!modifiers[nm]){
3396 modifiers[nm] = factory;
3397 }
3398 }
3399
3400 function getModifier(nm,elem, data){
3401 return new modifiers[nm](elem, data);
3402 }
3403
3404 return ob;
3405}());
3406
3407function ShapeModifier(){}
3408ShapeModifier.prototype.initModifierProperties = function(){};
3409ShapeModifier.prototype.addShapeToModifier = function(){};
3410ShapeModifier.prototype.addShape = function(data){
3411 if (!this.closed) {
3412 // 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.
3413 data.sh.container.addDynamicProperty(data.sh);
3414 var shapeData = {shape:data.sh, data: data, localShapeCollection:shapeCollection_pool.newShapeCollection()};
3415 this.shapes.push(shapeData);
3416 this.addShapeToModifier(shapeData);
3417 if (this._isAnimated) {
3418 data.setAsAnimated();
3419 }
3420 }
3421};
3422ShapeModifier.prototype.init = function(elem,data){
3423 this.shapes = [];
3424 this.elem = elem;
3425 this.initDynamicPropertyContainer(elem);
3426 this.initModifierProperties(elem,data);
3427 this.frameId = initialDefaultFrame;
3428 this.closed = false;
3429 this.k = false;
3430 if(this.dynamicProperties.length){
3431 this.k = true;
3432 }else{
3433 this.getValue(true);
3434 }
3435};
3436ShapeModifier.prototype.processKeys = function(){
3437 if(this.elem.globalData.frameId === this.frameId){
3438 return;
3439 }
3440 this.frameId = this.elem.globalData.frameId;
3441 this.iterateDynamicProperties();
3442};
3443
3444extendPrototype([DynamicPropertyContainer], ShapeModifier);
3445function TrimModifier(){
3446}
3447extendPrototype([ShapeModifier], TrimModifier);
3448TrimModifier.prototype.initModifierProperties = function(elem, data) {
3449 this.s = PropertyFactory.getProp(elem, data.s, 0, 0.01, this);
3450 this.e = PropertyFactory.getProp(elem, data.e, 0, 0.01, this);
3451 this.o = PropertyFactory.getProp(elem, data.o, 0, 0, this);
3452 this.sValue = 0;
3453 this.eValue = 0;
3454 this.getValue = this.processKeys;
3455 this.m = data.m;
3456 this._isAnimated = !!this.s.effectsSequence.length || !!this.e.effectsSequence.length || !!this.o.effectsSequence.length;
3457};
3458
3459TrimModifier.prototype.addShapeToModifier = function(shapeData){
3460 shapeData.pathsData = [];
3461};
3462
3463TrimModifier.prototype.calculateShapeEdges = function(s, e, shapeLength, addedLength, totalModifierLength) {
3464 var segments = [];
3465 if (e <= 1) {
3466 segments.push({
3467 s: s,
3468 e: e
3469 });
3470 } else if (s >= 1) {
3471 segments.push({
3472 s: s - 1,
3473 e: e - 1
3474 });
3475 } else {
3476 segments.push({
3477 s: s,
3478 e: 1
3479 });
3480 segments.push({
3481 s: 0,
3482 e: e - 1
3483 });
3484 }
3485 var shapeSegments = [];
3486 var i, len = segments.length, segmentOb;
3487 for (i = 0; i < len; i += 1) {
3488 segmentOb = segments[i];
3489 if (segmentOb.e * totalModifierLength < addedLength || segmentOb.s * totalModifierLength > addedLength + shapeLength) {
3490
3491 } else {
3492 var shapeS, shapeE;
3493 if (segmentOb.s * totalModifierLength <= addedLength) {
3494 shapeS = 0;
3495 } else {
3496 shapeS = (segmentOb.s * totalModifierLength - addedLength) / shapeLength;
3497 }
3498 if(segmentOb.e * totalModifierLength >= addedLength + shapeLength) {
3499 shapeE = 1;
3500 } else {
3501 shapeE = ((segmentOb.e * totalModifierLength - addedLength) / shapeLength);
3502 }
3503 shapeSegments.push([shapeS, shapeE]);
3504 }
3505 }
3506 if (!shapeSegments.length) {
3507 shapeSegments.push([0, 0]);
3508 }
3509 return shapeSegments;
3510};
3511
3512TrimModifier.prototype.releasePathsData = function(pathsData) {
3513 var i, len = pathsData.length;
3514 for (i = 0; i < len; i += 1) {
3515 segments_length_pool.release(pathsData[i]);
3516 }
3517 pathsData.length = 0;
3518 return pathsData;
3519};
3520
3521TrimModifier.prototype.processShapes = function(_isFirstFrame) {
3522 var s, e;
3523 if (this._mdf || _isFirstFrame) {
3524 var o = (this.o.v % 360) / 360;
3525 if (o < 0) {
3526 o += 1;
3527 }
3528 s = (this.s.v > 1 ? 1 : this.s.v < 0 ? 0 : this.s.v) + o;
3529 e = (this.e.v > 1 ? 1 : this.e.v < 0 ? 0 : this.e.v) + o;
3530 if (s === e) {
3531
3532 }
3533 if (s > e) {
3534 var _s = s;
3535 s = e;
3536 e = _s;
3537 }
3538 s = Math.round(s * 10000) * 0.0001;
3539 e = Math.round(e * 10000) * 0.0001;
3540 this.sValue = s;
3541 this.eValue = e;
3542 } else {
3543 s = this.sValue;
3544 e = this.eValue;
3545 }
3546 var shapePaths;
3547 var i, len = this.shapes.length, j, jLen;
3548 var pathsData, pathData, totalShapeLength, totalModifierLength = 0;
3549
3550 if (e === s) {
3551 for (i = 0; i < len; i += 1) {
3552 this.shapes[i].localShapeCollection.releaseShapes();
3553 this.shapes[i].shape._mdf = true;
3554 this.shapes[i].shape.paths = this.shapes[i].localShapeCollection;
3555 if (this._mdf) {
3556 this.shapes[i].pathsData.length = 0;
3557 }
3558 }
3559 } else if (!((e === 1 && s === 0) || (e===0 && s === 1))){
3560 var segments = [], shapeData, localShapeCollection;
3561 for (i = 0; i < len; i += 1) {
3562 shapeData = this.shapes[i];
3563 // if shape hasn't changed and trim properties haven't changed, cached previous path can be used
3564 if (!shapeData.shape._mdf && !this._mdf && !_isFirstFrame && this.m !== 2) {
3565 shapeData.shape.paths = shapeData.localShapeCollection;
3566 } else {
3567 shapePaths = shapeData.shape.paths;
3568 jLen = shapePaths._length;
3569 totalShapeLength = 0;
3570 if (!shapeData.shape._mdf && shapeData.pathsData.length) {
3571 totalShapeLength = shapeData.totalShapeLength;
3572 } else {
3573 pathsData = this.releasePathsData(shapeData.pathsData);
3574 for (j = 0; j < jLen; j += 1) {
3575 pathData = bez.getSegmentsLength(shapePaths.shapes[j]);
3576 pathsData.push(pathData);
3577 totalShapeLength += pathData.totalLength;
3578 }
3579 shapeData.totalShapeLength = totalShapeLength;
3580 shapeData.pathsData = pathsData;
3581 }
3582
3583 totalModifierLength += totalShapeLength;
3584 shapeData.shape._mdf = true;
3585 }
3586 }
3587 var shapeS = s, shapeE = e, addedLength = 0, edges;
3588 for (i = len - 1; i >= 0; i -= 1) {
3589 shapeData = this.shapes[i];
3590 if (shapeData.shape._mdf) {
3591 localShapeCollection = shapeData.localShapeCollection;
3592 localShapeCollection.releaseShapes();
3593 //if m === 2 means paths are trimmed individually so edges need to be found for this specific shape relative to whoel group
3594 if (this.m === 2 && len > 1) {
3595 edges = this.calculateShapeEdges(s, e, shapeData.totalShapeLength, addedLength, totalModifierLength);
3596 addedLength += shapeData.totalShapeLength;
3597 } else {
3598 edges = [[shapeS, shapeE]];
3599 }
3600 jLen = edges.length;
3601 for (j = 0; j < jLen; j += 1) {
3602 shapeS = edges[j][0];
3603 shapeE = edges[j][1];
3604 segments.length = 0;
3605 if (shapeE <= 1) {
3606 segments.push({
3607 s:shapeData.totalShapeLength * shapeS,
3608 e:shapeData.totalShapeLength * shapeE
3609 });
3610 } else if (shapeS >= 1) {
3611 segments.push({
3612 s:shapeData.totalShapeLength * (shapeS - 1),
3613 e:shapeData.totalShapeLength * (shapeE - 1)
3614 });
3615 } else {
3616 segments.push({
3617 s:shapeData.totalShapeLength * shapeS,
3618 e:shapeData.totalShapeLength
3619 });
3620 segments.push({
3621 s:0,
3622 e:shapeData.totalShapeLength * (shapeE - 1)
3623 });
3624 }
3625 var newShapesData = this.addShapes(shapeData,segments[0]);
3626 if (segments[0].s !== segments[0].e) {
3627 if (segments.length > 1) {
3628 var lastShapeInCollection = shapeData.shape.paths.shapes[shapeData.shape.paths._length - 1];
3629 if (lastShapeInCollection.c) {
3630 var lastShape = newShapesData.pop();
3631 this.addPaths(newShapesData, localShapeCollection);
3632 newShapesData = this.addShapes(shapeData, segments[1], lastShape);
3633 } else {
3634 this.addPaths(newShapesData, localShapeCollection);
3635 newShapesData = this.addShapes(shapeData, segments[1]);
3636 }
3637 }
3638 this.addPaths(newShapesData, localShapeCollection);
3639 }
3640
3641 }
3642 shapeData.shape.paths = localShapeCollection;
3643 }
3644 }
3645 } else if (this._mdf) {
3646 for (i = 0; i < len; i += 1) {
3647 //Releasign Trim Cached paths data when no trim applied in case shapes are modified inbetween.
3648 //Don't remove this even if it's losing cached info.
3649 this.shapes[i].pathsData.length = 0;
3650 this.shapes[i].shape._mdf = true;
3651 }
3652 }
3653};
3654
3655TrimModifier.prototype.addPaths = function(newPaths, localShapeCollection) {
3656 var i, len = newPaths.length;
3657 for (i = 0; i < len; i += 1) {
3658 localShapeCollection.addShape(newPaths[i]);
3659 }
3660};
3661
3662TrimModifier.prototype.addSegment = function(pt1, pt2, pt3, pt4, shapePath, pos, newShape) {
3663 shapePath.setXYAt(pt2[0], pt2[1], 'o', pos);
3664 shapePath.setXYAt(pt3[0], pt3[1], 'i', pos + 1);
3665 if(newShape){
3666 shapePath.setXYAt(pt1[0], pt1[1], 'v', pos);
3667 }
3668 shapePath.setXYAt(pt4[0], pt4[1], 'v', pos + 1);
3669};
3670
3671TrimModifier.prototype.addSegmentFromArray = function(points, shapePath, pos, newShape) {
3672 shapePath.setXYAt(points[1], points[5], 'o', pos);
3673 shapePath.setXYAt(points[2], points[6], 'i', pos + 1);
3674 if(newShape){
3675 shapePath.setXYAt(points[0], points[4], 'v', pos);
3676 }
3677 shapePath.setXYAt(points[3], points[7], 'v', pos + 1);
3678};
3679
3680TrimModifier.prototype.addShapes = function(shapeData, shapeSegment, shapePath) {
3681 var pathsData = shapeData.pathsData;
3682 var shapePaths = shapeData.shape.paths.shapes;
3683 var i, len = shapeData.shape.paths._length, j, jLen;
3684 var addedLength = 0;
3685 var currentLengthData,segmentCount;
3686 var lengths;
3687 var segment;
3688 var shapes = [];
3689 var initPos;
3690 var newShape = true;
3691 if (!shapePath) {
3692 shapePath = shape_pool.newElement();
3693 segmentCount = 0;
3694 initPos = 0;
3695 } else {
3696 segmentCount = shapePath._length;
3697 initPos = shapePath._length;
3698 }
3699 shapes.push(shapePath);
3700 for (i = 0; i < len; i += 1) {
3701 lengths = pathsData[i].lengths;
3702 shapePath.c = shapePaths[i].c;
3703 jLen = shapePaths[i].c ? lengths.length : lengths.length + 1;
3704 for (j = 1; j < jLen; j +=1) {
3705 currentLengthData = lengths[j-1];
3706 if (addedLength + currentLengthData.addedLength < shapeSegment.s) {
3707 addedLength += currentLengthData.addedLength;
3708 shapePath.c = false;
3709 } else if(addedLength > shapeSegment.e) {
3710 shapePath.c = false;
3711 break;
3712 } else {
3713 if (shapeSegment.s <= addedLength && shapeSegment.e >= addedLength + currentLengthData.addedLength) {
3714 this.addSegment(shapePaths[i].v[j - 1], shapePaths[i].o[j - 1], shapePaths[i].i[j], shapePaths[i].v[j], shapePath, segmentCount, newShape);
3715 newShape = false;
3716 } else {
3717 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]);
3718 this.addSegmentFromArray(segment, shapePath, segmentCount, newShape);
3719 // this.addSegment(segment.pt1, segment.pt3, segment.pt4, segment.pt2, shapePath, segmentCount, newShape);
3720 newShape = false;
3721 shapePath.c = false;
3722 }
3723 addedLength += currentLengthData.addedLength;
3724 segmentCount += 1;
3725 }
3726 }
3727 if (shapePaths[i].c && lengths.length) {
3728 currentLengthData = lengths[j - 1];
3729 if (addedLength <= shapeSegment.e) {
3730 var segmentLength = lengths[j - 1].addedLength;
3731 if (shapeSegment.s <= addedLength && shapeSegment.e >= addedLength + segmentLength) {
3732 this.addSegment(shapePaths[i].v[j - 1], shapePaths[i].o[j - 1], shapePaths[i].i[0], shapePaths[i].v[0], shapePath, segmentCount, newShape);
3733 newShape = false;
3734 } else {
3735 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]);
3736 this.addSegmentFromArray(segment, shapePath, segmentCount, newShape);
3737 // this.addSegment(segment.pt1, segment.pt3, segment.pt4, segment.pt2, shapePath, segmentCount, newShape);
3738 newShape = false;
3739 shapePath.c = false;
3740 }
3741 } else {
3742 shapePath.c = false;
3743 }
3744 addedLength += currentLengthData.addedLength;
3745 segmentCount += 1;
3746 }
3747 if (shapePath._length) {
3748 shapePath.setXYAt(shapePath.v[initPos][0], shapePath.v[initPos][1], 'i', initPos);
3749 shapePath.setXYAt(shapePath.v[shapePath._length - 1][0], shapePath.v[shapePath._length - 1][1],'o', shapePath._length - 1);
3750 }
3751 if (addedLength > shapeSegment.e) {
3752 break;
3753 }
3754 if (i < len - 1) {
3755 shapePath = shape_pool.newElement();
3756 newShape = true;
3757 shapes.push(shapePath);
3758 segmentCount = 0;
3759 }
3760 }
3761 return shapes;
3762};
3763
3764
3765ShapeModifiers.registerModifier('tm', TrimModifier);
3766function RoundCornersModifier(){}
3767extendPrototype([ShapeModifier],RoundCornersModifier);
3768RoundCornersModifier.prototype.initModifierProperties = function(elem,data){
3769 this.getValue = this.processKeys;
3770 this.rd = PropertyFactory.getProp(elem,data.r,0,null,this);
3771 this._isAnimated = !!this.rd.effectsSequence.length;
3772};
3773
3774RoundCornersModifier.prototype.processPath = function(path, round){
3775 var cloned_path = shape_pool.newElement();
3776 cloned_path.c = path.c;
3777 var i, len = path._length;
3778 var currentV,currentI,currentO,closerV, newV,newO,newI,distance,newPosPerc,index = 0;
3779 var vX,vY,oX,oY,iX,iY;
3780 for(i=0;i<len;i+=1){
3781 currentV = path.v[i];
3782 currentO = path.o[i];
3783 currentI = path.i[i];
3784 if(currentV[0]===currentO[0] && currentV[1]===currentO[1] && currentV[0]===currentI[0] && currentV[1]===currentI[1]){
3785 if((i===0 || i === len - 1) && !path.c){
3786 cloned_path.setTripleAt(currentV[0],currentV[1],currentO[0],currentO[1],currentI[0],currentI[1],index);
3787 /*cloned_path.v[index] = currentV;
3788 cloned_path.o[index] = currentO;
3789 cloned_path.i[index] = currentI;*/
3790 index += 1;
3791 } else {
3792 if(i===0){
3793 closerV = path.v[len-1];
3794 } else {
3795 closerV = path.v[i-1];
3796 }
3797 distance = Math.sqrt(Math.pow(currentV[0]-closerV[0],2)+Math.pow(currentV[1]-closerV[1],2));
3798 newPosPerc = distance ? Math.min(distance/2,round)/distance : 0;
3799 vX = iX = currentV[0]+(closerV[0]-currentV[0])*newPosPerc;
3800 vY = iY = currentV[1]-(currentV[1]-closerV[1])*newPosPerc;
3801 oX = vX-(vX-currentV[0])*roundCorner;
3802 oY = vY-(vY-currentV[1])*roundCorner;
3803 cloned_path.setTripleAt(vX,vY,oX,oY,iX,iY,index);
3804 index += 1;
3805
3806 if(i === len - 1){
3807 closerV = path.v[0];
3808 } else {
3809 closerV = path.v[i+1];
3810 }
3811 distance = Math.sqrt(Math.pow(currentV[0]-closerV[0],2)+Math.pow(currentV[1]-closerV[1],2));
3812 newPosPerc = distance ? Math.min(distance/2,round)/distance : 0;
3813 vX = oX = currentV[0]+(closerV[0]-currentV[0])*newPosPerc;
3814 vY = oY = currentV[1]+(closerV[1]-currentV[1])*newPosPerc;
3815 iX = vX-(vX-currentV[0])*roundCorner;
3816 iY = vY-(vY-currentV[1])*roundCorner;
3817 cloned_path.setTripleAt(vX,vY,oX,oY,iX,iY,index);
3818 index += 1;
3819 }
3820 } else {
3821 cloned_path.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);
3822 index += 1;
3823 }
3824 }
3825 return cloned_path;
3826};
3827
3828RoundCornersModifier.prototype.processShapes = function(_isFirstFrame){
3829 var shapePaths;
3830 var i, len = this.shapes.length;
3831 var j, jLen;
3832 var rd = this.rd.v;
3833
3834 if(rd !== 0){
3835 var shapeData, newPaths, localShapeCollection;
3836 for(i=0;i<len;i+=1){
3837 shapeData = this.shapes[i];
3838 newPaths = shapeData.shape.paths;
3839 localShapeCollection = shapeData.localShapeCollection;
3840 if(!(!shapeData.shape._mdf && !this._mdf && !_isFirstFrame)){
3841 localShapeCollection.releaseShapes();
3842 shapeData.shape._mdf = true;
3843 shapePaths = shapeData.shape.paths.shapes;
3844 jLen = shapeData.shape.paths._length;
3845 for(j=0;j<jLen;j+=1){
3846 localShapeCollection.addShape(this.processPath(shapePaths[j],rd));
3847 }
3848 }
3849 shapeData.shape.paths = shapeData.localShapeCollection;
3850 }
3851
3852 }
3853 if(!this.dynamicProperties.length){
3854 this._mdf = false;
3855 }
3856};
3857
3858ShapeModifiers.registerModifier('rd',RoundCornersModifier);
3859function PuckerAndBloatModifier(){}
3860extendPrototype([ShapeModifier],PuckerAndBloatModifier);
3861PuckerAndBloatModifier.prototype.initModifierProperties = function(elem,data){
3862 this.getValue = this.processKeys;
3863 this.amount = PropertyFactory.getProp(elem,data.a,0,null,this);
3864 this._isAnimated = !!this.amount.effectsSequence.length;
3865};
3866
3867PuckerAndBloatModifier.prototype.processPath = function(path, amount){
3868 var percent = amount / 100;
3869 var centerPoint = [0, 0];
3870 var pathLength = path._length, i = 0;
3871 for (i = 0; i < pathLength; i += 1) {
3872 centerPoint[0] += path.v[i][0];
3873 centerPoint[1] += path.v[i][1];
3874 }
3875 centerPoint[0] /= pathLength;
3876 centerPoint[1] /= pathLength;
3877 var cloned_path = shape_pool.newElement();
3878 cloned_path.c = path.c;
3879 var vX, vY, oX, oY, iX, iY;
3880 for(i = 0; i < pathLength; i += 1) {
3881 vX = path.v[i][0] + (centerPoint[0] - path.v[i][0]) * percent;
3882 vY = path.v[i][1] + (centerPoint[1] - path.v[i][1]) * percent;
3883 oX = path.o[i][0] + (centerPoint[0] - path.o[i][0]) * -percent;
3884 oY = path.o[i][1] + (centerPoint[1] - path.o[i][1]) * -percent;
3885 iX = path.i[i][0] + (centerPoint[0] - path.i[i][0]) * -percent;
3886 iY = path.i[i][1] + (centerPoint[1] - path.i[i][1]) * -percent;
3887 cloned_path.setTripleAt(vX, vY, oX, oY, iX, iY, i);
3888 }
3889 return cloned_path;
3890};
3891
3892PuckerAndBloatModifier.prototype.processShapes = function(_isFirstFrame){
3893 var shapePaths;
3894 var i, len = this.shapes.length;
3895 var j, jLen;
3896 var amount = this.amount.v;
3897
3898 if(amount !== 0){
3899 var shapeData, newPaths, localShapeCollection;
3900 for(i=0;i<len;i+=1){
3901 shapeData = this.shapes[i];
3902 newPaths = shapeData.shape.paths;
3903 localShapeCollection = shapeData.localShapeCollection;
3904 if(!(!shapeData.shape._mdf && !this._mdf && !_isFirstFrame)){
3905 localShapeCollection.releaseShapes();
3906 shapeData.shape._mdf = true;
3907 shapePaths = shapeData.shape.paths.shapes;
3908 jLen = shapeData.shape.paths._length;
3909 for(j=0;j<jLen;j+=1){
3910 localShapeCollection.addShape(this.processPath(shapePaths[j], amount));
3911 }
3912 }
3913 shapeData.shape.paths = shapeData.localShapeCollection;
3914 }
3915 }
3916 if(!this.dynamicProperties.length){
3917 this._mdf = false;
3918 }
3919};
3920ShapeModifiers.registerModifier('pb',PuckerAndBloatModifier);
3921function RepeaterModifier(){}
3922extendPrototype([ShapeModifier], RepeaterModifier);
3923
3924RepeaterModifier.prototype.initModifierProperties = function(elem,data){
3925 this.getValue = this.processKeys;
3926 this.c = PropertyFactory.getProp(elem,data.c,0,null,this);
3927 this.o = PropertyFactory.getProp(elem,data.o,0,null,this);
3928 this.tr = TransformPropertyFactory.getTransformProperty(elem,data.tr,this);
3929 this.so = PropertyFactory.getProp(elem,data.tr.so,0,0.01,this);
3930 this.eo = PropertyFactory.getProp(elem,data.tr.eo,0,0.01,this);
3931 this.data = data;
3932 if(!this.dynamicProperties.length){
3933 this.getValue(true);
3934 }
3935 this._isAnimated = !!this.dynamicProperties.length;
3936 this.pMatrix = new Matrix();
3937 this.rMatrix = new Matrix();
3938 this.sMatrix = new Matrix();
3939 this.tMatrix = new Matrix();
3940 this.matrix = new Matrix();
3941};
3942
3943RepeaterModifier.prototype.applyTransforms = function(pMatrix, rMatrix, sMatrix, transform, perc, inv){
3944 var dir = inv ? -1 : 1;
3945 var scaleX = transform.s.v[0] + (1 - transform.s.v[0]) * (1 - perc);
3946 var scaleY = transform.s.v[1] + (1 - transform.s.v[1]) * (1 - perc);
3947 pMatrix.translate(transform.p.v[0] * dir * perc, transform.p.v[1] * dir * perc, transform.p.v[2]);
3948 rMatrix.translate(-transform.a.v[0], -transform.a.v[1], transform.a.v[2]);
3949 rMatrix.rotate(-transform.r.v * dir * perc);
3950 rMatrix.translate(transform.a.v[0], transform.a.v[1], transform.a.v[2]);
3951 sMatrix.translate(-transform.a.v[0], -transform.a.v[1], transform.a.v[2]);
3952 sMatrix.scale(inv ? 1/scaleX : scaleX, inv ? 1/scaleY : scaleY);
3953 sMatrix.translate(transform.a.v[0], transform.a.v[1], transform.a.v[2]);
3954};
3955
3956RepeaterModifier.prototype.init = function(elem, arr, pos, elemsData) {
3957 this.elem = elem;
3958 this.arr = arr;
3959 this.pos = pos;
3960 this.elemsData = elemsData;
3961 this._currentCopies = 0;
3962 this._elements = [];
3963 this._groups = [];
3964 this.frameId = -1;
3965 this.initDynamicPropertyContainer(elem);
3966 this.initModifierProperties(elem,arr[pos]);
3967 var cont = 0;
3968 while(pos>0){
3969 pos -= 1;
3970 //this._elements.unshift(arr.splice(pos,1)[0]);
3971 this._elements.unshift(arr[pos]);
3972 cont += 1;
3973 }
3974 if(this.dynamicProperties.length){
3975 this.k = true;
3976 }else{
3977 this.getValue(true);
3978 }
3979};
3980
3981RepeaterModifier.prototype.resetElements = function(elements){
3982 var i, len = elements.length;
3983 for(i = 0; i < len; i += 1) {
3984 elements[i]._processed = false;
3985 if(elements[i].ty === 'gr'){
3986 this.resetElements(elements[i].it);
3987 }
3988 }
3989};
3990
3991RepeaterModifier.prototype.cloneElements = function(elements){
3992 var i, len = elements.length;
3993 var newElements = JSON.parse(JSON.stringify(elements));
3994 this.resetElements(newElements);
3995 return newElements;
3996};
3997
3998RepeaterModifier.prototype.changeGroupRender = function(elements, renderFlag) {
3999 var i, len = elements.length;
4000 for(i = 0; i < len; i += 1) {
4001 elements[i]._render = renderFlag;
4002 if(elements[i].ty === 'gr') {
4003 this.changeGroupRender(elements[i].it, renderFlag);
4004 }
4005 }
4006};
4007
4008RepeaterModifier.prototype.processShapes = function(_isFirstFrame) {
4009 var items, itemsTransform, i, dir, cont;
4010 if(this._mdf || _isFirstFrame){
4011 var copies = Math.ceil(this.c.v);
4012 if(this._groups.length < copies){
4013 while(this._groups.length < copies){
4014 var group = {
4015 it:this.cloneElements(this._elements),
4016 ty:'gr'
4017 };
4018 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"});
4019
4020 this.arr.splice(0,0,group);
4021 this._groups.splice(0,0,group);
4022 this._currentCopies += 1;
4023 }
4024 this.elem.reloadShapes();
4025 }
4026 cont = 0;
4027 var renderFlag;
4028 for(i = 0; i <= this._groups.length - 1; i += 1){
4029 renderFlag = cont < copies;
4030 this._groups[i]._render = renderFlag;
4031 this.changeGroupRender(this._groups[i].it, renderFlag);
4032 cont += 1;
4033 }
4034
4035 this._currentCopies = copies;
4036 ////
4037
4038 var offset = this.o.v;
4039 var offsetModulo = offset%1;
4040 var roundOffset = offset > 0 ? Math.floor(offset) : Math.ceil(offset);
4041 var k;
4042 var tMat = this.tr.v.props;
4043 var pProps = this.pMatrix.props;
4044 var rProps = this.rMatrix.props;
4045 var sProps = this.sMatrix.props;
4046 this.pMatrix.reset();
4047 this.rMatrix.reset();
4048 this.sMatrix.reset();
4049 this.tMatrix.reset();
4050 this.matrix.reset();
4051 var iteration = 0;
4052
4053 if(offset > 0) {
4054 while(iteration<roundOffset){
4055 this.applyTransforms(this.pMatrix, this.rMatrix, this.sMatrix, this.tr, 1, false);
4056 iteration += 1;
4057 }
4058 if(offsetModulo){
4059 this.applyTransforms(this.pMatrix, this.rMatrix, this.sMatrix, this.tr, offsetModulo, false);
4060 iteration += offsetModulo;
4061 }
4062 } else if(offset < 0) {
4063 while(iteration>roundOffset){
4064 this.applyTransforms(this.pMatrix, this.rMatrix, this.sMatrix, this.tr, 1, true);
4065 iteration -= 1;
4066 }
4067 if(offsetModulo){
4068 this.applyTransforms(this.pMatrix, this.rMatrix, this.sMatrix, this.tr, - offsetModulo, true);
4069 iteration -= offsetModulo;
4070 }
4071 }
4072 i = this.data.m === 1 ? 0 : this._currentCopies - 1;
4073 dir = this.data.m === 1 ? 1 : -1;
4074 cont = this._currentCopies;
4075 var j, jLen;
4076 while(cont){
4077 items = this.elemsData[i].it;
4078 itemsTransform = items[items.length - 1].transform.mProps.v.props;
4079 jLen = itemsTransform.length;
4080 items[items.length - 1].transform.mProps._mdf = true;
4081 items[items.length - 1].transform.op._mdf = true;
4082 items[items.length - 1].transform.op.v = this.so.v + (this.eo.v - this.so.v) * (i / (this._currentCopies - 1));
4083 if(iteration !== 0){
4084 if((i !== 0 && dir === 1) || (i !== this._currentCopies - 1 && dir === -1)){
4085 this.applyTransforms(this.pMatrix, this.rMatrix, this.sMatrix, this.tr, 1, false);
4086 }
4087 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]);
4088 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]);
4089 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]);
4090
4091 for(j=0;j<jLen;j+=1) {
4092 itemsTransform[j] = this.matrix.props[j];
4093 }
4094 this.matrix.reset();
4095 } else {
4096 this.matrix.reset();
4097 for(j=0;j<jLen;j+=1) {
4098 itemsTransform[j] = this.matrix.props[j];
4099 }
4100 }
4101 iteration += 1;
4102 cont -= 1;
4103 i += dir;
4104 }
4105 } else {
4106 cont = this._currentCopies;
4107 i = 0;
4108 dir = 1;
4109 while(cont){
4110 items = this.elemsData[i].it;
4111 itemsTransform = items[items.length - 1].transform.mProps.v.props;
4112 items[items.length - 1].transform.mProps._mdf = false;
4113 items[items.length - 1].transform.op._mdf = false;
4114 cont -= 1;
4115 i += dir;
4116 }
4117 }
4118};
4119
4120RepeaterModifier.prototype.addShape = function(){};
4121
4122ShapeModifiers.registerModifier('rp',RepeaterModifier);
4123function ShapeCollection(){
4124 this._length = 0;
4125 this._maxLength = 4;
4126 this.shapes = createSizedArray(this._maxLength);
4127}
4128
4129ShapeCollection.prototype.addShape = function(shapeData){
4130 if(this._length === this._maxLength){
4131 this.shapes = this.shapes.concat(createSizedArray(this._maxLength));
4132 this._maxLength *= 2;
4133 }
4134 this.shapes[this._length] = shapeData;
4135 this._length += 1;
4136};
4137
4138ShapeCollection.prototype.releaseShapes = function(){
4139 var i;
4140 for(i = 0; i < this._length; i += 1) {
4141 shape_pool.release(this.shapes[i]);
4142 }
4143 this._length = 0;
4144};
4145function DashProperty(elem, data, renderer, container) {
4146 this.elem = elem;
4147 this.frameId = -1;
4148 this.dataProps = createSizedArray(data.length);
4149 this.renderer = renderer;
4150 this.k = false;
4151 this.dashStr = '';
4152 this.dashArray = createTypedArray('float32', data.length ? data.length - 1 : 0);
4153 this.dashoffset = createTypedArray('float32', 1);
4154 this.initDynamicPropertyContainer(container);
4155 var i, len = data.length || 0, prop;
4156 for(i = 0; i < len; i += 1) {
4157 prop = PropertyFactory.getProp(elem,data[i].v,0, 0, this);
4158 this.k = prop.k || this.k;
4159 this.dataProps[i] = {n:data[i].n,p:prop};
4160 }
4161 if(!this.k){
4162 this.getValue(true);
4163 }
4164 this._isAnimated = this.k;
4165}
4166
4167DashProperty.prototype.getValue = function(forceRender) {
4168 if(this.elem.globalData.frameId === this.frameId && !forceRender){
4169 return;
4170 }
4171 this.frameId = this.elem.globalData.frameId;
4172 this.iterateDynamicProperties();
4173 this._mdf = this._mdf || forceRender;
4174 if (this._mdf) {
4175 var i = 0, len = this.dataProps.length;
4176 if(this.renderer === 'svg') {
4177 this.dashStr = '';
4178 }
4179 for(i=0;i<len;i+=1){
4180 if(this.dataProps[i].n != 'o'){
4181 if(this.renderer === 'svg') {
4182 this.dashStr += ' ' + this.dataProps[i].p.v;
4183 }else{
4184 this.dashArray[i] = this.dataProps[i].p.v;
4185 }
4186 }else{
4187 this.dashoffset[0] = this.dataProps[i].p.v;
4188 }
4189 }
4190 }
4191};
4192extendPrototype([DynamicPropertyContainer], DashProperty);
4193function GradientProperty(elem,data,container){
4194 this.data = data;
4195 this.c = createTypedArray('uint8c', data.p*4);
4196 var cLength = data.k.k[0].s ? (data.k.k[0].s.length - data.p*4) : data.k.k.length - data.p*4;
4197 this.o = createTypedArray('float32', cLength);
4198 this._cmdf = false;
4199 this._omdf = false;
4200 this._collapsable = this.checkCollapsable();
4201 this._hasOpacity = cLength;
4202 this.initDynamicPropertyContainer(container);
4203 this.prop = PropertyFactory.getProp(elem,data.k,1,null,this);
4204 this.k = this.prop.k;
4205 this.getValue(true);
4206}
4207
4208GradientProperty.prototype.comparePoints = function(values, points) {
4209 var i = 0, len = this.o.length/2, diff;
4210 while(i < len) {
4211 diff = Math.abs(values[i*4] - values[points*4 + i*2]);
4212 if(diff > 0.01){
4213 return false;
4214 }
4215 i += 1;
4216 }
4217 return true;
4218};
4219
4220GradientProperty.prototype.checkCollapsable = function() {
4221 if (this.o.length/2 !== this.c.length/4) {
4222 return false;
4223 }
4224 if (this.data.k.k[0].s) {
4225 var i = 0, len = this.data.k.k.length;
4226 while (i < len) {
4227 if (!this.comparePoints(this.data.k.k[i].s, this.data.p)) {
4228 return false;
4229 }
4230 i += 1;
4231 }
4232 } else if(!this.comparePoints(this.data.k.k, this.data.p)) {
4233 return false;
4234 }
4235 return true;
4236};
4237
4238GradientProperty.prototype.getValue = function(forceRender){
4239 this.prop.getValue();
4240 this._mdf = false;
4241 this._cmdf = false;
4242 this._omdf = false;
4243 if(this.prop._mdf || forceRender){
4244 var i, len = this.data.p*4;
4245 var mult, val;
4246 for(i=0;i<len;i+=1){
4247 mult = i%4 === 0 ? 100 : 255;
4248 val = Math.round(this.prop.v[i]*mult);
4249 if(this.c[i] !== val){
4250 this.c[i] = val;
4251 this._cmdf = !forceRender;
4252 }
4253 }
4254 if(this.o.length){
4255 len = this.prop.v.length;
4256 for(i=this.data.p*4;i<len;i+=1){
4257 mult = i%2 === 0 ? 100 : 1;
4258 val = i%2 === 0 ? Math.round(this.prop.v[i]*100):this.prop.v[i];
4259 if(this.o[i-this.data.p*4] !== val){
4260 this.o[i-this.data.p*4] = val;
4261 this._omdf = !forceRender;
4262 }
4263 }
4264 }
4265 this._mdf = !forceRender;
4266 }
4267};
4268
4269extendPrototype([DynamicPropertyContainer], GradientProperty);
4270var buildShapeString = function(pathNodes, length, closed, mat) {
4271 if(length === 0) {
4272 return '';
4273 }
4274 var _o = pathNodes.o;
4275 var _i = pathNodes.i;
4276 var _v = pathNodes.v;
4277 var i, shapeString = " M" + mat.applyToPointStringified(_v[0][0], _v[0][1]);
4278 for(i = 1; i < length; i += 1) {
4279 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]);
4280 }
4281 if (closed && length) {
4282 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]);
4283 shapeString += 'z';
4284 }
4285 return shapeString;
4286}
4287var audioControllerFactory = (function() {
4288
4289 function AudioController(audioFactory) {
4290 this.audios = [];
4291 this.audioFactory = audioFactory;
4292 this._volume = 1;
4293 this._isMuted = false;
4294 }
4295
4296 AudioController.prototype = {
4297 addAudio: function(audio) {
4298 this.audios.push(audio);
4299 },
4300 pause: function() {
4301 var i, len = this.audios.length;
4302 for(i = 0; i < len; i += 1) {
4303 this.audios[i].pause()
4304 }
4305 },
4306 resume: function() {
4307 var i, len = this.audios.length;
4308 for(i = 0; i < len; i += 1) {
4309 this.audios[i].resume()
4310 }
4311 },
4312 setRate: function(rateValue) {
4313 var i, len = this.audios.length;
4314 for(i = 0; i < len; i += 1) {
4315 this.audios[i].setRate(rateValue)
4316 }
4317 },
4318 createAudio: function(assetPath) {
4319 if (this.audioFactory) {
4320 return this.audioFactory(assetPath);
4321 } else if (Howl) {
4322 return new Howl({
4323 src: [assetPath]
4324 })
4325 } else {
4326 return {
4327 isPlaying: false,
4328 play: function(){this.isPlaying = true},
4329 seek: function(){this.isPlaying = false},
4330 playing: function(){},
4331 rate: function(){},
4332 setVolume: function(){},
4333 }
4334 }
4335 },
4336 setAudioFactory: function(audioFactory) {
4337 this.audioFactory = audioFactory;
4338 },
4339 setVolume: function(value) {
4340 this._volume = value;
4341 this._updateVolume();
4342 },
4343 mute: function() {
4344 this._isMuted = true;
4345 this._updateVolume();
4346 },
4347 unmute: function() {
4348 this._isMuted = false;
4349 this._updateVolume();
4350 },
4351 getVolume: function(value) {
4352 return this._volume;
4353 },
4354 _updateVolume: function() {
4355 var i, len = this.audios.length;
4356 for(i = 0; i < len; i += 1) {
4357 this.audios[i].volume(this._volume * (this._isMuted ? 0 : 1))
4358 }
4359 }
4360 }
4361
4362 return function() {
4363 return new AudioController()
4364 }
4365
4366}())
4367var ImagePreloader = (function(){
4368
4369 var proxyImage = (function(){
4370 var canvas = createTag('canvas');
4371 canvas.width = 1;
4372 canvas.height = 1;
4373 var ctx = canvas.getContext('2d');
4374 ctx.fillStyle = 'rgba(0,0,0,0)';
4375 ctx.fillRect(0, 0, 1, 1);
4376 return canvas;
4377 }())
4378
4379 function imageLoaded(){
4380 this.loadedAssets += 1;
4381 if(this.loadedAssets === this.totalImages){
4382 if(this.imagesLoadedCb) {
4383 this.imagesLoadedCb(null);
4384 }
4385 }
4386 }
4387
4388 function getAssetsPath(assetData, assetsPath, original_path) {
4389 var path = '';
4390 if (assetData.e) {
4391 path = assetData.p;
4392 } else if(assetsPath) {
4393 var imagePath = assetData.p;
4394 if (imagePath.indexOf('images/') !== -1) {
4395 imagePath = imagePath.split('/')[1];
4396 }
4397 path = assetsPath + imagePath;
4398 } else {
4399 path = original_path;
4400 path += assetData.u ? assetData.u : '';
4401 path += assetData.p;
4402 }
4403 return path;
4404 }
4405
4406 function createImageData(assetData) {
4407 var path = getAssetsPath(assetData, this.assetsPath, this.path);
4408 var img = createNS('image');
4409 img.addEventListener('load', this._imageLoaded, false);
4410 img.addEventListener('error', function() {
4411 ob.img = proxyImage;
4412 this._imageLoaded();
4413 }.bind(this), false);
4414 img.setAttributeNS('http://www.w3.org/1999/xlink','href', path);
4415 var ob = {
4416 img: img,
4417 assetData: assetData
4418 }
4419 return ob;
4420 }
4421
4422 function createImgData(assetData) {
4423 var path = getAssetsPath(assetData, this.assetsPath, this.path);
4424 var img = createTag('img');
4425 img.crossOrigin = 'anonymous';
4426 img.addEventListener('load', this._imageLoaded, false);
4427 img.addEventListener('error', function() {
4428 ob.img = proxyImage;
4429 this._imageLoaded();
4430 }.bind(this), false);
4431 img.src = path;
4432 var ob = {
4433 img: img,
4434 assetData: assetData
4435 }
4436 return ob;
4437 }
4438
4439 function loadAssets(assets, cb){
4440 this.imagesLoadedCb = cb;
4441 var i, len = assets.length;
4442 for (i = 0; i < len; i += 1) {
4443 if(!assets[i].layers){
4444 this.totalImages += 1;
4445 this.images.push(this._createImageData(assets[i]));
4446 }
4447 }
4448 }
4449
4450 function setPath(path){
4451 this.path = path || '';
4452 }
4453
4454 function setAssetsPath(path){
4455 this.assetsPath = path || '';
4456 }
4457
4458 function getImage(assetData) {
4459 var i = 0, len = this.images.length;
4460 while (i < len) {
4461 if (this.images[i].assetData === assetData) {
4462 return this.images[i].img;
4463 }
4464 i += 1;
4465 }
4466 }
4467
4468 function destroy() {
4469 this.imagesLoadedCb = null;
4470 this.images.length = 0;
4471 }
4472
4473 function loaded() {
4474 return this.totalImages === this.loadedAssets;
4475 }
4476
4477 function setCacheType(type) {
4478 if (type === 'svg') {
4479 this._createImageData = this.createImageData.bind(this);
4480 } else {
4481 this._createImageData = this.createImgData.bind(this);
4482 }
4483 }
4484
4485 function ImagePreloader(type){
4486 this._imageLoaded = imageLoaded.bind(this);
4487 this.assetsPath = '';
4488 this.path = '';
4489 this.totalImages = 0;
4490 this.loadedAssets = 0;
4491 this.imagesLoadedCb = null;
4492 this.images = [];
4493 };
4494
4495 ImagePreloader.prototype = {
4496 loadAssets: loadAssets,
4497 setAssetsPath: setAssetsPath,
4498 setPath: setPath,
4499 loaded: loaded,
4500 destroy: destroy,
4501 getImage: getImage,
4502 createImgData: createImgData,
4503 createImageData: createImageData,
4504 imageLoaded: imageLoaded,
4505 setCacheType: setCacheType,
4506 }
4507
4508 return ImagePreloader;
4509}());
4510var featureSupport = (function(){
4511 var ob = {
4512 maskType: true
4513 };
4514 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)) {
4515 ob.maskType = false;
4516 }
4517 return ob;
4518}());
4519var filtersFactory = (function(){
4520 var ob = {};
4521 ob.createFilter = createFilter;
4522 ob.createAlphaToLuminanceFilter = createAlphaToLuminanceFilter;
4523
4524 function createFilter(filId){
4525 var fil = createNS('filter');
4526 fil.setAttribute('id',filId);
4527 fil.setAttribute('filterUnits','objectBoundingBox');
4528 fil.setAttribute('x','0%');
4529 fil.setAttribute('y','0%');
4530 fil.setAttribute('width','100%');
4531 fil.setAttribute('height','100%');
4532 return fil;
4533 }
4534
4535 function createAlphaToLuminanceFilter(){
4536 var feColorMatrix = createNS('feColorMatrix');
4537 feColorMatrix.setAttribute('type','matrix');
4538 feColorMatrix.setAttribute('color-interpolation-filters','sRGB');
4539 feColorMatrix.setAttribute('values','0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 1');
4540 return feColorMatrix;
4541 }
4542
4543 return ob;
4544}());
4545var assetLoader = (function(){
4546
4547 function formatResponse(xhr) {
4548 if(xhr.response && typeof xhr.response === 'object') {
4549 return xhr.response;
4550 } else if(xhr.response && typeof xhr.response === 'string') {
4551 return JSON.parse(xhr.response);
4552 } else if(xhr.responseText) {
4553 return JSON.parse(xhr.responseText);
4554 }
4555 }
4556
4557 function loadAsset(path, callback, errorCallback) {
4558 var response;
4559 var xhr = new XMLHttpRequest();
4560 xhr.open('GET', path, true);
4561 // set responseType after calling open or IE will break.
4562 try {
4563 // This crashes on Android WebView prior to KitKat
4564 xhr.responseType = "json";
4565 } catch (err) {}
4566 xhr.send();
4567 xhr.onreadystatechange = function () {
4568 if (xhr.readyState == 4) {
4569 if(xhr.status == 200){
4570 response = formatResponse(xhr);
4571 callback(response);
4572 }else{
4573 try{
4574 response = formatResponse(xhr);
4575 callback(response);
4576 }catch(err){
4577 if(errorCallback) {
4578 errorCallback(err);
4579 }
4580 }
4581 }
4582 }
4583 };
4584 }
4585 return {
4586 load: loadAsset
4587 }
4588}())
4589
4590function TextAnimatorProperty(textData, renderType, elem){
4591 this._isFirstFrame = true;
4592 this._hasMaskedPath = false;
4593 this._frameId = -1;
4594 this._textData = textData;
4595 this._renderType = renderType;
4596 this._elem = elem;
4597 this._animatorsData = createSizedArray(this._textData.a.length);
4598 this._pathData = {};
4599 this._moreOptions = {
4600 alignment: {}
4601 };
4602 this.renderedLetters = [];
4603 this.lettersChangedFlag = false;
4604 this.initDynamicPropertyContainer(elem);
4605
4606}
4607
4608TextAnimatorProperty.prototype.searchProperties = function(){
4609 var i, len = this._textData.a.length, animatorProps;
4610 var getProp = PropertyFactory.getProp;
4611 for(i=0;i<len;i+=1){
4612 animatorProps = this._textData.a[i];
4613 this._animatorsData[i] = new TextAnimatorDataProperty(this._elem, animatorProps, this);
4614 }
4615 if(this._textData.p && 'm' in this._textData.p){
4616 this._pathData = {
4617 f: getProp(this._elem,this._textData.p.f,0,0,this),
4618 l: getProp(this._elem,this._textData.p.l,0,0,this),
4619 r: this._textData.p.r,
4620 m: this._elem.maskManager.getMaskProperty(this._textData.p.m)
4621 };
4622 this._hasMaskedPath = true;
4623 } else {
4624 this._hasMaskedPath = false;
4625 }
4626 this._moreOptions.alignment = getProp(this._elem,this._textData.m.a,1,0,this);
4627};
4628
4629TextAnimatorProperty.prototype.getMeasures = function(documentData, lettersChangedFlag){
4630 this.lettersChangedFlag = lettersChangedFlag;
4631 if(!this._mdf && !this._isFirstFrame && !lettersChangedFlag && (!this._hasMaskedPath || !this._pathData.m._mdf)) {
4632 return;
4633 }
4634 this._isFirstFrame = false;
4635 var alignment = this._moreOptions.alignment.v;
4636 var animators = this._animatorsData;
4637 var textData = this._textData;
4638 var matrixHelper = this.mHelper;
4639 var renderType = this._renderType;
4640 var renderedLettersCount = this.renderedLetters.length;
4641 var data = this.data;
4642 var xPos,yPos;
4643 var i, len;
4644 var letters = documentData.l, pathInfo, currentLength, currentPoint, segmentLength, flag, pointInd, segmentInd, prevPoint, points, segments, partialLength, totalLength, perc, tanAngle, mask;
4645 if(this._hasMaskedPath) {
4646 mask = this._pathData.m;
4647 if(!this._pathData.n || this._pathData._mdf){
4648 var paths = mask.v;
4649 if(this._pathData.r){
4650 paths = paths.reverse();
4651 }
4652 // TODO: release bezier data cached from previous pathInfo: this._pathData.pi
4653 pathInfo = {
4654 tLength: 0,
4655 segments: []
4656 };
4657 len = paths._length - 1;
4658 var bezierData;
4659 totalLength = 0;
4660 for (i = 0; i < len; i += 1) {
4661 bezierData = bez.buildBezierData(paths.v[i]
4662 , paths.v[i + 1]
4663 , [paths.o[i][0] - paths.v[i][0], paths.o[i][1] - paths.v[i][1]]
4664 , [paths.i[i + 1][0] - paths.v[i + 1][0], paths.i[i + 1][1] - paths.v[i + 1][1]]);
4665 pathInfo.tLength += bezierData.segmentLength;
4666 pathInfo.segments.push(bezierData);
4667 totalLength += bezierData.segmentLength;
4668 }
4669 i = len;
4670 if (mask.v.c) {
4671 bezierData = bez.buildBezierData(paths.v[i]
4672 , paths.v[0]
4673 , [paths.o[i][0] - paths.v[i][0], paths.o[i][1] - paths.v[i][1]]
4674 , [paths.i[0][0] - paths.v[0][0], paths.i[0][1] - paths.v[0][1]]);
4675 pathInfo.tLength += bezierData.segmentLength;
4676 pathInfo.segments.push(bezierData);
4677 totalLength += bezierData.segmentLength;
4678 }
4679 this._pathData.pi = pathInfo;
4680 }
4681 pathInfo = this._pathData.pi;
4682
4683 currentLength = this._pathData.f.v;
4684 segmentInd = 0;
4685 pointInd = 1;
4686 segmentLength = 0;
4687 flag = true;
4688 segments = pathInfo.segments;
4689 if (currentLength < 0 && mask.v.c) {
4690 if (pathInfo.tLength < Math.abs(currentLength)) {
4691 currentLength = -Math.abs(currentLength) % pathInfo.tLength;
4692 }
4693 segmentInd = segments.length - 1;
4694 points = segments[segmentInd].points;
4695 pointInd = points.length - 1;
4696 while (currentLength < 0) {
4697 currentLength += points[pointInd].partialLength;
4698 pointInd -= 1;
4699 if (pointInd < 0) {
4700 segmentInd -= 1;
4701 points = segments[segmentInd].points;
4702 pointInd = points.length - 1;
4703 }
4704 }
4705
4706 }
4707 points = segments[segmentInd].points;
4708 prevPoint = points[pointInd - 1];
4709 currentPoint = points[pointInd];
4710 partialLength = currentPoint.partialLength;
4711 }
4712
4713
4714 len = letters.length;
4715 xPos = 0;
4716 yPos = 0;
4717 var yOff = documentData.finalSize * 1.2 * 0.714;
4718 var firstLine = true;
4719 var animatorProps, animatorSelector;
4720 var j, jLen;
4721 var letterValue;
4722
4723 jLen = animators.length;
4724 var lastLetter;
4725
4726 var mult, ind = -1, offf, xPathPos, yPathPos;
4727 var initPathPos = currentLength,initSegmentInd = segmentInd, initPointInd = pointInd, currentLine = -1;
4728 var elemOpacity;
4729 var sc,sw,fc,k;
4730 var lineLength = 0;
4731 var letterSw, letterSc, letterFc, letterM = '', letterP = this.defaultPropsArray, letterO;
4732
4733 //
4734 if(documentData.j === 2 || documentData.j === 1) {
4735 var animatorJustifyOffset = 0;
4736 var animatorFirstCharOffset = 0;
4737 var justifyOffsetMult = documentData.j === 2 ? -0.5 : -1;
4738 var lastIndex = 0;
4739 var isNewLine = true;
4740
4741 for (i = 0; i < len; i += 1) {
4742 if (letters[i].n) {
4743 if(animatorJustifyOffset) {
4744 animatorJustifyOffset += animatorFirstCharOffset;
4745 }
4746 while (lastIndex < i) {
4747 letters[lastIndex].animatorJustifyOffset = animatorJustifyOffset;
4748 lastIndex += 1;
4749 }
4750 animatorJustifyOffset = 0;
4751 isNewLine = true;
4752 } else {
4753 for (j = 0; j < jLen; j += 1) {
4754 animatorProps = animators[j].a;
4755 if (animatorProps.t.propType) {
4756 if (isNewLine && documentData.j === 2) {
4757 animatorFirstCharOffset += animatorProps.t.v * justifyOffsetMult;
4758 }
4759 animatorSelector = animators[j].s;
4760 mult = animatorSelector.getMult(letters[i].anIndexes[j], textData.a[j].s.totalChars);
4761 if (mult.length) {
4762 animatorJustifyOffset += animatorProps.t.v*mult[0] * justifyOffsetMult;
4763 } else {
4764 animatorJustifyOffset += animatorProps.t.v*mult * justifyOffsetMult;
4765 }
4766 }
4767 }
4768 isNewLine = false;
4769 }
4770 }
4771 if(animatorJustifyOffset) {
4772 animatorJustifyOffset += animatorFirstCharOffset;
4773 }
4774 while(lastIndex < i) {
4775 letters[lastIndex].animatorJustifyOffset = animatorJustifyOffset;
4776 lastIndex += 1;
4777 }
4778 }
4779 //
4780
4781 for( i = 0; i < len; i += 1) {
4782
4783 matrixHelper.reset();
4784 elemOpacity = 1;
4785 if(letters[i].n) {
4786 xPos = 0;
4787 yPos += documentData.yOffset;
4788 yPos += firstLine ? 1 : 0;
4789 currentLength = initPathPos ;
4790 firstLine = false;
4791 lineLength = 0;
4792 if(this._hasMaskedPath) {
4793 segmentInd = initSegmentInd;
4794 pointInd = initPointInd;
4795 points = segments[segmentInd].points;
4796 prevPoint = points[pointInd - 1];
4797 currentPoint = points[pointInd];
4798 partialLength = currentPoint.partialLength;
4799 segmentLength = 0;
4800 }
4801 letterO = letterSw = letterFc = letterM = '';
4802 letterP = this.defaultPropsArray;
4803 }else{
4804 if(this._hasMaskedPath) {
4805 if(currentLine !== letters[i].line){
4806 switch(documentData.j){
4807 case 1:
4808 currentLength += totalLength - documentData.lineWidths[letters[i].line];
4809 break;
4810 case 2:
4811 currentLength += (totalLength - documentData.lineWidths[letters[i].line])/2;
4812 break;
4813 }
4814 currentLine = letters[i].line;
4815 }
4816 if (ind !== letters[i].ind) {
4817 if (letters[ind]) {
4818 currentLength += letters[ind].extra;
4819 }
4820 currentLength += letters[i].an / 2;
4821 ind = letters[i].ind;
4822 }
4823 currentLength += alignment[0] * letters[i].an / 200;
4824 var animatorOffset = 0;
4825 for (j = 0; j < jLen; j += 1) {
4826 animatorProps = animators[j].a;
4827 if (animatorProps.p.propType) {
4828 animatorSelector = animators[j].s;
4829 mult = animatorSelector.getMult(letters[i].anIndexes[j],textData.a[j].s.totalChars);
4830 if(mult.length){
4831 animatorOffset += animatorProps.p.v[0] * mult[0];
4832 } else{
4833 animatorOffset += animatorProps.p.v[0] * mult;
4834 }
4835
4836 }
4837 if (animatorProps.a.propType) {
4838 animatorSelector = animators[j].s;
4839 mult = animatorSelector.getMult(letters[i].anIndexes[j],textData.a[j].s.totalChars);
4840 if(mult.length){
4841 animatorOffset += animatorProps.a.v[0] * mult[0];
4842 } else{
4843 animatorOffset += animatorProps.a.v[0] * mult;
4844 }
4845
4846 }
4847 }
4848 flag = true;
4849 while (flag) {
4850 if (segmentLength + partialLength >= currentLength + animatorOffset || !points) {
4851 perc = (currentLength + animatorOffset - segmentLength) / currentPoint.partialLength;
4852 xPathPos = prevPoint.point[0] + (currentPoint.point[0] - prevPoint.point[0]) * perc;
4853 yPathPos = prevPoint.point[1] + (currentPoint.point[1] - prevPoint.point[1]) * perc;
4854 matrixHelper.translate(-alignment[0]*letters[i].an/200, -(alignment[1] * yOff / 100));
4855 flag = false;
4856 } else if (points) {
4857 segmentLength += currentPoint.partialLength;
4858 pointInd += 1;
4859 if (pointInd >= points.length) {
4860 pointInd = 0;
4861 segmentInd += 1;
4862 if (!segments[segmentInd]) {
4863 if (mask.v.c) {
4864 pointInd = 0;
4865 segmentInd = 0;
4866 points = segments[segmentInd].points;
4867 } else {
4868 segmentLength -= currentPoint.partialLength;
4869 points = null;
4870 }
4871 } else {
4872 points = segments[segmentInd].points;
4873 }
4874 }
4875 if (points) {
4876 prevPoint = currentPoint;
4877 currentPoint = points[pointInd];
4878 partialLength = currentPoint.partialLength;
4879 }
4880 }
4881 }
4882 offf = letters[i].an / 2 - letters[i].add;
4883 matrixHelper.translate(-offf, 0, 0);
4884 } else {
4885 offf = letters[i].an/2 - letters[i].add;
4886 matrixHelper.translate(-offf,0,0);
4887
4888 // Grouping alignment
4889 matrixHelper.translate(-alignment[0]*letters[i].an/200, -alignment[1]*yOff/100, 0);
4890 }
4891
4892 lineLength += letters[i].l/2;
4893 for(j=0;j<jLen;j+=1){
4894 animatorProps = animators[j].a;
4895 if (animatorProps.t.propType) {
4896 animatorSelector = animators[j].s;
4897 mult = animatorSelector.getMult(letters[i].anIndexes[j],textData.a[j].s.totalChars);
4898 //This condition is to prevent applying tracking to first character in each line. Might be better to use a boolean "isNewLine"
4899 if(xPos !== 0 || documentData.j !== 0) {
4900 if(this._hasMaskedPath) {
4901 if(mult.length) {
4902 currentLength += animatorProps.t.v*mult[0];
4903 } else {
4904 currentLength += animatorProps.t.v*mult;
4905 }
4906 }else{
4907 if(mult.length) {
4908 xPos += animatorProps.t.v*mult[0];
4909 } else {
4910 xPos += animatorProps.t.v*mult;
4911 }
4912 }
4913 }
4914 }
4915 }
4916 lineLength += letters[i].l/2;
4917 if(documentData.strokeWidthAnim) {
4918 sw = documentData.sw || 0;
4919 }
4920 if(documentData.strokeColorAnim) {
4921 if(documentData.sc){
4922 sc = [documentData.sc[0], documentData.sc[1], documentData.sc[2]];
4923 }else{
4924 sc = [0,0,0];
4925 }
4926 }
4927 if(documentData.fillColorAnim && documentData.fc) {
4928 fc = [documentData.fc[0], documentData.fc[1], documentData.fc[2]];
4929 }
4930 for(j=0;j<jLen;j+=1){
4931 animatorProps = animators[j].a;
4932 if (animatorProps.a.propType) {
4933 animatorSelector = animators[j].s;
4934 mult = animatorSelector.getMult(letters[i].anIndexes[j],textData.a[j].s.totalChars);
4935
4936 if(mult.length){
4937 matrixHelper.translate(-animatorProps.a.v[0]*mult[0], -animatorProps.a.v[1]*mult[1], animatorProps.a.v[2]*mult[2]);
4938 } else {
4939 matrixHelper.translate(-animatorProps.a.v[0]*mult, -animatorProps.a.v[1]*mult, animatorProps.a.v[2]*mult);
4940 }
4941 }
4942 }
4943 for(j=0;j<jLen;j+=1){
4944 animatorProps = animators[j].a;
4945 if (animatorProps.s.propType) {
4946 animatorSelector = animators[j].s;
4947 mult = animatorSelector.getMult(letters[i].anIndexes[j],textData.a[j].s.totalChars);
4948 if(mult.length){
4949 matrixHelper.scale(1+((animatorProps.s.v[0]-1)*mult[0]),1+((animatorProps.s.v[1]-1)*mult[1]),1);
4950 } else {
4951 matrixHelper.scale(1+((animatorProps.s.v[0]-1)*mult),1+((animatorProps.s.v[1]-1)*mult),1);
4952 }
4953 }
4954 }
4955 for(j=0;j<jLen;j+=1) {
4956 animatorProps = animators[j].a;
4957 animatorSelector = animators[j].s;
4958 mult = animatorSelector.getMult(letters[i].anIndexes[j],textData.a[j].s.totalChars);
4959 if (animatorProps.sk.propType) {
4960 if(mult.length) {
4961 matrixHelper.skewFromAxis(-animatorProps.sk.v * mult[0], animatorProps.sa.v * mult[1]);
4962 } else {
4963 matrixHelper.skewFromAxis(-animatorProps.sk.v * mult, animatorProps.sa.v * mult);
4964 }
4965 }
4966 if (animatorProps.r.propType) {
4967 if(mult.length) {
4968 matrixHelper.rotateZ(-animatorProps.r.v * mult[2]);
4969 } else {
4970 matrixHelper.rotateZ(-animatorProps.r.v * mult);
4971 }
4972 }
4973 if (animatorProps.ry.propType) {
4974
4975 if(mult.length) {
4976 matrixHelper.rotateY(animatorProps.ry.v*mult[1]);
4977 }else{
4978 matrixHelper.rotateY(animatorProps.ry.v*mult);
4979 }
4980 }
4981 if (animatorProps.rx.propType) {
4982 if(mult.length) {
4983 matrixHelper.rotateX(animatorProps.rx.v*mult[0]);
4984 } else {
4985 matrixHelper.rotateX(animatorProps.rx.v*mult);
4986 }
4987 }
4988 if (animatorProps.o.propType) {
4989 if(mult.length) {
4990 elemOpacity += ((animatorProps.o.v)*mult[0] - elemOpacity)*mult[0];
4991 } else {
4992 elemOpacity += ((animatorProps.o.v)*mult - elemOpacity)*mult;
4993 }
4994 }
4995 if (documentData.strokeWidthAnim && animatorProps.sw.propType) {
4996 if(mult.length) {
4997 sw += animatorProps.sw.v*mult[0];
4998 } else {
4999 sw += animatorProps.sw.v*mult;
5000 }
5001 }
5002 if (documentData.strokeColorAnim && animatorProps.sc.propType) {
5003 for(k=0;k<3;k+=1){
5004 if(mult.length) {
5005 sc[k] = sc[k] + (animatorProps.sc.v[k] - sc[k])*mult[0];
5006 } else {
5007 sc[k] = sc[k] + (animatorProps.sc.v[k] - sc[k])*mult;
5008 }
5009 }
5010 }
5011 if (documentData.fillColorAnim && documentData.fc) {
5012 if(animatorProps.fc.propType){
5013 for(k=0;k<3;k+=1){
5014 if(mult.length) {
5015 fc[k] = fc[k] + (animatorProps.fc.v[k] - fc[k])*mult[0];
5016 } else {
5017 fc[k] = fc[k] + (animatorProps.fc.v[k] - fc[k])*mult;
5018 }
5019 }
5020 }
5021 if(animatorProps.fh.propType){
5022 if(mult.length) {
5023 fc = addHueToRGB(fc,animatorProps.fh.v*mult[0]);
5024 } else {
5025 fc = addHueToRGB(fc,animatorProps.fh.v*mult);
5026 }
5027 }
5028 if(animatorProps.fs.propType){
5029 if(mult.length) {
5030 fc = addSaturationToRGB(fc,animatorProps.fs.v*mult[0]);
5031 } else {
5032 fc = addSaturationToRGB(fc,animatorProps.fs.v*mult);
5033 }
5034 }
5035 if(animatorProps.fb.propType){
5036 if(mult.length) {
5037 fc = addBrightnessToRGB(fc,animatorProps.fb.v*mult[0]);
5038 } else {
5039 fc = addBrightnessToRGB(fc,animatorProps.fb.v*mult);
5040 }
5041 }
5042 }
5043 }
5044
5045 for(j=0;j<jLen;j+=1){
5046 animatorProps = animators[j].a;
5047
5048 if (animatorProps.p.propType) {
5049 animatorSelector = animators[j].s;
5050 mult = animatorSelector.getMult(letters[i].anIndexes[j],textData.a[j].s.totalChars);
5051 if(this._hasMaskedPath) {
5052 if(mult.length) {
5053 matrixHelper.translate(0, animatorProps.p.v[1] * mult[0], -animatorProps.p.v[2] * mult[1]);
5054 } else {
5055 matrixHelper.translate(0, animatorProps.p.v[1] * mult, -animatorProps.p.v[2] * mult);
5056 }
5057 }else{
5058 if(mult.length) {
5059 matrixHelper.translate(animatorProps.p.v[0] * mult[0], animatorProps.p.v[1] * mult[1], -animatorProps.p.v[2] * mult[2]);
5060 } else {
5061 matrixHelper.translate(animatorProps.p.v[0] * mult, animatorProps.p.v[1] * mult, -animatorProps.p.v[2] * mult);
5062
5063 }
5064 }
5065 }
5066 }
5067 if(documentData.strokeWidthAnim){
5068 letterSw = sw < 0 ? 0 : sw;
5069 }
5070 if(documentData.strokeColorAnim){
5071 letterSc = 'rgb('+Math.round(sc[0]*255)+','+Math.round(sc[1]*255)+','+Math.round(sc[2]*255)+')';
5072 }
5073 if(documentData.fillColorAnim && documentData.fc){
5074 letterFc = 'rgb('+Math.round(fc[0]*255)+','+Math.round(fc[1]*255)+','+Math.round(fc[2]*255)+')';
5075 }
5076
5077 if(this._hasMaskedPath) {
5078 matrixHelper.translate(0,-documentData.ls);
5079
5080 matrixHelper.translate(0, alignment[1]*yOff/100 + yPos,0);
5081 if (textData.p.p) {
5082 tanAngle = (currentPoint.point[1] - prevPoint.point[1]) / (currentPoint.point[0] - prevPoint.point[0]);
5083 var rot = Math.atan(tanAngle) * 180 / Math.PI;
5084 if (currentPoint.point[0] < prevPoint.point[0]) {
5085 rot += 180;
5086 }
5087 matrixHelper.rotate(-rot * Math.PI / 180);
5088 }
5089 matrixHelper.translate(xPathPos, yPathPos, 0);
5090 currentLength -= alignment[0]*letters[i].an/200;
5091 if(letters[i+1] && ind !== letters[i+1].ind){
5092 currentLength += letters[i].an / 2;
5093 currentLength += documentData.tr/1000*documentData.finalSize;
5094 }
5095 }else{
5096
5097 matrixHelper.translate(xPos,yPos,0);
5098
5099 if(documentData.ps){
5100 //matrixHelper.translate(documentData.ps[0],documentData.ps[1],0);
5101 matrixHelper.translate(documentData.ps[0],documentData.ps[1] + documentData.ascent,0);
5102 }
5103 switch(documentData.j){
5104 case 1:
5105 matrixHelper.translate(letters[i].animatorJustifyOffset + documentData.justifyOffset + (documentData.boxWidth - documentData.lineWidths[letters[i].line]),0,0);
5106 break;
5107 case 2:
5108 matrixHelper.translate(letters[i].animatorJustifyOffset + documentData.justifyOffset + (documentData.boxWidth - documentData.lineWidths[letters[i].line])/2,0,0);
5109 break;
5110 }
5111 matrixHelper.translate(0,-documentData.ls);
5112 matrixHelper.translate(offf,0,0);
5113 matrixHelper.translate(alignment[0]*letters[i].an/200,alignment[1]*yOff/100,0);
5114 xPos += letters[i].l + documentData.tr/1000*documentData.finalSize;
5115 }
5116 if(renderType === 'html'){
5117 letterM = matrixHelper.toCSS();
5118 }else if(renderType === 'svg'){
5119 letterM = matrixHelper.to2dCSS();
5120 }else{
5121 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]];
5122 }
5123 letterO = elemOpacity;
5124 }
5125
5126 if(renderedLettersCount <= i) {
5127 letterValue = new LetterProps(letterO,letterSw,letterSc,letterFc,letterM,letterP);
5128 this.renderedLetters.push(letterValue);
5129 renderedLettersCount += 1;
5130 this.lettersChangedFlag = true;
5131 } else {
5132 letterValue = this.renderedLetters[i];
5133 this.lettersChangedFlag = letterValue.update(letterO, letterSw, letterSc, letterFc, letterM, letterP) || this.lettersChangedFlag;
5134 }
5135 }
5136};
5137
5138TextAnimatorProperty.prototype.getValue = function(){
5139 if(this._elem.globalData.frameId === this._frameId){
5140 return;
5141 }
5142 this._frameId = this._elem.globalData.frameId;
5143 this.iterateDynamicProperties();
5144};
5145
5146TextAnimatorProperty.prototype.mHelper = new Matrix();
5147TextAnimatorProperty.prototype.defaultPropsArray = [];
5148extendPrototype([DynamicPropertyContainer], TextAnimatorProperty);
5149function TextAnimatorDataProperty(elem, animatorProps, container) {
5150 var defaultData = {propType:false};
5151 var getProp = PropertyFactory.getProp;
5152 var textAnimator_animatables = animatorProps.a;
5153 this.a = {
5154 r: textAnimator_animatables.r ? getProp(elem, textAnimator_animatables.r, 0, degToRads, container) : defaultData,
5155 rx: textAnimator_animatables.rx ? getProp(elem, textAnimator_animatables.rx, 0, degToRads, container) : defaultData,
5156 ry: textAnimator_animatables.ry ? getProp(elem, textAnimator_animatables.ry, 0, degToRads, container) : defaultData,
5157 sk: textAnimator_animatables.sk ? getProp(elem, textAnimator_animatables.sk, 0, degToRads, container) : defaultData,
5158 sa: textAnimator_animatables.sa ? getProp(elem, textAnimator_animatables.sa, 0, degToRads, container) : defaultData,
5159 s: textAnimator_animatables.s ? getProp(elem, textAnimator_animatables.s, 1, 0.01, container) : defaultData,
5160 a: textAnimator_animatables.a ? getProp(elem, textAnimator_animatables.a, 1, 0, container) : defaultData,
5161 o: textAnimator_animatables.o ? getProp(elem, textAnimator_animatables.o, 0, 0.01, container) : defaultData,
5162 p: textAnimator_animatables.p ? getProp(elem,textAnimator_animatables.p, 1, 0, container) : defaultData,
5163 sw: textAnimator_animatables.sw ? getProp(elem, textAnimator_animatables.sw, 0, 0, container) : defaultData,
5164 sc: textAnimator_animatables.sc ? getProp(elem, textAnimator_animatables.sc, 1, 0, container) : defaultData,
5165 fc: textAnimator_animatables.fc ? getProp(elem, textAnimator_animatables.fc, 1, 0, container) : defaultData,
5166 fh: textAnimator_animatables.fh ? getProp(elem, textAnimator_animatables.fh, 0, 0, container) : defaultData,
5167 fs: textAnimator_animatables.fs ? getProp(elem, textAnimator_animatables.fs, 0, 0.01, container) : defaultData,
5168 fb: textAnimator_animatables.fb ? getProp(elem, textAnimator_animatables.fb, 0, 0.01, container) : defaultData,
5169 t: textAnimator_animatables.t ? getProp(elem, textAnimator_animatables.t, 0, 0, container) : defaultData
5170 };
5171
5172 this.s = TextSelectorProp.getTextSelectorProp(elem,animatorProps.s, container);
5173 this.s.t = animatorProps.s.t;
5174}
5175function LetterProps(o, sw, sc, fc, m, p){
5176 this.o = o;
5177 this.sw = sw;
5178 this.sc = sc;
5179 this.fc = fc;
5180 this.m = m;
5181 this.p = p;
5182 this._mdf = {
5183 o: true,
5184 sw: !!sw,
5185 sc: !!sc,
5186 fc: !!fc,
5187 m: true,
5188 p: true
5189 };
5190}
5191
5192LetterProps.prototype.update = function(o, sw, sc, fc, m, p) {
5193 this._mdf.o = false;
5194 this._mdf.sw = false;
5195 this._mdf.sc = false;
5196 this._mdf.fc = false;
5197 this._mdf.m = false;
5198 this._mdf.p = false;
5199 var updated = false;
5200
5201 if(this.o !== o) {
5202 this.o = o;
5203 this._mdf.o = true;
5204 updated = true;
5205 }
5206 if(this.sw !== sw) {
5207 this.sw = sw;
5208 this._mdf.sw = true;
5209 updated = true;
5210 }
5211 if(this.sc !== sc) {
5212 this.sc = sc;
5213 this._mdf.sc = true;
5214 updated = true;
5215 }
5216 if(this.fc !== fc) {
5217 this.fc = fc;
5218 this._mdf.fc = true;
5219 updated = true;
5220 }
5221 if(this.m !== m) {
5222 this.m = m;
5223 this._mdf.m = true;
5224 updated = true;
5225 }
5226 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])) {
5227 this.p = p;
5228 this._mdf.p = true;
5229 updated = true;
5230 }
5231 return updated;
5232};
5233function TextProperty(elem, data){
5234 this._frameId = initialDefaultFrame;
5235 this.pv = '';
5236 this.v = '';
5237 this.kf = false;
5238 this._isFirstFrame = true;
5239 this._mdf = false;
5240 this.data = data;
5241 this.elem = elem;
5242 this.comp = this.elem.comp;
5243 this.keysIndex = 0;
5244 this.canResize = false;
5245 this.minimumFontSize = 1;
5246 this.effectsSequence = [];
5247 this.currentData = {
5248 ascent: 0,
5249 boxWidth: this.defaultBoxWidth,
5250 f: '',
5251 fStyle: '',
5252 fWeight: '',
5253 fc: '',
5254 j: '',
5255 justifyOffset: '',
5256 l: [],
5257 lh: 0,
5258 lineWidths: [],
5259 ls: '',
5260 of: '',
5261 s: '',
5262 sc: '',
5263 sw: 0,
5264 t: 0,
5265 tr: 0,
5266 sz:0,
5267 ps:null,
5268 fillColorAnim: false,
5269 strokeColorAnim: false,
5270 strokeWidthAnim: false,
5271 yOffset: 0,
5272 finalSize:0,
5273 finalText:[],
5274 finalLineHeight: 0,
5275 __complete: false
5276
5277 };
5278 this.copyData(this.currentData, this.data.d.k[0].s);
5279
5280 if(!this.searchProperty()) {
5281 this.completeTextData(this.currentData);
5282 }
5283}
5284
5285TextProperty.prototype.defaultBoxWidth = [0,0];
5286
5287TextProperty.prototype.copyData = function(obj, data) {
5288 for(var s in data) {
5289 if(data.hasOwnProperty(s)) {
5290 obj[s] = data[s];
5291 }
5292 }
5293 return obj;
5294}
5295
5296TextProperty.prototype.setCurrentData = function(data){
5297 if(!data.__complete) {
5298 this.completeTextData(data);
5299 }
5300 this.currentData = data;
5301 this.currentData.boxWidth = this.currentData.boxWidth || this.defaultBoxWidth;
5302 this._mdf = true;
5303};
5304
5305TextProperty.prototype.searchProperty = function() {
5306 return this.searchKeyframes();
5307};
5308
5309TextProperty.prototype.searchKeyframes = function() {
5310 this.kf = this.data.d.k.length > 1;
5311 if(this.kf) {
5312 this.addEffect(this.getKeyframeValue.bind(this));
5313 }
5314 return this.kf;
5315}
5316
5317TextProperty.prototype.addEffect = function(effectFunction) {
5318 this.effectsSequence.push(effectFunction);
5319 this.elem.addDynamicProperty(this);
5320};
5321
5322TextProperty.prototype.getValue = function(_finalValue) {
5323 if((this.elem.globalData.frameId === this.frameId || !this.effectsSequence.length) && !_finalValue) {
5324 return;
5325 }
5326 this.currentData.t = this.data.d.k[this.keysIndex].s.t;
5327 var currentValue = this.currentData;
5328 var currentIndex = this.keysIndex;
5329 if(this.lock) {
5330 this.setCurrentData(this.currentData);
5331 return;
5332 }
5333 this.lock = true;
5334 this._mdf = false;
5335 var multipliedValue;
5336 var i, len = this.effectsSequence.length;
5337 var finalValue = _finalValue || this.data.d.k[this.keysIndex].s;
5338 for(i = 0; i < len; i += 1) {
5339 //Checking if index changed to prevent creating a new object every time the expression updates.
5340 if(currentIndex !== this.keysIndex) {
5341 finalValue = this.effectsSequence[i](finalValue, finalValue.t);
5342 } else {
5343 finalValue = this.effectsSequence[i](this.currentData, finalValue.t);
5344 }
5345 }
5346 if(currentValue !== finalValue) {
5347 this.setCurrentData(finalValue);
5348 }
5349 this.pv = this.v = this.currentData;
5350 this.lock = false;
5351 this.frameId = this.elem.globalData.frameId;
5352}
5353
5354TextProperty.prototype.getKeyframeValue = function() {
5355 var textKeys = this.data.d.k, textDocumentData;
5356 var frameNum = this.elem.comp.renderedFrame;
5357 var i = 0, len = textKeys.length;
5358 while(i <= len - 1) {
5359 textDocumentData = textKeys[i].s;
5360 if(i === len - 1 || textKeys[i+1].t > frameNum){
5361 break;
5362 }
5363 i += 1;
5364 }
5365 if(this.keysIndex !== i) {
5366 this.keysIndex = i;
5367 }
5368 return this.data.d.k[this.keysIndex].s;
5369};
5370
5371TextProperty.prototype.buildFinalText = function(text) {
5372 var combinedCharacters = FontManager.getCombinedCharacterCodes();
5373 var charactersArray = [];
5374 var i = 0, len = text.length;
5375 var charCode;
5376 while (i < len) {
5377 charCode = text.charCodeAt(i);
5378 if (combinedCharacters.indexOf(charCode) !== -1) {
5379 charactersArray[charactersArray.length - 1] += text.charAt(i);
5380 } else {
5381 if (charCode >= 0xD800 && charCode <= 0xDBFF) {
5382 charCode = text.charCodeAt(i + 1);
5383 if (charCode >= 0xDC00 && charCode <= 0xDFFF) {
5384 charactersArray.push(text.substr(i, 2));
5385 ++i;
5386 } else {
5387 charactersArray.push(text.charAt(i));
5388 }
5389 } else {
5390 charactersArray.push(text.charAt(i));
5391 }
5392 }
5393 i += 1;
5394 }
5395 return charactersArray;
5396}
5397
5398TextProperty.prototype.completeTextData = function(documentData) {
5399 documentData.__complete = true;
5400 var fontManager = this.elem.globalData.fontManager;
5401 var data = this.data;
5402 var letters = [];
5403 var i, len;
5404 var newLineFlag, index = 0, val;
5405 var anchorGrouping = data.m.g;
5406 var currentSize = 0, currentPos = 0, currentLine = 0, lineWidths = [];
5407 var lineWidth = 0;
5408 var maxLineWidth = 0;
5409 var j, jLen;
5410 var fontData = fontManager.getFontByName(documentData.f);
5411 var charData, cLength = 0;
5412 var styles = fontData.fStyle ? fontData.fStyle.split(' ') : [];
5413
5414 var fWeight = 'normal', fStyle = 'normal';
5415 len = styles.length;
5416 var styleName;
5417 for(i=0;i<len;i+=1){
5418 styleName = styles[i].toLowerCase();
5419 switch(styleName) {
5420 case 'italic':
5421 fStyle = 'italic';
5422 break;
5423 case 'bold':
5424 fWeight = '700';
5425 break;
5426 case 'black':
5427 fWeight = '900';
5428 break;
5429 case 'medium':
5430 fWeight = '500';
5431 break;
5432 case 'regular':
5433 case 'normal':
5434 fWeight = '400';
5435 break;
5436 case 'light':
5437 case 'thin':
5438 fWeight = '200';
5439 break;
5440 }
5441 }
5442 documentData.fWeight = fontData.fWeight || fWeight;
5443 documentData.fStyle = fStyle;
5444 documentData.finalSize = documentData.s;
5445 documentData.finalText = this.buildFinalText(documentData.t);
5446 len = documentData.finalText.length;
5447 documentData.finalLineHeight = documentData.lh;
5448 var trackingOffset = documentData.tr/1000*documentData.finalSize;
5449 var charCode;
5450 if(documentData.sz){
5451 var flag = true;
5452 var boxWidth = documentData.sz[0];
5453 var boxHeight = documentData.sz[1];
5454 var currentHeight, finalText;
5455 while(flag) {
5456 finalText = this.buildFinalText(documentData.t);
5457 currentHeight = 0;
5458 lineWidth = 0;
5459 len = finalText.length;
5460 trackingOffset = documentData.tr/1000*documentData.finalSize;
5461 var lastSpaceIndex = -1;
5462 for(i=0;i<len;i+=1){
5463 charCode = finalText[i].charCodeAt(0);
5464 newLineFlag = false;
5465 if(finalText[i] === ' '){
5466 lastSpaceIndex = i;
5467 }else if(charCode === 13 || charCode === 3){
5468 lineWidth = 0;
5469 newLineFlag = true;
5470 currentHeight += documentData.finalLineHeight || documentData.finalSize*1.2;
5471 }
5472 if(fontManager.chars){
5473 charData = fontManager.getCharData(finalText[i], fontData.fStyle, fontData.fFamily);
5474 cLength = newLineFlag ? 0 : charData.w*documentData.finalSize/100;
5475 }else{
5476 //tCanvasHelper.font = documentData.s + 'px '+ fontData.fFamily;
5477 cLength = fontManager.measureText(finalText[i], documentData.f, documentData.finalSize);
5478 }
5479 if(lineWidth + cLength > boxWidth && finalText[i] !== ' '){
5480 if(lastSpaceIndex === -1){
5481 len += 1;
5482 } else {
5483 i = lastSpaceIndex;
5484 }
5485 currentHeight += documentData.finalLineHeight || documentData.finalSize*1.2;
5486 finalText.splice(i, lastSpaceIndex === i ? 1 : 0,"\r");
5487 //finalText = finalText.substr(0,i) + "\r" + finalText.substr(i === lastSpaceIndex ? i + 1 : i);
5488 lastSpaceIndex = -1;
5489 lineWidth = 0;
5490 }else {
5491 lineWidth += cLength;
5492 lineWidth += trackingOffset;
5493 }
5494 }
5495 currentHeight += fontData.ascent*documentData.finalSize/100;
5496 if(this.canResize && documentData.finalSize > this.minimumFontSize && boxHeight < currentHeight) {
5497 documentData.finalSize -= 1;
5498 documentData.finalLineHeight = documentData.finalSize * documentData.lh / documentData.s;
5499 } else {
5500 documentData.finalText = finalText;
5501 len = documentData.finalText.length;
5502 flag = false;
5503 }
5504 }
5505
5506 }
5507 lineWidth = - trackingOffset;
5508 cLength = 0;
5509 var uncollapsedSpaces = 0;
5510 var currentChar;
5511 for (i = 0;i < len ;i += 1) {
5512 newLineFlag = false;
5513 currentChar = documentData.finalText[i];
5514 charCode = currentChar.charCodeAt(0);
5515 if (charCode === 13 || charCode === 3) {
5516 uncollapsedSpaces = 0;
5517 lineWidths.push(lineWidth);
5518 maxLineWidth = lineWidth > maxLineWidth ? lineWidth : maxLineWidth;
5519 lineWidth = - 2 * trackingOffset;
5520 val = '';
5521 newLineFlag = true;
5522 currentLine += 1;
5523 }else{
5524 val = currentChar;
5525 }
5526 if(fontManager.chars){
5527 charData = fontManager.getCharData(currentChar, fontData.fStyle, fontManager.getFontByName(documentData.f).fFamily);
5528 cLength = newLineFlag ? 0 : charData.w*documentData.finalSize/100;
5529 }else{
5530 //var charWidth = fontManager.measureText(val, documentData.f, documentData.finalSize);
5531 //tCanvasHelper.font = documentData.finalSize + 'px '+ fontManager.getFontByName(documentData.f).fFamily;
5532 cLength = fontManager.measureText(val, documentData.f, documentData.finalSize);
5533 }
5534
5535 //
5536 if(currentChar === ' '){
5537 uncollapsedSpaces += cLength + trackingOffset;
5538 } else {
5539 lineWidth += cLength + trackingOffset + uncollapsedSpaces;
5540 uncollapsedSpaces = 0;
5541 }
5542 letters.push({l:cLength,an:cLength,add:currentSize,n:newLineFlag, anIndexes:[], val: val, line: currentLine, animatorJustifyOffset: 0});
5543 if(anchorGrouping == 2){
5544 currentSize += cLength;
5545 if(val === '' || val === ' ' || i === len - 1){
5546 if(val === '' || val === ' '){
5547 currentSize -= cLength;
5548 }
5549 while(currentPos<=i){
5550 letters[currentPos].an = currentSize;
5551 letters[currentPos].ind = index;
5552 letters[currentPos].extra = cLength;
5553 currentPos += 1;
5554 }
5555 index += 1;
5556 currentSize = 0;
5557 }
5558 }else if(anchorGrouping == 3){
5559 currentSize += cLength;
5560 if(val === '' || i === len - 1){
5561 if(val === ''){
5562 currentSize -= cLength;
5563 }
5564 while(currentPos<=i){
5565 letters[currentPos].an = currentSize;
5566 letters[currentPos].ind = index;
5567 letters[currentPos].extra = cLength;
5568 currentPos += 1;
5569 }
5570 currentSize = 0;
5571 index += 1;
5572 }
5573 }else{
5574 letters[index].ind = index;
5575 letters[index].extra = 0;
5576 index += 1;
5577 }
5578 }
5579 documentData.l = letters;
5580 maxLineWidth = lineWidth > maxLineWidth ? lineWidth : maxLineWidth;
5581 lineWidths.push(lineWidth);
5582 if(documentData.sz){
5583 documentData.boxWidth = documentData.sz[0];
5584 documentData.justifyOffset = 0;
5585 }else{
5586 documentData.boxWidth = maxLineWidth;
5587 switch(documentData.j){
5588 case 1:
5589 documentData.justifyOffset = - documentData.boxWidth;
5590 break;
5591 case 2:
5592 documentData.justifyOffset = - documentData.boxWidth/2;
5593 break;
5594 default:
5595 documentData.justifyOffset = 0;
5596 }
5597 }
5598 documentData.lineWidths = lineWidths;
5599
5600 var animators = data.a, animatorData, letterData;
5601 jLen = animators.length;
5602 var based, ind, indexes = [];
5603 for(j=0;j<jLen;j+=1){
5604 animatorData = animators[j];
5605 if(animatorData.a.sc){
5606 documentData.strokeColorAnim = true;
5607 }
5608 if(animatorData.a.sw){
5609 documentData.strokeWidthAnim = true;
5610 }
5611 if(animatorData.a.fc || animatorData.a.fh || animatorData.a.fs || animatorData.a.fb){
5612 documentData.fillColorAnim = true;
5613 }
5614 ind = 0;
5615 based = animatorData.s.b;
5616 for(i=0;i<len;i+=1){
5617 letterData = letters[i];
5618 letterData.anIndexes[j] = ind;
5619 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))){
5620 if(animatorData.s.rn === 1){
5621 indexes.push(ind);
5622 }
5623 ind += 1;
5624 }
5625 }
5626 data.a[j].s.totalChars = ind;
5627 var currentInd = -1, newInd;
5628 if(animatorData.s.rn === 1){
5629 for(i = 0; i < len; i += 1){
5630 letterData = letters[i];
5631 if(currentInd != letterData.anIndexes[j]){
5632 currentInd = letterData.anIndexes[j];
5633 newInd = indexes.splice(Math.floor(Math.random()*indexes.length),1)[0];
5634 }
5635 letterData.anIndexes[j] = newInd;
5636 }
5637 }
5638 }
5639 documentData.yOffset = documentData.finalLineHeight || documentData.finalSize*1.2;
5640 documentData.ls = documentData.ls || 0;
5641 documentData.ascent = fontData.ascent*documentData.finalSize/100;
5642};
5643
5644TextProperty.prototype.updateDocumentData = function(newData, index) {
5645 index = index === undefined ? this.keysIndex : index;
5646 var dData = this.copyData({}, this.data.d.k[index].s);
5647 dData = this.copyData(dData, newData);
5648 this.data.d.k[index].s = dData;
5649 this.recalculate(index);
5650 this.elem.addDynamicProperty(this);
5651};
5652
5653TextProperty.prototype.recalculate = function(index) {
5654 var dData = this.data.d.k[index].s;
5655 dData.__complete = false;
5656 this.keysIndex = 0;
5657 this._isFirstFrame = true;
5658 this.getValue(dData);
5659}
5660
5661TextProperty.prototype.canResizeFont = function(_canResize) {
5662 this.canResize = _canResize;
5663 this.recalculate(this.keysIndex);
5664 this.elem.addDynamicProperty(this);
5665};
5666
5667TextProperty.prototype.setMinimumFontSize = function(_fontValue) {
5668 this.minimumFontSize = Math.floor(_fontValue) || 1;
5669 this.recalculate(this.keysIndex);
5670 this.elem.addDynamicProperty(this);
5671};
5672
5673var TextSelectorProp = (function(){
5674 var max = Math.max;
5675 var min = Math.min;
5676 var floor = Math.floor;
5677
5678 function TextSelectorProp(elem,data){
5679 this._currentTextLength = -1;
5680 this.k = false;
5681 this.data = data;
5682 this.elem = elem;
5683 this.comp = elem.comp;
5684 this.finalS = 0;
5685 this.finalE = 0;
5686 this.initDynamicPropertyContainer(elem);
5687 this.s = PropertyFactory.getProp(elem,data.s || {k:0},0,0,this);
5688 if('e' in data){
5689 this.e = PropertyFactory.getProp(elem,data.e,0,0,this);
5690 }else{
5691 this.e = {v:100};
5692 }
5693 this.o = PropertyFactory.getProp(elem,data.o || {k:0},0,0,this);
5694 this.xe = PropertyFactory.getProp(elem,data.xe || {k:0},0,0,this);
5695 this.ne = PropertyFactory.getProp(elem,data.ne || {k:0},0,0,this);
5696 this.a = PropertyFactory.getProp(elem,data.a,0,0.01,this);
5697 if(!this.dynamicProperties.length){
5698 this.getValue();
5699 }
5700 }
5701
5702 TextSelectorProp.prototype = {
5703 getMult: function(ind) {
5704 if(this._currentTextLength !== this.elem.textProperty.currentData.l.length) {
5705 this.getValue();
5706 }
5707 //var easer = bez.getEasingCurve(this.ne.v/100,0,1-this.xe.v/100,1);
5708 var x1 = 0;
5709 var y1 = 0;
5710 var x2 = 1;
5711 var y2 = 1;
5712 if(this.ne.v > 0) {
5713 x1 = this.ne.v / 100.0;
5714 }
5715 else {
5716 y1 = -this.ne.v / 100.0;
5717 }
5718 if(this.xe.v > 0) {
5719 x2 = 1.0 - this.xe.v / 100.0;
5720 }
5721 else {
5722 y2 = 1.0 + this.xe.v / 100.0;
5723 }
5724 var easer = BezierFactory.getBezierEasing(x1, y1, x2, y2).get;
5725
5726 var mult = 0;
5727 var s = this.finalS;
5728 var e = this.finalE;
5729 var type = this.data.sh;
5730 if (type === 2){
5731 if (e === s) {
5732 mult = ind >= e ? 1 : 0;
5733 } else {
5734 mult = max(0, min(0.5 / (e - s) + (ind - s) / (e - s), 1));
5735 }
5736 mult = easer(mult);
5737 } else if(type === 3) {
5738 if (e === s) {
5739 mult = ind >= e ? 0 : 1;
5740 }else{
5741 mult = 1 - max(0, min(0.5 / (e - s) + (ind - s) / (e - s),1));
5742 }
5743
5744 mult = easer(mult);
5745 } else if (type === 4) {
5746 if (e === s) {
5747 mult = 0;
5748 } else {
5749 mult = max(0, min(0.5 / (e - s) + (ind - s) / (e - s), 1));
5750 if (mult < 0.5) {
5751 mult *= 2;
5752 } else {
5753 mult = 1 - 2 * (mult - 0.5);
5754 }
5755 }
5756 mult = easer(mult);
5757 } else if (type === 5) {
5758 if (e === s){
5759 mult = 0;
5760 } else {
5761 var tot = e - s;
5762 /*ind += 0.5;
5763 mult = -4/(tot*tot)*(ind*ind)+(4/tot)*ind;*/
5764 ind = min(max(0, ind + 0.5 - s), e - s);
5765 var x = -tot/2+ind;
5766 var a = tot/2;
5767 mult = Math.sqrt(1 - (x * x) / (a * a));
5768 }
5769 mult = easer(mult);
5770 } else if (type === 6) {
5771 if (e === s){
5772 mult = 0;
5773 } else {
5774 ind = min(max(0, ind + 0.5 - s), e - s);
5775 mult = (1 + (Math.cos((Math.PI + Math.PI * 2 * (ind) / (e - s))))) / 2;
5776 }
5777 mult = easer(mult);
5778 } else {
5779 if (ind >= floor(s)) {
5780 if (ind - s < 0) {
5781 mult = max(0, min(min(e, 1) - (s - ind), 1));
5782 } else {
5783 mult = max(0, min(e - ind, 1));
5784 }
5785 }
5786 mult = easer(mult);
5787 }
5788 return mult*this.a.v;
5789 },
5790 getValue: function(newCharsFlag) {
5791 this.iterateDynamicProperties();
5792 this._mdf = newCharsFlag || this._mdf;
5793 this._currentTextLength = this.elem.textProperty.currentData.l.length || 0;
5794 if(newCharsFlag && this.data.r === 2) {
5795 this.e.v = this._currentTextLength;
5796 }
5797 var divisor = this.data.r === 2 ? 1 : 100 / this.data.totalChars;
5798 var o = this.o.v/divisor;
5799 var s = this.s.v/divisor + o;
5800 var e = (this.e.v/divisor) + o;
5801 if(s>e){
5802 var _s = s;
5803 s = e;
5804 e = _s;
5805 }
5806 this.finalS = s;
5807 this.finalE = e;
5808 }
5809 }
5810 extendPrototype([DynamicPropertyContainer], TextSelectorProp);
5811
5812 function getTextSelectorProp(elem, data,arr) {
5813 return new TextSelectorProp(elem, data, arr);
5814 }
5815
5816 return {
5817 getTextSelectorProp: getTextSelectorProp
5818 };
5819}());
5820
5821
5822var pool_factory = (function() {
5823 return function(initialLength, _create, _release, _clone) {
5824
5825 var _length = 0;
5826 var _maxLength = initialLength;
5827 var pool = createSizedArray(_maxLength);
5828
5829 var ob = {
5830 newElement: newElement,
5831 release: release
5832 };
5833
5834 function newElement(){
5835 var element;
5836 if(_length){
5837 _length -= 1;
5838 element = pool[_length];
5839 } else {
5840 element = _create();
5841 }
5842 return element;
5843 }
5844
5845 function release(element) {
5846 if(_length === _maxLength) {
5847 pool = pooling.double(pool);
5848 _maxLength = _maxLength*2;
5849 }
5850 if (_release) {
5851 _release(element);
5852 }
5853 pool[_length] = element;
5854 _length += 1;
5855 }
5856
5857 function clone() {
5858 var clonedElement = newElement();
5859 return _clone(clonedElement);
5860 }
5861
5862 return ob;
5863 };
5864}());
5865
5866var pooling = (function(){
5867
5868 function double(arr){
5869 return arr.concat(createSizedArray(arr.length));
5870 }
5871
5872 return {
5873 double: double
5874 };
5875}());
5876var point_pool = (function(){
5877
5878 function create() {
5879 return createTypedArray('float32', 2);
5880 }
5881 return pool_factory(8, create);
5882}());
5883var shape_pool = (function(){
5884
5885 function create() {
5886 return new ShapePath();
5887 }
5888
5889 function release(shapePath) {
5890 var len = shapePath._length, i;
5891 for(i = 0; i < len; i += 1) {
5892 point_pool.release(shapePath.v[i]);
5893 point_pool.release(shapePath.i[i]);
5894 point_pool.release(shapePath.o[i]);
5895 shapePath.v[i] = null;
5896 shapePath.i[i] = null;
5897 shapePath.o[i] = null;
5898 }
5899 shapePath._length = 0;
5900 shapePath.c = false;
5901 }
5902
5903 function clone(shape) {
5904 var cloned = factory.newElement();
5905 var i, len = shape._length === undefined ? shape.v.length : shape._length;
5906 cloned.setLength(len);
5907 cloned.c = shape.c;
5908 var pt;
5909
5910 for(i = 0; i < len; i += 1) {
5911 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);
5912 }
5913 return cloned;
5914 }
5915
5916 var factory = pool_factory(4, create, release);
5917 factory.clone = clone;
5918
5919 return factory;
5920}());
5921var shapeCollection_pool = (function(){
5922 var ob = {
5923 newShapeCollection: newShapeCollection,
5924 release: release
5925 };
5926
5927 var _length = 0;
5928 var _maxLength = 4;
5929 var pool = createSizedArray(_maxLength);
5930
5931 function newShapeCollection(){
5932 var shapeCollection;
5933 if(_length){
5934 _length -= 1;
5935 shapeCollection = pool[_length];
5936 } else {
5937 shapeCollection = new ShapeCollection();
5938 }
5939 return shapeCollection;
5940 }
5941
5942 function release(shapeCollection) {
5943 var i, len = shapeCollection._length;
5944 for(i = 0; i < len; i += 1) {
5945 shape_pool.release(shapeCollection.shapes[i]);
5946 }
5947 shapeCollection._length = 0;
5948
5949 if(_length === _maxLength) {
5950 pool = pooling.double(pool);
5951 _maxLength = _maxLength*2;
5952 }
5953 pool[_length] = shapeCollection;
5954 _length += 1;
5955 }
5956
5957 return ob;
5958}());
5959var segments_length_pool = (function(){
5960
5961 function create() {
5962 return {
5963 lengths: [],
5964 totalLength: 0
5965 };
5966 }
5967
5968 function release(element) {
5969 var i, len = element.lengths.length;
5970 for(i=0;i<len;i+=1) {
5971 bezier_length_pool.release(element.lengths[i]);
5972 }
5973 element.lengths.length = 0;
5974 }
5975
5976 return pool_factory(8, create, release);
5977}());
5978var bezier_length_pool = (function(){
5979
5980 function create() {
5981 return {
5982 addedLength: 0,
5983 percents: createTypedArray('float32', defaultCurveSegments),
5984 lengths: createTypedArray('float32', defaultCurveSegments),
5985 };
5986 }
5987 return pool_factory(8, create);
5988}());
5989function BaseRenderer(){}
5990BaseRenderer.prototype.checkLayers = function(num){
5991 var i, len = this.layers.length, data;
5992 this.completeLayers = true;
5993 for (i = len - 1; i >= 0; i--) {
5994 if (!this.elements[i]) {
5995 data = this.layers[i];
5996 if(data.ip - data.st <= (num - this.layers[i].st) && data.op - data.st > (num - this.layers[i].st))
5997 {
5998 this.buildItem(i);
5999 }
6000 }
6001 this.completeLayers = this.elements[i] ? this.completeLayers:false;
6002 }
6003 this.checkPendingElements();
6004};
6005
6006BaseRenderer.prototype.createItem = function(layer){
6007 switch(layer.ty){
6008 case 2:
6009 return this.createImage(layer);
6010 case 0:
6011 return this.createComp(layer);
6012 case 1:
6013 return this.createSolid(layer);
6014 case 3:
6015 return this.createNull(layer);
6016 case 4:
6017 return this.createShape(layer);
6018 case 5:
6019 return this.createText(layer);
6020 case 6:
6021 return this.createAudio(layer);
6022 case 13:
6023 return this.createCamera(layer);
6024 }
6025 return this.createNull(layer);
6026};
6027
6028BaseRenderer.prototype.createCamera = function(){
6029 throw new Error('You\'re using a 3d camera. Try the html renderer.');
6030};
6031
6032BaseRenderer.prototype.createAudio = function(data){
6033 return new AudioElement(data, this.globalData, this);
6034};
6035
6036BaseRenderer.prototype.buildAllItems = function(){
6037 var i, len = this.layers.length;
6038 for(i=0;i<len;i+=1){
6039 this.buildItem(i);
6040 }
6041 this.checkPendingElements();
6042};
6043
6044BaseRenderer.prototype.includeLayers = function(newLayers){
6045 this.completeLayers = false;
6046 var i, len = newLayers.length;
6047 var j, jLen = this.layers.length;
6048 for(i=0;i<len;i+=1){
6049 j = 0;
6050 while(j<jLen){
6051 if(this.layers[j].id == newLayers[i].id){
6052 this.layers[j] = newLayers[i];
6053 break;
6054 }
6055 j += 1;
6056 }
6057 }
6058};
6059
6060BaseRenderer.prototype.setProjectInterface = function(pInterface){
6061 this.globalData.projectInterface = pInterface;
6062};
6063
6064BaseRenderer.prototype.initItems = function(){
6065 if(!this.globalData.progressiveLoad){
6066 this.buildAllItems();
6067 }
6068};
6069BaseRenderer.prototype.buildElementParenting = function(element, parentName, hierarchy) {
6070 var elements = this.elements;
6071 var layers = this.layers;
6072 var i=0, len = layers.length;
6073 while (i < len) {
6074 if (layers[i].ind == parentName) {
6075 if (!elements[i] || elements[i] === true) {
6076 this.buildItem(i);
6077 this.addPendingElement(element);
6078 } else {
6079 hierarchy.push(elements[i]);
6080 elements[i].setAsParent();
6081 if(layers[i].parent !== undefined) {
6082 this.buildElementParenting(element, layers[i].parent, hierarchy);
6083 } else {
6084 element.setHierarchy(hierarchy);
6085 }
6086 }
6087 }
6088 i += 1;
6089 }
6090};
6091
6092BaseRenderer.prototype.addPendingElement = function(element){
6093 this.pendingElements.push(element);
6094};
6095
6096BaseRenderer.prototype.searchExtraCompositions = function(assets){
6097 var i, len = assets.length;
6098 for(i=0;i<len;i+=1){
6099 if(assets[i].xt){
6100 var comp = this.createComp(assets[i]);
6101 comp.initExpressions();
6102 this.globalData.projectInterface.registerComposition(comp);
6103 }
6104 }
6105};
6106
6107BaseRenderer.prototype.setupGlobalData = function(animData, fontsContainer) {
6108 this.globalData.fontManager = new FontManager();
6109 this.globalData.fontManager.addChars(animData.chars);
6110 this.globalData.fontManager.addFonts(animData.fonts, fontsContainer);
6111 this.globalData.getAssetData = this.animationItem.getAssetData.bind(this.animationItem);
6112 this.globalData.getAssetsPath = this.animationItem.getAssetsPath.bind(this.animationItem);
6113 this.globalData.imageLoader = this.animationItem.imagePreloader;
6114 this.globalData.audioController = this.animationItem.audioController;
6115 this.globalData.frameId = 0;
6116 this.globalData.frameRate = animData.fr;
6117 this.globalData.nm = animData.nm;
6118 this.globalData.compSize = {
6119 w: animData.w,
6120 h: animData.h
6121 }
6122}
6123function SVGRenderer(animationItem, config){
6124 this.animationItem = animationItem;
6125 this.layers = null;
6126 this.renderedFrame = -1;
6127 this.svgElement = createNS('svg');
6128 var ariaLabel = '';
6129 if (config && config.title) {
6130 var titleElement = createNS('title');
6131 var titleId = createElementID();
6132 titleElement.setAttribute('id', titleId);
6133 titleElement.textContent = config.title;
6134 this.svgElement.appendChild(titleElement);
6135 ariaLabel += titleId;
6136 }
6137 if (config && config.description) {
6138 var descElement = createNS('desc');
6139 var descId = createElementID();
6140 descElement.setAttribute('id', descId);
6141 descElement.textContent = config.description;
6142 this.svgElement.appendChild(descElement);
6143 ariaLabel += ' ' + descId;
6144 }
6145 if (ariaLabel) {
6146 this.svgElement.setAttribute('aria-labelledby', ariaLabel)
6147 }
6148 var defs = createNS( 'defs');
6149 this.svgElement.appendChild(defs);
6150 var maskElement = createNS('g');
6151 this.svgElement.appendChild(maskElement);
6152 this.layerElement = maskElement;
6153 this.renderConfig = {
6154 preserveAspectRatio: (config && config.preserveAspectRatio) || 'xMidYMid meet',
6155 imagePreserveAspectRatio: (config && config.imagePreserveAspectRatio) || 'xMidYMid slice',
6156 progressiveLoad: (config && config.progressiveLoad) || false,
6157 hideOnTransparent: (config && config.hideOnTransparent === false) ? false : true,
6158 viewBoxOnly: (config && config.viewBoxOnly) || false,
6159 viewBoxSize: (config && config.viewBoxSize) || false,
6160 className: (config && config.className) || '',
6161 id: (config && config.id) || '',
6162 focusable: config && config.focusable,
6163 filterSize: {
6164 width: config && config.filterSize && config.filterSize.width || '100%',
6165 height: config && config.filterSize && config.filterSize.height || '100%',
6166 x: config && config.filterSize && config.filterSize.x || '0%',
6167 y: config && config.filterSize && config.filterSize.y || '0%',
6168 }
6169 };
6170
6171 this.globalData = {
6172 _mdf: false,
6173 frameNum: -1,
6174 defs: defs,
6175 renderConfig: this.renderConfig
6176 };
6177 this.elements = [];
6178 this.pendingElements = [];
6179 this.destroyed = false;
6180 this.rendererType = 'svg';
6181
6182}
6183
6184extendPrototype([BaseRenderer],SVGRenderer);
6185
6186SVGRenderer.prototype.createNull = function (data) {
6187 return new NullElement(data,this.globalData,this);
6188};
6189
6190SVGRenderer.prototype.createShape = function (data) {
6191 return new SVGShapeElement(data,this.globalData,this);
6192};
6193
6194SVGRenderer.prototype.createText = function (data) {
6195 return new SVGTextElement(data,this.globalData,this);
6196
6197};
6198
6199SVGRenderer.prototype.createImage = function (data) {
6200 return new IImageElement(data,this.globalData,this);
6201};
6202
6203SVGRenderer.prototype.createComp = function (data) {
6204 return new SVGCompElement(data,this.globalData,this);
6205
6206};
6207
6208SVGRenderer.prototype.createSolid = function (data) {
6209 return new ISolidElement(data,this.globalData,this);
6210};
6211
6212SVGRenderer.prototype.configAnimation = function(animData){
6213 this.svgElement.setAttribute('xmlns','http://www.w3.org/2000/svg');
6214 if(this.renderConfig.viewBoxSize) {
6215 this.svgElement.setAttribute('viewBox',this.renderConfig.viewBoxSize);
6216 } else {
6217 this.svgElement.setAttribute('viewBox','0 0 '+animData.w+' '+animData.h);
6218 }
6219
6220 if(!this.renderConfig.viewBoxOnly) {
6221 this.svgElement.setAttribute('width',animData.w);
6222 this.svgElement.setAttribute('height',animData.h);
6223 this.svgElement.style.width = '100%';
6224 this.svgElement.style.height = '100%';
6225 this.svgElement.style.transform = 'translate3d(0,0,0)';
6226 }
6227 if (this.renderConfig.className) {
6228 this.svgElement.setAttribute('class', this.renderConfig.className);
6229 }
6230 if (this.renderConfig.id) {
6231 this.svgElement.setAttribute('id', this.renderConfig.id);
6232 }
6233 if (this.renderConfig.focusable !== undefined) {
6234 this.svgElement.setAttribute('focusable', this.renderConfig.focusable);
6235 }
6236 this.svgElement.setAttribute('preserveAspectRatio',this.renderConfig.preserveAspectRatio);
6237 //this.layerElement.style.transform = 'translate3d(0,0,0)';
6238 //this.layerElement.style.transformOrigin = this.layerElement.style.mozTransformOrigin = this.layerElement.style.webkitTransformOrigin = this.layerElement.style['-webkit-transform'] = "0px 0px 0px";
6239 this.animationItem.wrapper.appendChild(this.svgElement);
6240 //Mask animation
6241 var defs = this.globalData.defs;
6242
6243 this.setupGlobalData(animData, defs);
6244 this.globalData.progressiveLoad = this.renderConfig.progressiveLoad;
6245 this.data = animData;
6246
6247 var maskElement = createNS( 'clipPath');
6248 var rect = createNS('rect');
6249 rect.setAttribute('width',animData.w);
6250 rect.setAttribute('height',animData.h);
6251 rect.setAttribute('x',0);
6252 rect.setAttribute('y',0);
6253 var maskId = createElementID();
6254 maskElement.setAttribute('id', maskId);
6255 maskElement.appendChild(rect);
6256 this.layerElement.setAttribute("clip-path", "url(" + locationHref + "#"+maskId+")");
6257
6258 defs.appendChild(maskElement);
6259 this.layers = animData.layers;
6260 this.elements = createSizedArray(animData.layers.length);
6261};
6262
6263
6264SVGRenderer.prototype.destroy = function () {
6265 this.animationItem.wrapper.innerText = '';
6266 this.layerElement = null;
6267 this.globalData.defs = null;
6268 var i, len = this.layers ? this.layers.length : 0;
6269 for (i = 0; i < len; i++) {
6270 if(this.elements[i]){
6271 this.elements[i].destroy();
6272 }
6273 }
6274 this.elements.length = 0;
6275 this.destroyed = true;
6276 this.animationItem = null;
6277};
6278
6279SVGRenderer.prototype.updateContainerSize = function () {
6280};
6281
6282SVGRenderer.prototype.buildItem = function(pos){
6283 var elements = this.elements;
6284 if(elements[pos] || this.layers[pos].ty == 99){
6285 return;
6286 }
6287 elements[pos] = true;
6288 var element = this.createItem(this.layers[pos]);
6289
6290 elements[pos] = element;
6291 if(expressionsPlugin){
6292 if(this.layers[pos].ty === 0){
6293 this.globalData.projectInterface.registerComposition(element);
6294 }
6295 element.initExpressions();
6296 }
6297 this.appendElementInPos(element,pos);
6298 if(this.layers[pos].tt){
6299 if(!this.elements[pos - 1] || this.elements[pos - 1] === true){
6300 this.buildItem(pos - 1);
6301 this.addPendingElement(element);
6302 } else {
6303 element.setMatte(elements[pos - 1].layerId);
6304 }
6305 }
6306};
6307
6308SVGRenderer.prototype.checkPendingElements = function(){
6309 while(this.pendingElements.length){
6310 var element = this.pendingElements.pop();
6311 element.checkParenting();
6312 if(element.data.tt){
6313 var i = 0, len = this.elements.length;
6314 while(i<len){
6315 if(this.elements[i] === element){
6316 element.setMatte(this.elements[i - 1].layerId);
6317 break;
6318 }
6319 i += 1;
6320 }
6321 }
6322 }
6323};
6324
6325SVGRenderer.prototype.renderFrame = function(num){
6326 if(this.renderedFrame === num || this.destroyed){
6327 return;
6328 }
6329 if(num === null){
6330 num = this.renderedFrame;
6331 }else{
6332 this.renderedFrame = num;
6333 }
6334 // console.log('-------');
6335 // console.log('FRAME ',num);
6336 this.globalData.frameNum = num;
6337 this.globalData.frameId += 1;
6338 this.globalData.projectInterface.currentFrame = num;
6339 this.globalData._mdf = false;
6340 var i, len = this.layers.length;
6341 if(!this.completeLayers){
6342 this.checkLayers(num);
6343 }
6344 for (i = len - 1; i >= 0; i--) {
6345 if(this.completeLayers || this.elements[i]){
6346 this.elements[i].prepareFrame(num - this.layers[i].st);
6347 }
6348 }
6349 if(this.globalData._mdf) {
6350 for (i = 0; i < len; i += 1) {
6351 if(this.completeLayers || this.elements[i]){
6352 this.elements[i].renderFrame();
6353 }
6354 }
6355 }
6356};
6357
6358SVGRenderer.prototype.appendElementInPos = function(element, pos){
6359 var newElement = element.getBaseElement();
6360 if(!newElement){
6361 return;
6362 }
6363 var i = 0;
6364 var nextElement;
6365 while(i<pos){
6366 if(this.elements[i] && this.elements[i]!== true && this.elements[i].getBaseElement()){
6367 nextElement = this.elements[i].getBaseElement();
6368 }
6369 i += 1;
6370 }
6371 if(nextElement){
6372 this.layerElement.insertBefore(newElement, nextElement);
6373 } else {
6374 this.layerElement.appendChild(newElement);
6375 }
6376};
6377
6378SVGRenderer.prototype.hide = function(){
6379 this.layerElement.style.display = 'none';
6380};
6381
6382SVGRenderer.prototype.show = function(){
6383 this.layerElement.style.display = 'block';
6384};
6385
6386function CanvasRenderer(animationItem, config){
6387 this.animationItem = animationItem;
6388 this.renderConfig = {
6389 clearCanvas: (config && config.clearCanvas !== undefined) ? config.clearCanvas : true,
6390 context: (config && config.context) || null,
6391 progressiveLoad: (config && config.progressiveLoad) || false,
6392 preserveAspectRatio: (config && config.preserveAspectRatio) || 'xMidYMid meet',
6393 imagePreserveAspectRatio: (config && config.imagePreserveAspectRatio) || 'xMidYMid slice',
6394 className: (config && config.className) || '',
6395 id: (config && config.id) || '',
6396 };
6397 this.renderConfig.dpr = (config && config.dpr) || 1;
6398 if (this.animationItem.wrapper) {
6399 this.renderConfig.dpr = (config && config.dpr) || window.devicePixelRatio || 1;
6400 }
6401 this.renderedFrame = -1;
6402 this.globalData = {
6403 frameNum: -1,
6404 _mdf: false,
6405 renderConfig: this.renderConfig,
6406 currentGlobalAlpha: -1
6407 };
6408 this.contextData = new CVContextData();
6409 this.elements = [];
6410 this.pendingElements = [];
6411 this.transformMat = new Matrix();
6412 this.completeLayers = false;
6413 this.rendererType = 'canvas';
6414}
6415extendPrototype([BaseRenderer],CanvasRenderer);
6416
6417CanvasRenderer.prototype.createShape = function (data) {
6418 return new CVShapeElement(data, this.globalData, this);
6419};
6420
6421CanvasRenderer.prototype.createText = function (data) {
6422 return new CVTextElement(data, this.globalData, this);
6423};
6424
6425CanvasRenderer.prototype.createImage = function (data) {
6426 return new CVImageElement(data, this.globalData, this);
6427};
6428
6429CanvasRenderer.prototype.createComp = function (data) {
6430 return new CVCompElement(data, this.globalData, this);
6431};
6432
6433CanvasRenderer.prototype.createSolid = function (data) {
6434 return new CVSolidElement(data, this.globalData, this);
6435};
6436
6437CanvasRenderer.prototype.createNull = SVGRenderer.prototype.createNull;
6438
6439CanvasRenderer.prototype.ctxTransform = function(props){
6440 if(props[0] === 1 && props[1] === 0 && props[4] === 0 && props[5] === 1 && props[12] === 0 && props[13] === 0){
6441 return;
6442 }
6443 if(!this.renderConfig.clearCanvas){
6444 this.canvasContext.transform(props[0],props[1],props[4],props[5],props[12],props[13]);
6445 return;
6446 }
6447 this.transformMat.cloneFromProps(props);
6448 var cProps = this.contextData.cTr.props;
6449 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]);
6450 //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]);
6451 this.contextData.cTr.cloneFromProps(this.transformMat.props);
6452 var trProps = this.contextData.cTr.props;
6453 this.canvasContext.setTransform(trProps[0],trProps[1],trProps[4],trProps[5],trProps[12],trProps[13]);
6454};
6455
6456CanvasRenderer.prototype.ctxOpacity = function(op){
6457 /*if(op === 1){
6458 return;
6459 }*/
6460 if(!this.renderConfig.clearCanvas){
6461 this.canvasContext.globalAlpha *= op < 0 ? 0 : op;
6462 this.globalData.currentGlobalAlpha = this.contextData.cO;
6463 return;
6464 }
6465 this.contextData.cO *= op < 0 ? 0 : op;
6466 if(this.globalData.currentGlobalAlpha !== this.contextData.cO) {
6467 this.canvasContext.globalAlpha = this.contextData.cO;
6468 this.globalData.currentGlobalAlpha = this.contextData.cO;
6469 }
6470};
6471
6472CanvasRenderer.prototype.reset = function(){
6473 if(!this.renderConfig.clearCanvas){
6474 this.canvasContext.restore();
6475 return;
6476 }
6477 this.contextData.reset();
6478};
6479
6480CanvasRenderer.prototype.save = function(actionFlag){
6481 if(!this.renderConfig.clearCanvas){
6482 this.canvasContext.save();
6483 return;
6484 }
6485 if(actionFlag){
6486 this.canvasContext.save();
6487 }
6488 var props = this.contextData.cTr.props;
6489 if(this.contextData._length <= this.contextData.cArrPos) {
6490 this.contextData.duplicate();
6491 }
6492 var i, arr = this.contextData.saved[this.contextData.cArrPos];
6493 for (i = 0; i < 16; i += 1) {
6494 arr[i] = props[i];
6495 }
6496 this.contextData.savedOp[this.contextData.cArrPos] = this.contextData.cO;
6497 this.contextData.cArrPos += 1;
6498};
6499
6500CanvasRenderer.prototype.restore = function(actionFlag){
6501 if(!this.renderConfig.clearCanvas){
6502 this.canvasContext.restore();
6503 return;
6504 }
6505 if(actionFlag){
6506 this.canvasContext.restore();
6507 this.globalData.blendMode = 'source-over';
6508 }
6509 this.contextData.cArrPos -= 1;
6510 var popped = this.contextData.saved[this.contextData.cArrPos];
6511 var i,arr = this.contextData.cTr.props;
6512 for(i=0;i<16;i+=1){
6513 arr[i] = popped[i];
6514 }
6515 this.canvasContext.setTransform(popped[0],popped[1],popped[4],popped[5],popped[12],popped[13]);
6516 popped = this.contextData.savedOp[this.contextData.cArrPos];
6517 this.contextData.cO = popped;
6518 if(this.globalData.currentGlobalAlpha !== popped) {
6519 this.canvasContext.globalAlpha = popped;
6520 this.globalData.currentGlobalAlpha = popped;
6521 }
6522};
6523
6524CanvasRenderer.prototype.configAnimation = function(animData){
6525 if(this.animationItem.wrapper){
6526 this.animationItem.container = createTag('canvas');
6527 this.animationItem.container.style.width = '100%';
6528 this.animationItem.container.style.height = '100%';
6529 //this.animationItem.container.style.transform = 'translate3d(0,0,0)';
6530 //this.animationItem.container.style.webkitTransform = 'translate3d(0,0,0)';
6531 this.animationItem.container.style.transformOrigin = this.animationItem.container.style.mozTransformOrigin = this.animationItem.container.style.webkitTransformOrigin = this.animationItem.container.style['-webkit-transform'] = "0px 0px 0px";
6532 this.animationItem.wrapper.appendChild(this.animationItem.container);
6533 this.canvasContext = this.animationItem.container.getContext('2d');
6534 if(this.renderConfig.className) {
6535 this.animationItem.container.setAttribute('class', this.renderConfig.className);
6536 }
6537 if(this.renderConfig.id) {
6538 this.animationItem.container.setAttribute('id', this.renderConfig.id);
6539 }
6540 }else{
6541 this.canvasContext = this.renderConfig.context;
6542 }
6543 this.data = animData;
6544 this.layers = animData.layers;
6545 this.transformCanvas = {
6546 w: animData.w,
6547 h:animData.h,
6548 sx:0,
6549 sy:0,
6550 tx:0,
6551 ty:0
6552 };
6553 this.setupGlobalData(animData, document.body);
6554 this.globalData.canvasContext = this.canvasContext;
6555 this.globalData.renderer = this;
6556 this.globalData.isDashed = false;
6557 this.globalData.progressiveLoad = this.renderConfig.progressiveLoad;
6558 this.globalData.transformCanvas = this.transformCanvas;
6559 this.elements = createSizedArray(animData.layers.length);
6560
6561 this.updateContainerSize();
6562};
6563
6564CanvasRenderer.prototype.updateContainerSize = function () {
6565 this.reset();
6566 var elementWidth,elementHeight;
6567 if(this.animationItem.wrapper && this.animationItem.container){
6568 elementWidth = this.animationItem.wrapper.offsetWidth;
6569 elementHeight = this.animationItem.wrapper.offsetHeight;
6570 this.animationItem.container.setAttribute('width',elementWidth * this.renderConfig.dpr );
6571 this.animationItem.container.setAttribute('height',elementHeight * this.renderConfig.dpr);
6572 }else{
6573 elementWidth = this.canvasContext.canvas.width * this.renderConfig.dpr;
6574 elementHeight = this.canvasContext.canvas.height * this.renderConfig.dpr;
6575 }
6576 var elementRel,animationRel;
6577 if(this.renderConfig.preserveAspectRatio.indexOf('meet') !== -1 || this.renderConfig.preserveAspectRatio.indexOf('slice') !== -1){
6578 var par = this.renderConfig.preserveAspectRatio.split(' ');
6579 var fillType = par[1] || 'meet';
6580 var pos = par[0] || 'xMidYMid';
6581 var xPos = pos.substr(0,4);
6582 var yPos = pos.substr(4);
6583 elementRel = elementWidth/elementHeight;
6584 animationRel = this.transformCanvas.w/this.transformCanvas.h;
6585 if(animationRel>elementRel && fillType === 'meet' || animationRel<elementRel && fillType === 'slice'){
6586 this.transformCanvas.sx = elementWidth/(this.transformCanvas.w/this.renderConfig.dpr);
6587 this.transformCanvas.sy = elementWidth/(this.transformCanvas.w/this.renderConfig.dpr);
6588 }else{
6589 this.transformCanvas.sx = elementHeight/(this.transformCanvas.h / this.renderConfig.dpr);
6590 this.transformCanvas.sy = elementHeight/(this.transformCanvas.h / this.renderConfig.dpr);
6591 }
6592
6593 if(xPos === 'xMid' && ((animationRel<elementRel && fillType==='meet') || (animationRel>elementRel && fillType === 'slice'))){
6594 this.transformCanvas.tx = (elementWidth-this.transformCanvas.w*(elementHeight/this.transformCanvas.h))/2*this.renderConfig.dpr;
6595 } else if(xPos === 'xMax' && ((animationRel<elementRel && fillType==='meet') || (animationRel>elementRel && fillType === 'slice'))){
6596 this.transformCanvas.tx = (elementWidth-this.transformCanvas.w*(elementHeight/this.transformCanvas.h))*this.renderConfig.dpr;
6597 } else {
6598 this.transformCanvas.tx = 0;
6599 }
6600 if(yPos === 'YMid' && ((animationRel>elementRel && fillType==='meet') || (animationRel<elementRel && fillType === 'slice'))){
6601 this.transformCanvas.ty = ((elementHeight-this.transformCanvas.h*(elementWidth/this.transformCanvas.w))/2)*this.renderConfig.dpr;
6602 } else if(yPos === 'YMax' && ((animationRel>elementRel && fillType==='meet') || (animationRel<elementRel && fillType === 'slice'))){
6603 this.transformCanvas.ty = ((elementHeight-this.transformCanvas.h*(elementWidth/this.transformCanvas.w)))*this.renderConfig.dpr;
6604 } else {
6605 this.transformCanvas.ty = 0;
6606 }
6607
6608 }else if(this.renderConfig.preserveAspectRatio == 'none'){
6609 this.transformCanvas.sx = elementWidth/(this.transformCanvas.w/this.renderConfig.dpr);
6610 this.transformCanvas.sy = elementHeight/(this.transformCanvas.h/this.renderConfig.dpr);
6611 this.transformCanvas.tx = 0;
6612 this.transformCanvas.ty = 0;
6613 }else{
6614 this.transformCanvas.sx = this.renderConfig.dpr;
6615 this.transformCanvas.sy = this.renderConfig.dpr;
6616 this.transformCanvas.tx = 0;
6617 this.transformCanvas.ty = 0;
6618 }
6619 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];
6620 /*var i, len = this.elements.length;
6621 for(i=0;i<len;i+=1){
6622 if(this.elements[i] && this.elements[i].data.ty === 0){
6623 this.elements[i].resize(this.globalData.transformCanvas);
6624 }
6625 }*/
6626 this.ctxTransform(this.transformCanvas.props);
6627 this.canvasContext.beginPath();
6628 this.canvasContext.rect(0,0,this.transformCanvas.w,this.transformCanvas.h);
6629 this.canvasContext.closePath();
6630 this.canvasContext.clip();
6631
6632 this.renderFrame(this.renderedFrame, true);
6633};
6634
6635CanvasRenderer.prototype.destroy = function () {
6636 if(this.renderConfig.clearCanvas) {
6637 this.animationItem.wrapper.innerText = '';
6638 }
6639 var i, len = this.layers ? this.layers.length : 0;
6640 for (i = len - 1; i >= 0; i-=1) {
6641 if(this.elements[i]) {
6642 this.elements[i].destroy();
6643 }
6644 }
6645 this.elements.length = 0;
6646 this.globalData.canvasContext = null;
6647 this.animationItem.container = null;
6648 this.destroyed = true;
6649};
6650
6651CanvasRenderer.prototype.renderFrame = function(num, forceRender){
6652 if((this.renderedFrame === num && this.renderConfig.clearCanvas === true && !forceRender) || this.destroyed || num === -1){
6653 return;
6654 }
6655 this.renderedFrame = num;
6656 this.globalData.frameNum = num - this.animationItem._isFirstFrame;
6657 this.globalData.frameId += 1;
6658 this.globalData._mdf = !this.renderConfig.clearCanvas || forceRender;
6659 this.globalData.projectInterface.currentFrame = num;
6660
6661 // console.log('--------');
6662 // console.log('NEW: ',num);
6663 var i, len = this.layers.length;
6664 if(!this.completeLayers){
6665 this.checkLayers(num);
6666 }
6667
6668 for (i = 0; i < len; i++) {
6669 if(this.completeLayers || this.elements[i]){
6670 this.elements[i].prepareFrame(num - this.layers[i].st);
6671 }
6672 }
6673 if(this.globalData._mdf) {
6674 if(this.renderConfig.clearCanvas === true){
6675 this.canvasContext.clearRect(0, 0, this.transformCanvas.w, this.transformCanvas.h);
6676 }else{
6677 this.save();
6678 }
6679 for (i = len - 1; i >= 0; i-=1) {
6680 if(this.completeLayers || this.elements[i]){
6681 this.elements[i].renderFrame();
6682 }
6683 }
6684 if(this.renderConfig.clearCanvas !== true){
6685 this.restore();
6686 }
6687 }
6688};
6689
6690CanvasRenderer.prototype.buildItem = function(pos){
6691 var elements = this.elements;
6692 if(elements[pos] || this.layers[pos].ty == 99){
6693 return;
6694 }
6695 var element = this.createItem(this.layers[pos], this,this.globalData);
6696 elements[pos] = element;
6697 element.initExpressions();
6698 /*if(this.layers[pos].ty === 0){
6699 element.resize(this.globalData.transformCanvas);
6700 }*/
6701};
6702
6703CanvasRenderer.prototype.checkPendingElements = function(){
6704 while(this.pendingElements.length){
6705 var element = this.pendingElements.pop();
6706 element.checkParenting();
6707 }
6708};
6709
6710CanvasRenderer.prototype.hide = function(){
6711 this.animationItem.container.style.display = 'none';
6712};
6713
6714CanvasRenderer.prototype.show = function(){
6715 this.animationItem.container.style.display = 'block';
6716};
6717
6718function MaskElement(data,element,globalData) {
6719 this.data = data;
6720 this.element = element;
6721 this.globalData = globalData;
6722 this.storedData = [];
6723 this.masksProperties = this.data.masksProperties || [];
6724 this.maskElement = null;
6725 var defs = this.globalData.defs;
6726 var i, len = this.masksProperties ? this.masksProperties.length : 0;
6727 this.viewData = createSizedArray(len);
6728 this.solidPath = '';
6729
6730
6731 var path, properties = this.masksProperties;
6732 var count = 0;
6733 var currentMasks = [];
6734 var j, jLen;
6735 var layerId = createElementID();
6736 var rect, expansor, feMorph,x;
6737 var maskType = 'clipPath', maskRef = 'clip-path';
6738 for (i = 0; i < len; i++) {
6739 if((properties[i].mode !== 'a' && properties[i].mode !== 'n')|| properties[i].inv || properties[i].o.k !== 100 || properties[i].o.x){
6740 maskType = 'mask';
6741 maskRef = 'mask';
6742 }
6743
6744 if((properties[i].mode == 's' || properties[i].mode == 'i') && count === 0){
6745 rect = createNS( 'rect');
6746 rect.setAttribute('fill', '#ffffff');
6747 rect.setAttribute('width', this.element.comp.data.w || 0);
6748 rect.setAttribute('height', this.element.comp.data.h || 0);
6749 currentMasks.push(rect);
6750 } else {
6751 rect = null;
6752 }
6753
6754 path = createNS( 'path');
6755 if(properties[i].mode == 'n') {
6756 // TODO move this to a factory or to a constructor
6757 this.viewData[i] = {
6758 op: PropertyFactory.getProp(this.element,properties[i].o,0,0.01,this.element),
6759 prop: ShapePropertyFactory.getShapeProp(this.element,properties[i],3),
6760 elem: path,
6761 lastPath: ''
6762 };
6763 defs.appendChild(path);
6764 continue;
6765 }
6766 count += 1;
6767
6768 path.setAttribute('fill', properties[i].mode === 's' ? '#000000':'#ffffff');
6769 path.setAttribute('clip-rule','nonzero');
6770 var filterID;
6771
6772 if (properties[i].x.k !== 0) {
6773 maskType = 'mask';
6774 maskRef = 'mask';
6775 x = PropertyFactory.getProp(this.element,properties[i].x,0,null,this.element);
6776 filterID = createElementID();
6777 expansor = createNS('filter');
6778 expansor.setAttribute('id',filterID);
6779 feMorph = createNS('feMorphology');
6780 feMorph.setAttribute('operator','erode');
6781 feMorph.setAttribute('in','SourceGraphic');
6782 feMorph.setAttribute('radius','0');
6783 expansor.appendChild(feMorph);
6784 defs.appendChild(expansor);
6785 path.setAttribute('stroke', properties[i].mode === 's' ? '#000000':'#ffffff');
6786 } else {
6787 feMorph = null;
6788 x = null;
6789 }
6790
6791 // TODO move this to a factory or to a constructor
6792 this.storedData[i] = {
6793 elem: path,
6794 x: x,
6795 expan: feMorph,
6796 lastPath: '',
6797 lastOperator:'',
6798 filterId:filterID,
6799 lastRadius:0
6800 };
6801 if(properties[i].mode == 'i'){
6802 jLen = currentMasks.length;
6803 var g = createNS('g');
6804 for(j=0;j<jLen;j+=1){
6805 g.appendChild(currentMasks[j]);
6806 }
6807 var mask = createNS('mask');
6808 mask.setAttribute('mask-type','alpha');
6809 mask.setAttribute('id',layerId+'_'+count);
6810 mask.appendChild(path);
6811 defs.appendChild(mask);
6812 g.setAttribute('mask','url(' + locationHref + '#'+layerId+'_'+count+')');
6813
6814 currentMasks.length = 0;
6815 currentMasks.push(g);
6816 }else{
6817 currentMasks.push(path);
6818 }
6819 if(properties[i].inv && !this.solidPath){
6820 this.solidPath = this.createLayerSolidPath();
6821 }
6822 // TODO move this to a factory or to a constructor
6823 this.viewData[i] = {
6824 elem: path,
6825 lastPath: '',
6826 op: PropertyFactory.getProp(this.element,properties[i].o,0,0.01,this.element),
6827 prop:ShapePropertyFactory.getShapeProp(this.element,properties[i],3),
6828 invRect: rect
6829 };
6830 if(!this.viewData[i].prop.k){
6831 this.drawPath(properties[i],this.viewData[i].prop.v,this.viewData[i]);
6832 }
6833 }
6834
6835 this.maskElement = createNS( maskType);
6836
6837 len = currentMasks.length;
6838 for(i=0;i<len;i+=1){
6839 this.maskElement.appendChild(currentMasks[i]);
6840 }
6841
6842 if(count > 0){
6843 this.maskElement.setAttribute('id', layerId);
6844 this.element.maskedElement.setAttribute(maskRef, "url(" + locationHref + "#" + layerId + ")");
6845 defs.appendChild(this.maskElement);
6846 }
6847 if (this.viewData.length) {
6848 this.element.addRenderableComponent(this);
6849 }
6850
6851}
6852
6853MaskElement.prototype.getMaskProperty = function(pos){
6854 return this.viewData[pos].prop;
6855};
6856
6857MaskElement.prototype.renderFrame = function (isFirstFrame) {
6858 var finalMat = this.element.finalTransform.mat;
6859 var i, len = this.masksProperties.length;
6860 for (i = 0; i < len; i++) {
6861 if(this.viewData[i].prop._mdf || isFirstFrame){
6862 this.drawPath(this.masksProperties[i],this.viewData[i].prop.v,this.viewData[i]);
6863 }
6864 if(this.viewData[i].op._mdf || isFirstFrame){
6865 this.viewData[i].elem.setAttribute('fill-opacity',this.viewData[i].op.v);
6866 }
6867 if(this.masksProperties[i].mode !== 'n'){
6868 if(this.viewData[i].invRect && (this.element.finalTransform.mProp._mdf || isFirstFrame)){
6869 this.viewData[i].invRect.setAttribute('transform', finalMat.getInverseMatrix().to2dCSS())
6870 }
6871 if(this.storedData[i].x && (this.storedData[i].x._mdf || isFirstFrame)){
6872 var feMorph = this.storedData[i].expan;
6873 if(this.storedData[i].x.v < 0){
6874 if(this.storedData[i].lastOperator !== 'erode'){
6875 this.storedData[i].lastOperator = 'erode';
6876 this.storedData[i].elem.setAttribute('filter','url(' + locationHref + '#'+this.storedData[i].filterId+')');
6877 }
6878 feMorph.setAttribute('radius',-this.storedData[i].x.v);
6879 }else{
6880 if(this.storedData[i].lastOperator !== 'dilate'){
6881 this.storedData[i].lastOperator = 'dilate';
6882 this.storedData[i].elem.setAttribute('filter',null);
6883 }
6884 this.storedData[i].elem.setAttribute('stroke-width', this.storedData[i].x.v*2);
6885
6886 }
6887 }
6888 }
6889 }
6890};
6891
6892MaskElement.prototype.getMaskelement = function () {
6893 return this.maskElement;
6894};
6895
6896MaskElement.prototype.createLayerSolidPath = function(){
6897 var path = 'M0,0 ';
6898 path += ' h' + this.globalData.compSize.w ;
6899 path += ' v' + this.globalData.compSize.h ;
6900 path += ' h-' + this.globalData.compSize.w ;
6901 path += ' v-' + this.globalData.compSize.h + ' ';
6902 return path;
6903};
6904
6905MaskElement.prototype.drawPath = function(pathData,pathNodes,viewData){
6906 var pathString = " M"+pathNodes.v[0][0]+','+pathNodes.v[0][1];
6907 var i, len;
6908 len = pathNodes._length;
6909 for(i=1;i<len;i+=1){
6910 //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];
6911 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];
6912 }
6913 //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];
6914 if(pathNodes.c && len > 1){
6915 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];
6916 }
6917 //pathNodes.__renderedString = pathString;
6918
6919 if(viewData.lastPath !== pathString){
6920 var pathShapeValue = '';
6921 if(viewData.elem){
6922 if(pathNodes.c){
6923 pathShapeValue = pathData.inv ? this.solidPath + pathString : pathString;
6924 }
6925 viewData.elem.setAttribute('d',pathShapeValue);
6926 }
6927 viewData.lastPath = pathString;
6928 }
6929};
6930
6931MaskElement.prototype.destroy = function(){
6932 this.element = null;
6933 this.globalData = null;
6934 this.maskElement = null;
6935 this.data = null;
6936 this.masksProperties = null;
6937};
6938
6939/**
6940 * @file
6941 * Handles AE's layer parenting property.
6942 *
6943 */
6944
6945function HierarchyElement(){}
6946
6947HierarchyElement.prototype = {
6948 /**
6949 * @function
6950 * Initializes hierarchy properties
6951 *
6952 */
6953 initHierarchy: function() {
6954 //element's parent list
6955 this.hierarchy = [];
6956 //if element is parent of another layer _isParent will be true
6957 this._isParent = false;
6958 this.checkParenting();
6959 },
6960 /**
6961 * @function
6962 * Sets layer's hierarchy.
6963 * @param {array} hierarch
6964 * layer's parent list
6965 *
6966 */
6967 setHierarchy: function(hierarchy){
6968 this.hierarchy = hierarchy;
6969 },
6970 /**
6971 * @function
6972 * Sets layer as parent.
6973 *
6974 */
6975 setAsParent: function() {
6976 this._isParent = true;
6977 },
6978 /**
6979 * @function
6980 * Searches layer's parenting chain
6981 *
6982 */
6983 checkParenting: function(){
6984 if (this.data.parent !== undefined){
6985 this.comp.buildElementParenting(this, this.data.parent, []);
6986 }
6987 }
6988};
6989/**
6990 * @file
6991 * Handles element's layer frame update.
6992 * Checks layer in point and out point
6993 *
6994 */
6995
6996function FrameElement(){}
6997
6998FrameElement.prototype = {
6999 /**
7000 * @function
7001 * Initializes frame related properties.
7002 *
7003 */
7004 initFrame: function(){
7005 //set to true when inpoint is rendered
7006 this._isFirstFrame = false;
7007 //list of animated properties
7008 this.dynamicProperties = [];
7009 // If layer has been modified in current tick this will be true
7010 this._mdf = false;
7011 },
7012 /**
7013 * @function
7014 * Calculates all dynamic values
7015 *
7016 * @param {number} num
7017 * current frame number in Layer's time
7018 * @param {boolean} isVisible
7019 * if layers is currently in range
7020 *
7021 */
7022 prepareProperties: function(num, isVisible) {
7023 var i, len = this.dynamicProperties.length;
7024 for (i = 0;i < len; i += 1) {
7025 if (isVisible || (this._isParent && this.dynamicProperties[i].propType === 'transform')) {
7026 this.dynamicProperties[i].getValue();
7027 if (this.dynamicProperties[i]._mdf) {
7028 this.globalData._mdf = true;
7029 this._mdf = true;
7030 }
7031 }
7032 }
7033 },
7034 addDynamicProperty: function(prop) {
7035 if(this.dynamicProperties.indexOf(prop) === -1) {
7036 this.dynamicProperties.push(prop);
7037 }
7038 }
7039};
7040function TransformElement(){}
7041
7042TransformElement.prototype = {
7043 initTransform: function() {
7044 this.finalTransform = {
7045 mProp: this.data.ks ? TransformPropertyFactory.getTransformProperty(this, this.data.ks, this) : {o:0},
7046 _matMdf: false,
7047 _opMdf: false,
7048 mat: new Matrix()
7049 };
7050 if (this.data.ao) {
7051 this.finalTransform.mProp.autoOriented = true;
7052 }
7053
7054 //TODO: check TYPE 11: Guided elements
7055 if (this.data.ty !== 11) {
7056 //this.createElements();
7057 }
7058 },
7059 renderTransform: function() {
7060
7061 this.finalTransform._opMdf = this.finalTransform.mProp.o._mdf || this._isFirstFrame;
7062 this.finalTransform._matMdf = this.finalTransform.mProp._mdf || this._isFirstFrame;
7063
7064 if (this.hierarchy) {
7065 var mat;
7066 var finalMat = this.finalTransform.mat;
7067 var i = 0, len = this.hierarchy.length;
7068 //Checking if any of the transformation matrices in the hierarchy chain has changed.
7069 if (!this.finalTransform._matMdf) {
7070 while (i < len) {
7071 if (this.hierarchy[i].finalTransform.mProp._mdf) {
7072 this.finalTransform._matMdf = true;
7073 break;
7074 }
7075 i += 1;
7076 }
7077 }
7078
7079 if (this.finalTransform._matMdf) {
7080 mat = this.finalTransform.mProp.v.props;
7081 finalMat.cloneFromProps(mat);
7082 for (i = 0; i < len; i += 1) {
7083 mat = this.hierarchy[i].finalTransform.mProp.v.props;
7084 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]);
7085 }
7086 }
7087 }
7088 },
7089 globalToLocal: function(pt) {
7090 var transforms = [];
7091 transforms.push(this.finalTransform);
7092 var flag = true;
7093 var comp = this.comp;
7094 while (flag) {
7095 if (comp.finalTransform) {
7096 if (comp.data.hasMask) {
7097 transforms.splice(0, 0, comp.finalTransform);
7098 }
7099 comp = comp.comp;
7100 } else {
7101 flag = false;
7102 }
7103 }
7104 var i, len = transforms.length,ptNew;
7105 for (i = 0; i < len; i += 1) {
7106 ptNew = transforms[i].mat.applyToPointArray(0, 0, 0);
7107 //ptNew = transforms[i].mat.applyToPointArray(pt[0],pt[1],pt[2]);
7108 pt = [pt[0] - ptNew[0], pt[1] - ptNew[1], 0];
7109 }
7110 return pt;
7111 },
7112 mHelper: new Matrix()
7113};
7114function RenderableElement(){
7115
7116}
7117
7118RenderableElement.prototype = {
7119 initRenderable: function() {
7120 //layer's visibility related to inpoint and outpoint. Rename isVisible to isInRange
7121 this.isInRange = false;
7122 //layer's display state
7123 this.hidden = false;
7124 // If layer's transparency equals 0, it can be hidden
7125 this.isTransparent = false;
7126 //list of animated components
7127 this.renderableComponents = [];
7128 },
7129 addRenderableComponent: function(component) {
7130 if(this.renderableComponents.indexOf(component) === -1) {
7131 this.renderableComponents.push(component);
7132 }
7133 },
7134 removeRenderableComponent: function(component) {
7135 if(this.renderableComponents.indexOf(component) !== -1) {
7136 this.renderableComponents.splice(this.renderableComponents.indexOf(component), 1);
7137 }
7138 },
7139 prepareRenderableFrame: function(num) {
7140 this.checkLayerLimits(num);
7141 },
7142 checkTransparency: function(){
7143 if(this.finalTransform.mProp.o.v <= 0) {
7144 if(!this.isTransparent && this.globalData.renderConfig.hideOnTransparent){
7145 this.isTransparent = true;
7146 this.hide();
7147 }
7148 } else if(this.isTransparent) {
7149 this.isTransparent = false;
7150 this.show();
7151 }
7152 },
7153 /**
7154 * @function
7155 * Initializes frame related properties.
7156 *
7157 * @param {number} num
7158 * current frame number in Layer's time
7159 *
7160 */
7161 checkLayerLimits: function(num) {
7162 if(this.data.ip - this.data.st <= num && this.data.op - this.data.st > num)
7163 {
7164 if(this.isInRange !== true){
7165 this.globalData._mdf = true;
7166 this._mdf = true;
7167 this.isInRange = true;
7168 this.show();
7169 }
7170 } else {
7171 if(this.isInRange !== false){
7172 this.globalData._mdf = true;
7173 this.isInRange = false;
7174 this.hide();
7175 }
7176 }
7177 },
7178 renderRenderable: function() {
7179 var i, len = this.renderableComponents.length;
7180 for(i = 0; i < len; i += 1) {
7181 this.renderableComponents[i].renderFrame(this._isFirstFrame);
7182 }
7183 /*this.maskManager.renderFrame(this.finalTransform.mat);
7184 this.renderableEffectsManager.renderFrame(this._isFirstFrame);*/
7185 },
7186 sourceRectAtTime: function(){
7187 return {
7188 top:0,
7189 left:0,
7190 width:100,
7191 height:100
7192 };
7193 },
7194 getLayerSize: function(){
7195 if(this.data.ty === 5){
7196 return {w:this.data.textData.width,h:this.data.textData.height};
7197 }else{
7198 return {w:this.data.width,h:this.data.height};
7199 }
7200 }
7201};
7202function RenderableDOMElement() {}
7203
7204(function(){
7205 var _prototype = {
7206 initElement: function(data,globalData,comp) {
7207 this.initFrame();
7208 this.initBaseData(data, globalData, comp);
7209 this.initTransform(data, globalData, comp);
7210 this.initHierarchy();
7211 this.initRenderable();
7212 this.initRendererElement();
7213 this.createContainerElements();
7214 this.createRenderableComponents();
7215 this.createContent();
7216 this.hide();
7217 },
7218 hide: function(){
7219 if (!this.hidden && (!this.isInRange || this.isTransparent)) {
7220 var elem = this.baseElement || this.layerElement;
7221 elem.style.display = 'none';
7222 this.hidden = true;
7223 }
7224 },
7225 show: function(){
7226 if (this.isInRange && !this.isTransparent){
7227 if (!this.data.hd) {
7228 var elem = this.baseElement || this.layerElement;
7229 elem.style.display = 'block';
7230 }
7231 this.hidden = false;
7232 this._isFirstFrame = true;
7233 }
7234 },
7235 renderFrame: function() {
7236 //If it is exported as hidden (data.hd === true) no need to render
7237 //If it is not visible no need to render
7238 if (this.data.hd || this.hidden) {
7239 return;
7240 }
7241 this.renderTransform();
7242 this.renderRenderable();
7243 this.renderElement();
7244 this.renderInnerContent();
7245 if (this._isFirstFrame) {
7246 this._isFirstFrame = false;
7247 }
7248 },
7249 renderInnerContent: function() {},
7250 prepareFrame: function(num) {
7251 this._mdf = false;
7252 this.prepareRenderableFrame(num);
7253 this.prepareProperties(num, this.isInRange);
7254 this.checkTransparency();
7255 },
7256 destroy: function(){
7257 this.innerElem = null;
7258 this.destroyBaseElement();
7259 }
7260 };
7261 extendPrototype([RenderableElement, createProxyFunction(_prototype)], RenderableDOMElement);
7262}());
7263function ProcessedElement(element, position) {
7264 this.elem = element;
7265 this.pos = position;
7266}
7267function SVGShapeData(transformers, level, shape) {
7268 this.caches = [];
7269 this.styles = [];
7270 this.transformers = transformers;
7271 this.lStr = '';
7272 this.sh = shape;
7273 this.lvl = level;
7274 //TODO find if there are some cases where _isAnimated can be false.
7275 // For now, since shapes add up with other shapes. They have to be calculated every time.
7276 // One way of finding out is checking if all styles associated to this shape depend only of this shape
7277 this._isAnimated = !!shape.k;
7278 // TODO: commenting this for now since all shapes are animated
7279 var i = 0, len = transformers.length;
7280 while(i < len) {
7281 if(transformers[i].mProps.dynamicProperties.length) {
7282 this._isAnimated = true;
7283 break;
7284 }
7285 i += 1;
7286 }
7287}
7288
7289SVGShapeData.prototype.setAsAnimated = function() {
7290 this._isAnimated = true;
7291}
7292function ShapeGroupData() {
7293 this.it = [];
7294 this.prevViewData = [];
7295 this.gr = createNS('g');
7296}
7297function ShapeTransformManager() {
7298 this.sequences = {};
7299 this.sequenceList = [];
7300 this.transform_key_count = 0;
7301}
7302
7303ShapeTransformManager.prototype = {
7304 addTransformSequence: function(transforms) {
7305 var i, len = transforms.length;
7306 var key = '_';
7307 for(i = 0; i < len; i += 1) {
7308 key += transforms[i].transform.key + '_';
7309 }
7310 var sequence = this.sequences[key];
7311 if(!sequence) {
7312 sequence = {
7313 transforms: [].concat(transforms),
7314 finalTransform: new Matrix(),
7315 _mdf: false
7316 };
7317 this.sequences[key] = sequence;
7318 this.sequenceList.push(sequence);
7319 }
7320 return sequence;
7321 },
7322 processSequence: function(sequence, isFirstFrame) {
7323 var i = 0, len = sequence.transforms.length, _mdf = isFirstFrame;
7324 while (i < len && !isFirstFrame) {
7325 if (sequence.transforms[i].transform.mProps._mdf) {
7326 _mdf = true;
7327 break;
7328 }
7329 i += 1
7330 }
7331 if (_mdf) {
7332 var props;
7333 sequence.finalTransform.reset();
7334 for (i = len - 1; i >= 0; i -= 1) {
7335 props = sequence.transforms[i].transform.mProps.v.props;
7336 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]);
7337 }
7338 }
7339 sequence._mdf = _mdf;
7340
7341 },
7342 processSequences: function(isFirstFrame) {
7343 var i, len = this.sequenceList.length;
7344 for (i = 0; i < len; i += 1) {
7345 this.processSequence(this.sequenceList[i], isFirstFrame);
7346 }
7347
7348 },
7349 getNewKey: function() {
7350 return '_' + this.transform_key_count++;
7351 }
7352}
7353function CVShapeData(element, data, styles, transformsManager) {
7354 this.styledShapes = [];
7355 this.tr = [0,0,0,0,0,0];
7356 var ty = 4;
7357 if(data.ty == 'rc'){
7358 ty = 5;
7359 }else if(data.ty == 'el'){
7360 ty = 6;
7361 }else if(data.ty == 'sr'){
7362 ty = 7;
7363 }
7364 this.sh = ShapePropertyFactory.getShapeProp(element,data,ty,element);
7365 var i , len = styles.length,styledShape;
7366 for (i = 0; i < len; i += 1) {
7367 if (!styles[i].closed) {
7368 styledShape = {
7369 transforms: transformsManager.addTransformSequence(styles[i].transforms),
7370 trNodes: []
7371 }
7372 this.styledShapes.push(styledShape);
7373 styles[i].elements.push(styledShape);
7374 }
7375 }
7376}
7377
7378CVShapeData.prototype.setAsAnimated = SVGShapeData.prototype.setAsAnimated;
7379function BaseElement(){
7380}
7381
7382BaseElement.prototype = {
7383 checkMasks: function(){
7384 if(!this.data.hasMask){
7385 return false;
7386 }
7387 var i = 0, len = this.data.masksProperties.length;
7388 while(i<len) {
7389 if((this.data.masksProperties[i].mode !== 'n' && this.data.masksProperties[i].cl !== false)) {
7390 return true;
7391 }
7392 i += 1;
7393 }
7394 return false;
7395 },
7396 initExpressions: function(){
7397 this.layerInterface = LayerExpressionInterface(this);
7398 if(this.data.hasMask && this.maskManager) {
7399 this.layerInterface.registerMaskInterface(this.maskManager);
7400 }
7401 var effectsInterface = EffectsExpressionInterface.createEffectsInterface(this,this.layerInterface);
7402 this.layerInterface.registerEffectsInterface(effectsInterface);
7403
7404 if(this.data.ty === 0 || this.data.xt){
7405 this.compInterface = CompExpressionInterface(this);
7406 } else if(this.data.ty === 4){
7407 this.layerInterface.shapeInterface = ShapeExpressionInterface(this.shapesData,this.itemsData,this.layerInterface);
7408 this.layerInterface.content = this.layerInterface.shapeInterface;
7409 } else if(this.data.ty === 5){
7410 this.layerInterface.textInterface = TextExpressionInterface(this);
7411 this.layerInterface.text = this.layerInterface.textInterface;
7412 }
7413 },
7414 setBlendMode: function(){
7415 var blendModeValue = getBlendMode(this.data.bm);
7416 var elem = this.baseElement || this.layerElement;
7417
7418 elem.style['mix-blend-mode'] = blendModeValue;
7419 },
7420 initBaseData: function(data, globalData, comp){
7421 this.globalData = globalData;
7422 this.comp = comp;
7423 this.data = data;
7424 this.layerId = createElementID();
7425
7426 //Stretch factor for old animations missing this property.
7427 if(!this.data.sr){
7428 this.data.sr = 1;
7429 }
7430 // effects manager
7431 this.effectsManager = new EffectsManager(this.data,this,this.dynamicProperties);
7432
7433 },
7434 getType: function(){
7435 return this.type;
7436 }
7437 ,sourceRectAtTime: function(){}
7438}
7439function NullElement(data,globalData,comp){
7440 this.initFrame();
7441 this.initBaseData(data, globalData, comp);
7442 this.initFrame();
7443 this.initTransform(data, globalData, comp);
7444 this.initHierarchy();
7445}
7446
7447NullElement.prototype.prepareFrame = function(num) {
7448 this.prepareProperties(num, true);
7449};
7450
7451NullElement.prototype.renderFrame = function() {
7452};
7453
7454NullElement.prototype.getBaseElement = function() {
7455 return null;
7456};
7457
7458NullElement.prototype.destroy = function() {
7459};
7460
7461NullElement.prototype.sourceRectAtTime = function() {
7462};
7463
7464NullElement.prototype.hide = function() {
7465};
7466
7467extendPrototype([BaseElement,TransformElement,HierarchyElement,FrameElement], NullElement);
7468
7469function SVGBaseElement(){
7470}
7471
7472SVGBaseElement.prototype = {
7473 initRendererElement: function() {
7474 this.layerElement = createNS('g');
7475 },
7476 createContainerElements: function(){
7477 this.matteElement = createNS('g');
7478 this.transformedElement = this.layerElement;
7479 this.maskedElement = this.layerElement;
7480 this._sizeChanged = false;
7481 var layerElementParent = null;
7482 //If this layer acts as a mask for the following layer
7483 var filId, fil, gg;
7484 if (this.data.td) {
7485 if (this.data.td == 3 || this.data.td == 1) {
7486 var masker = createNS('mask');
7487 masker.setAttribute('id', this.layerId);
7488 masker.setAttribute('mask-type', this.data.td == 3 ? 'luminance' : 'alpha');
7489 masker.appendChild(this.layerElement);
7490 layerElementParent = masker;
7491 this.globalData.defs.appendChild(masker);
7492 // This is only for IE and Edge when mask if of type alpha
7493 if (!featureSupport.maskType && this.data.td == 1) {
7494 masker.setAttribute('mask-type', 'luminance');
7495 filId = createElementID();
7496 fil = filtersFactory.createFilter(filId);
7497 this.globalData.defs.appendChild(fil);
7498 fil.appendChild(filtersFactory.createAlphaToLuminanceFilter());
7499 gg = createNS('g');
7500 gg.appendChild(this.layerElement);
7501 layerElementParent = gg;
7502 masker.appendChild(gg);
7503 gg.setAttribute('filter','url(' + locationHref + '#' + filId + ')');
7504 }
7505 } else if(this.data.td == 2) {
7506 var maskGroup = createNS('mask');
7507 maskGroup.setAttribute('id', this.layerId);
7508 maskGroup.setAttribute('mask-type','alpha');
7509 var maskGrouper = createNS('g');
7510 maskGroup.appendChild(maskGrouper);
7511 filId = createElementID();
7512 fil = filtersFactory.createFilter(filId);
7513 ////
7514
7515 // This solution doesn't work on Android when meta tag with viewport attribute is set
7516 /*var feColorMatrix = createNS('feColorMatrix');
7517 feColorMatrix.setAttribute('type', 'matrix');
7518 feColorMatrix.setAttribute('color-interpolation-filters', 'sRGB');
7519 feColorMatrix.setAttribute('values','1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 -1 1');
7520 fil.appendChild(feColorMatrix);*/
7521 ////
7522 var feCTr = createNS('feComponentTransfer');
7523 feCTr.setAttribute('in','SourceGraphic');
7524 fil.appendChild(feCTr);
7525 var feFunc = createNS('feFuncA');
7526 feFunc.setAttribute('type','table');
7527 feFunc.setAttribute('tableValues','1.0 0.0');
7528 feCTr.appendChild(feFunc);
7529 ////
7530 this.globalData.defs.appendChild(fil);
7531 var alphaRect = createNS('rect');
7532 alphaRect.setAttribute('width', this.comp.data.w);
7533 alphaRect.setAttribute('height', this.comp.data.h);
7534 alphaRect.setAttribute('x','0');
7535 alphaRect.setAttribute('y','0');
7536 alphaRect.setAttribute('fill','#ffffff');
7537 alphaRect.setAttribute('opacity','0');
7538 maskGrouper.setAttribute('filter', 'url(' + locationHref + '#'+filId+')');
7539 maskGrouper.appendChild(alphaRect);
7540 maskGrouper.appendChild(this.layerElement);
7541 layerElementParent = maskGrouper;
7542 if (!featureSupport.maskType) {
7543 maskGroup.setAttribute('mask-type', 'luminance');
7544 fil.appendChild(filtersFactory.createAlphaToLuminanceFilter());
7545 gg = createNS('g');
7546 maskGrouper.appendChild(alphaRect);
7547 gg.appendChild(this.layerElement);
7548 layerElementParent = gg;
7549 maskGrouper.appendChild(gg);
7550 }
7551 this.globalData.defs.appendChild(maskGroup);
7552 }
7553 } else if (this.data.tt) {
7554 this.matteElement.appendChild(this.layerElement);
7555 layerElementParent = this.matteElement;
7556 this.baseElement = this.matteElement;
7557 } else {
7558 this.baseElement = this.layerElement;
7559 }
7560 if (this.data.ln) {
7561 this.layerElement.setAttribute('id', this.data.ln);
7562 }
7563 if (this.data.cl) {
7564 this.layerElement.setAttribute('class', this.data.cl);
7565 }
7566 //Clipping compositions to hide content that exceeds boundaries. If collapsed transformations is on, component should not be clipped
7567 if (this.data.ty === 0 && !this.data.hd) {
7568 var cp = createNS( 'clipPath');
7569 var pt = createNS('path');
7570 pt.setAttribute('d','M0,0 L' + this.data.w + ',0' + ' L' + this.data.w + ',' + this.data.h + ' L0,' + this.data.h + 'z');
7571 var clipId = createElementID();
7572 cp.setAttribute('id',clipId);
7573 cp.appendChild(pt);
7574 this.globalData.defs.appendChild(cp);
7575
7576 if (this.checkMasks()) {
7577 var cpGroup = createNS('g');
7578 cpGroup.setAttribute('clip-path','url(' + locationHref + '#'+clipId + ')');
7579 cpGroup.appendChild(this.layerElement);
7580 this.transformedElement = cpGroup;
7581 if (layerElementParent) {
7582 layerElementParent.appendChild(this.transformedElement);
7583 } else {
7584 this.baseElement = this.transformedElement;
7585 }
7586 } else {
7587 this.layerElement.setAttribute('clip-path','url(' + locationHref + '#'+clipId+')');
7588 }
7589
7590 }
7591 if (this.data.bm !== 0) {
7592 this.setBlendMode();
7593 }
7594
7595 },
7596 renderElement: function() {
7597 if (this.finalTransform._matMdf) {
7598 this.transformedElement.setAttribute('transform', this.finalTransform.mat.to2dCSS());
7599 }
7600 if (this.finalTransform._opMdf) {
7601 this.transformedElement.setAttribute('opacity', this.finalTransform.mProp.o.v);
7602 }
7603 },
7604 destroyBaseElement: function() {
7605 this.layerElement = null;
7606 this.matteElement = null;
7607 this.maskManager.destroy();
7608 },
7609 getBaseElement: function() {
7610 if (this.data.hd) {
7611 return null;
7612 }
7613 return this.baseElement;
7614 },
7615 createRenderableComponents: function() {
7616 this.maskManager = new MaskElement(this.data, this, this.globalData);
7617 this.renderableEffectsManager = new SVGEffects(this);
7618 },
7619 setMatte: function(id) {
7620 if (!this.matteElement) {
7621 return;
7622 }
7623 this.matteElement.setAttribute("mask", "url(" + locationHref + "#" + id + ")");
7624 }
7625};
7626function IShapeElement(){
7627}
7628
7629IShapeElement.prototype = {
7630 addShapeToModifiers: function(data) {
7631 var i, len = this.shapeModifiers.length;
7632 for(i=0;i<len;i+=1){
7633 this.shapeModifiers[i].addShape(data);
7634 }
7635 },
7636 isShapeInAnimatedModifiers: function(data) {
7637 var i = 0, len = this.shapeModifiers.length;
7638 while(i < len) {
7639 if(this.shapeModifiers[i].isAnimatedWithShape(data)) {
7640 return true;
7641 }
7642 }
7643 return false;
7644 },
7645 renderModifiers: function() {
7646 if(!this.shapeModifiers.length){
7647 return;
7648 }
7649 var i, len = this.shapes.length;
7650 for(i=0;i<len;i+=1){
7651 this.shapes[i].sh.reset();
7652 }
7653
7654 len = this.shapeModifiers.length;
7655 for(i=len-1;i>=0;i-=1){
7656 this.shapeModifiers[i].processShapes(this._isFirstFrame);
7657 }
7658 },
7659 lcEnum: {
7660 '1': 'butt',
7661 '2': 'round',
7662 '3': 'square'
7663 },
7664 ljEnum: {
7665 '1': 'miter',
7666 '2': 'round',
7667 '3': 'bevel'
7668 },
7669 searchProcessedElement: function(elem){
7670 var elements = this.processedElements;
7671 var i = 0, len = elements.length;
7672 while (i < len) {
7673 if (elements[i].elem === elem) {
7674 return elements[i].pos;
7675 }
7676 i += 1;
7677 }
7678 return 0;
7679 },
7680 addProcessedElement: function(elem, pos){
7681 var elements = this.processedElements;
7682 var i = elements.length;
7683 while(i) {
7684 i -= 1;
7685 if (elements[i].elem === elem) {
7686 elements[i].pos = pos;
7687 return;
7688 }
7689 }
7690 elements.push(new ProcessedElement(elem, pos));
7691 },
7692 prepareFrame: function(num) {
7693 this.prepareRenderableFrame(num);
7694 this.prepareProperties(num, this.isInRange);
7695 }
7696};
7697function ITextElement(){
7698}
7699
7700ITextElement.prototype.initElement = function(data,globalData,comp){
7701 this.lettersChangedFlag = true;
7702 this.initFrame();
7703 this.initBaseData(data, globalData, comp);
7704 this.textProperty = new TextProperty(this, data.t, this.dynamicProperties);
7705 this.textAnimator = new TextAnimatorProperty(data.t, this.renderType, this);
7706 this.initTransform(data, globalData, comp);
7707 this.initHierarchy();
7708 this.initRenderable();
7709 this.initRendererElement();
7710 this.createContainerElements();
7711 this.createRenderableComponents();
7712 this.createContent();
7713 this.hide();
7714 this.textAnimator.searchProperties(this.dynamicProperties);
7715};
7716
7717ITextElement.prototype.prepareFrame = function(num) {
7718 this._mdf = false;
7719 this.prepareRenderableFrame(num);
7720 this.prepareProperties(num, this.isInRange);
7721 if(this.textProperty._mdf || this.textProperty._isFirstFrame) {
7722 this.buildNewText();
7723 this.textProperty._isFirstFrame = false;
7724 this.textProperty._mdf = false;
7725 }
7726};
7727
7728ITextElement.prototype.createPathShape = function(matrixHelper, shapes) {
7729 var j,jLen = shapes.length;
7730 var k, kLen, pathNodes;
7731 var shapeStr = '';
7732 for(j=0;j<jLen;j+=1){
7733 pathNodes = shapes[j].ks.k;
7734 shapeStr += buildShapeString(pathNodes, pathNodes.i.length, true, matrixHelper);
7735 }
7736 return shapeStr;
7737};
7738
7739ITextElement.prototype.updateDocumentData = function(newData, index) {
7740 this.textProperty.updateDocumentData(newData, index);
7741};
7742
7743ITextElement.prototype.canResizeFont = function(_canResize) {
7744 this.textProperty.canResizeFont(_canResize);
7745};
7746
7747ITextElement.prototype.setMinimumFontSize = function(_fontSize) {
7748 this.textProperty.setMinimumFontSize(_fontSize);
7749};
7750
7751ITextElement.prototype.applyTextPropertiesToMatrix = function(documentData, matrixHelper, lineNumber, xPos, yPos) {
7752 if(documentData.ps){
7753 matrixHelper.translate(documentData.ps[0],documentData.ps[1] + documentData.ascent,0);
7754 }
7755 matrixHelper.translate(0,-documentData.ls,0);
7756 switch(documentData.j){
7757 case 1:
7758 matrixHelper.translate(documentData.justifyOffset + (documentData.boxWidth - documentData.lineWidths[lineNumber]),0,0);
7759 break;
7760 case 2:
7761 matrixHelper.translate(documentData.justifyOffset + (documentData.boxWidth - documentData.lineWidths[lineNumber] )/2,0,0);
7762 break;
7763 }
7764 matrixHelper.translate(xPos, yPos, 0);
7765};
7766
7767
7768ITextElement.prototype.buildColor = function(colorData) {
7769 return 'rgb(' + Math.round(colorData[0]*255) + ',' + Math.round(colorData[1]*255) + ',' + Math.round(colorData[2]*255) + ')';
7770};
7771
7772ITextElement.prototype.emptyProp = new LetterProps();
7773
7774ITextElement.prototype.destroy = function(){
7775
7776};
7777function ICompElement(){}
7778
7779extendPrototype([BaseElement, TransformElement, HierarchyElement, FrameElement, RenderableDOMElement], ICompElement);
7780
7781ICompElement.prototype.initElement = function(data,globalData,comp) {
7782 this.initFrame();
7783 this.initBaseData(data, globalData, comp);
7784 this.initTransform(data, globalData, comp);
7785 this.initRenderable();
7786 this.initHierarchy();
7787 this.initRendererElement();
7788 this.createContainerElements();
7789 this.createRenderableComponents();
7790 if(this.data.xt || !globalData.progressiveLoad){
7791 this.buildAllItems();
7792 }
7793 this.hide();
7794};
7795
7796/*ICompElement.prototype.hide = function(){
7797 if(!this.hidden){
7798 this.hideElement();
7799 var i,len = this.elements.length;
7800 for( i = 0; i < len; i+=1 ){
7801 if(this.elements[i]){
7802 this.elements[i].hide();
7803 }
7804 }
7805 }
7806};*/
7807
7808ICompElement.prototype.prepareFrame = function(num){
7809 this._mdf = false;
7810 this.prepareRenderableFrame(num);
7811 this.prepareProperties(num, this.isInRange);
7812 if(!this.isInRange && !this.data.xt){
7813 return;
7814 }
7815
7816 if (!this.tm._placeholder) {
7817 var timeRemapped = this.tm.v;
7818 if(timeRemapped === this.data.op){
7819 timeRemapped = this.data.op - 1;
7820 }
7821 this.renderedFrame = timeRemapped;
7822 } else {
7823 this.renderedFrame = num/this.data.sr;
7824 }
7825 var i,len = this.elements.length;
7826 if(!this.completeLayers){
7827 this.checkLayers(this.renderedFrame);
7828 }
7829 //This iteration needs to be backwards because of how expressions connect between each other
7830 for( i = len - 1; i >= 0; i -= 1 ){
7831 if(this.completeLayers || this.elements[i]){
7832 this.elements[i].prepareFrame(this.renderedFrame - this.layers[i].st);
7833 if(this.elements[i]._mdf) {
7834 this._mdf = true;
7835 }
7836 }
7837 }
7838};
7839
7840ICompElement.prototype.renderInnerContent = function() {
7841 var i,len = this.layers.length;
7842 for( i = 0; i < len; i += 1 ){
7843 if(this.completeLayers || this.elements[i]){
7844 this.elements[i].renderFrame();
7845 }
7846 }
7847};
7848
7849ICompElement.prototype.setElements = function(elems){
7850 this.elements = elems;
7851};
7852
7853ICompElement.prototype.getElements = function(){
7854 return this.elements;
7855};
7856
7857ICompElement.prototype.destroyElements = function(){
7858 var i,len = this.layers.length;
7859 for( i = 0; i < len; i+=1 ){
7860 if(this.elements[i]){
7861 this.elements[i].destroy();
7862 }
7863 }
7864};
7865
7866ICompElement.prototype.destroy = function(){
7867 this.destroyElements();
7868 this.destroyBaseElement();
7869};
7870
7871function IImageElement(data,globalData,comp){
7872 this.assetData = globalData.getAssetData(data.refId);
7873 this.initElement(data,globalData,comp);
7874 this.sourceRect = {top:0,left:0,width:this.assetData.w,height:this.assetData.h};
7875}
7876
7877extendPrototype([BaseElement,TransformElement,SVGBaseElement,HierarchyElement,FrameElement,RenderableDOMElement], IImageElement);
7878
7879IImageElement.prototype.createContent = function(){
7880
7881 var assetPath = this.globalData.getAssetsPath(this.assetData);
7882
7883 this.innerElem = createNS('image');
7884 this.innerElem.setAttribute('width',this.assetData.w+"px");
7885 this.innerElem.setAttribute('height',this.assetData.h+"px");
7886 this.innerElem.setAttribute('preserveAspectRatio',this.assetData.pr || this.globalData.renderConfig.imagePreserveAspectRatio);
7887 this.innerElem.setAttributeNS('http://www.w3.org/1999/xlink','href',assetPath);
7888
7889 this.layerElement.appendChild(this.innerElem);
7890};
7891
7892IImageElement.prototype.sourceRectAtTime = function() {
7893 return this.sourceRect;
7894}
7895function ISolidElement(data,globalData,comp){
7896 this.initElement(data,globalData,comp);
7897}
7898extendPrototype([IImageElement], ISolidElement);
7899
7900ISolidElement.prototype.createContent = function(){
7901
7902 var rect = createNS('rect');
7903 ////rect.style.width = this.data.sw;
7904 ////rect.style.height = this.data.sh;
7905 ////rect.style.fill = this.data.sc;
7906 rect.setAttribute('width',this.data.sw);
7907 rect.setAttribute('height',this.data.sh);
7908 rect.setAttribute('fill',this.data.sc);
7909 this.layerElement.appendChild(rect);
7910};
7911function AudioElement(data,globalData,comp){
7912 this.initFrame();
7913 this.initRenderable();
7914 this.assetData = globalData.getAssetData(data.refId);
7915 this.initBaseData(data, globalData, comp);
7916 this._isPlaying = false;
7917 this._canPlay = false;
7918 var assetPath = this.globalData.getAssetsPath(this.assetData);
7919 this.audio = this.globalData.audioController.createAudio(assetPath);
7920 this._currentTime = 0;
7921 this.globalData.audioController.addAudio(this);
7922 this.tm = data.tm ? PropertyFactory.getProp(this, data.tm, 0, globalData.frameRate,this) : {_placeholder:true};
7923}
7924
7925AudioElement.prototype.prepareFrame = function(num) {
7926 this.prepareRenderableFrame(num, true);
7927 this.prepareProperties(num, true);
7928 if (!this.tm._placeholder) {
7929 var timeRemapped = this.tm.v;
7930 this._currentTime = timeRemapped;
7931 } else {
7932 this._currentTime = num / this.data.sr;
7933 }
7934};
7935
7936extendPrototype([RenderableElement,BaseElement,FrameElement], AudioElement);
7937
7938AudioElement.prototype.renderFrame = function() {
7939 if (this.isInRange && this._canPlay) {
7940 if (!this._isPlaying) {
7941 this.audio.play();
7942 this.audio.seek(this._currentTime / this.globalData.frameRate);
7943 this._isPlaying = true;
7944 } else if (!this.audio.playing()
7945 || Math.abs(this._currentTime / this.globalData.frameRate - this.audio.seek()) > 0.1
7946 ) {
7947 this.audio.seek(this._currentTime / this.globalData.frameRate)
7948 }
7949 }
7950};
7951
7952AudioElement.prototype.show = function() {
7953 // this.audio.play()
7954};
7955
7956AudioElement.prototype.hide = function() {
7957 this.audio.pause();
7958 this._isPlaying = false;
7959};
7960
7961AudioElement.prototype.pause = function() {
7962 this.audio.pause();
7963 this._isPlaying = false;
7964 this._canPlay = false;
7965};
7966
7967AudioElement.prototype.resume = function() {
7968 this._canPlay = true;
7969};
7970
7971AudioElement.prototype.setRate = function(rateValue) {
7972 this.audio.rate(rateValue);
7973};
7974
7975AudioElement.prototype.volume = function(volumeValue) {
7976 this.audio.volume(volumeValue);
7977};
7978
7979AudioElement.prototype.getBaseElement = function() {
7980 return null;
7981};
7982
7983AudioElement.prototype.destroy = function() {
7984};
7985
7986AudioElement.prototype.sourceRectAtTime = function() {
7987};
7988
7989AudioElement.prototype.initExpressions = function() {
7990};
7991
7992
7993function SVGShapeElement(data,globalData,comp){
7994 //List of drawable elements
7995 this.shapes = [];
7996 // Full shape data
7997 this.shapesData = data.shapes;
7998 //List of styles that will be applied to shapes
7999 this.stylesList = [];
8000 //List of modifiers that will be applied to shapes
8001 this.shapeModifiers = [];
8002 //List of items in shape tree
8003 this.itemsData = [];
8004 //List of items in previous shape tree
8005 this.processedElements = [];
8006 // List of animated components
8007 this.animatedContents = [];
8008 this.initElement(data,globalData,comp);
8009 //Moving any property that doesn't get too much access after initialization because of v8 way of handling more than 10 properties.
8010 // List of elements that have been created
8011 this.prevViewData = [];
8012 //Moving any property that doesn't get too much access after initialization because of v8 way of handling more than 10 properties.
8013}
8014
8015extendPrototype([BaseElement,TransformElement,SVGBaseElement,IShapeElement,HierarchyElement,FrameElement,RenderableDOMElement], SVGShapeElement);
8016
8017SVGShapeElement.prototype.initSecondaryElement = function() {
8018};
8019
8020SVGShapeElement.prototype.identityMatrix = new Matrix();
8021
8022SVGShapeElement.prototype.buildExpressionInterface = function(){};
8023
8024SVGShapeElement.prototype.createContent = function(){
8025 this.searchShapes(this.shapesData,this.itemsData,this.prevViewData,this.layerElement, 0, [], true);
8026 this.filterUniqueShapes();
8027};
8028
8029/*
8030This method searches for multiple shapes that affect a single element and one of them is animated
8031*/
8032SVGShapeElement.prototype.filterUniqueShapes = function(){
8033 var i, len = this.shapes.length, shape;
8034 var j, jLen = this.stylesList.length;
8035 var style, count = 0;
8036 var tempShapes = [];
8037 var areAnimated = false;
8038 for(j = 0; j < jLen; j += 1) {
8039 style = this.stylesList[j];
8040 areAnimated = false;
8041 tempShapes.length = 0;
8042 for(i = 0; i < len; i += 1) {
8043 shape = this.shapes[i];
8044 if(shape.styles.indexOf(style) !== -1) {
8045 tempShapes.push(shape);
8046 areAnimated = shape._isAnimated || areAnimated;
8047 }
8048 }
8049 if(tempShapes.length > 1 && areAnimated) {
8050 this.setShapesAsAnimated(tempShapes);
8051 }
8052 }
8053}
8054
8055SVGShapeElement.prototype.setShapesAsAnimated = function(shapes){
8056 var i, len = shapes.length;
8057 for(i = 0; i < len; i += 1) {
8058 shapes[i].setAsAnimated();
8059 }
8060}
8061
8062SVGShapeElement.prototype.createStyleElement = function(data, level){
8063 //TODO: prevent drawing of hidden styles
8064 var elementData;
8065 var styleOb = new SVGStyleData(data, level);
8066
8067 var pathElement = styleOb.pElem;
8068 if(data.ty === 'st') {
8069 elementData = new SVGStrokeStyleData(this, data, styleOb);
8070 } else if(data.ty === 'fl') {
8071 elementData = new SVGFillStyleData(this, data, styleOb);
8072 } else if(data.ty === 'gf' || data.ty === 'gs') {
8073 var gradientConstructor = data.ty === 'gf' ? SVGGradientFillStyleData : SVGGradientStrokeStyleData;
8074 elementData = new gradientConstructor(this, data, styleOb);
8075 this.globalData.defs.appendChild(elementData.gf);
8076 if (elementData.maskId) {
8077 this.globalData.defs.appendChild(elementData.ms);
8078 this.globalData.defs.appendChild(elementData.of);
8079 pathElement.setAttribute('mask','url(' + locationHref + '#' + elementData.maskId + ')');
8080 }
8081 }
8082
8083 if(data.ty === 'st' || data.ty === 'gs') {
8084 pathElement.setAttribute('stroke-linecap', this.lcEnum[data.lc] || 'round');
8085 pathElement.setAttribute('stroke-linejoin',this.ljEnum[data.lj] || 'round');
8086 pathElement.setAttribute('fill-opacity','0');
8087 if(data.lj === 1) {
8088 pathElement.setAttribute('stroke-miterlimit',data.ml);
8089 }
8090 }
8091
8092 if(data.r === 2) {
8093 pathElement.setAttribute('fill-rule', 'evenodd');
8094 }
8095
8096 if(data.ln){
8097 pathElement.setAttribute('id',data.ln);
8098 }
8099 if(data.cl){
8100 pathElement.setAttribute('class',data.cl);
8101 }
8102 if(data.bm){
8103 pathElement.style['mix-blend-mode'] = getBlendMode(data.bm);
8104 }
8105 this.stylesList.push(styleOb);
8106 this.addToAnimatedContents(data, elementData);
8107 return elementData;
8108};
8109
8110SVGShapeElement.prototype.createGroupElement = function(data) {
8111 var elementData = new ShapeGroupData();
8112 if(data.ln){
8113 elementData.gr.setAttribute('id',data.ln);
8114 }
8115 if(data.cl){
8116 elementData.gr.setAttribute('class',data.cl);
8117 }
8118 if(data.bm){
8119 elementData.gr.style['mix-blend-mode'] = getBlendMode(data.bm);
8120 }
8121 return elementData;
8122};
8123
8124SVGShapeElement.prototype.createTransformElement = function(data, container) {
8125 var transformProperty = TransformPropertyFactory.getTransformProperty(this,data,this);
8126 var elementData = new SVGTransformData(transformProperty, transformProperty.o, container);
8127 this.addToAnimatedContents(data, elementData);
8128 return elementData;
8129};
8130
8131SVGShapeElement.prototype.createShapeElement = function(data, ownTransformers, level) {
8132 var ty = 4;
8133 if(data.ty === 'rc'){
8134 ty = 5;
8135 }else if(data.ty === 'el'){
8136 ty = 6;
8137 }else if(data.ty === 'sr'){
8138 ty = 7;
8139 }
8140 var shapeProperty = ShapePropertyFactory.getShapeProp(this,data,ty,this);
8141 var elementData = new SVGShapeData(ownTransformers, level, shapeProperty);
8142 this.shapes.push(elementData);
8143 this.addShapeToModifiers(elementData);
8144 this.addToAnimatedContents(data, elementData);
8145 return elementData;
8146};
8147
8148SVGShapeElement.prototype.addToAnimatedContents = function(data, element) {
8149 var i = 0, len = this.animatedContents.length;
8150 while(i < len) {
8151 if(this.animatedContents[i].element === element) {
8152 return;
8153 }
8154 i += 1;
8155 }
8156 this.animatedContents.push({
8157 fn: SVGElementsRenderer.createRenderFunction(data),
8158 element: element,
8159 data: data
8160 });
8161};
8162
8163SVGShapeElement.prototype.setElementStyles = function(elementData){
8164 var arr = elementData.styles;
8165 var j, jLen = this.stylesList.length;
8166 for (j = 0; j < jLen; j += 1) {
8167 if (!this.stylesList[j].closed) {
8168 arr.push(this.stylesList[j]);
8169 }
8170 }
8171};
8172
8173SVGShapeElement.prototype.reloadShapes = function(){
8174 this._isFirstFrame = true;
8175 var i, len = this.itemsData.length;
8176 for( i = 0; i < len; i += 1) {
8177 this.prevViewData[i] = this.itemsData[i];
8178 }
8179 this.searchShapes(this.shapesData,this.itemsData,this.prevViewData,this.layerElement, 0, [], true);
8180 this.filterUniqueShapes();
8181 len = this.dynamicProperties.length;
8182 for(i = 0; i < len; i += 1) {
8183 this.dynamicProperties[i].getValue();
8184 }
8185 this.renderModifiers();
8186};
8187
8188SVGShapeElement.prototype.searchShapes = function(arr,itemsData,prevViewData,container, level, transformers, render){
8189 var ownTransformers = [].concat(transformers);
8190 var i, len = arr.length - 1;
8191 var j, jLen;
8192 var ownStyles = [], ownModifiers = [], styleOb, currentTransform, modifier, processedPos;
8193 for(i=len;i>=0;i-=1){
8194 processedPos = this.searchProcessedElement(arr[i]);
8195 if(!processedPos){
8196 arr[i]._render = render;
8197 } else {
8198 itemsData[i] = prevViewData[processedPos - 1];
8199 }
8200 if(arr[i].ty == 'fl' || arr[i].ty == 'st' || arr[i].ty == 'gf' || arr[i].ty == 'gs'){
8201 if(!processedPos){
8202 itemsData[i] = this.createStyleElement(arr[i], level);
8203 } else {
8204 itemsData[i].style.closed = false;
8205 }
8206 if(arr[i]._render){
8207 container.appendChild(itemsData[i].style.pElem);
8208 }
8209 ownStyles.push(itemsData[i].style);
8210 }else if(arr[i].ty == 'gr'){
8211 if(!processedPos){
8212 itemsData[i] = this.createGroupElement(arr[i]);
8213 } else {
8214 jLen = itemsData[i].it.length;
8215 for(j=0;j<jLen;j+=1){
8216 itemsData[i].prevViewData[j] = itemsData[i].it[j];
8217 }
8218 }
8219 this.searchShapes(arr[i].it,itemsData[i].it,itemsData[i].prevViewData,itemsData[i].gr, level + 1, ownTransformers, render);
8220 if(arr[i]._render){
8221 container.appendChild(itemsData[i].gr);
8222 }
8223 }else if(arr[i].ty == 'tr'){
8224 if(!processedPos){
8225 itemsData[i] = this.createTransformElement(arr[i], container);
8226 }
8227 currentTransform = itemsData[i].transform;
8228 ownTransformers.push(currentTransform);
8229 }else if(arr[i].ty == 'sh' || arr[i].ty == 'rc' || arr[i].ty == 'el' || arr[i].ty == 'sr'){
8230 if(!processedPos){
8231 itemsData[i] = this.createShapeElement(arr[i], ownTransformers, level);
8232 }
8233 this.setElementStyles(itemsData[i]);
8234
8235 }else if(arr[i].ty == 'tm' || arr[i].ty == 'rd' || arr[i].ty == 'ms' || arr[i].ty == 'pb'){
8236 if(!processedPos){
8237 modifier = ShapeModifiers.getModifier(arr[i].ty);
8238 modifier.init(this,arr[i]);
8239 itemsData[i] = modifier;
8240 this.shapeModifiers.push(modifier);
8241 } else {
8242 modifier = itemsData[i];
8243 modifier.closed = false;
8244 }
8245 ownModifiers.push(modifier);
8246 }else if(arr[i].ty == 'rp'){
8247 if(!processedPos){
8248 modifier = ShapeModifiers.getModifier(arr[i].ty);
8249 itemsData[i] = modifier;
8250 modifier.init(this,arr,i,itemsData);
8251 this.shapeModifiers.push(modifier);
8252 render = false;
8253 }else{
8254 modifier = itemsData[i];
8255 modifier.closed = true;
8256 }
8257 ownModifiers.push(modifier);
8258 }
8259 this.addProcessedElement(arr[i], i + 1);
8260 }
8261 len = ownStyles.length;
8262 for(i=0;i<len;i+=1){
8263 ownStyles[i].closed = true;
8264 }
8265 len = ownModifiers.length;
8266 for(i=0;i<len;i+=1){
8267 ownModifiers[i].closed = true;
8268 }
8269};
8270
8271SVGShapeElement.prototype.renderInnerContent = function() {
8272 this.renderModifiers();
8273 var i, len = this.stylesList.length;
8274 for(i=0;i<len;i+=1){
8275 this.stylesList[i].reset();
8276 }
8277 this.renderShape();
8278
8279 for (i = 0; i < len; i += 1) {
8280 if (this.stylesList[i]._mdf || this._isFirstFrame) {
8281 if(this.stylesList[i].msElem){
8282 this.stylesList[i].msElem.setAttribute('d', this.stylesList[i].d);
8283 //Adding M0 0 fixes same mask bug on all browsers
8284 this.stylesList[i].d = 'M0 0' + this.stylesList[i].d;
8285 }
8286 this.stylesList[i].pElem.setAttribute('d', this.stylesList[i].d || 'M0 0');
8287 }
8288 }
8289};
8290
8291SVGShapeElement.prototype.renderShape = function() {
8292 var i, len = this.animatedContents.length;
8293 var animatedContent;
8294 for(i = 0; i < len; i += 1) {
8295 animatedContent = this.animatedContents[i];
8296 if((this._isFirstFrame || animatedContent.element._isAnimated) && animatedContent.data !== true) {
8297 animatedContent.fn(animatedContent.data, animatedContent.element, this._isFirstFrame);
8298 }
8299 }
8300}
8301
8302SVGShapeElement.prototype.destroy = function(){
8303 this.destroyBaseElement();
8304 this.shapesData = null;
8305 this.itemsData = null;
8306};
8307
8308function CVContextData() {
8309 this.saved = [];
8310 this.cArrPos = 0;
8311 this.cTr = new Matrix();
8312 this.cO = 1;
8313 var i, len = 15;
8314 this.savedOp = createTypedArray('float32', len);
8315 for(i=0;i<len;i+=1){
8316 this.saved[i] = createTypedArray('float32', 16);
8317 }
8318 this._length = len;
8319}
8320
8321CVContextData.prototype.duplicate = function() {
8322 var newLength = this._length * 2;
8323 var currentSavedOp = this.savedOp;
8324 this.savedOp = createTypedArray('float32', newLength);
8325 this.savedOp.set(currentSavedOp);
8326 var i = 0;
8327 for(i = this._length; i < newLength; i += 1) {
8328 this.saved[i] = createTypedArray('float32', 16);
8329 }
8330 this._length = newLength;
8331};
8332
8333CVContextData.prototype.reset = function() {
8334 this.cArrPos = 0;
8335 this.cTr.reset();
8336 this.cO = 1;
8337};
8338function CVBaseElement(){
8339}
8340
8341CVBaseElement.prototype = {
8342 createElements: function(){},
8343 initRendererElement: function(){},
8344 createContainerElements: function(){
8345 this.canvasContext = this.globalData.canvasContext;
8346 this.renderableEffectsManager = new CVEffects(this);
8347 },
8348 createContent: function(){},
8349 setBlendMode: function(){
8350 var globalData = this.globalData;
8351 if(globalData.blendMode !== this.data.bm) {
8352 globalData.blendMode = this.data.bm;
8353 var blendModeValue = getBlendMode(this.data.bm);
8354 globalData.canvasContext.globalCompositeOperation = blendModeValue;
8355 }
8356 },
8357 createRenderableComponents: function(){
8358 this.maskManager = new CVMaskElement(this.data, this);
8359 },
8360 hideElement: function(){
8361 if (!this.hidden && (!this.isInRange || this.isTransparent)) {
8362 this.hidden = true;
8363 }
8364 },
8365 showElement: function(){
8366 if (this.isInRange && !this.isTransparent){
8367 this.hidden = false;
8368 this._isFirstFrame = true;
8369 this.maskManager._isFirstFrame = true;
8370 }
8371 },
8372 renderFrame: function() {
8373 if (this.hidden || this.data.hd) {
8374 return;
8375 }
8376 this.renderTransform();
8377 this.renderRenderable();
8378 this.setBlendMode();
8379 var forceRealStack = this.data.ty === 0;
8380 this.globalData.renderer.save(forceRealStack);
8381 this.globalData.renderer.ctxTransform(this.finalTransform.mat.props);
8382 this.globalData.renderer.ctxOpacity(this.finalTransform.mProp.o.v);
8383 this.renderInnerContent();
8384 this.globalData.renderer.restore(forceRealStack);
8385 if(this.maskManager.hasMasks) {
8386 this.globalData.renderer.restore(true);
8387 }
8388 if (this._isFirstFrame) {
8389 this._isFirstFrame = false;
8390 }
8391 },
8392 destroy: function(){
8393 this.canvasContext = null;
8394 this.data = null;
8395 this.globalData = null;
8396 this.maskManager.destroy();
8397 },
8398 mHelper: new Matrix()
8399};
8400CVBaseElement.prototype.hide = CVBaseElement.prototype.hideElement;
8401CVBaseElement.prototype.show = CVBaseElement.prototype.showElement;
8402
8403function CVImageElement(data, globalData, comp){
8404 this.assetData = globalData.getAssetData(data.refId);
8405 this.img = globalData.imageLoader.getImage(this.assetData);
8406 this.initElement(data,globalData,comp);
8407}
8408extendPrototype([BaseElement, TransformElement, CVBaseElement, HierarchyElement, FrameElement, RenderableElement], CVImageElement);
8409
8410CVImageElement.prototype.initElement = SVGShapeElement.prototype.initElement;
8411CVImageElement.prototype.prepareFrame = IImageElement.prototype.prepareFrame;
8412
8413CVImageElement.prototype.createContent = function(){
8414
8415 if (this.img.width && (this.assetData.w !== this.img.width || this.assetData.h !== this.img.height)) {
8416 var canvas = createTag('canvas');
8417 canvas.width = this.assetData.w;
8418 canvas.height = this.assetData.h;
8419 var ctx = canvas.getContext('2d');
8420
8421 var imgW = this.img.width;
8422 var imgH = this.img.height;
8423 var imgRel = imgW / imgH;
8424 var canvasRel = this.assetData.w/this.assetData.h;
8425 var widthCrop, heightCrop;
8426 var par = this.assetData.pr || this.globalData.renderConfig.imagePreserveAspectRatio;
8427 if((imgRel > canvasRel && par === 'xMidYMid slice') || (imgRel < canvasRel && par !== 'xMidYMid slice')) {
8428 heightCrop = imgH;
8429 widthCrop = heightCrop*canvasRel;
8430 } else {
8431 widthCrop = imgW;
8432 heightCrop = widthCrop/canvasRel;
8433 }
8434 ctx.drawImage(this.img,(imgW-widthCrop)/2,(imgH-heightCrop)/2,widthCrop,heightCrop,0,0,this.assetData.w,this.assetData.h);
8435 this.img = canvas;
8436 }
8437
8438};
8439
8440CVImageElement.prototype.renderInnerContent = function(parentMatrix){
8441 this.canvasContext.drawImage(this.img, 0, 0);
8442};
8443
8444CVImageElement.prototype.destroy = function(){
8445 this.img = null;
8446};
8447function CVCompElement(data, globalData, comp) {
8448 this.completeLayers = false;
8449 this.layers = data.layers;
8450 this.pendingElements = [];
8451 this.elements = createSizedArray(this.layers.length);
8452 this.initElement(data, globalData, comp);
8453 this.tm = data.tm ? PropertyFactory.getProp(this,data.tm,0,globalData.frameRate, this) : {_placeholder:true};
8454}
8455
8456extendPrototype([CanvasRenderer, ICompElement, CVBaseElement], CVCompElement);
8457
8458CVCompElement.prototype.renderInnerContent = function() {
8459 var ctx = this.canvasContext;
8460 ctx.beginPath();
8461 ctx.moveTo(0, 0);
8462 ctx.lineTo(this.data.w, 0);
8463 ctx.lineTo(this.data.w, this.data.h);
8464 ctx.lineTo(0, this.data.h);
8465 ctx.lineTo(0, 0);
8466 ctx.clip();
8467 var i,len = this.layers.length;
8468 for( i = len - 1; i >= 0; i -= 1 ){
8469 if(this.completeLayers || this.elements[i]){
8470 this.elements[i].renderFrame();
8471 }
8472 }
8473};
8474
8475CVCompElement.prototype.destroy = function(){
8476 var i,len = this.layers.length;
8477 for( i = len - 1; i >= 0; i -= 1 ){
8478 if(this.elements[i]) {
8479 this.elements[i].destroy();
8480 }
8481 }
8482 this.layers = null;
8483 this.elements = null;
8484};
8485
8486function CVMaskElement(data,element){
8487 this.data = data;
8488 this.element = element;
8489 this.masksProperties = this.data.masksProperties || [];
8490 this.viewData = createSizedArray(this.masksProperties.length);
8491 var i, len = this.masksProperties.length, hasMasks = false;
8492 for (i = 0; i < len; i++) {
8493 if(this.masksProperties[i].mode !== 'n'){
8494 hasMasks = true;
8495 }
8496 this.viewData[i] = ShapePropertyFactory.getShapeProp(this.element,this.masksProperties[i],3);
8497 }
8498 this.hasMasks = hasMasks;
8499 if(hasMasks) {
8500 this.element.addRenderableComponent(this);
8501 }
8502}
8503
8504CVMaskElement.prototype.renderFrame = function () {
8505 if(!this.hasMasks){
8506 return;
8507 }
8508 var transform = this.element.finalTransform.mat;
8509 var ctx = this.element.canvasContext;
8510 var i, len = this.masksProperties.length;
8511 var pt,pts,data;
8512 ctx.beginPath();
8513 for (i = 0; i < len; i++) {
8514 if(this.masksProperties[i].mode !== 'n'){
8515 if (this.masksProperties[i].inv) {
8516 ctx.moveTo(0, 0);
8517 ctx.lineTo(this.element.globalData.compSize.w, 0);
8518 ctx.lineTo(this.element.globalData.compSize.w, this.element.globalData.compSize.h);
8519 ctx.lineTo(0, this.element.globalData.compSize.h);
8520 ctx.lineTo(0, 0);
8521 }
8522 data = this.viewData[i].v;
8523 pt = transform.applyToPointArray(data.v[0][0],data.v[0][1],0);
8524 ctx.moveTo(pt[0], pt[1]);
8525 var j, jLen = data._length;
8526 for (j = 1; j < jLen; j++) {
8527 pts = transform.applyToTriplePoints(data.o[j - 1], data.i[j], data.v[j]);
8528 ctx.bezierCurveTo(pts[0], pts[1], pts[2], pts[3], pts[4], pts[5]);
8529 }
8530 pts = transform.applyToTriplePoints(data.o[j - 1], data.i[0], data.v[0]);
8531 ctx.bezierCurveTo(pts[0], pts[1], pts[2], pts[3], pts[4], pts[5]);
8532 }
8533 }
8534 this.element.globalData.renderer.save(true);
8535 ctx.clip();
8536};
8537
8538CVMaskElement.prototype.getMaskProperty = MaskElement.prototype.getMaskProperty;
8539
8540CVMaskElement.prototype.destroy = function(){
8541 this.element = null;
8542};
8543function CVShapeElement(data, globalData, comp) {
8544 this.shapes = [];
8545 this.shapesData = data.shapes;
8546 this.stylesList = [];
8547 this.itemsData = [];
8548 this.prevViewData = [];
8549 this.shapeModifiers = [];
8550 this.processedElements = [];
8551 this.transformsManager = new ShapeTransformManager();
8552 this.initElement(data, globalData, comp);
8553}
8554
8555extendPrototype([BaseElement,TransformElement,CVBaseElement,IShapeElement,HierarchyElement,FrameElement,RenderableElement], CVShapeElement);
8556
8557CVShapeElement.prototype.initElement = RenderableDOMElement.prototype.initElement;
8558
8559CVShapeElement.prototype.transformHelper = {opacity:1,_opMdf:false};
8560
8561CVShapeElement.prototype.dashResetter = [];
8562
8563CVShapeElement.prototype.createContent = function(){
8564 this.searchShapes(this.shapesData,this.itemsData,this.prevViewData, true, []);
8565};
8566
8567CVShapeElement.prototype.createStyleElement = function(data, transforms) {
8568 var styleElem = {
8569 data: data,
8570 type: data.ty,
8571 preTransforms: this.transformsManager.addTransformSequence(transforms),
8572 transforms: [],
8573 elements: [],
8574 closed: data.hd === true
8575 };
8576 var elementData = {};
8577 if(data.ty == 'fl' || data.ty == 'st'){
8578 elementData.c = PropertyFactory.getProp(this,data.c,1,255,this);
8579 if(!elementData.c.k){
8580 styleElem.co = 'rgb('+bm_floor(elementData.c.v[0])+','+bm_floor(elementData.c.v[1])+','+bm_floor(elementData.c.v[2])+')';
8581 }
8582 } else if (data.ty === 'gf' || data.ty === 'gs') {
8583 elementData.s = PropertyFactory.getProp(this,data.s,1,null,this);
8584 elementData.e = PropertyFactory.getProp(this,data.e,1,null,this);
8585 elementData.h = PropertyFactory.getProp(this,data.h||{k:0},0,0.01,this);
8586 elementData.a = PropertyFactory.getProp(this,data.a||{k:0},0,degToRads,this);
8587 elementData.g = new GradientProperty(this,data.g,this);
8588 }
8589 elementData.o = PropertyFactory.getProp(this,data.o,0,0.01,this);
8590 if(data.ty == 'st' || data.ty == 'gs') {
8591 styleElem.lc = this.lcEnum[data.lc] || 'round';
8592 styleElem.lj = this.ljEnum[data.lj] || 'round';
8593 if(data.lj == 1) {
8594 styleElem.ml = data.ml;
8595 }
8596 elementData.w = PropertyFactory.getProp(this,data.w,0,null,this);
8597 if(!elementData.w.k){
8598 styleElem.wi = elementData.w.v;
8599 }
8600 if(data.d){
8601 var d = new DashProperty(this,data.d,'canvas', this);
8602 elementData.d = d;
8603 if(!elementData.d.k){
8604 styleElem.da = elementData.d.dashArray;
8605 styleElem.do = elementData.d.dashoffset[0];
8606 }
8607 }
8608 } else {
8609 styleElem.r = data.r === 2 ? 'evenodd' : 'nonzero';
8610 }
8611 this.stylesList.push(styleElem);
8612 elementData.style = styleElem;
8613 return elementData;
8614};
8615
8616CVShapeElement.prototype.createGroupElement = function(data) {
8617 var elementData = {
8618 it: [],
8619 prevViewData: []
8620 };
8621 return elementData;
8622};
8623
8624CVShapeElement.prototype.createTransformElement = function(data) {
8625 var elementData = {
8626 transform : {
8627 opacity: 1,
8628 _opMdf:false,
8629 key: this.transformsManager.getNewKey(),
8630 op: PropertyFactory.getProp(this,data.o,0,0.01,this),
8631 mProps: TransformPropertyFactory.getTransformProperty(this,data,this)
8632 }
8633 };
8634 return elementData;
8635};
8636
8637CVShapeElement.prototype.createShapeElement = function(data) {
8638 var elementData = new CVShapeData(this, data, this.stylesList, this.transformsManager);
8639
8640 this.shapes.push(elementData);
8641 this.addShapeToModifiers(elementData);
8642 return elementData;
8643};
8644
8645CVShapeElement.prototype.reloadShapes = function() {
8646 this._isFirstFrame = true;
8647 var i, len = this.itemsData.length;
8648 for (i = 0; i < len; i += 1) {
8649 this.prevViewData[i] = this.itemsData[i];
8650 }
8651 this.searchShapes(this.shapesData,this.itemsData,this.prevViewData, true, []);
8652 len = this.dynamicProperties.length;
8653 for (i = 0; i < len; i += 1) {
8654 this.dynamicProperties[i].getValue();
8655 }
8656 this.renderModifiers();
8657 this.transformsManager.processSequences(this._isFirstFrame);
8658};
8659
8660CVShapeElement.prototype.addTransformToStyleList = function(transform) {
8661 var i, len = this.stylesList.length;
8662 for (i = 0; i < len; i += 1) {
8663 if(!this.stylesList[i].closed) {
8664 this.stylesList[i].transforms.push(transform);
8665 }
8666 }
8667}
8668
8669CVShapeElement.prototype.removeTransformFromStyleList = function() {
8670 var i, len = this.stylesList.length;
8671 for (i = 0; i < len; i += 1) {
8672 if(!this.stylesList[i].closed) {
8673 this.stylesList[i].transforms.pop();
8674 }
8675 }
8676}
8677
8678CVShapeElement.prototype.closeStyles = function(styles) {
8679 var i, len = styles.length, j, jLen;
8680 for (i = 0; i < len; i += 1) {
8681 styles[i].closed = true;
8682 }
8683}
8684
8685CVShapeElement.prototype.searchShapes = function(arr,itemsData, prevViewData, shouldRender, transforms){
8686 var i, len = arr.length - 1;
8687 var j, jLen;
8688 var ownStyles = [], ownModifiers = [], processedPos, modifier, currentTransform;
8689 var ownTransforms = [].concat(transforms);
8690 for(i=len;i>=0;i-=1){
8691 processedPos = this.searchProcessedElement(arr[i]);
8692 if(!processedPos){
8693 arr[i]._shouldRender = shouldRender;
8694 } else {
8695 itemsData[i] = prevViewData[processedPos - 1];
8696 }
8697 if(arr[i].ty == 'fl' || arr[i].ty == 'st'|| arr[i].ty == 'gf'|| arr[i].ty == 'gs'){
8698 if(!processedPos){
8699 itemsData[i] = this.createStyleElement(arr[i], ownTransforms);
8700 } else {
8701 itemsData[i].style.closed = false;
8702 }
8703
8704 ownStyles.push(itemsData[i].style);
8705 }else if(arr[i].ty == 'gr'){
8706 if(!processedPos){
8707 itemsData[i] = this.createGroupElement(arr[i]);
8708 } else {
8709 jLen = itemsData[i].it.length;
8710 for(j=0;j<jLen;j+=1){
8711 itemsData[i].prevViewData[j] = itemsData[i].it[j];
8712 }
8713 }
8714 this.searchShapes(arr[i].it,itemsData[i].it,itemsData[i].prevViewData, shouldRender, ownTransforms);
8715 }else if(arr[i].ty == 'tr'){
8716 if(!processedPos){
8717 currentTransform = this.createTransformElement(arr[i]);
8718 itemsData[i] = currentTransform;
8719 }
8720 ownTransforms.push(itemsData[i]);
8721 this.addTransformToStyleList(itemsData[i]);
8722 }else if(arr[i].ty == 'sh' || arr[i].ty == 'rc' || arr[i].ty == 'el' || arr[i].ty == 'sr'){
8723 if(!processedPos){
8724 itemsData[i] = this.createShapeElement(arr[i]);
8725 }
8726
8727 }else if(arr[i].ty == 'tm' || arr[i].ty == 'rd' || arr[i].ty == 'pb'){
8728 if(!processedPos){
8729 modifier = ShapeModifiers.getModifier(arr[i].ty);
8730 modifier.init(this,arr[i]);
8731 itemsData[i] = modifier;
8732 this.shapeModifiers.push(modifier);
8733 } else {
8734 modifier = itemsData[i];
8735 modifier.closed = false;
8736 }
8737 ownModifiers.push(modifier);
8738 } else if(arr[i].ty == 'rp'){
8739 if(!processedPos){
8740 modifier = ShapeModifiers.getModifier(arr[i].ty);
8741 itemsData[i] = modifier;
8742 modifier.init(this,arr,i,itemsData);
8743 this.shapeModifiers.push(modifier);
8744 shouldRender = false;
8745 }else{
8746 modifier = itemsData[i];
8747 modifier.closed = true;
8748 }
8749 ownModifiers.push(modifier);
8750 }
8751 this.addProcessedElement(arr[i], i + 1);
8752 }
8753 this.removeTransformFromStyleList();
8754 this.closeStyles(ownStyles);
8755 len = ownModifiers.length;
8756 for(i=0;i<len;i+=1){
8757 ownModifiers[i].closed = true;
8758 }
8759};
8760
8761CVShapeElement.prototype.renderInnerContent = function() {
8762 this.transformHelper.opacity = 1;
8763 this.transformHelper._opMdf = false;
8764 this.renderModifiers();
8765 this.transformsManager.processSequences(this._isFirstFrame);
8766 this.renderShape(this.transformHelper,this.shapesData,this.itemsData,true);
8767};
8768
8769CVShapeElement.prototype.renderShapeTransform = function(parentTransform, groupTransform) {
8770 var props, groupMatrix;
8771 if(parentTransform._opMdf || groupTransform.op._mdf || this._isFirstFrame) {
8772 groupTransform.opacity = parentTransform.opacity;
8773 groupTransform.opacity *= groupTransform.op.v;
8774 groupTransform._opMdf = true;
8775 }
8776};
8777
8778CVShapeElement.prototype.drawLayer = function() {
8779 var i, len = this.stylesList.length;
8780 var j, jLen, k, kLen,elems,nodes, renderer = this.globalData.renderer, ctx = this.globalData.canvasContext, type, currentStyle;
8781 for(i=0;i<len;i+=1){
8782 currentStyle = this.stylesList[i];
8783 type = currentStyle.type;
8784
8785 //Skipping style when
8786 //Stroke width equals 0
8787 //style should not be rendered (extra unused repeaters)
8788 //current opacity equals 0
8789 //global opacity equals 0
8790 if(((type === 'st' || type === 'gs') && currentStyle.wi === 0) || !currentStyle.data._shouldRender || currentStyle.coOp === 0 || this.globalData.currentGlobalAlpha === 0){
8791 continue;
8792 }
8793 renderer.save();
8794 elems = currentStyle.elements;
8795 if(type === 'st' || type === 'gs'){
8796 ctx.strokeStyle = type === 'st' ? currentStyle.co : currentStyle.grd;
8797 ctx.lineWidth = currentStyle.wi;
8798 ctx.lineCap = currentStyle.lc;
8799 ctx.lineJoin = currentStyle.lj;
8800 ctx.miterLimit = currentStyle.ml || 0;
8801 } else {
8802 ctx.fillStyle = type === 'fl' ? currentStyle.co : currentStyle.grd;
8803 }
8804 renderer.ctxOpacity(currentStyle.coOp);
8805 if(type !== 'st' && type !== 'gs'){
8806 ctx.beginPath();
8807 }
8808 renderer.ctxTransform(currentStyle.preTransforms.finalTransform.props);
8809 jLen = elems.length;
8810 for(j=0;j<jLen;j+=1){
8811 if(type === 'st' || type === 'gs'){
8812 ctx.beginPath();
8813 if(currentStyle.da){
8814 ctx.setLineDash(currentStyle.da);
8815 ctx.lineDashOffset = currentStyle.do;
8816 }
8817 }
8818 nodes = elems[j].trNodes;
8819 kLen = nodes.length;
8820
8821 for(k=0;k<kLen;k+=1){
8822 if(nodes[k].t == 'm'){
8823 ctx.moveTo(nodes[k].p[0],nodes[k].p[1]);
8824 }else if(nodes[k].t == 'c'){
8825 ctx.bezierCurveTo(nodes[k].pts[0],nodes[k].pts[1],nodes[k].pts[2],nodes[k].pts[3],nodes[k].pts[4],nodes[k].pts[5]);
8826 }else{
8827 ctx.closePath();
8828 }
8829 }
8830 if(type === 'st' || type === 'gs'){
8831 ctx.stroke();
8832 if(currentStyle.da){
8833 ctx.setLineDash(this.dashResetter);
8834 }
8835 }
8836 }
8837 if(type !== 'st' && type !== 'gs'){
8838 ctx.fill(currentStyle.r);
8839 }
8840 renderer.restore();
8841 }
8842};
8843
8844CVShapeElement.prototype.renderShape = function(parentTransform,items,data,isMain){
8845 var i, len = items.length - 1;
8846 var groupTransform;
8847 groupTransform = parentTransform;
8848 for(i=len;i>=0;i-=1){
8849 if(items[i].ty == 'tr'){
8850 groupTransform = data[i].transform;
8851 this.renderShapeTransform(parentTransform, groupTransform);
8852 }else if(items[i].ty == 'sh' || items[i].ty == 'el' || items[i].ty == 'rc' || items[i].ty == 'sr'){
8853 this.renderPath(items[i],data[i]);
8854 }else if(items[i].ty == 'fl'){
8855 this.renderFill(items[i],data[i],groupTransform);
8856 }else if(items[i].ty == 'st'){
8857 this.renderStroke(items[i],data[i],groupTransform);
8858 }else if(items[i].ty == 'gf' || items[i].ty == 'gs'){
8859 this.renderGradientFill(items[i],data[i],groupTransform);
8860 }else if(items[i].ty == 'gr'){
8861 this.renderShape(groupTransform,items[i].it,data[i].it);
8862 }else if(items[i].ty == 'tm'){
8863 //
8864 }
8865 }
8866 if(isMain){
8867 this.drawLayer();
8868 }
8869
8870};
8871
8872CVShapeElement.prototype.renderStyledShape = function(styledShape, shape){
8873 if(this._isFirstFrame || shape._mdf || styledShape.transforms._mdf) {
8874 var shapeNodes = styledShape.trNodes;
8875 var paths = shape.paths;
8876 var i, len, j, jLen = paths._length;
8877 shapeNodes.length = 0;
8878 var groupTransformMat = styledShape.transforms.finalTransform;
8879 for (j = 0; j < jLen; j += 1) {
8880 var pathNodes = paths.shapes[j];
8881 if(pathNodes && pathNodes.v){
8882 len = pathNodes._length;
8883 for (i = 1; i < len; i += 1) {
8884 if (i === 1) {
8885 shapeNodes.push({
8886 t: 'm',
8887 p: groupTransformMat.applyToPointArray(pathNodes.v[0][0], pathNodes.v[0][1], 0)
8888 });
8889 }
8890 shapeNodes.push({
8891 t: 'c',
8892 pts: groupTransformMat.applyToTriplePoints(pathNodes.o[i - 1], pathNodes.i[i], pathNodes.v[i])
8893 });
8894 }
8895 if (len === 1) {
8896 shapeNodes.push({
8897 t: 'm',
8898 p: groupTransformMat.applyToPointArray(pathNodes.v[0][0], pathNodes.v[0][1], 0)
8899 });
8900 }
8901 if (pathNodes.c && len) {
8902 shapeNodes.push({
8903 t: 'c',
8904 pts: groupTransformMat.applyToTriplePoints(pathNodes.o[i - 1], pathNodes.i[0], pathNodes.v[0])
8905 });
8906 shapeNodes.push({
8907 t: 'z'
8908 });
8909 }
8910 }
8911 }
8912 styledShape.trNodes = shapeNodes;
8913 }
8914}
8915
8916CVShapeElement.prototype.renderPath = function(pathData,itemData){
8917 if(pathData.hd !== true && pathData._shouldRender) {
8918 var i, len = itemData.styledShapes.length;
8919 for (i = 0; i < len; i += 1) {
8920 this.renderStyledShape(itemData.styledShapes[i], itemData.sh);
8921 }
8922 }
8923};
8924
8925CVShapeElement.prototype.renderFill = function(styleData,itemData, groupTransform){
8926 var styleElem = itemData.style;
8927
8928 if (itemData.c._mdf || this._isFirstFrame) {
8929 styleElem.co = 'rgb('
8930 + bm_floor(itemData.c.v[0]) + ','
8931 + bm_floor(itemData.c.v[1]) + ','
8932 + bm_floor(itemData.c.v[2]) + ')';
8933 }
8934 if (itemData.o._mdf || groupTransform._opMdf || this._isFirstFrame) {
8935 styleElem.coOp = itemData.o.v * groupTransform.opacity;
8936 }
8937};
8938
8939CVShapeElement.prototype.renderGradientFill = function(styleData,itemData, groupTransform){
8940 var styleElem = itemData.style;
8941 if(!styleElem.grd || itemData.g._mdf || itemData.s._mdf || itemData.e._mdf || (styleData.t !== 1 && (itemData.h._mdf || itemData.a._mdf))) {
8942 var ctx = this.globalData.canvasContext;
8943 var grd;
8944 var pt1 = itemData.s.v, pt2 = itemData.e.v;
8945 if (styleData.t === 1) {
8946 grd = ctx.createLinearGradient(pt1[0], pt1[1], pt2[0], pt2[1]);
8947 } else {
8948 var rad = Math.sqrt(Math.pow(pt1[0] - pt2[0], 2) + Math.pow(pt1[1] - pt2[1], 2));
8949 var ang = Math.atan2(pt2[1] - pt1[1], pt2[0] - pt1[0]);
8950
8951 var percent = itemData.h.v >= 1 ? 0.99 : itemData.h.v <= -1 ? -0.99: itemData.h.v;
8952 var dist = rad * percent;
8953 var x = Math.cos(ang + itemData.a.v) * dist + pt1[0];
8954 var y = Math.sin(ang + itemData.a.v) * dist + pt1[1];
8955 var grd = ctx.createRadialGradient(x, y, 0, pt1[0], pt1[1], rad);
8956 }
8957
8958 var i, len = styleData.g.p;
8959 var cValues = itemData.g.c;
8960 var opacity = 1;
8961
8962 for (i = 0; i < len; i += 1){
8963 if(itemData.g._hasOpacity && itemData.g._collapsable) {
8964 opacity = itemData.g.o[i*2 + 1];
8965 }
8966 grd.addColorStop(cValues[i * 4] / 100,'rgba('+ cValues[i * 4 + 1] + ',' + cValues[i * 4 + 2] + ','+cValues[i * 4 + 3] + ',' + opacity + ')');
8967 }
8968 styleElem.grd = grd;
8969 }
8970 styleElem.coOp = itemData.o.v*groupTransform.opacity;
8971
8972};
8973
8974CVShapeElement.prototype.renderStroke = function(styleData,itemData, groupTransform){
8975 var styleElem = itemData.style;
8976 var d = itemData.d;
8977 if(d && (d._mdf || this._isFirstFrame)){
8978 styleElem.da = d.dashArray;
8979 styleElem.do = d.dashoffset[0];
8980 }
8981 if(itemData.c._mdf || this._isFirstFrame){
8982 styleElem.co = 'rgb('+bm_floor(itemData.c.v[0])+','+bm_floor(itemData.c.v[1])+','+bm_floor(itemData.c.v[2])+')';
8983 }
8984 if(itemData.o._mdf || groupTransform._opMdf || this._isFirstFrame){
8985 styleElem.coOp = itemData.o.v*groupTransform.opacity;
8986 }
8987 if(itemData.w._mdf || this._isFirstFrame){
8988 styleElem.wi = itemData.w.v;
8989 }
8990};
8991
8992
8993CVShapeElement.prototype.destroy = function(){
8994 this.shapesData = null;
8995 this.globalData = null;
8996 this.canvasContext = null;
8997 this.stylesList.length = 0;
8998 this.itemsData.length = 0;
8999};
9000
9001
9002function CVSolidElement(data, globalData, comp) {
9003 this.initElement(data,globalData,comp);
9004}
9005extendPrototype([BaseElement, TransformElement, CVBaseElement, HierarchyElement, FrameElement, RenderableElement], CVSolidElement);
9006
9007CVSolidElement.prototype.initElement = SVGShapeElement.prototype.initElement;
9008CVSolidElement.prototype.prepareFrame = IImageElement.prototype.prepareFrame;
9009
9010CVSolidElement.prototype.renderInnerContent = function() {
9011 var ctx = this.canvasContext;
9012 ctx.fillStyle = this.data.sc;
9013 ctx.fillRect(0, 0, this.data.sw, this.data.sh);
9014 //
9015};
9016function CVTextElement(data, globalData, comp){
9017 this.textSpans = [];
9018 this.yOffset = 0;
9019 this.fillColorAnim = false;
9020 this.strokeColorAnim = false;
9021 this.strokeWidthAnim = false;
9022 this.stroke = false;
9023 this.fill = false;
9024 this.justifyOffset = 0;
9025 this.currentRender = null;
9026 this.renderType = 'canvas';
9027 this.values = {
9028 fill: 'rgba(0,0,0,0)',
9029 stroke: 'rgba(0,0,0,0)',
9030 sWidth: 0,
9031 fValue: ''
9032 };
9033 this.initElement(data,globalData,comp);
9034}
9035extendPrototype([BaseElement,TransformElement,CVBaseElement,HierarchyElement,FrameElement,RenderableElement,ITextElement], CVTextElement);
9036
9037CVTextElement.prototype.tHelper = createTag('canvas').getContext('2d');
9038
9039CVTextElement.prototype.buildNewText = function(){
9040 var documentData = this.textProperty.currentData;
9041 this.renderedLetters = createSizedArray(documentData.l ? documentData.l.length : 0);
9042
9043 var hasFill = false;
9044 if(documentData.fc) {
9045 hasFill = true;
9046 this.values.fill = this.buildColor(documentData.fc);
9047 }else{
9048 this.values.fill = 'rgba(0,0,0,0)';
9049 }
9050 this.fill = hasFill;
9051 var hasStroke = false;
9052 if(documentData.sc){
9053 hasStroke = true;
9054 this.values.stroke = this.buildColor(documentData.sc);
9055 this.values.sWidth = documentData.sw;
9056 }
9057 var fontData = this.globalData.fontManager.getFontByName(documentData.f);
9058 var i, len;
9059 var letters = documentData.l;
9060 var matrixHelper = this.mHelper;
9061 this.stroke = hasStroke;
9062 this.values.fValue = documentData.finalSize + 'px '+ this.globalData.fontManager.getFontByName(documentData.f).fFamily;
9063 len = documentData.finalText.length;
9064 //this.tHelper.font = this.values.fValue;
9065 var charData, shapeData, k, kLen, shapes, j, jLen, pathNodes, commands, pathArr, singleShape = this.data.singleShape;
9066 var trackingOffset = documentData.tr/1000*documentData.finalSize;
9067 var xPos = 0, yPos = 0, firstLine = true;
9068 var cnt = 0;
9069 for (i = 0; i < len; i += 1) {
9070 charData = this.globalData.fontManager.getCharData(documentData.finalText[i], fontData.fStyle, this.globalData.fontManager.getFontByName(documentData.f).fFamily);
9071 shapeData = charData && charData.data || {};
9072 matrixHelper.reset();
9073 if(singleShape && letters[i].n) {
9074 xPos = -trackingOffset;
9075 yPos += documentData.yOffset;
9076 yPos += firstLine ? 1 : 0;
9077 firstLine = false;
9078 }
9079
9080 shapes = shapeData.shapes ? shapeData.shapes[0].it : [];
9081 jLen = shapes.length;
9082 matrixHelper.scale(documentData.finalSize/100,documentData.finalSize/100);
9083 if(singleShape){
9084 this.applyTextPropertiesToMatrix(documentData, matrixHelper, letters[i].line, xPos, yPos);
9085 }
9086 commands = createSizedArray(jLen);
9087 for(j=0;j<jLen;j+=1){
9088 kLen = shapes[j].ks.k.i.length;
9089 pathNodes = shapes[j].ks.k;
9090 pathArr = [];
9091 for(k=1;k<kLen;k+=1){
9092 if(k==1){
9093 pathArr.push(matrixHelper.applyToX(pathNodes.v[0][0],pathNodes.v[0][1],0),matrixHelper.applyToY(pathNodes.v[0][0],pathNodes.v[0][1],0));
9094 }
9095 pathArr.push(matrixHelper.applyToX(pathNodes.o[k-1][0],pathNodes.o[k-1][1],0),matrixHelper.applyToY(pathNodes.o[k-1][0],pathNodes.o[k-1][1],0),matrixHelper.applyToX(pathNodes.i[k][0],pathNodes.i[k][1],0),matrixHelper.applyToY(pathNodes.i[k][0],pathNodes.i[k][1],0),matrixHelper.applyToX(pathNodes.v[k][0],pathNodes.v[k][1],0),matrixHelper.applyToY(pathNodes.v[k][0],pathNodes.v[k][1],0));
9096 }
9097 pathArr.push(matrixHelper.applyToX(pathNodes.o[k-1][0],pathNodes.o[k-1][1],0),matrixHelper.applyToY(pathNodes.o[k-1][0],pathNodes.o[k-1][1],0),matrixHelper.applyToX(pathNodes.i[0][0],pathNodes.i[0][1],0),matrixHelper.applyToY(pathNodes.i[0][0],pathNodes.i[0][1],0),matrixHelper.applyToX(pathNodes.v[0][0],pathNodes.v[0][1],0),matrixHelper.applyToY(pathNodes.v[0][0],pathNodes.v[0][1],0));
9098 commands[j] = pathArr;
9099 }
9100 if(singleShape){
9101 xPos += letters[i].l;
9102 xPos += trackingOffset;
9103 }
9104 if(this.textSpans[cnt]){
9105 this.textSpans[cnt].elem = commands;
9106 } else {
9107 this.textSpans[cnt] = {elem: commands};
9108 }
9109 cnt +=1;
9110 }
9111};
9112
9113CVTextElement.prototype.renderInnerContent = function(){
9114 var ctx = this.canvasContext;
9115 var finalMat = this.finalTransform.mat.props;
9116 ctx.font = this.values.fValue;
9117 ctx.lineCap = 'butt';
9118 ctx.lineJoin = 'miter';
9119 ctx.miterLimit = 4;
9120
9121 if(!this.data.singleShape){
9122 this.textAnimator.getMeasures(this.textProperty.currentData, this.lettersChangedFlag);
9123 }
9124
9125 var i,len, j, jLen, k, kLen;
9126 var renderedLetters = this.textAnimator.renderedLetters;
9127
9128 var letters = this.textProperty.currentData.l;
9129
9130 len = letters.length;
9131 var renderedLetter;
9132 var lastFill = null, lastStroke = null, lastStrokeW = null, commands, pathArr;
9133 for(i=0;i<len;i+=1){
9134 if(letters[i].n){
9135 continue;
9136 }
9137 renderedLetter = renderedLetters[i];
9138 if(renderedLetter){
9139 this.globalData.renderer.save();
9140 this.globalData.renderer.ctxTransform(renderedLetter.p);
9141 this.globalData.renderer.ctxOpacity(renderedLetter.o);
9142 }
9143 if(this.fill){
9144 if(renderedLetter && renderedLetter.fc){
9145 if(lastFill !== renderedLetter.fc){
9146 lastFill = renderedLetter.fc;
9147 ctx.fillStyle = renderedLetter.fc;
9148 }
9149 }else if(lastFill !== this.values.fill){
9150 lastFill = this.values.fill;
9151 ctx.fillStyle = this.values.fill;
9152 }
9153 commands = this.textSpans[i].elem;
9154 jLen = commands.length;
9155 this.globalData.canvasContext.beginPath();
9156 for(j=0;j<jLen;j+=1) {
9157 pathArr = commands[j];
9158 kLen = pathArr.length;
9159 this.globalData.canvasContext.moveTo(pathArr[0], pathArr[1]);
9160 for (k = 2; k < kLen; k += 6) {
9161 this.globalData.canvasContext.bezierCurveTo(pathArr[k], pathArr[k + 1], pathArr[k + 2], pathArr[k + 3], pathArr[k + 4], pathArr[k + 5]);
9162 }
9163 }
9164 this.globalData.canvasContext.closePath();
9165 this.globalData.canvasContext.fill();
9166 ///ctx.fillText(this.textSpans[i].val,0,0);
9167 }
9168 if(this.stroke){
9169 if(renderedLetter && renderedLetter.sw){
9170 if(lastStrokeW !== renderedLetter.sw){
9171 lastStrokeW = renderedLetter.sw;
9172 ctx.lineWidth = renderedLetter.sw;
9173 }
9174 }else if(lastStrokeW !== this.values.sWidth){
9175 lastStrokeW = this.values.sWidth;
9176 ctx.lineWidth = this.values.sWidth;
9177 }
9178 if(renderedLetter && renderedLetter.sc){
9179 if(lastStroke !== renderedLetter.sc){
9180 lastStroke = renderedLetter.sc;
9181 ctx.strokeStyle = renderedLetter.sc;
9182 }
9183 }else if(lastStroke !== this.values.stroke){
9184 lastStroke = this.values.stroke;
9185 ctx.strokeStyle = this.values.stroke;
9186 }
9187 commands = this.textSpans[i].elem;
9188 jLen = commands.length;
9189 this.globalData.canvasContext.beginPath();
9190 for(j=0;j<jLen;j+=1) {
9191 pathArr = commands[j];
9192 kLen = pathArr.length;
9193 this.globalData.canvasContext.moveTo(pathArr[0], pathArr[1]);
9194 for (k = 2; k < kLen; k += 6) {
9195 this.globalData.canvasContext.bezierCurveTo(pathArr[k], pathArr[k + 1], pathArr[k + 2], pathArr[k + 3], pathArr[k + 4], pathArr[k + 5]);
9196 }
9197 }
9198 this.globalData.canvasContext.closePath();
9199 this.globalData.canvasContext.stroke();
9200 ///ctx.strokeText(letters[i].val,0,0);
9201 }
9202 if(renderedLetter) {
9203 this.globalData.renderer.restore();
9204 }
9205 }
9206};
9207function CVEffects() {
9208
9209}
9210CVEffects.prototype.renderFrame = function(){};
9211var animationManager = (function(){
9212 var moduleOb = {};
9213 var registeredAnimations = [];
9214 var initTime = 0;
9215 var len = 0;
9216 var playingAnimationsNum = 0;
9217 var _stopped = true;
9218 var _isFrozen = false;
9219
9220 function removeElement(ev){
9221 var i = 0;
9222 var animItem = ev.target;
9223 while(i<len) {
9224 if (registeredAnimations[i].animation === animItem) {
9225 registeredAnimations.splice(i, 1);
9226 i -= 1;
9227 len -= 1;
9228 if(!animItem.isPaused){
9229 subtractPlayingCount();
9230 }
9231 }
9232 i += 1;
9233 }
9234 }
9235
9236 function registerAnimation(element, animationData){
9237 if(!element){
9238 return null;
9239 }
9240 var i=0;
9241 while(i<len){
9242 if(registeredAnimations[i].elem == element && registeredAnimations[i].elem !== null ){
9243 return registeredAnimations[i].animation;
9244 }
9245 i+=1;
9246 }
9247 var animItem = new AnimationItem();
9248 setupAnimation(animItem, element);
9249 animItem.setData(element, animationData);
9250 return animItem;
9251 }
9252
9253 function getRegisteredAnimations() {
9254 var i, len = registeredAnimations.length;
9255 var animations = [];
9256 for(i = 0; i < len; i += 1) {
9257 animations.push(registeredAnimations[i].animation);
9258 }
9259 return animations;
9260 }
9261
9262 function addPlayingCount(){
9263 playingAnimationsNum += 1;
9264 activate();
9265 }
9266
9267 function subtractPlayingCount(){
9268 playingAnimationsNum -= 1;
9269 }
9270
9271 function setupAnimation(animItem, element){
9272 animItem.addEventListener('destroy',removeElement);
9273 animItem.addEventListener('_active',addPlayingCount);
9274 animItem.addEventListener('_idle',subtractPlayingCount);
9275 registeredAnimations.push({elem: element,animation:animItem});
9276 len += 1;
9277 }
9278
9279 function loadAnimation(params){
9280 var animItem = new AnimationItem();
9281 setupAnimation(animItem, null);
9282 animItem.setParams(params);
9283 return animItem;
9284 }
9285
9286
9287 function setSpeed(val,animation){
9288 var i;
9289 for(i=0;i<len;i+=1){
9290 registeredAnimations[i].animation.setSpeed(val, animation);
9291 }
9292 }
9293
9294 function setDirection(val, animation){
9295 var i;
9296 for(i=0;i<len;i+=1){
9297 registeredAnimations[i].animation.setDirection(val, animation);
9298 }
9299 }
9300
9301 function play(animation){
9302 var i;
9303 for(i=0;i<len;i+=1){
9304 registeredAnimations[i].animation.play(animation);
9305 }
9306 }
9307 function resume(nowTime) {
9308 var elapsedTime = nowTime - initTime;
9309 var i;
9310 for(i=0;i<len;i+=1){
9311 registeredAnimations[i].animation.advanceTime(elapsedTime);
9312 }
9313 initTime = nowTime;
9314 if(playingAnimationsNum && !_isFrozen) {
9315 window.requestAnimationFrame(resume);
9316 } else {
9317 _stopped = true;
9318 }
9319 }
9320
9321 function first(nowTime){
9322 initTime = nowTime;
9323 window.requestAnimationFrame(resume);
9324 }
9325
9326 function pause(animation) {
9327 var i;
9328 for(i=0;i<len;i+=1){
9329 registeredAnimations[i].animation.pause(animation);
9330 }
9331 }
9332
9333 function goToAndStop(value,isFrame,animation) {
9334 var i;
9335 for(i=0;i<len;i+=1){
9336 registeredAnimations[i].animation.goToAndStop(value,isFrame,animation);
9337 }
9338 }
9339
9340 function stop(animation) {
9341 var i;
9342 for(i=0;i<len;i+=1){
9343 registeredAnimations[i].animation.stop(animation);
9344 }
9345 }
9346
9347 function togglePause(animation) {
9348 var i;
9349 for(i=0;i<len;i+=1){
9350 registeredAnimations[i].animation.togglePause(animation);
9351 }
9352 }
9353
9354 function destroy(animation) {
9355 var i;
9356 for(i=(len-1);i>=0;i-=1){
9357 registeredAnimations[i].animation.destroy(animation);
9358 }
9359 }
9360
9361 function searchAnimations(animationData, standalone, renderer){
9362 var animElements = [].concat([].slice.call(document.getElementsByClassName('lottie')),
9363 [].slice.call(document.getElementsByClassName('bodymovin')));
9364 var i, len = animElements.length;
9365 for(i=0;i<len;i+=1){
9366 if(renderer){
9367 animElements[i].setAttribute('data-bm-type',renderer);
9368 }
9369 registerAnimation(animElements[i], animationData);
9370 }
9371 if(standalone && len === 0){
9372 if(!renderer){
9373 renderer = 'svg';
9374 }
9375 var body = document.getElementsByTagName('body')[0];
9376 body.innerText = '';
9377 var div = createTag('div');
9378 div.style.width = '100%';
9379 div.style.height = '100%';
9380 div.setAttribute('data-bm-type',renderer);
9381 body.appendChild(div);
9382 registerAnimation(div, animationData);
9383 }
9384 }
9385
9386 function resize(){
9387 var i;
9388 for(i=0;i<len;i+=1){
9389 registeredAnimations[i].animation.resize();
9390 }
9391 }
9392
9393 function activate(){
9394 if(!_isFrozen && playingAnimationsNum){
9395 if(_stopped) {
9396 window.requestAnimationFrame(first);
9397 _stopped = false;
9398 }
9399 }
9400 }
9401
9402 function freeze() {
9403 _isFrozen = true;
9404 }
9405
9406 function unfreeze() {
9407 _isFrozen = false;
9408 activate();
9409 }
9410
9411 function setVolume(val,animation) {
9412 var i;
9413 for(i=0;i<len;i+=1){
9414 registeredAnimations[i].animation.setVolume(val, animation);
9415 }
9416 }
9417
9418 function mute(animation) {
9419 var i;
9420 for(i=0;i<len;i+=1){
9421 registeredAnimations[i].animation.mute(animation);
9422 }
9423 }
9424
9425 function unmute(animation) {
9426 var i;
9427 for(i=0;i<len;i+=1){
9428 registeredAnimations[i].animation.unmute(animation);
9429 }
9430 }
9431
9432 moduleOb.registerAnimation = registerAnimation;
9433 moduleOb.loadAnimation = loadAnimation;
9434 moduleOb.setSpeed = setSpeed;
9435 moduleOb.setDirection = setDirection;
9436 moduleOb.play = play;
9437 moduleOb.pause = pause;
9438 moduleOb.stop = stop;
9439 moduleOb.togglePause = togglePause;
9440 moduleOb.searchAnimations = searchAnimations;
9441 moduleOb.resize = resize;
9442 //moduleOb.start = start;
9443 moduleOb.goToAndStop = goToAndStop;
9444 moduleOb.destroy = destroy;
9445 moduleOb.freeze = freeze;
9446 moduleOb.unfreeze = unfreeze;
9447 moduleOb.setVolume = setVolume;
9448 moduleOb.mute = mute;
9449 moduleOb.unmute = unmute;
9450 moduleOb.getRegisteredAnimations = getRegisteredAnimations;
9451 return moduleOb;
9452}());
9453
9454var AnimationItem = function () {
9455 this._cbs = [];
9456 this.name = '';
9457 this.path = '';
9458 this.isLoaded = false;
9459 this.currentFrame = 0;
9460 this.currentRawFrame = 0;
9461 this.firstFrame = 0;
9462 this.totalFrames = 0;
9463 this.frameRate = 0;
9464 this.frameMult = 0;
9465 this.playSpeed = 1;
9466 this.playDirection = 1;
9467 this.playCount = 0;
9468 this.animationData = {};
9469 this.assets = [];
9470 this.isPaused = true;
9471 this.autoplay = false;
9472 this.loop = true;
9473 this.renderer = null;
9474 this.animationID = createElementID();
9475 this.assetsPath = '';
9476 this.timeCompleted = 0;
9477 this.segmentPos = 0;
9478 this.isSubframeEnabled = subframeEnabled;
9479 this.segments = [];
9480 this._idle = true;
9481 this._completedLoop = false;
9482 this.projectInterface = ProjectInterface();
9483 this.imagePreloader = new ImagePreloader();
9484 this.audioController = audioControllerFactory();
9485};
9486
9487extendPrototype([BaseEvent], AnimationItem);
9488
9489AnimationItem.prototype.setParams = function(params) {
9490 if(params.wrapper || params.container){
9491 this.wrapper = params.wrapper || params.container;
9492 }
9493 var animType = params.animType ? params.animType : params.renderer ? params.renderer : 'svg';
9494 switch(animType){
9495 case 'canvas':
9496 this.renderer = new CanvasRenderer(this, params.rendererSettings);
9497 break;
9498 case 'svg':
9499 this.renderer = new SVGRenderer(this, params.rendererSettings);
9500 break;
9501 default:
9502 this.renderer = new HybridRenderer(this, params.rendererSettings);
9503 break;
9504 }
9505 this.imagePreloader.setCacheType(animType);
9506 this.renderer.setProjectInterface(this.projectInterface);
9507 this.animType = animType;
9508 if (params.loop === ''
9509 || params.loop === null
9510 || params.loop === undefined
9511 || params.loop === true)
9512 {
9513 this.loop = true;
9514 } else if (params.loop === false) {
9515 this.loop = false;
9516 } else {
9517 this.loop = parseInt(params.loop);
9518 }
9519 this.autoplay = 'autoplay' in params ? params.autoplay : true;
9520 this.name = params.name ? params.name : '';
9521 this.autoloadSegments = params.hasOwnProperty('autoloadSegments') ? params.autoloadSegments : true;
9522 this.assetsPath = params.assetsPath;
9523 this.initialSegment = params.initialSegment;
9524 if (params.audioFactory) {
9525 this.audioController.setAudioFactory(params.audioFactory);
9526 }
9527 if (params.animationData) {
9528 this.configAnimation(params.animationData);
9529 } else if(params.path){
9530
9531 if( params.path.lastIndexOf('\\') !== -1){
9532 this.path = params.path.substr(0,params.path.lastIndexOf('\\')+1);
9533 } else {
9534 this.path = params.path.substr(0,params.path.lastIndexOf('/')+1);
9535 }
9536 this.fileName = params.path.substr(params.path.lastIndexOf('/')+1);
9537 this.fileName = this.fileName.substr(0,this.fileName.lastIndexOf('.json'));
9538
9539 assetLoader.load(params.path, this.configAnimation.bind(this), function() {
9540 this.trigger('data_failed');
9541 }.bind(this));
9542 }
9543
9544};
9545
9546AnimationItem.prototype.setData = function (wrapper, animationData) {
9547 var params = {
9548 wrapper: wrapper,
9549 animationData: animationData ? (typeof animationData === "object") ? animationData : JSON.parse(animationData) : null
9550 };
9551 var wrapperAttributes = wrapper.attributes;
9552
9553 params.path = wrapperAttributes.getNamedItem('data-animation-path') ? wrapperAttributes.getNamedItem('data-animation-path').value : wrapperAttributes.getNamedItem('data-bm-path') ? wrapperAttributes.getNamedItem('data-bm-path').value : wrapperAttributes.getNamedItem('bm-path') ? wrapperAttributes.getNamedItem('bm-path').value : '';
9554 params.animType = wrapperAttributes.getNamedItem('data-anim-type') ? wrapperAttributes.getNamedItem('data-anim-type').value : wrapperAttributes.getNamedItem('data-bm-type') ? wrapperAttributes.getNamedItem('data-bm-type').value : wrapperAttributes.getNamedItem('bm-type') ? wrapperAttributes.getNamedItem('bm-type').value : wrapperAttributes.getNamedItem('data-bm-renderer') ? wrapperAttributes.getNamedItem('data-bm-renderer').value : wrapperAttributes.getNamedItem('bm-renderer') ? wrapperAttributes.getNamedItem('bm-renderer').value : 'canvas';
9555
9556 var loop = wrapperAttributes.getNamedItem('data-anim-loop') ? wrapperAttributes.getNamedItem('data-anim-loop').value : wrapperAttributes.getNamedItem('data-bm-loop') ? wrapperAttributes.getNamedItem('data-bm-loop').value : wrapperAttributes.getNamedItem('bm-loop') ? wrapperAttributes.getNamedItem('bm-loop').value : '';
9557 if(loop === ''){
9558 }else if(loop === 'false'){
9559 params.loop = false;
9560 }else if(loop === 'true'){
9561 params.loop = true;
9562 }else{
9563 params.loop = parseInt(loop);
9564 }
9565 var autoplay = wrapperAttributes.getNamedItem('data-anim-autoplay') ? wrapperAttributes.getNamedItem('data-anim-autoplay').value : wrapperAttributes.getNamedItem('data-bm-autoplay') ? wrapperAttributes.getNamedItem('data-bm-autoplay').value : wrapperAttributes.getNamedItem('bm-autoplay') ? wrapperAttributes.getNamedItem('bm-autoplay').value : true;
9566 params.autoplay = autoplay !== "false";
9567
9568 params.name = wrapperAttributes.getNamedItem('data-name') ? wrapperAttributes.getNamedItem('data-name').value : wrapperAttributes.getNamedItem('data-bm-name') ? wrapperAttributes.getNamedItem('data-bm-name').value : wrapperAttributes.getNamedItem('bm-name') ? wrapperAttributes.getNamedItem('bm-name').value : '';
9569 var prerender = wrapperAttributes.getNamedItem('data-anim-prerender') ? wrapperAttributes.getNamedItem('data-anim-prerender').value : wrapperAttributes.getNamedItem('data-bm-prerender') ? wrapperAttributes.getNamedItem('data-bm-prerender').value : wrapperAttributes.getNamedItem('bm-prerender') ? wrapperAttributes.getNamedItem('bm-prerender').value : '';
9570
9571 if(prerender === 'false'){
9572 params.prerender = false;
9573 }
9574 this.setParams(params);
9575};
9576
9577AnimationItem.prototype.includeLayers = function(data) {
9578 if(data.op > this.animationData.op){
9579 this.animationData.op = data.op;
9580 this.totalFrames = Math.floor(data.op - this.animationData.ip);
9581 }
9582 var layers = this.animationData.layers;
9583 var i, len = layers.length;
9584 var newLayers = data.layers;
9585 var j, jLen = newLayers.length;
9586 for(j=0;j<jLen;j+=1){
9587 i = 0;
9588 while(i<len){
9589 if(layers[i].id == newLayers[j].id){
9590 layers[i] = newLayers[j];
9591 break;
9592 }
9593 i += 1;
9594 }
9595 }
9596 if(data.chars || data.fonts){
9597 this.renderer.globalData.fontManager.addChars(data.chars);
9598 this.renderer.globalData.fontManager.addFonts(data.fonts, this.renderer.globalData.defs);
9599 }
9600 if(data.assets){
9601 len = data.assets.length;
9602 for(i = 0; i < len; i += 1){
9603 this.animationData.assets.push(data.assets[i]);
9604 }
9605 }
9606 this.animationData.__complete = false;
9607 dataManager.completeData(this.animationData,this.renderer.globalData.fontManager);
9608 this.renderer.includeLayers(data.layers);
9609 if(expressionsPlugin){
9610 expressionsPlugin.initExpressions(this);
9611 }
9612 this.loadNextSegment();
9613};
9614
9615AnimationItem.prototype.loadNextSegment = function() {
9616 var segments = this.animationData.segments;
9617 if(!segments || segments.length === 0 || !this.autoloadSegments){
9618 this.trigger('data_ready');
9619 this.timeCompleted = this.totalFrames;
9620 return;
9621 }
9622 var segment = segments.shift();
9623 this.timeCompleted = segment.time * this.frameRate;
9624 var segmentPath = this.path+this.fileName+'_' + this.segmentPos + '.json';
9625 this.segmentPos += 1;
9626 assetLoader.load(segmentPath, this.includeLayers.bind(this), function() {
9627 this.trigger('data_failed');
9628 }.bind(this));
9629};
9630
9631AnimationItem.prototype.loadSegments = function() {
9632 var segments = this.animationData.segments;
9633 if(!segments) {
9634 this.timeCompleted = this.totalFrames;
9635 }
9636 this.loadNextSegment();
9637};
9638
9639AnimationItem.prototype.imagesLoaded = function() {
9640 this.trigger('loaded_images');
9641 this.checkLoaded()
9642}
9643
9644AnimationItem.prototype.preloadImages = function() {
9645 this.imagePreloader.setAssetsPath(this.assetsPath);
9646 this.imagePreloader.setPath(this.path);
9647 this.imagePreloader.loadAssets(this.animationData.assets, this.imagesLoaded.bind(this));
9648}
9649
9650AnimationItem.prototype.configAnimation = function (animData) {
9651 if(!this.renderer){
9652 return;
9653 }
9654 try {
9655 this.animationData = animData;
9656
9657 if (this.initialSegment) {
9658 this.totalFrames = Math.floor(this.initialSegment[1] - this.initialSegment[0]);
9659 this.firstFrame = Math.round(this.initialSegment[0]);
9660 } else {
9661 this.totalFrames = Math.floor(this.animationData.op - this.animationData.ip);
9662 this.firstFrame = Math.round(this.animationData.ip);
9663 }
9664 this.renderer.configAnimation(animData);
9665 if(!animData.assets){
9666 animData.assets = [];
9667 }
9668
9669 this.assets = this.animationData.assets;
9670 this.frameRate = this.animationData.fr;
9671 this.frameMult = this.animationData.fr / 1000;
9672 this.renderer.searchExtraCompositions(animData.assets);
9673 this.trigger('config_ready');
9674 this.preloadImages();
9675 this.loadSegments();
9676 this.updaFrameModifier();
9677 this.waitForFontsLoaded();
9678 if (this.isPaused) {
9679 this.audioController.pause();
9680 }
9681 } catch(error) {
9682 this.triggerConfigError(error);
9683 }
9684};
9685
9686AnimationItem.prototype.waitForFontsLoaded = function(){
9687 if(!this.renderer) {
9688 return;
9689 }
9690 if(this.renderer.globalData.fontManager.isLoaded){
9691 this.checkLoaded();
9692 }else{
9693 setTimeout(this.waitForFontsLoaded.bind(this),20);
9694 }
9695}
9696
9697AnimationItem.prototype.checkLoaded = function () {
9698 if (!this.isLoaded
9699 && this.renderer.globalData.fontManager.isLoaded
9700 && (this.imagePreloader.loaded() || this.renderer.rendererType !== 'canvas')
9701 ) {
9702 this.isLoaded = true;
9703 dataManager.completeData(this.animationData, this.renderer.globalData.fontManager);
9704 if(expressionsPlugin){
9705 expressionsPlugin.initExpressions(this);
9706 }
9707 this.renderer.initItems();
9708 setTimeout(function() {
9709 this.trigger('DOMLoaded');
9710 }.bind(this), 0);
9711 this.gotoFrame();
9712 if(this.autoplay){
9713 this.play();
9714 }
9715 }
9716};
9717
9718AnimationItem.prototype.resize = function () {
9719 this.renderer.updateContainerSize();
9720};
9721
9722AnimationItem.prototype.setSubframe = function(flag){
9723 this.isSubframeEnabled = !!flag;
9724};
9725
9726AnimationItem.prototype.gotoFrame = function () {
9727 this.currentFrame = this.isSubframeEnabled ? this.currentRawFrame : ~~this.currentRawFrame;
9728
9729 if(this.timeCompleted !== this.totalFrames && this.currentFrame > this.timeCompleted){
9730 this.currentFrame = this.timeCompleted;
9731 }
9732 this.trigger('enterFrame');
9733 this.renderFrame();
9734};
9735
9736AnimationItem.prototype.renderFrame = function () {
9737 if(this.isLoaded === false){
9738 return;
9739 }
9740 try {
9741 this.renderer.renderFrame(this.currentFrame + this.firstFrame);
9742 } catch(error) {
9743 this.triggerRenderFrameError(error);
9744 }
9745};
9746
9747AnimationItem.prototype.play = function (name) {
9748 if(name && this.name != name){
9749 return;
9750 }
9751 if (this.isPaused === true) {
9752 this.isPaused = false;
9753 this.audioController.resume();
9754 if(this._idle){
9755 this._idle = false;
9756 this.trigger('_active');
9757 }
9758 }
9759};
9760
9761AnimationItem.prototype.pause = function (name) {
9762 if(name && this.name != name){
9763 return;
9764 }
9765 if(this.isPaused === false){
9766 this.isPaused = true;
9767 this._idle = true;
9768 this.trigger('_idle');
9769 this.audioController.pause();
9770 }
9771};
9772
9773AnimationItem.prototype.togglePause = function (name) {
9774 if(name && this.name != name){
9775 return;
9776 }
9777 if(this.isPaused === true){
9778 this.play();
9779 }else{
9780 this.pause();
9781 }
9782};
9783
9784AnimationItem.prototype.stop = function (name) {
9785 if(name && this.name != name){
9786 return;
9787 }
9788 this.pause();
9789 this.playCount = 0;
9790 this._completedLoop = false;
9791 this.setCurrentRawFrameValue(0);
9792};
9793
9794AnimationItem.prototype.goToAndStop = function (value, isFrame, name) {
9795 if(name && this.name != name){
9796 return;
9797 }
9798 if(isFrame){
9799 this.setCurrentRawFrameValue(value);
9800 }else{
9801 this.setCurrentRawFrameValue(value * this.frameModifier);
9802 }
9803 this.pause();
9804};
9805
9806AnimationItem.prototype.goToAndPlay = function (value, isFrame, name) {
9807 this.goToAndStop(value, isFrame, name);
9808 this.play();
9809};
9810
9811AnimationItem.prototype.advanceTime = function (value) {
9812 if (this.isPaused === true || this.isLoaded === false) {
9813 return;
9814 }
9815 var nextValue = this.currentRawFrame + value * this.frameModifier;
9816 var _isComplete = false;
9817 // Checking if nextValue > totalFrames - 1 for addressing non looping and looping animations.
9818 // If animation won't loop, it should stop at totalFrames - 1. If it will loop it should complete the last frame and then loop.
9819 if (nextValue >= this.totalFrames - 1 && this.frameModifier > 0) {
9820 if (!this.loop || this.playCount === this.loop) {
9821 if (!this.checkSegments(nextValue > this.totalFrames ? nextValue % this.totalFrames : 0)) {
9822 _isComplete = true;
9823 nextValue = this.totalFrames - 1;
9824 }
9825 } else if (nextValue >= this.totalFrames) {
9826 this.playCount += 1;
9827 if (!this.checkSegments(nextValue % this.totalFrames)) {
9828 this.setCurrentRawFrameValue(nextValue % this.totalFrames);
9829 this._completedLoop = true;
9830 this.trigger('loopComplete');
9831 }
9832 } else {
9833 this.setCurrentRawFrameValue(nextValue);
9834 }
9835 } else if(nextValue < 0) {
9836 if (!this.checkSegments(nextValue % this.totalFrames)) {
9837 if (this.loop && !(this.playCount-- <= 0 && this.loop !== true)) {
9838 this.setCurrentRawFrameValue(this.totalFrames + (nextValue % this.totalFrames));
9839 if(!this._completedLoop) {
9840 this._completedLoop = true;
9841 } else {
9842 this.trigger('loopComplete');
9843 }
9844 } else {
9845 _isComplete = true;
9846 nextValue = 0;
9847 }
9848 }
9849 } else {
9850 this.setCurrentRawFrameValue(nextValue);
9851 }
9852 if (_isComplete) {
9853 this.setCurrentRawFrameValue(nextValue);
9854 this.pause();
9855 this.trigger('complete');
9856 }
9857};
9858
9859AnimationItem.prototype.adjustSegment = function(arr, offset){
9860 this.playCount = 0;
9861 if(arr[1] < arr[0]){
9862 if(this.frameModifier > 0){
9863 if(this.playSpeed < 0){
9864 this.setSpeed(-this.playSpeed);
9865 } else {
9866 this.setDirection(-1);
9867 }
9868 }
9869 this.timeCompleted = this.totalFrames = arr[0] - arr[1];
9870 this.firstFrame = arr[1];
9871 this.setCurrentRawFrameValue(this.totalFrames - 0.001 - offset);
9872 } else if(arr[1] > arr[0]){
9873 if(this.frameModifier < 0){
9874 if(this.playSpeed < 0){
9875 this.setSpeed(-this.playSpeed);
9876 } else {
9877 this.setDirection(1);
9878 }
9879 }
9880 this.timeCompleted = this.totalFrames = arr[1] - arr[0];
9881 this.firstFrame = arr[0];
9882 this.setCurrentRawFrameValue(0.001 + offset);
9883 }
9884 this.trigger('segmentStart');
9885};
9886AnimationItem.prototype.setSegment = function (init,end) {
9887 var pendingFrame = -1;
9888 if(this.isPaused) {
9889 if (this.currentRawFrame + this.firstFrame < init) {
9890 pendingFrame = init;
9891 } else if (this.currentRawFrame + this.firstFrame > end) {
9892 pendingFrame = end - init;
9893 }
9894 }
9895
9896 this.firstFrame = init;
9897 this.timeCompleted = this.totalFrames = end - init;
9898 if(pendingFrame !== -1) {
9899 this.goToAndStop(pendingFrame,true);
9900 }
9901};
9902
9903AnimationItem.prototype.playSegments = function (arr, forceFlag) {
9904 if (forceFlag) {
9905 this.segments.length = 0;
9906 }
9907 if (typeof arr[0] === 'object') {
9908 var i, len = arr.length;
9909 for (i = 0; i < len; i += 1) {
9910 this.segments.push(arr[i]);
9911 }
9912 } else {
9913 this.segments.push(arr);
9914 }
9915 if (this.segments.length && forceFlag) {
9916 this.adjustSegment(this.segments.shift(), 0);
9917 }
9918 if (this.isPaused) {
9919 this.play();
9920 }
9921};
9922
9923AnimationItem.prototype.resetSegments = function (forceFlag) {
9924 this.segments.length = 0;
9925 this.segments.push([this.animationData.ip,this.animationData.op]);
9926 //this.segments.push([this.animationData.ip*this.frameRate,Math.floor(this.animationData.op - this.animationData.ip+this.animationData.ip*this.frameRate)]);
9927 if (forceFlag) {
9928 this.checkSegments(0);
9929 }
9930};
9931AnimationItem.prototype.checkSegments = function(offset) {
9932 if (this.segments.length) {
9933 this.adjustSegment(this.segments.shift(), offset);
9934 return true;
9935 }
9936 return false;
9937};
9938
9939AnimationItem.prototype.destroy = function (name) {
9940 if ((name && this.name != name) || !this.renderer) {
9941 return;
9942 }
9943 this.renderer.destroy();
9944 this.imagePreloader.destroy();
9945 this.trigger('destroy');
9946 this._cbs = null;
9947 this.onEnterFrame = this.onLoopComplete = this.onComplete = this.onSegmentStart = this.onDestroy = null;
9948 this.renderer = null;
9949};
9950
9951AnimationItem.prototype.setCurrentRawFrameValue = function(value){
9952 this.currentRawFrame = value;
9953 this.gotoFrame();
9954};
9955
9956AnimationItem.prototype.setSpeed = function (val) {
9957 this.playSpeed = val;
9958 this.updaFrameModifier();
9959};
9960
9961AnimationItem.prototype.setDirection = function (val) {
9962 this.playDirection = val < 0 ? -1 : 1;
9963 this.updaFrameModifier();
9964};
9965
9966AnimationItem.prototype.setVolume = function (val, name) {
9967 if (name && this.name !== name) {
9968 return;
9969 }
9970 this.audioController.setVolume(val);
9971};
9972
9973AnimationItem.prototype.getVolume = function () {
9974 return this.audioController.getVolume();
9975};
9976
9977AnimationItem.prototype.mute = function (name) {
9978 if (name && this.name !== name) {
9979 return;
9980 }
9981 this.audioController.mute();
9982};
9983
9984AnimationItem.prototype.unmute = function (name) {
9985 if(name && this.name !== name){
9986 return;
9987 }
9988 this.audioController.unmute();
9989};
9990
9991AnimationItem.prototype.updaFrameModifier = function () {
9992 this.frameModifier = this.frameMult * this.playSpeed * this.playDirection;
9993 this.audioController.setRate(this.playSpeed * this.playDirection)
9994};
9995
9996AnimationItem.prototype.getPath = function () {
9997 return this.path;
9998};
9999
10000AnimationItem.prototype.getAssetsPath = function (assetData) {
10001 var path = '';
10002 if(assetData.e) {
10003 path = assetData.p;
10004 } else if(this.assetsPath){
10005 var imagePath = assetData.p;
10006 if(imagePath.indexOf('images/') !== -1){
10007 imagePath = imagePath.split('/')[1];
10008 }
10009 path = this.assetsPath + imagePath;
10010 } else {
10011 path = this.path;
10012 path += assetData.u ? assetData.u : '';
10013 path += assetData.p;
10014 }
10015 return path;
10016};
10017
10018AnimationItem.prototype.getAssetData = function (id) {
10019 var i = 0, len = this.assets.length;
10020 while (i < len) {
10021 if(id == this.assets[i].id){
10022 return this.assets[i];
10023 }
10024 i += 1;
10025 }
10026};
10027
10028AnimationItem.prototype.hide = function () {
10029 this.renderer.hide();
10030};
10031
10032AnimationItem.prototype.show = function () {
10033 this.renderer.show();
10034};
10035
10036AnimationItem.prototype.getDuration = function (isFrame) {
10037 return isFrame ? this.totalFrames : this.totalFrames / this.frameRate;
10038};
10039
10040AnimationItem.prototype.trigger = function(name){
10041 if(this._cbs && this._cbs[name]){
10042 switch(name){
10043 case 'enterFrame':
10044 this.triggerEvent(name,new BMEnterFrameEvent(name,this.currentFrame,this.totalFrames,this.frameModifier));
10045 break;
10046 case 'loopComplete':
10047 this.triggerEvent(name,new BMCompleteLoopEvent(name,this.loop,this.playCount,this.frameMult));
10048 break;
10049 case 'complete':
10050 this.triggerEvent(name,new BMCompleteEvent(name,this.frameMult));
10051 break;
10052 case 'segmentStart':
10053 this.triggerEvent(name,new BMSegmentStartEvent(name,this.firstFrame,this.totalFrames));
10054 break;
10055 case 'destroy':
10056 this.triggerEvent(name,new BMDestroyEvent(name,this));
10057 break;
10058 default:
10059 this.triggerEvent(name);
10060 }
10061 }
10062 if(name === 'enterFrame' && this.onEnterFrame){
10063 this.onEnterFrame.call(this,new BMEnterFrameEvent(name,this.currentFrame,this.totalFrames,this.frameMult));
10064 }
10065 if(name === 'loopComplete' && this.onLoopComplete){
10066 this.onLoopComplete.call(this,new BMCompleteLoopEvent(name,this.loop,this.playCount,this.frameMult));
10067 }
10068 if(name === 'complete' && this.onComplete){
10069 this.onComplete.call(this,new BMCompleteEvent(name,this.frameMult));
10070 }
10071 if(name === 'segmentStart' && this.onSegmentStart){
10072 this.onSegmentStart.call(this,new BMSegmentStartEvent(name,this.firstFrame,this.totalFrames));
10073 }
10074 if(name === 'destroy' && this.onDestroy){
10075 this.onDestroy.call(this,new BMDestroyEvent(name,this));
10076 }
10077};
10078
10079AnimationItem.prototype.triggerRenderFrameError = function(nativeError) {
10080
10081 var error = new BMRenderFrameErrorEvent(nativeError, this.currentFrame);
10082 this.triggerEvent('error', error);
10083
10084 if (this.onError) {
10085 this.onError.call(this, error);
10086 }
10087}
10088
10089AnimationItem.prototype.triggerConfigError = function(nativeError) {
10090
10091 var error = new BMConfigErrorEvent(nativeError, this.currentFrame);
10092 this.triggerEvent('error', error);
10093
10094 if (this.onError) {
10095 this.onError.call(this, error);
10096 }
10097}
10098var Expressions = (function(){
10099 var ob = {};
10100 ob.initExpressions = initExpressions;
10101
10102
10103 function initExpressions(animation){
10104
10105 var stackCount = 0;
10106 var registers = [];
10107
10108 function pushExpression() {
10109 stackCount += 1;
10110 }
10111
10112 function popExpression() {
10113 stackCount -= 1;
10114 if (stackCount === 0) {
10115 releaseInstances();
10116 }
10117 }
10118
10119 function registerExpressionProperty(expression) {
10120 if (registers.indexOf(expression) === -1) {
10121 registers.push(expression)
10122 }
10123 }
10124
10125 function releaseInstances() {
10126 var i, len = registers.length;
10127 for (i = 0; i < len; i += 1) {
10128 registers[i].release();
10129 }
10130 registers.length = 0;
10131 }
10132
10133 animation.renderer.compInterface = CompExpressionInterface(animation.renderer);
10134 animation.renderer.globalData.projectInterface.registerComposition(animation.renderer);
10135 animation.renderer.globalData.pushExpression = pushExpression;
10136 animation.renderer.globalData.popExpression = popExpression;
10137 animation.renderer.globalData.registerExpressionProperty = registerExpressionProperty;
10138 }
10139 return ob;
10140}());
10141
10142expressionsPlugin = Expressions;
10143
10144var ExpressionManager = (function(){
10145 'use strict';
10146 var ob = {};
10147 var Math = BMMath;
10148 var window = null;
10149 var document = null;
10150
10151 function $bm_isInstanceOfArray(arr) {
10152 return arr.constructor === Array || arr.constructor === Float32Array;
10153 }
10154
10155 function isNumerable(tOfV, v) {
10156 return tOfV === 'number' || tOfV === 'boolean' || tOfV === 'string' || v instanceof Number;
10157 }
10158
10159 function $bm_neg(a){
10160 var tOfA = typeof a;
10161 if(tOfA === 'number' || tOfA === 'boolean' || a instanceof Number ){
10162 return -a;
10163 }
10164 if($bm_isInstanceOfArray(a)){
10165 var i, lenA = a.length;
10166 var retArr = [];
10167 for(i=0;i<lenA;i+=1){
10168 retArr[i] = -a[i];
10169 }
10170 return retArr;
10171 }
10172 if (a.propType) {
10173 return a.v;
10174 }
10175 }
10176
10177 var easeInBez = BezierFactory.getBezierEasing(0.333,0,.833,.833, 'easeIn').get;
10178 var easeOutBez = BezierFactory.getBezierEasing(0.167,0.167,.667,1, 'easeOut').get;
10179 var easeInOutBez = BezierFactory.getBezierEasing(.33,0,.667,1, 'easeInOut').get;
10180
10181 function sum(a,b) {
10182 var tOfA = typeof a;
10183 var tOfB = typeof b;
10184 if(tOfA === 'string' || tOfB === 'string'){
10185 return a + b;
10186 }
10187 if(isNumerable(tOfA, a) && isNumerable(tOfB, b)) {
10188 return a + b;
10189 }
10190 if($bm_isInstanceOfArray(a) && isNumerable(tOfB, b)){
10191 a = a.slice(0);
10192 a[0] = a[0] + b;
10193 return a;
10194 }
10195 if(isNumerable(tOfA, a) && $bm_isInstanceOfArray(b)){
10196 b = b.slice(0);
10197 b[0] = a + b[0];
10198 return b;
10199 }
10200 if($bm_isInstanceOfArray(a) && $bm_isInstanceOfArray(b)){
10201
10202 var i = 0, lenA = a.length, lenB = b.length;
10203 var retArr = [];
10204 while(i<lenA || i < lenB){
10205 if((typeof a[i] === 'number' || a[i] instanceof Number) && (typeof b[i] === 'number' || b[i] instanceof Number)){
10206 retArr[i] = a[i] + b[i];
10207 }else{
10208 retArr[i] = b[i] === undefined ? a[i] : a[i] || b[i];
10209 }
10210 i += 1;
10211 }
10212 return retArr;
10213 }
10214 return 0;
10215 }
10216 var add = sum;
10217
10218 function sub(a,b) {
10219 var tOfA = typeof a;
10220 var tOfB = typeof b;
10221 if(isNumerable(tOfA, a) && isNumerable(tOfB, b)) {
10222 if(tOfA === 'string') {
10223 a = parseInt(a);
10224 }
10225 if(tOfB === 'string') {
10226 b = parseInt(b);
10227 }
10228 return a - b;
10229 }
10230 if( $bm_isInstanceOfArray(a) && isNumerable(tOfB, b)){
10231 a = a.slice(0);
10232 a[0] = a[0] - b;
10233 return a;
10234 }
10235 if(isNumerable(tOfA, a) && $bm_isInstanceOfArray(b)){
10236 b = b.slice(0);
10237 b[0] = a - b[0];
10238 return b;
10239 }
10240 if($bm_isInstanceOfArray(a) && $bm_isInstanceOfArray(b)){
10241 var i = 0, lenA = a.length, lenB = b.length;
10242 var retArr = [];
10243 while(i<lenA || i < lenB){
10244 if((typeof a[i] === 'number' || a[i] instanceof Number) && (typeof b[i] === 'number' || b[i] instanceof Number)){
10245 retArr[i] = a[i] - b[i];
10246 }else{
10247 retArr[i] = b[i] === undefined ? a[i] : a[i] || b[i];
10248 }
10249 i += 1;
10250 }
10251 return retArr;
10252 }
10253 return 0;
10254 }
10255
10256 function mul(a,b) {
10257 var tOfA = typeof a;
10258 var tOfB = typeof b;
10259 var arr;
10260 if(isNumerable(tOfA, a) && isNumerable(tOfB, b)) {
10261 return a * b;
10262 }
10263
10264 var i, len;
10265 if($bm_isInstanceOfArray(a) && isNumerable(tOfB, b)){
10266 len = a.length;
10267 arr = createTypedArray('float32', len);
10268 for(i=0;i<len;i+=1){
10269 arr[i] = a[i] * b;
10270 }
10271 return arr;
10272 }
10273 if(isNumerable(tOfA, a) && $bm_isInstanceOfArray(b)){
10274 len = b.length;
10275 arr = createTypedArray('float32', len);
10276 for(i=0;i<len;i+=1){
10277 arr[i] = a * b[i];
10278 }
10279 return arr;
10280 }
10281 return 0;
10282 }
10283
10284 function div(a,b) {
10285 var tOfA = typeof a;
10286 var tOfB = typeof b;
10287 var arr;
10288 if(isNumerable(tOfA, a) && isNumerable(tOfB, b)) {
10289 return a / b;
10290 }
10291 var i, len;
10292 if($bm_isInstanceOfArray(a) && isNumerable(tOfB, b)){
10293 len = a.length;
10294 arr = createTypedArray('float32', len);
10295 for(i=0;i<len;i+=1){
10296 arr[i] = a[i] / b;
10297 }
10298 return arr;
10299 }
10300 if(isNumerable(tOfA, a) && $bm_isInstanceOfArray(b)){
10301 len = b.length;
10302 arr = createTypedArray('float32', len);
10303 for(i=0;i<len;i+=1){
10304 arr[i] = a / b[i];
10305 }
10306 return arr;
10307 }
10308 return 0;
10309 }
10310 function mod(a,b) {
10311 if(typeof a === 'string') {
10312 a = parseInt(a);
10313 }
10314 if(typeof b === 'string') {
10315 b = parseInt(b);
10316 }
10317 return a % b;
10318 }
10319 var $bm_sum = sum;
10320 var $bm_sub = sub;
10321 var $bm_mul = mul;
10322 var $bm_div = div;
10323 var $bm_mod = mod;
10324
10325 function clamp(num, min, max) {
10326 if(min > max){
10327 var mm = max;
10328 max = min;
10329 min = mm;
10330 }
10331 return Math.min(Math.max(num, min), max);
10332 }
10333
10334 function radiansToDegrees(val) {
10335 return val/degToRads;
10336 }
10337 var radians_to_degrees = radiansToDegrees;
10338
10339 function degreesToRadians(val) {
10340 return val*degToRads;
10341 }
10342 var degrees_to_radians = radiansToDegrees;
10343
10344 var helperLengthArray = [0,0,0,0,0,0];
10345
10346 function length(arr1, arr2) {
10347 if (typeof arr1 === 'number' || arr1 instanceof Number) {
10348 arr2 = arr2 || 0;
10349 return Math.abs(arr1 - arr2);
10350 }
10351 if(!arr2) {
10352 arr2 = helperLengthArray;
10353 }
10354 var i, len = Math.min(arr1.length, arr2.length);
10355 var addedLength = 0;
10356 for (i = 0; i < len; i += 1) {
10357 addedLength += Math.pow(arr2[i] - arr1[i], 2);
10358 }
10359 return Math.sqrt(addedLength);
10360 }
10361
10362 function normalize(vec) {
10363 return div(vec, length(vec));
10364 }
10365
10366 function rgbToHsl(val) {
10367 var r = val[0]; var g = val[1]; var b = val[2];
10368 var max = Math.max(r, g, b), min = Math.min(r, g, b);
10369 var h, s, l = (max + min) / 2;
10370
10371 if(max == min){
10372 h = s = 0; // achromatic
10373 }else{
10374 var d = max - min;
10375 s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
10376 switch(max){
10377 case r: h = (g - b) / d + (g < b ? 6 : 0); break;
10378 case g: h = (b - r) / d + 2; break;
10379 case b: h = (r - g) / d + 4; break;
10380 }
10381 h /= 6;
10382 }
10383
10384 return [h, s, l,val[3]];
10385 }
10386
10387 function hue2rgb(p, q, t){
10388 if(t < 0) t += 1;
10389 if(t > 1) t -= 1;
10390 if(t < 1/6) return p + (q - p) * 6 * t;
10391 if(t < 1/2) return q;
10392 if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
10393 return p;
10394 }
10395
10396 function hslToRgb(val){
10397 var h = val[0];
10398 var s = val[1];
10399 var l = val[2];
10400
10401 var r, g, b;
10402
10403 if(s === 0){
10404 r = g = b = l; // achromatic
10405 }else{
10406
10407 var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
10408 var p = 2 * l - q;
10409 r = hue2rgb(p, q, h + 1/3);
10410 g = hue2rgb(p, q, h);
10411 b = hue2rgb(p, q, h - 1/3);
10412 }
10413
10414 return [r, g , b, val[3]];
10415 }
10416
10417 function linear(t, tMin, tMax, value1, value2){
10418 if(value1 === undefined || value2 === undefined){
10419 value1 = tMin;
10420 value2 = tMax;
10421 tMin = 0;
10422 tMax = 1;
10423 }
10424 if(tMax < tMin) {
10425 var _tMin = tMax;
10426 tMax = tMin;
10427 tMin = _tMin;
10428 }
10429 if(t <= tMin) {
10430 return value1;
10431 }else if(t >= tMax){
10432 return value2;
10433 }
10434 var perc = tMax === tMin ? 0 : (t-tMin)/(tMax-tMin);
10435 if(!value1.length){
10436 return value1 + (value2-value1)*perc;
10437 }
10438 var i, len = value1.length;
10439 var arr = createTypedArray('float32', len);
10440 for(i=0;i<len;i+=1){
10441 arr[i] = value1[i] + (value2[i]-value1[i])*perc;
10442 }
10443 return arr;
10444 }
10445 function random(min,max){
10446 if(max === undefined){
10447 if(min === undefined){
10448 min = 0;
10449 max = 1;
10450 } else {
10451 max = min;
10452 min = undefined;
10453 }
10454 }
10455 if(max.length){
10456 var i, len = max.length;
10457 if(!min){
10458 min = createTypedArray('float32', len);
10459 }
10460 var arr = createTypedArray('float32', len);
10461 var rnd = BMMath.random();
10462 for(i=0;i<len;i+=1){
10463 arr[i] = min[i] + rnd*(max[i]-min[i]);
10464 }
10465 return arr;
10466 }
10467 if(min === undefined){
10468 min = 0;
10469 }
10470 var rndm = BMMath.random();
10471 return min + rndm*(max-min);
10472 }
10473
10474 function createPath(points, inTangents, outTangents, closed) {
10475 var i, len = points.length;
10476 var path = shape_pool.newElement();
10477 path.setPathData(!!closed, len);
10478 var arrPlaceholder = [0,0], inVertexPoint, outVertexPoint;
10479 for(i = 0; i < len; i += 1) {
10480 inVertexPoint = (inTangents && inTangents[i]) ? inTangents[i] : arrPlaceholder;
10481 outVertexPoint = (outTangents && outTangents[i]) ? outTangents[i] : arrPlaceholder;
10482 path.setTripleAt(points[i][0],points[i][1],outVertexPoint[0] + points[i][0],outVertexPoint[1] + points[i][1],inVertexPoint[0] + points[i][0],inVertexPoint[1] + points[i][1],i,true);
10483 }
10484 return path;
10485 }
10486
10487 function initiateExpression(elem,data,property){
10488 var val = data.x;
10489 var needsVelocity = /velocity(?![\w\d])/.test(val);
10490 var _needsRandom = val.indexOf('random') !== -1;
10491 var elemType = elem.data.ty;
10492 var transform,$bm_transform,content,effect;
10493 var thisProperty = property;
10494 thisProperty.valueAtTime = thisProperty.getValueAtTime;
10495 Object.defineProperty(thisProperty, 'value', {
10496 get: function() {
10497 return thisProperty.v
10498 }
10499 })
10500 elem.comp.frameDuration = 1/elem.comp.globalData.frameRate;
10501 elem.comp.displayStartTime = 0;
10502 var inPoint = elem.data.ip/elem.comp.globalData.frameRate;
10503 var outPoint = elem.data.op/elem.comp.globalData.frameRate;
10504 var width = elem.data.sw ? elem.data.sw : 0;
10505 var height = elem.data.sh ? elem.data.sh : 0;
10506 var name = elem.data.nm;
10507 var loopIn, loop_in, loopOut, loop_out, smooth;
10508 var toWorld,fromWorld,fromComp,toComp,fromCompToSurface, position, rotation, anchorPoint, scale, thisLayer, thisComp,mask,valueAtTime,velocityAtTime;
10509 var __expression_functions = [];
10510 if(data.xf) {
10511 var i, len = data.xf.length;
10512 for(i = 0; i < len; i += 1) {
10513 __expression_functions[i] = eval('(function(){ return ' + data.xf[i] + '}())');
10514 }
10515 }
10516
10517 var scoped_bm_rt;
10518 var expression_function = eval('[function _expression_function(){' + val+';scoped_bm_rt=$bm_rt}' + ']')[0];
10519 var numKeys = property.kf ? data.k.length : 0;
10520
10521 var active = !this.data || this.data.hd !== true;
10522
10523 var wiggle = function wiggle(freq,amp){
10524 var i,j, len = this.pv.length ? this.pv.length : 1;
10525 var addedAmps = createTypedArray('float32', len);
10526 freq = 5;
10527 var iterations = Math.floor(time*freq);
10528 i = 0;
10529 j = 0;
10530 while(i<iterations){
10531 //var rnd = BMMath.random();
10532 for(j=0;j<len;j+=1){
10533 addedAmps[j] += -amp + amp*2*BMMath.random();
10534 //addedAmps[j] += -amp + amp*2*rnd;
10535 }
10536 i += 1;
10537 }
10538 //var rnd2 = BMMath.random();
10539 var periods = time*freq;
10540 var perc = periods - Math.floor(periods);
10541 var arr = createTypedArray('float32', len);
10542 if(len>1){
10543 for(j=0;j<len;j+=1){
10544 arr[j] = this.pv[j] + addedAmps[j] + (-amp + amp*2*BMMath.random())*perc;
10545 //arr[j] = this.pv[j] + addedAmps[j] + (-amp + amp*2*rnd)*perc;
10546 //arr[i] = this.pv[i] + addedAmp + amp1*perc + amp2*(1-perc);
10547 }
10548 return arr;
10549 } else {
10550 return this.pv + addedAmps[0] + (-amp + amp*2*BMMath.random())*perc;
10551 }
10552 }.bind(this);
10553
10554 if(thisProperty.loopIn) {
10555 loopIn = thisProperty.loopIn.bind(thisProperty);
10556 loop_in = loopIn;
10557 }
10558
10559 if(thisProperty.loopOut) {
10560 loopOut = thisProperty.loopOut.bind(thisProperty);
10561 loop_out = loopOut;
10562 }
10563
10564 if(thisProperty.smooth) {
10565 smooth = thisProperty.smooth.bind(thisProperty);
10566 }
10567
10568 function loopInDuration(type,duration){
10569 return loopIn(type,duration,true);
10570 }
10571
10572 function loopOutDuration(type,duration){
10573 return loopOut(type,duration,true);
10574 }
10575
10576 if(this.getValueAtTime) {
10577 valueAtTime = this.getValueAtTime.bind(this);
10578 }
10579
10580 if(this.getVelocityAtTime) {
10581 velocityAtTime = this.getVelocityAtTime.bind(this);
10582 }
10583
10584 var comp = elem.comp.globalData.projectInterface.bind(elem.comp.globalData.projectInterface);
10585
10586 function lookAt(elem1,elem2){
10587 var fVec = [elem2[0]-elem1[0],elem2[1]-elem1[1],elem2[2]-elem1[2]];
10588 var pitch = Math.atan2(fVec[0],Math.sqrt(fVec[1]*fVec[1]+fVec[2]*fVec[2]))/degToRads;
10589 var yaw = -Math.atan2(fVec[1],fVec[2])/degToRads;
10590 return [yaw,pitch,0];
10591 }
10592
10593 function easeOut(t, tMin, tMax, val1, val2){
10594 return applyEase(easeOutBez, t, tMin, tMax, val1, val2);
10595 }
10596
10597 function easeIn(t, tMin, tMax, val1, val2){
10598 return applyEase(easeInBez, t, tMin, tMax, val1, val2);
10599 }
10600
10601 function ease(t, tMin, tMax, val1, val2){
10602 return applyEase(easeInOutBez, t, tMin, tMax, val1, val2);
10603 }
10604
10605 function applyEase(fn, t, tMin, tMax, val1, val2) {
10606 if(val1 === undefined){
10607 val1 = tMin;
10608 val2 = tMax;
10609 } else {
10610 t = (t - tMin) / (tMax - tMin);
10611 }
10612 t = t > 1 ? 1 : t < 0 ? 0 : t;
10613 var mult = fn(t);
10614 if($bm_isInstanceOfArray(val1)) {
10615 var i, len = val1.length;
10616 var arr = createTypedArray('float32', len);
10617 for (i = 0; i < len; i += 1) {
10618 arr[i] = (val2[i] - val1[i]) * mult + val1[i];
10619 }
10620 return arr;
10621 } else {
10622 return (val2 - val1) * mult + val1;
10623 }
10624 }
10625
10626 function nearestKey(time){
10627 var i, len = data.k.length,index,keyTime;
10628 if(!data.k.length || typeof(data.k[0]) === 'number'){
10629 index = 0;
10630 keyTime = 0;
10631 } else {
10632 index = -1;
10633 time *= elem.comp.globalData.frameRate;
10634 if (time < data.k[0].t) {
10635 index = 1;
10636 keyTime = data.k[0].t;
10637 } else {
10638 for(i=0;i<len-1;i+=1){
10639 if(time === data.k[i].t){
10640 index = i + 1;
10641 keyTime = data.k[i].t;
10642 break;
10643 }else if(time>data.k[i].t && time<data.k[i+1].t){
10644 if(time-data.k[i].t > data.k[i+1].t - time){
10645 index = i + 2;
10646 keyTime = data.k[i+1].t;
10647 } else {
10648 index = i + 1;
10649 keyTime = data.k[i].t;
10650 }
10651 break;
10652 }
10653 }
10654 if(index === -1){
10655 index = i + 1;
10656 keyTime = data.k[i].t;
10657 }
10658 }
10659
10660 }
10661 var ob = {};
10662 ob.index = index;
10663 ob.time = keyTime/elem.comp.globalData.frameRate;
10664 return ob;
10665 }
10666
10667 function key(ind){
10668 var ob, i, len;
10669 if(!data.k.length || typeof(data.k[0]) === 'number'){
10670 throw new Error('The property has no keyframe at index ' + ind);
10671 }
10672 ind -= 1;
10673 ob = {
10674 time: data.k[ind].t/elem.comp.globalData.frameRate,
10675 value: []
10676 };
10677 var arr = data.k[ind].hasOwnProperty('s') ? data.k[ind].s : data.k[ind - 1].e;
10678
10679 len = arr.length;
10680 for(i=0;i<len;i+=1){
10681 ob[i] = arr[i];
10682 ob.value[i] = arr[i]
10683 }
10684 return ob;
10685 }
10686
10687 function framesToTime(frames, fps) {
10688 if (!fps) {
10689 fps = elem.comp.globalData.frameRate;
10690 }
10691 return frames / fps;
10692 }
10693
10694 function timeToFrames(t, fps) {
10695 if (!t && t !== 0) {
10696 t = time;
10697 }
10698 if (!fps) {
10699 fps = elem.comp.globalData.frameRate;
10700 }
10701 return t * fps;
10702 }
10703
10704 function seedRandom(seed){
10705 BMMath.seedrandom(randSeed + seed);
10706 }
10707
10708 function sourceRectAtTime() {
10709 return elem.sourceRectAtTime();
10710 }
10711
10712 function substring(init, end) {
10713 if(typeof value === 'string') {
10714 if(end === undefined) {
10715 return value.substring(init)
10716 }
10717 return value.substring(init, end)
10718 }
10719 return '';
10720 }
10721
10722 function substr(init, end) {
10723 if(typeof value === 'string') {
10724 if(end === undefined) {
10725 return value.substr(init)
10726 }
10727 return value.substr(init, end)
10728 }
10729 return '';
10730 }
10731
10732 function posterizeTime(framesPerSecond) {
10733 time = framesPerSecond === 0 ? 0 : Math.floor(time * framesPerSecond) / framesPerSecond
10734 value = valueAtTime(time)
10735 }
10736
10737 var time, velocity, value, text, textIndex, textTotal, selectorValue;
10738 var index = elem.data.ind;
10739 var hasParent = !!(elem.hierarchy && elem.hierarchy.length);
10740 var parent;
10741 var randSeed = Math.floor(Math.random()*1000000);
10742 var globalData = elem.globalData;
10743 function executeExpression(_value) {
10744 // globalData.pushExpression();
10745 value = _value;
10746 if (_needsRandom) {
10747 seedRandom(randSeed);
10748 }
10749 if (this.frameExpressionId === elem.globalData.frameId && this.propType !== 'textSelector') {
10750 return value;
10751 }
10752 if(this.propType === 'textSelector'){
10753 textIndex = this.textIndex;
10754 textTotal = this.textTotal;
10755 selectorValue = this.selectorValue;
10756 }
10757 if (!thisLayer) {
10758 text = elem.layerInterface.text;
10759 thisLayer = elem.layerInterface;
10760 thisComp = elem.comp.compInterface;
10761 toWorld = thisLayer.toWorld.bind(thisLayer);
10762 fromWorld = thisLayer.fromWorld.bind(thisLayer);
10763 fromComp = thisLayer.fromComp.bind(thisLayer);
10764 toComp = thisLayer.toComp.bind(thisLayer);
10765 mask = thisLayer.mask ? thisLayer.mask.bind(thisLayer) : null;
10766 fromCompToSurface = fromComp;
10767 }
10768 if (!transform) {
10769 transform = elem.layerInterface("ADBE Transform Group");
10770 $bm_transform = transform;
10771 if(transform) {
10772 anchorPoint = transform.anchorPoint;
10773 /*position = transform.position;
10774 rotation = transform.rotation;
10775 scale = transform.scale;*/
10776 }
10777 }
10778
10779 if (elemType === 4 && !content) {
10780 content = thisLayer("ADBE Root Vectors Group");
10781 }
10782 if (!effect) {
10783 effect = thisLayer(4);
10784 }
10785 hasParent = !!(elem.hierarchy && elem.hierarchy.length);
10786 if (hasParent && !parent) {
10787 parent = elem.hierarchy[0].layerInterface;
10788 }
10789 time = this.comp.renderedFrame/this.comp.globalData.frameRate;
10790 if (needsVelocity) {
10791 velocity = velocityAtTime(time);
10792 }
10793 expression_function();
10794 this.frameExpressionId = elem.globalData.frameId;
10795
10796 //TODO: Check if it's possible to return on ShapeInterface the .v value
10797 if (scoped_bm_rt.propType === "shape") {
10798 scoped_bm_rt = scoped_bm_rt.v;
10799 }
10800 // globalData.popExpression();
10801 return scoped_bm_rt;
10802 }
10803 return executeExpression;
10804 }
10805
10806 ob.initiateExpression = initiateExpression;
10807 return ob;
10808}());
10809var expressionHelpers = (function(){
10810
10811 function searchExpressions(elem,data,prop){
10812 if(data.x){
10813 prop.k = true;
10814 prop.x = true;
10815 prop.initiateExpression = ExpressionManager.initiateExpression;
10816 prop.effectsSequence.push(prop.initiateExpression(elem,data,prop).bind(prop));
10817 }
10818 }
10819
10820 function getValueAtTime(frameNum) {
10821 frameNum *= this.elem.globalData.frameRate;
10822 frameNum -= this.offsetTime;
10823 if(frameNum !== this._cachingAtTime.lastFrame) {
10824 this._cachingAtTime.lastIndex = this._cachingAtTime.lastFrame < frameNum ? this._cachingAtTime.lastIndex : 0;
10825 this._cachingAtTime.value = this.interpolateValue(frameNum, this._cachingAtTime);
10826 this._cachingAtTime.lastFrame = frameNum;
10827 }
10828 return this._cachingAtTime.value;
10829
10830 }
10831
10832 function getSpeedAtTime(frameNum) {
10833 var delta = -0.01;
10834 var v1 = this.getValueAtTime(frameNum);
10835 var v2 = this.getValueAtTime(frameNum + delta);
10836 var speed = 0;
10837 if(v1.length){
10838 var i;
10839 for(i=0;i<v1.length;i+=1){
10840 speed += Math.pow(v2[i] - v1[i], 2);
10841 }
10842 speed = Math.sqrt(speed) * 100;
10843 } else {
10844 speed = 0;
10845 }
10846 return speed;
10847 }
10848
10849 function getVelocityAtTime(frameNum) {
10850 if(this.vel !== undefined){
10851 return this.vel;
10852 }
10853 var delta = -0.001;
10854 //frameNum += this.elem.data.st;
10855 var v1 = this.getValueAtTime(frameNum);
10856 var v2 = this.getValueAtTime(frameNum + delta);
10857 var velocity;
10858 if(v1.length){
10859 velocity = createTypedArray('float32', v1.length);
10860 var i;
10861 for(i=0;i<v1.length;i+=1){
10862 //removing frameRate
10863 //if needed, don't add it here
10864 //velocity[i] = this.elem.globalData.frameRate*((v2[i] - v1[i])/delta);
10865 velocity[i] = (v2[i] - v1[i])/delta;
10866 }
10867 } else {
10868 velocity = (v2 - v1)/delta;
10869 }
10870 return velocity;
10871 }
10872
10873 function getStaticValueAtTime() {
10874 return this.pv;
10875 }
10876
10877 function setGroupProperty(propertyGroup){
10878 this.propertyGroup = propertyGroup;
10879 }
10880
10881 return {
10882 searchExpressions: searchExpressions,
10883 getSpeedAtTime: getSpeedAtTime,
10884 getVelocityAtTime: getVelocityAtTime,
10885 getValueAtTime: getValueAtTime,
10886 getStaticValueAtTime: getStaticValueAtTime,
10887 setGroupProperty: setGroupProperty,
10888 }
10889}());
10890(function addPropertyDecorator() {
10891
10892 function loopOut(type,duration,durationFlag){
10893 if(!this.k || !this.keyframes){
10894 return this.pv;
10895 }
10896 type = type ? type.toLowerCase() : '';
10897 var currentFrame = this.comp.renderedFrame;
10898 var keyframes = this.keyframes;
10899 var lastKeyFrame = keyframes[keyframes.length - 1].t;
10900 if(currentFrame<=lastKeyFrame){
10901 return this.pv;
10902 }else{
10903 var cycleDuration, firstKeyFrame;
10904 if(!durationFlag){
10905 if(!duration || duration > keyframes.length - 1){
10906 duration = keyframes.length - 1;
10907 }
10908 firstKeyFrame = keyframes[keyframes.length - 1 - duration].t;
10909 cycleDuration = lastKeyFrame - firstKeyFrame;
10910 } else {
10911 if(!duration){
10912 cycleDuration = Math.max(0,lastKeyFrame - this.elem.data.ip);
10913 } else {
10914 cycleDuration = Math.abs(lastKeyFrame - elem.comp.globalData.frameRate*duration);
10915 }
10916 firstKeyFrame = lastKeyFrame - cycleDuration;
10917 }
10918 var i, len, ret;
10919 if(type === 'pingpong') {
10920 var iterations = Math.floor((currentFrame - firstKeyFrame)/cycleDuration);
10921 if(iterations % 2 !== 0){
10922 return this.getValueAtTime(((cycleDuration - (currentFrame - firstKeyFrame) % cycleDuration + firstKeyFrame)) / this.comp.globalData.frameRate, 0);
10923 }
10924 } else if(type === 'offset'){
10925 var initV = this.getValueAtTime(firstKeyFrame / this.comp.globalData.frameRate, 0);
10926 var endV = this.getValueAtTime(lastKeyFrame / this.comp.globalData.frameRate, 0);
10927 var current = this.getValueAtTime(((currentFrame - firstKeyFrame) % cycleDuration + firstKeyFrame) / this.comp.globalData.frameRate, 0);
10928 var repeats = Math.floor((currentFrame - firstKeyFrame)/cycleDuration);
10929 if(this.pv.length){
10930 ret = new Array(initV.length);
10931 len = ret.length;
10932 for(i=0;i<len;i+=1){
10933 ret[i] = (endV[i]-initV[i])*repeats + current[i];
10934 }
10935 return ret;
10936 }
10937 return (endV-initV)*repeats + current;
10938 } else if(type === 'continue'){
10939 var lastValue = this.getValueAtTime(lastKeyFrame / this.comp.globalData.frameRate, 0);
10940 var nextLastValue = this.getValueAtTime((lastKeyFrame - 0.001) / this.comp.globalData.frameRate, 0);
10941 if(this.pv.length){
10942 ret = new Array(lastValue.length);
10943 len = ret.length;
10944 for(i=0;i<len;i+=1){
10945 ret[i] = lastValue[i] + (lastValue[i]-nextLastValue[i])*((currentFrame - lastKeyFrame)/ this.comp.globalData.frameRate)/0.0005;
10946 }
10947 return ret;
10948 }
10949 return lastValue + (lastValue-nextLastValue)*(((currentFrame - lastKeyFrame))/0.001);
10950 }
10951 return this.getValueAtTime((((currentFrame - firstKeyFrame) % cycleDuration + firstKeyFrame)) / this.comp.globalData.frameRate, 0);
10952 }
10953 }
10954
10955 function loopIn(type,duration, durationFlag) {
10956 if(!this.k){
10957 return this.pv;
10958 }
10959 type = type ? type.toLowerCase() : '';
10960 var currentFrame = this.comp.renderedFrame;
10961 var keyframes = this.keyframes;
10962 var firstKeyFrame = keyframes[0].t;
10963 if(currentFrame>=firstKeyFrame){
10964 return this.pv;
10965 }else{
10966 var cycleDuration, lastKeyFrame;
10967 if(!durationFlag){
10968 if(!duration || duration > keyframes.length - 1){
10969 duration = keyframes.length - 1;
10970 }
10971 lastKeyFrame = keyframes[duration].t;
10972 cycleDuration = lastKeyFrame - firstKeyFrame;
10973 } else {
10974 if(!duration){
10975 cycleDuration = Math.max(0,this.elem.data.op - firstKeyFrame);
10976 } else {
10977 cycleDuration = Math.abs(elem.comp.globalData.frameRate*duration);
10978 }
10979 lastKeyFrame = firstKeyFrame + cycleDuration;
10980 }
10981 var i, len, ret;
10982 if(type === 'pingpong') {
10983 var iterations = Math.floor((firstKeyFrame - currentFrame)/cycleDuration);
10984 if(iterations % 2 === 0){
10985 return this.getValueAtTime((((firstKeyFrame - currentFrame)%cycleDuration + firstKeyFrame)) / this.comp.globalData.frameRate, 0);
10986 }
10987 } else if(type === 'offset'){
10988 var initV = this.getValueAtTime(firstKeyFrame / this.comp.globalData.frameRate, 0);
10989 var endV = this.getValueAtTime(lastKeyFrame / this.comp.globalData.frameRate, 0);
10990 var current = this.getValueAtTime((cycleDuration - (firstKeyFrame - currentFrame)%cycleDuration + firstKeyFrame) / this.comp.globalData.frameRate, 0);
10991 var repeats = Math.floor((firstKeyFrame - currentFrame)/cycleDuration)+1;
10992 if(this.pv.length){
10993 ret = new Array(initV.length);
10994 len = ret.length;
10995 for(i=0;i<len;i+=1){
10996 ret[i] = current[i]-(endV[i]-initV[i])*repeats;
10997 }
10998 return ret;
10999 }
11000 return current-(endV-initV)*repeats;
11001 } else if(type === 'continue'){
11002 var firstValue = this.getValueAtTime(firstKeyFrame / this.comp.globalData.frameRate, 0);
11003 var nextFirstValue = this.getValueAtTime((firstKeyFrame + 0.001) / this.comp.globalData.frameRate, 0);
11004 if(this.pv.length){
11005 ret = new Array(firstValue.length);
11006 len = ret.length;
11007 for(i=0;i<len;i+=1){
11008 ret[i] = firstValue[i] + (firstValue[i]-nextFirstValue[i])*(firstKeyFrame - currentFrame)/0.001;
11009 }
11010 return ret;
11011 }
11012 return firstValue + (firstValue-nextFirstValue)*(firstKeyFrame - currentFrame)/0.001;
11013 }
11014 return this.getValueAtTime(((cycleDuration - (firstKeyFrame - currentFrame) % cycleDuration + firstKeyFrame)) / this.comp.globalData.frameRate, 0);
11015 }
11016 }
11017
11018 function smooth(width, samples) {
11019 if (!this.k){
11020 return this.pv;
11021 }
11022 width = (width || 0.4) * 0.5;
11023 samples = Math.floor(samples || 5);
11024 if (samples <= 1) {
11025 return this.pv;
11026 }
11027 var currentTime = this.comp.renderedFrame / this.comp.globalData.frameRate;
11028 var initFrame = currentTime - width;
11029 var endFrame = currentTime + width;
11030 var sampleFrequency = samples > 1 ? (endFrame - initFrame) / (samples - 1) : 1;
11031 var i = 0, j = 0;
11032 var value;
11033 if (this.pv.length) {
11034 value = createTypedArray('float32', this.pv.length);
11035 } else {
11036 value = 0;
11037 }
11038 var sampleValue;
11039 while (i < samples) {
11040 sampleValue = this.getValueAtTime(initFrame + i * sampleFrequency);
11041 if(this.pv.length) {
11042 for (j = 0; j < this.pv.length; j += 1) {
11043 value[j] += sampleValue[j];
11044 }
11045 } else {
11046 value += sampleValue;
11047 }
11048 i += 1;
11049 }
11050 if(this.pv.length) {
11051 for (j = 0; j < this.pv.length; j += 1) {
11052 value[j] /= samples;
11053 }
11054 } else {
11055 value /= samples;
11056 }
11057 return value;
11058 }
11059
11060 function getValueAtTime(frameNum) {
11061 frameNum *= this.elem.globalData.frameRate;
11062 frameNum -= this.offsetTime;
11063 if(frameNum !== this._cachingAtTime.lastFrame) {
11064 this._cachingAtTime.lastIndex = this._cachingAtTime.lastFrame < frameNum ? this._cachingAtTime.lastIndex : 0;
11065 this._cachingAtTime.value = this.interpolateValue(frameNum, this._cachingAtTime);
11066 this._cachingAtTime.lastFrame = frameNum;
11067 }
11068 return this._cachingAtTime.value;
11069
11070 }
11071
11072 function getTransformValueAtTime(time) {
11073 if (!this._transformCachingAtTime) {
11074 this._transformCachingAtTime = {
11075 v: new Matrix(),
11076 };
11077 }
11078 ////
11079 var matrix = this._transformCachingAtTime.v;
11080 matrix.cloneFromProps(this.pre.props);
11081 if (this.appliedTransformations < 1) {
11082 var anchor = this.a.getValueAtTime(time);
11083 matrix.translate(-anchor[0], -anchor[1], anchor[2]);
11084 }
11085 if (this.appliedTransformations < 2) {
11086 var scale = this.s.getValueAtTime(time);
11087 matrix.scale(scale[0], scale[1], scale[2]);
11088 }
11089 if (this.sk && this.appliedTransformations < 3) {
11090 var skew = this.sk.getValueAtTime(time);
11091 var skewAxis = this.sa.getValueAtTime(time);
11092 matrix.skewFromAxis(-skew, skewAxis);
11093 }
11094 if (this.r && this.appliedTransformations < 4) {
11095 var rotation = this.r.getValueAtTime(time);
11096 matrix.rotate(-rotation);
11097 } else if (!this.r && this.appliedTransformations < 4){
11098 var rotationZ = this.rz.getValueAtTime(time);
11099 var rotationY = this.ry.getValueAtTime(time);
11100 var rotationX = this.rx.getValueAtTime(time);
11101 var orientation = this.or.getValueAtTime(time);
11102 matrix.rotateZ(-rotationZ.v)
11103 .rotateY(rotationY.v)
11104 .rotateX(rotationX.v)
11105 .rotateZ(-orientation[2])
11106 .rotateY(orientation[1])
11107 .rotateX(orientation[0]);
11108 }
11109 if (this.data.p && this.data.p.s) {
11110 var positionX = this.px.getValueAtTime(time);
11111 var positionY = this.py.getValueAtTime(time);
11112 if (this.data.p.z) {
11113 var positionZ = this.pz.getValueAtTime(time);
11114 matrix.translate(positionX, positionY, -positionZ);
11115 } else {
11116 matrix.translate(positionX, positionY, 0);
11117 }
11118 } else {
11119 var position = this.p.getValueAtTime(time);
11120 matrix.translate(position[0], position[1], -position[2]);
11121 }
11122 return matrix;
11123 ////
11124 }
11125
11126 function getTransformStaticValueAtTime(time) {
11127
11128 }
11129
11130 var getTransformProperty = TransformPropertyFactory.getTransformProperty;
11131 TransformPropertyFactory.getTransformProperty = function(elem, data, container) {
11132 var prop = getTransformProperty(elem, data, container);
11133 if(prop.dynamicProperties.length) {
11134 prop.getValueAtTime = getTransformValueAtTime.bind(prop);
11135 } else {
11136 prop.getValueAtTime = getTransformStaticValueAtTime.bind(prop);
11137 }
11138 prop.setGroupProperty = expressionHelpers.setGroupProperty;
11139 return prop;
11140 };
11141
11142 var propertyGetProp = PropertyFactory.getProp;
11143 PropertyFactory.getProp = function(elem,data,type, mult, container){
11144 var prop = propertyGetProp(elem,data,type, mult, container);
11145 //prop.getVelocityAtTime = getVelocityAtTime;
11146 //prop.loopOut = loopOut;
11147 //prop.loopIn = loopIn;
11148 if(prop.kf){
11149 prop.getValueAtTime = expressionHelpers.getValueAtTime.bind(prop);
11150 } else {
11151 prop.getValueAtTime = expressionHelpers.getStaticValueAtTime.bind(prop);
11152 }
11153 prop.setGroupProperty = expressionHelpers.setGroupProperty;
11154 prop.loopOut = loopOut;
11155 prop.loopIn = loopIn;
11156 prop.smooth = smooth;
11157 prop.getVelocityAtTime = expressionHelpers.getVelocityAtTime.bind(prop);
11158 prop.getSpeedAtTime = expressionHelpers.getSpeedAtTime.bind(prop);
11159 prop.numKeys = data.a === 1 ? data.k.length : 0;
11160 prop.propertyIndex = data.ix;
11161 var value = 0;
11162 if(type !== 0) {
11163 value = createTypedArray('float32', data.a === 1 ? data.k[0].s.length : data.k.length);
11164 }
11165 prop._cachingAtTime = {
11166 lastFrame: initialDefaultFrame,
11167 lastIndex: 0,
11168 value: value
11169 };
11170 expressionHelpers.searchExpressions(elem,data,prop);
11171 if(prop.k){
11172 container.addDynamicProperty(prop);
11173 }
11174
11175 return prop;
11176 };
11177
11178 function getShapeValueAtTime(frameNum) {
11179 //For now this caching object is created only when needed instead of creating it when the shape is initialized.
11180 if (!this._cachingAtTime) {
11181 this._cachingAtTime = {
11182 shapeValue: shape_pool.clone(this.pv),
11183 lastIndex: 0,
11184 lastTime: initialDefaultFrame
11185 };
11186 }
11187
11188 frameNum *= this.elem.globalData.frameRate;
11189 frameNum -= this.offsetTime;
11190 if(frameNum !== this._cachingAtTime.lastTime) {
11191 this._cachingAtTime.lastIndex = this._cachingAtTime.lastTime < frameNum ? this._caching.lastIndex : 0;
11192 this._cachingAtTime.lastTime = frameNum;
11193 this.interpolateShape(frameNum, this._cachingAtTime.shapeValue, this._cachingAtTime);
11194 }
11195 return this._cachingAtTime.shapeValue;
11196 }
11197
11198 var ShapePropertyConstructorFunction = ShapePropertyFactory.getConstructorFunction();
11199 var KeyframedShapePropertyConstructorFunction = ShapePropertyFactory.getKeyframedConstructorFunction();
11200
11201 function ShapeExpressions(){}
11202 ShapeExpressions.prototype = {
11203 vertices: function(prop, time){
11204 if (this.k) {
11205 this.getValue();
11206 }
11207 var shapePath = this.v;
11208 if(time !== undefined) {
11209 shapePath = this.getValueAtTime(time, 0);
11210 }
11211 var i, len = shapePath._length;
11212 var vertices = shapePath[prop];
11213 var points = shapePath.v;
11214 var arr = createSizedArray(len);
11215 for(i = 0; i < len; i += 1) {
11216 if(prop === 'i' || prop === 'o') {
11217 arr[i] = [vertices[i][0] - points[i][0], vertices[i][1] - points[i][1]];
11218 } else {
11219 arr[i] = [vertices[i][0], vertices[i][1]];
11220 }
11221
11222 }
11223 return arr;
11224 },
11225 points: function(time){
11226 return this.vertices('v', time);
11227 },
11228 inTangents: function(time){
11229 return this.vertices('i', time);
11230 },
11231 outTangents: function(time){
11232 return this.vertices('o', time);
11233 },
11234 isClosed: function(){
11235 return this.v.c;
11236 },
11237 pointOnPath: function(perc, time){
11238 var shapePath = this.v;
11239 if(time !== undefined) {
11240 shapePath = this.getValueAtTime(time, 0);
11241 }
11242 if(!this._segmentsLength) {
11243 this._segmentsLength = bez.getSegmentsLength(shapePath);
11244 }
11245
11246 var segmentsLength = this._segmentsLength;
11247 var lengths = segmentsLength.lengths;
11248 var lengthPos = segmentsLength.totalLength * perc;
11249 var i = 0, len = lengths.length;
11250 var j = 0, jLen;
11251 var accumulatedLength = 0, pt;
11252 while(i < len) {
11253 if(accumulatedLength + lengths[i].addedLength > lengthPos) {
11254 var initIndex = i;
11255 var endIndex = (shapePath.c && i === len - 1) ? 0 : i + 1;
11256 var segmentPerc = (lengthPos - accumulatedLength)/lengths[i].addedLength;
11257 pt = bez.getPointInSegment(shapePath.v[initIndex], shapePath.v[endIndex], shapePath.o[initIndex], shapePath.i[endIndex], segmentPerc, lengths[i]);
11258 break;
11259 } else {
11260 accumulatedLength += lengths[i].addedLength;
11261 }
11262 i += 1;
11263 }
11264 if(!pt){
11265 pt = shapePath.c ? [shapePath.v[0][0],shapePath.v[0][1]]:[shapePath.v[shapePath._length-1][0],shapePath.v[shapePath._length-1][1]];
11266 }
11267 return pt;
11268 },
11269 vectorOnPath: function(perc, time, vectorType){
11270 //perc doesn't use triple equality because it can be a Number object as well as a primitive.
11271 perc = perc == 1 ? this.v.c ? 0 : 0.999 : perc;
11272 var pt1 = this.pointOnPath(perc, time);
11273 var pt2 = this.pointOnPath(perc + 0.001, time);
11274 var xLength = pt2[0] - pt1[0];
11275 var yLength = pt2[1] - pt1[1];
11276 var magnitude = Math.sqrt(Math.pow(xLength,2) + Math.pow(yLength,2));
11277 if (magnitude === 0) {
11278 return [0,0];
11279 }
11280 var unitVector = vectorType === 'tangent' ? [xLength/magnitude, yLength/magnitude] : [-yLength/magnitude, xLength/magnitude];
11281 return unitVector;
11282 },
11283 tangentOnPath: function(perc, time){
11284 return this.vectorOnPath(perc, time, 'tangent');
11285 },
11286 normalOnPath: function(perc, time){
11287 return this.vectorOnPath(perc, time, 'normal');
11288 },
11289 setGroupProperty: expressionHelpers.setGroupProperty,
11290 getValueAtTime: expressionHelpers.getStaticValueAtTime
11291 };
11292 extendPrototype([ShapeExpressions], ShapePropertyConstructorFunction);
11293 extendPrototype([ShapeExpressions], KeyframedShapePropertyConstructorFunction);
11294 KeyframedShapePropertyConstructorFunction.prototype.getValueAtTime = getShapeValueAtTime;
11295 KeyframedShapePropertyConstructorFunction.prototype.initiateExpression = ExpressionManager.initiateExpression;
11296
11297 var propertyGetShapeProp = ShapePropertyFactory.getShapeProp;
11298 ShapePropertyFactory.getShapeProp = function(elem,data,type, arr, trims){
11299 var prop = propertyGetShapeProp(elem,data,type, arr, trims);
11300 prop.propertyIndex = data.ix;
11301 prop.lock = false;
11302 if(type === 3){
11303 expressionHelpers.searchExpressions(elem,data.pt,prop);
11304 } else if(type === 4){
11305 expressionHelpers.searchExpressions(elem,data.ks,prop);
11306 }
11307 if(prop.k){
11308 elem.addDynamicProperty(prop);
11309 }
11310 return prop;
11311 };
11312}());
11313(function addDecorator() {
11314
11315 function searchExpressions(){
11316 if(this.data.d.x){
11317 this.calculateExpression = ExpressionManager.initiateExpression.bind(this)(this.elem,this.data.d,this);
11318 this.addEffect(this.getExpressionValue.bind(this));
11319 return true;
11320 }
11321 }
11322
11323 TextProperty.prototype.getExpressionValue = function(currentValue, text) {
11324 var newValue = this.calculateExpression(text);
11325 if(currentValue.t !== newValue) {
11326 var newData = {};
11327 this.copyData(newData, currentValue);
11328 newData.t = newValue.toString();
11329 newData.__complete = false;
11330 return newData;
11331 }
11332 return currentValue;
11333 }
11334
11335 TextProperty.prototype.searchProperty = function(){
11336
11337 var isKeyframed = this.searchKeyframes();
11338 var hasExpressions = this.searchExpressions();
11339 this.kf = isKeyframed || hasExpressions;
11340 return this.kf;
11341 };
11342
11343 TextProperty.prototype.searchExpressions = searchExpressions;
11344
11345}());
11346var ShapePathInterface = (
11347
11348 function() {
11349
11350 return function pathInterfaceFactory(shape,view,propertyGroup){
11351 var prop = view.sh;
11352
11353 function interfaceFunction(val){
11354 if(val === 'Shape' || val === 'shape' || val === 'Path' || val === 'path' || val === 'ADBE Vector Shape' || val === 2){
11355 return interfaceFunction.path;
11356 }
11357 }
11358
11359 var _propertyGroup = propertyGroupFactory(interfaceFunction, propertyGroup);
11360 prop.setGroupProperty(PropertyInterface('Path', _propertyGroup));
11361 Object.defineProperties(interfaceFunction, {
11362 'path': {
11363 get: function(){
11364 if(prop.k){
11365 prop.getValue();
11366 }
11367 return prop;
11368 }
11369 },
11370 'shape': {
11371 get: function(){
11372 if(prop.k){
11373 prop.getValue();
11374 }
11375 return prop;
11376 }
11377 },
11378 '_name': { value: shape.nm },
11379 'ix': { value: shape.ix },
11380 'propertyIndex': { value: shape.ix },
11381 'mn': { value: shape.mn },
11382 'propertyGroup': {value: propertyGroup},
11383 });
11384 return interfaceFunction;
11385 }
11386 }()
11387)
11388var propertyGroupFactory = (function() {
11389 return function(interfaceFunction, parentPropertyGroup) {
11390 return function(val) {
11391 val = val === undefined ? 1 : val
11392 if(val <= 0){
11393 return interfaceFunction;
11394 } else{
11395 return parentPropertyGroup(val-1);
11396 }
11397 }
11398 }
11399}())
11400var PropertyInterface = (function() {
11401 return function(propertyName, propertyGroup) {
11402
11403 var interfaceFunction = {
11404 _name: propertyName
11405 }
11406
11407 function _propertyGroup(val){
11408 val = val === undefined ? 1 : val
11409 if(val <= 0){
11410 return interfaceFunction;
11411 } else {
11412 return propertyGroup(--val);
11413 }
11414 }
11415
11416 return _propertyGroup;
11417 }
11418}())
11419var ShapeExpressionInterface = (function(){
11420
11421 function iterateElements(shapes,view, propertyGroup){
11422 var arr = [];
11423 var i, len = shapes ? shapes.length : 0;
11424 for(i=0;i<len;i+=1){
11425 if(shapes[i].ty == 'gr'){
11426 arr.push(groupInterfaceFactory(shapes[i],view[i],propertyGroup));
11427 }else if(shapes[i].ty == 'fl'){
11428 arr.push(fillInterfaceFactory(shapes[i],view[i],propertyGroup));
11429 }else if(shapes[i].ty == 'st'){
11430 arr.push(strokeInterfaceFactory(shapes[i],view[i],propertyGroup));
11431 }else if(shapes[i].ty == 'tm'){
11432 arr.push(trimInterfaceFactory(shapes[i],view[i],propertyGroup));
11433 }else if(shapes[i].ty == 'tr'){
11434 //arr.push(transformInterfaceFactory(shapes[i],view[i],propertyGroup));
11435 }else if(shapes[i].ty == 'el'){
11436 arr.push(ellipseInterfaceFactory(shapes[i],view[i],propertyGroup));
11437 }else if(shapes[i].ty == 'sr'){
11438 arr.push(starInterfaceFactory(shapes[i],view[i],propertyGroup));
11439 } else if(shapes[i].ty == 'sh'){
11440 arr.push(ShapePathInterface(shapes[i],view[i],propertyGroup));
11441 } else if(shapes[i].ty == 'rc'){
11442 arr.push(rectInterfaceFactory(shapes[i],view[i],propertyGroup));
11443 } else if(shapes[i].ty == 'rd'){
11444 arr.push(roundedInterfaceFactory(shapes[i],view[i],propertyGroup));
11445 } else if(shapes[i].ty == 'rp'){
11446 arr.push(repeaterInterfaceFactory(shapes[i],view[i],propertyGroup));
11447 }
11448 }
11449 return arr;
11450 }
11451
11452 function contentsInterfaceFactory(shape,view, propertyGroup){
11453 var interfaces;
11454 var interfaceFunction = function _interfaceFunction(value){
11455 var i = 0, len = interfaces.length;
11456 while(i<len){
11457 if(interfaces[i]._name === value || interfaces[i].mn === value || interfaces[i].propertyIndex === value || interfaces[i].ix === value || interfaces[i].ind === value){
11458 return interfaces[i];
11459 }
11460 i+=1;
11461 }
11462 if(typeof value === 'number'){
11463 return interfaces[value-1];
11464 }
11465 };
11466
11467 interfaceFunction.propertyGroup = propertyGroupFactory(interfaceFunction, propertyGroup);
11468 interfaces = iterateElements(shape.it, view.it, interfaceFunction.propertyGroup);
11469 interfaceFunction.numProperties = interfaces.length;
11470 var transformInterface = transformInterfaceFactory(shape.it[shape.it.length - 1],view.it[view.it.length - 1],interfaceFunction.propertyGroup);
11471 interfaceFunction.transform = transformInterface;
11472 interfaceFunction.propertyIndex = shape.cix;
11473 interfaceFunction._name = shape.nm;
11474
11475 return interfaceFunction;
11476 }
11477
11478 function groupInterfaceFactory(shape,view, propertyGroup){
11479 var interfaceFunction = function _interfaceFunction(value){
11480 switch(value){
11481 case 'ADBE Vectors Group':
11482 case 'Contents':
11483 case 2:
11484 return interfaceFunction.content;
11485 //Not necessary for now. Keeping them here in case a new case appears
11486 //case 'ADBE Vector Transform Group':
11487 //case 3:
11488 default:
11489 return interfaceFunction.transform;
11490 }
11491 };
11492 interfaceFunction.propertyGroup = propertyGroupFactory(interfaceFunction, propertyGroup);
11493 var content = contentsInterfaceFactory(shape,view,interfaceFunction.propertyGroup);
11494 var transformInterface = transformInterfaceFactory(shape.it[shape.it.length - 1],view.it[view.it.length - 1],interfaceFunction.propertyGroup);
11495 interfaceFunction.content = content;
11496 interfaceFunction.transform = transformInterface;
11497 Object.defineProperty(interfaceFunction, '_name', {
11498 get: function(){
11499 return shape.nm;
11500 }
11501 });
11502 //interfaceFunction.content = interfaceFunction;
11503 interfaceFunction.numProperties = shape.np;
11504 interfaceFunction.propertyIndex = shape.ix;
11505 interfaceFunction.nm = shape.nm;
11506 interfaceFunction.mn = shape.mn;
11507 return interfaceFunction;
11508 }
11509
11510 function fillInterfaceFactory(shape,view,propertyGroup){
11511 function interfaceFunction(val){
11512 if(val === 'Color' || val === 'color'){
11513 return interfaceFunction.color;
11514 } else if(val === 'Opacity' || val === 'opacity'){
11515 return interfaceFunction.opacity;
11516 }
11517 }
11518 Object.defineProperties(interfaceFunction, {
11519 'color': {
11520 get: ExpressionPropertyInterface(view.c)
11521 },
11522 'opacity': {
11523 get: ExpressionPropertyInterface(view.o)
11524 },
11525 '_name': { value: shape.nm },
11526 'mn': { value: shape.mn }
11527 });
11528
11529 view.c.setGroupProperty(PropertyInterface('Color', propertyGroup));
11530 view.o.setGroupProperty(PropertyInterface('Opacity', propertyGroup));
11531 return interfaceFunction;
11532 }
11533
11534 function strokeInterfaceFactory(shape,view,propertyGroup){
11535 var _propertyGroup = propertyGroupFactory(interfaceFunction, propertyGroup);
11536 var _dashPropertyGroup = propertyGroupFactory(dashOb, _propertyGroup);
11537 function addPropertyToDashOb(i) {
11538 Object.defineProperty(dashOb, shape.d[i].nm, {
11539 get: ExpressionPropertyInterface(view.d.dataProps[i].p)
11540 });
11541 }
11542 var i, len = shape.d ? shape.d.length : 0;
11543 var dashOb = {};
11544 for (i = 0; i < len; i += 1) {
11545 addPropertyToDashOb(i);
11546 view.d.dataProps[i].p.setGroupProperty(_dashPropertyGroup);
11547 }
11548
11549 function interfaceFunction(val){
11550 if(val === 'Color' || val === 'color'){
11551 return interfaceFunction.color;
11552 } else if(val === 'Opacity' || val === 'opacity'){
11553 return interfaceFunction.opacity;
11554 } else if(val === 'Stroke Width' || val === 'stroke width'){
11555 return interfaceFunction.strokeWidth;
11556 }
11557 }
11558 Object.defineProperties(interfaceFunction, {
11559 'color': {
11560 get: ExpressionPropertyInterface(view.c)
11561 },
11562 'opacity': {
11563 get: ExpressionPropertyInterface(view.o)
11564 },
11565 'strokeWidth': {
11566 get: ExpressionPropertyInterface(view.w)
11567 },
11568 'dash': {
11569 get: function() {
11570 return dashOb;
11571 }
11572 },
11573 '_name': { value: shape.nm },
11574 'mn': { value: shape.mn }
11575 });
11576
11577 view.c.setGroupProperty(PropertyInterface('Color', _propertyGroup));
11578 view.o.setGroupProperty(PropertyInterface('Opacity', _propertyGroup));
11579 view.w.setGroupProperty(PropertyInterface('Stroke Width', _propertyGroup));
11580 return interfaceFunction;
11581 }
11582
11583 function trimInterfaceFactory(shape,view,propertyGroup){
11584
11585 function interfaceFunction(val){
11586 if(val === shape.e.ix || val === 'End' || val === 'end'){
11587 return interfaceFunction.end;
11588 }
11589 if(val === shape.s.ix){
11590 return interfaceFunction.start;
11591 }
11592 if(val === shape.o.ix){
11593 return interfaceFunction.offset;
11594 }
11595 }
11596
11597 var _propertyGroup = propertyGroupFactory(interfaceFunction, propertyGroup);
11598 interfaceFunction.propertyIndex = shape.ix;
11599
11600 view.s.setGroupProperty(PropertyInterface('Start', _propertyGroup));
11601 view.e.setGroupProperty(PropertyInterface('End', _propertyGroup));
11602 view.o.setGroupProperty(PropertyInterface('Offset', _propertyGroup));
11603 interfaceFunction.propertyIndex = shape.ix;
11604 interfaceFunction.propertyGroup = propertyGroup;
11605
11606 Object.defineProperties(interfaceFunction, {
11607 'start': {
11608 get: ExpressionPropertyInterface(view.s)
11609 },
11610 'end': {
11611 get: ExpressionPropertyInterface(view.e)
11612 },
11613 'offset': {
11614 get: ExpressionPropertyInterface(view.o)
11615 },
11616 '_name': { value: shape.nm }
11617 });
11618 interfaceFunction.mn = shape.mn;
11619 return interfaceFunction;
11620 }
11621
11622 function transformInterfaceFactory(shape,view,propertyGroup){
11623
11624 function interfaceFunction(value){
11625 if(shape.a.ix === value || value === 'Anchor Point'){
11626 return interfaceFunction.anchorPoint;
11627 }
11628 if(shape.o.ix === value || value === 'Opacity'){
11629 return interfaceFunction.opacity;
11630 }
11631 if(shape.p.ix === value || value === 'Position'){
11632 return interfaceFunction.position;
11633 }
11634 if(shape.r.ix === value || value === 'Rotation' || value === 'ADBE Vector Rotation'){
11635 return interfaceFunction.rotation;
11636 }
11637 if(shape.s.ix === value || value === 'Scale'){
11638 return interfaceFunction.scale;
11639 }
11640 if(shape.sk && shape.sk.ix === value || value === 'Skew'){
11641 return interfaceFunction.skew;
11642 }
11643 if(shape.sa && shape.sa.ix === value || value === 'Skew Axis'){
11644 return interfaceFunction.skewAxis;
11645 }
11646 }
11647
11648 var _propertyGroup = propertyGroupFactory(interfaceFunction, propertyGroup);
11649 view.transform.mProps.o.setGroupProperty(PropertyInterface('Opacity', _propertyGroup));
11650 view.transform.mProps.p.setGroupProperty(PropertyInterface('Position', _propertyGroup));
11651 view.transform.mProps.a.setGroupProperty(PropertyInterface('Anchor Point', _propertyGroup));
11652 view.transform.mProps.s.setGroupProperty(PropertyInterface('Scale', _propertyGroup));
11653 view.transform.mProps.r.setGroupProperty(PropertyInterface('Rotation', _propertyGroup));
11654 if(view.transform.mProps.sk){
11655 view.transform.mProps.sk.setGroupProperty(PropertyInterface('Skew', _propertyGroup));
11656 view.transform.mProps.sa.setGroupProperty(PropertyInterface('Skew Angle', _propertyGroup));
11657 }
11658 view.transform.op.setGroupProperty(PropertyInterface('Opacity', _propertyGroup));
11659 Object.defineProperties(interfaceFunction, {
11660 'opacity': {
11661 get: ExpressionPropertyInterface(view.transform.mProps.o)
11662 },
11663 'position': {
11664 get: ExpressionPropertyInterface(view.transform.mProps.p)
11665 },
11666 'anchorPoint': {
11667 get: ExpressionPropertyInterface(view.transform.mProps.a)
11668 },
11669 'scale': {
11670 get: ExpressionPropertyInterface(view.transform.mProps.s)
11671 },
11672 'rotation': {
11673 get: ExpressionPropertyInterface(view.transform.mProps.r)
11674 },
11675 'skew': {
11676 get: ExpressionPropertyInterface(view.transform.mProps.sk)
11677 },
11678 'skewAxis': {
11679 get: ExpressionPropertyInterface(view.transform.mProps.sa)
11680 },
11681 '_name': { value: shape.nm }
11682 });
11683 interfaceFunction.ty = 'tr';
11684 interfaceFunction.mn = shape.mn;
11685 interfaceFunction.propertyGroup = propertyGroup;
11686 return interfaceFunction;
11687 }
11688
11689 function ellipseInterfaceFactory(shape,view,propertyGroup){
11690
11691 function interfaceFunction(value){
11692 if(shape.p.ix === value){
11693 return interfaceFunction.position;
11694 }
11695 if(shape.s.ix === value){
11696 return interfaceFunction.size;
11697 }
11698 }
11699 var _propertyGroup = propertyGroupFactory(interfaceFunction, propertyGroup);
11700 interfaceFunction.propertyIndex = shape.ix;
11701 var prop = view.sh.ty === 'tm' ? view.sh.prop : view.sh;
11702 prop.s.setGroupProperty(PropertyInterface('Size', _propertyGroup));
11703 prop.p.setGroupProperty(PropertyInterface('Position', _propertyGroup));
11704
11705 Object.defineProperties(interfaceFunction, {
11706 'size': {
11707 get: ExpressionPropertyInterface(prop.s)
11708 },
11709 'position': {
11710 get: ExpressionPropertyInterface(prop.p)
11711 },
11712 '_name': { value: shape.nm }
11713 });
11714 interfaceFunction.mn = shape.mn;
11715 return interfaceFunction;
11716 }
11717
11718 function starInterfaceFactory(shape,view,propertyGroup){
11719
11720 function interfaceFunction(value){
11721 if(shape.p.ix === value){
11722 return interfaceFunction.position;
11723 }
11724 if(shape.r.ix === value){
11725 return interfaceFunction.rotation;
11726 }
11727 if(shape.pt.ix === value){
11728 return interfaceFunction.points;
11729 }
11730 if(shape.or.ix === value || 'ADBE Vector Star Outer Radius' === value){
11731 return interfaceFunction.outerRadius;
11732 }
11733 if(shape.os.ix === value){
11734 return interfaceFunction.outerRoundness;
11735 }
11736 if(shape.ir && (shape.ir.ix === value || 'ADBE Vector Star Inner Radius' === value)){
11737 return interfaceFunction.innerRadius;
11738 }
11739 if(shape.is && shape.is.ix === value){
11740 return interfaceFunction.innerRoundness;
11741 }
11742
11743 }
11744
11745 var _propertyGroup = propertyGroupFactory(interfaceFunction, propertyGroup);
11746 var prop = view.sh.ty === 'tm' ? view.sh.prop : view.sh;
11747 interfaceFunction.propertyIndex = shape.ix;
11748 prop.or.setGroupProperty(PropertyInterface('Outer Radius', _propertyGroup));
11749 prop.os.setGroupProperty(PropertyInterface('Outer Roundness', _propertyGroup));
11750 prop.pt.setGroupProperty(PropertyInterface('Points', _propertyGroup));
11751 prop.p.setGroupProperty(PropertyInterface('Position', _propertyGroup));
11752 prop.r.setGroupProperty(PropertyInterface('Rotation', _propertyGroup));
11753 if(shape.ir){
11754 prop.ir.setGroupProperty(PropertyInterface('Inner Radius', _propertyGroup));
11755 prop.is.setGroupProperty(PropertyInterface('Inner Roundness', _propertyGroup));
11756 }
11757
11758 Object.defineProperties(interfaceFunction, {
11759 'position': {
11760 get: ExpressionPropertyInterface(prop.p)
11761 },
11762 'rotation': {
11763 get: ExpressionPropertyInterface(prop.r)
11764 },
11765 'points': {
11766 get: ExpressionPropertyInterface(prop.pt)
11767 },
11768 'outerRadius': {
11769 get: ExpressionPropertyInterface(prop.or)
11770 },
11771 'outerRoundness': {
11772 get: ExpressionPropertyInterface(prop.os)
11773 },
11774 'innerRadius': {
11775 get: ExpressionPropertyInterface(prop.ir)
11776 },
11777 'innerRoundness': {
11778 get: ExpressionPropertyInterface(prop.is)
11779 },
11780 '_name': { value: shape.nm }
11781 });
11782 interfaceFunction.mn = shape.mn;
11783 return interfaceFunction;
11784 }
11785
11786 function rectInterfaceFactory(shape,view,propertyGroup){
11787
11788 function interfaceFunction(value){
11789 if(shape.p.ix === value){
11790 return interfaceFunction.position;
11791 }
11792 if(shape.r.ix === value){
11793 return interfaceFunction.roundness;
11794 }
11795 if(shape.s.ix === value || value === 'Size' || value === 'ADBE Vector Rect Size'){
11796 return interfaceFunction.size;
11797 }
11798
11799 }
11800 var _propertyGroup = propertyGroupFactory(interfaceFunction, propertyGroup);
11801
11802 var prop = view.sh.ty === 'tm' ? view.sh.prop : view.sh;
11803 interfaceFunction.propertyIndex = shape.ix;
11804 prop.p.setGroupProperty(PropertyInterface('Position', _propertyGroup));
11805 prop.s.setGroupProperty(PropertyInterface('Size', _propertyGroup));
11806 prop.r.setGroupProperty(PropertyInterface('Rotation', _propertyGroup));
11807
11808 Object.defineProperties(interfaceFunction, {
11809 'position': {
11810 get: ExpressionPropertyInterface(prop.p)
11811 },
11812 'roundness': {
11813 get: ExpressionPropertyInterface(prop.r)
11814 },
11815 'size': {
11816 get: ExpressionPropertyInterface(prop.s)
11817 },
11818 '_name': { value: shape.nm }
11819 });
11820 interfaceFunction.mn = shape.mn;
11821 return interfaceFunction;
11822 }
11823
11824 function roundedInterfaceFactory(shape,view,propertyGroup){
11825
11826 function interfaceFunction(value){
11827 if(shape.r.ix === value || 'Round Corners 1' === value){
11828 return interfaceFunction.radius;
11829 }
11830 }
11831
11832 var _propertyGroup = propertyGroupFactory(interfaceFunction, propertyGroup);
11833 var prop = view;
11834 interfaceFunction.propertyIndex = shape.ix;
11835 prop.rd.setGroupProperty(PropertyInterface('Radius', _propertyGroup));
11836
11837 Object.defineProperties(interfaceFunction, {
11838 'radius': {
11839 get: ExpressionPropertyInterface(prop.rd)
11840 },
11841 '_name': { value: shape.nm }
11842 });
11843 interfaceFunction.mn = shape.mn;
11844 return interfaceFunction;
11845 }
11846
11847 function repeaterInterfaceFactory(shape,view,propertyGroup){
11848
11849 function interfaceFunction(value){
11850 if(shape.c.ix === value || 'Copies' === value){
11851 return interfaceFunction.copies;
11852 } else if(shape.o.ix === value || 'Offset' === value){
11853 return interfaceFunction.offset;
11854 }
11855 }
11856
11857 var _propertyGroup = propertyGroupFactory(interfaceFunction, propertyGroup);
11858 var prop = view;
11859 interfaceFunction.propertyIndex = shape.ix;
11860 prop.c.setGroupProperty(PropertyInterface('Copies', _propertyGroup));
11861 prop.o.setGroupProperty(PropertyInterface('Offset', _propertyGroup));
11862 Object.defineProperties(interfaceFunction, {
11863 'copies': {
11864 get: ExpressionPropertyInterface(prop.c)
11865 },
11866 'offset': {
11867 get: ExpressionPropertyInterface(prop.o)
11868 },
11869 '_name': { value: shape.nm }
11870 });
11871 interfaceFunction.mn = shape.mn;
11872 return interfaceFunction;
11873 }
11874
11875 return function(shapes,view,propertyGroup) {
11876 var interfaces;
11877 function _interfaceFunction(value){
11878 if(typeof value === 'number'){
11879 value = value === undefined ? 1 : value
11880 if (value === 0) {
11881 return propertyGroup
11882 } else {
11883 return interfaces[value-1];
11884 }
11885 } else {
11886 var i = 0, len = interfaces.length;
11887 while(i<len){
11888 if(interfaces[i]._name === value){
11889 return interfaces[i];
11890 }
11891 i+=1;
11892 }
11893 }
11894 }
11895 _interfaceFunction.propertyGroup = propertyGroup;
11896 interfaces = iterateElements(shapes, view, _interfaceFunction);
11897 _interfaceFunction.numProperties = interfaces.length;
11898 return _interfaceFunction;
11899 };
11900}());
11901
11902var TextExpressionInterface = (function(){
11903 return function(elem){
11904 var _prevValue, _sourceText;
11905 function _thisLayerFunction(name){
11906 switch(name){
11907 case "ADBE Text Document":
11908 return _thisLayerFunction.sourceText;
11909 }
11910 }
11911 Object.defineProperty(_thisLayerFunction, "sourceText", {
11912 get: function(){
11913 elem.textProperty.getValue()
11914 var stringValue = elem.textProperty.currentData.t;
11915 if(stringValue !== _prevValue) {
11916 elem.textProperty.currentData.t = _prevValue;
11917 _sourceText = new String(stringValue);
11918 //If stringValue is an empty string, eval returns undefined, so it has to be returned as a String primitive
11919 _sourceText.value = stringValue ? stringValue : new String(stringValue);
11920 }
11921 return _sourceText;
11922 }
11923 });
11924 return _thisLayerFunction;
11925 };
11926}());
11927var LayerExpressionInterface = (function (){
11928 function toWorld(arr, time){
11929 var toWorldMat = new Matrix();
11930 toWorldMat.reset();
11931 var transformMat;
11932 if (time !== undefined) {
11933 toWorldMat = this._elem.finalTransform.mProp.getValueAtTime(time);
11934 } else {
11935 transformMat = this._elem.finalTransform.mProp;
11936 transformMat.applyToMatrix(toWorldMat);
11937 }
11938 if(this._elem.hierarchy && this._elem.hierarchy.length){
11939 var i, len = this._elem.hierarchy.length;
11940 for(i=0;i<len;i+=1){
11941 this._elem.hierarchy[i].finalTransform.mProp.applyToMatrix(toWorldMat);
11942 }
11943 return toWorldMat.applyToPointArray(arr[0],arr[1],arr[2]||0);
11944 }
11945 return toWorldMat.applyToPointArray(arr[0],arr[1],arr[2]||0);
11946 }
11947 function fromWorld(arr, time){
11948 var toWorldMat = new Matrix();
11949 toWorldMat.reset();
11950 var transformMat;
11951 if (time !== undefined) {
11952 toWorldMat = this._elem.finalTransform.mProp.getValueAtTime(time);
11953 } else {
11954 transformMat = this._elem.finalTransform.mProp;
11955 transformMat.applyToMatrix(toWorldMat);
11956 }
11957 if (this._elem.hierarchy && this._elem.hierarchy.length){
11958 var i, len = this._elem.hierarchy.length;
11959 for(i=0;i<len;i+=1){
11960 this._elem.hierarchy[i].finalTransform.mProp.applyToMatrix(toWorldMat);
11961 }
11962 return toWorldMat.inversePoint(arr);
11963 }
11964 return toWorldMat.inversePoint(arr);
11965 }
11966 function fromComp(arr){
11967 var toWorldMat = new Matrix();
11968 toWorldMat.reset();
11969 this._elem.finalTransform.mProp.applyToMatrix(toWorldMat);
11970 if(this._elem.hierarchy && this._elem.hierarchy.length){
11971 var i, len = this._elem.hierarchy.length;
11972 for(i=0;i<len;i+=1){
11973 this._elem.hierarchy[i].finalTransform.mProp.applyToMatrix(toWorldMat);
11974 }
11975 return toWorldMat.inversePoint(arr);
11976 }
11977 return toWorldMat.inversePoint(arr);
11978 }
11979
11980 function sampleImage() {
11981 return [1,1,1,1];
11982 }
11983
11984
11985 return function(elem){
11986
11987 var transformInterface;
11988
11989 function _registerMaskInterface(maskManager){
11990 _thisLayerFunction.mask = new MaskManagerInterface(maskManager, elem);
11991 }
11992 function _registerEffectsInterface(effects){
11993 _thisLayerFunction.effect = effects;
11994 }
11995
11996 function _thisLayerFunction(name){
11997 switch(name){
11998 case "ADBE Root Vectors Group":
11999 case "Contents":
12000 case 2:
12001 return _thisLayerFunction.shapeInterface;
12002 case 1:
12003 case 6:
12004 case "Transform":
12005 case "transform":
12006 case "ADBE Transform Group":
12007 return transformInterface;
12008 case 4:
12009 case "ADBE Effect Parade":
12010 case "effects":
12011 case "Effects":
12012 return _thisLayerFunction.effect;
12013 case "ADBE Text Properties":
12014 return _thisLayerFunction.textInterface;
12015 }
12016 }
12017 _thisLayerFunction.toWorld = toWorld;
12018 _thisLayerFunction.fromWorld = fromWorld;
12019 _thisLayerFunction.toComp = toWorld;
12020 _thisLayerFunction.fromComp = fromComp;
12021 _thisLayerFunction.sampleImage = sampleImage;
12022 _thisLayerFunction.sourceRectAtTime = elem.sourceRectAtTime.bind(elem);
12023 _thisLayerFunction._elem = elem;
12024 transformInterface = TransformExpressionInterface(elem.finalTransform.mProp);
12025 var anchorPointDescriptor = getDescriptor(transformInterface, 'anchorPoint');
12026 Object.defineProperties(_thisLayerFunction,{
12027 hasParent: {
12028 get: function(){
12029 return elem.hierarchy.length;
12030 }
12031 },
12032 parent: {
12033 get: function(){
12034 return elem.hierarchy[0].layerInterface;
12035 }
12036 },
12037 rotation: getDescriptor(transformInterface, 'rotation'),
12038 scale: getDescriptor(transformInterface, 'scale'),
12039 position: getDescriptor(transformInterface, 'position'),
12040 opacity: getDescriptor(transformInterface, 'opacity'),
12041 anchorPoint: anchorPointDescriptor,
12042 anchor_point: anchorPointDescriptor,
12043 transform: {
12044 get: function () {
12045 return transformInterface;
12046 }
12047 },
12048 active: {
12049 get: function(){
12050 return elem.isInRange;
12051 }
12052 }
12053 });
12054
12055 _thisLayerFunction.startTime = elem.data.st;
12056 _thisLayerFunction.index = elem.data.ind;
12057 _thisLayerFunction.source = elem.data.refId;
12058 _thisLayerFunction.height = elem.data.ty === 0 ? elem.data.h : 100;
12059 _thisLayerFunction.width = elem.data.ty === 0 ? elem.data.w : 100;
12060 _thisLayerFunction.inPoint = elem.data.ip/elem.comp.globalData.frameRate;
12061 _thisLayerFunction.outPoint = elem.data.op/elem.comp.globalData.frameRate;
12062 _thisLayerFunction._name = elem.data.nm;
12063
12064 _thisLayerFunction.registerMaskInterface = _registerMaskInterface;
12065 _thisLayerFunction.registerEffectsInterface = _registerEffectsInterface;
12066 return _thisLayerFunction;
12067 };
12068}());
12069
12070var CompExpressionInterface = (function () {
12071 return function(comp) {
12072 function _thisLayerFunction(name) {
12073 var i = 0, len = comp.layers.length;
12074 while ( i < len) {
12075 if (comp.layers[i].nm === name || comp.layers[i].ind === name) {
12076 return comp.elements[i].layerInterface;
12077 }
12078 i += 1;
12079 }
12080 return null;
12081 //return {active:false};
12082 }
12083 Object.defineProperty(_thisLayerFunction, "_name", { value: comp.data.nm });
12084 _thisLayerFunction.layer = _thisLayerFunction;
12085 _thisLayerFunction.pixelAspect = 1;
12086 _thisLayerFunction.height = comp.data.h || comp.globalData.compSize.h;
12087 _thisLayerFunction.width = comp.data.w || comp.globalData.compSize.w;
12088 _thisLayerFunction.pixelAspect = 1;
12089 _thisLayerFunction.frameDuration = 1 / comp.globalData.frameRate;
12090 _thisLayerFunction.displayStartTime = 0;
12091 _thisLayerFunction.numLayers = comp.layers.length;
12092 return _thisLayerFunction;
12093 };
12094}());
12095var TransformExpressionInterface = (function (){
12096 return function(transform){
12097 function _thisFunction(name){
12098 switch(name){
12099 case "scale":
12100 case "Scale":
12101 case "ADBE Scale":
12102 case 6:
12103 return _thisFunction.scale;
12104 case "rotation":
12105 case "Rotation":
12106 case "ADBE Rotation":
12107 case "ADBE Rotate Z":
12108 case 10:
12109 return _thisFunction.rotation;
12110 case "ADBE Rotate X":
12111 return _thisFunction.xRotation;
12112 case "ADBE Rotate Y":
12113 return _thisFunction.yRotation;
12114 case "position":
12115 case "Position":
12116 case "ADBE Position":
12117 case 2:
12118 return _thisFunction.position;
12119 case 'ADBE Position_0':
12120 return _thisFunction.xPosition;
12121 case 'ADBE Position_1':
12122 return _thisFunction.yPosition;
12123 case 'ADBE Position_2':
12124 return _thisFunction.zPosition;
12125 case "anchorPoint":
12126 case "AnchorPoint":
12127 case "Anchor Point":
12128 case "ADBE AnchorPoint":
12129 case 1:
12130 return _thisFunction.anchorPoint;
12131 case "opacity":
12132 case "Opacity":
12133 case 11:
12134 return _thisFunction.opacity;
12135 }
12136 }
12137
12138 Object.defineProperty(_thisFunction, "rotation", {
12139 get: ExpressionPropertyInterface(transform.r || transform.rz)
12140 });
12141
12142 Object.defineProperty(_thisFunction, "zRotation", {
12143 get: ExpressionPropertyInterface(transform.rz || transform.r)
12144 });
12145
12146 Object.defineProperty(_thisFunction, "xRotation", {
12147 get: ExpressionPropertyInterface(transform.rx)
12148 });
12149
12150 Object.defineProperty(_thisFunction, "yRotation", {
12151 get: ExpressionPropertyInterface(transform.ry)
12152 });
12153 Object.defineProperty(_thisFunction, "scale", {
12154 get: ExpressionPropertyInterface(transform.s)
12155 });
12156
12157 if(transform.p) {
12158 var _transformFactory = ExpressionPropertyInterface(transform.p);
12159 } else {
12160 var _px = ExpressionPropertyInterface(transform.px);
12161 var _py = ExpressionPropertyInterface(transform.py);
12162 var _pz;
12163 if (transform.pz) {
12164 _pz = ExpressionPropertyInterface(transform.pz);
12165 }
12166 }
12167 Object.defineProperty(_thisFunction, "position", {
12168 get: function () {
12169 if(transform.p) {
12170 return _transformFactory();
12171 } else {
12172 return [
12173 _px(),
12174 _py(),
12175 _pz ? _pz() : 0];
12176 }
12177 }
12178 });
12179
12180 Object.defineProperty(_thisFunction, "xPosition", {
12181 get: ExpressionPropertyInterface(transform.px)
12182 });
12183
12184 Object.defineProperty(_thisFunction, "yPosition", {
12185 get: ExpressionPropertyInterface(transform.py)
12186 });
12187
12188 Object.defineProperty(_thisFunction, "zPosition", {
12189 get: ExpressionPropertyInterface(transform.pz)
12190 });
12191
12192 Object.defineProperty(_thisFunction, "anchorPoint", {
12193 get: ExpressionPropertyInterface(transform.a)
12194 });
12195
12196 Object.defineProperty(_thisFunction, "opacity", {
12197 get: ExpressionPropertyInterface(transform.o)
12198 });
12199
12200 Object.defineProperty(_thisFunction, "skew", {
12201 get: ExpressionPropertyInterface(transform.sk)
12202 });
12203
12204 Object.defineProperty(_thisFunction, "skewAxis", {
12205 get: ExpressionPropertyInterface(transform.sa)
12206 });
12207
12208 Object.defineProperty(_thisFunction, "orientation", {
12209 get: ExpressionPropertyInterface(transform.or)
12210 });
12211
12212 return _thisFunction;
12213 };
12214}());
12215var ProjectInterface = (function (){
12216
12217 function registerComposition(comp){
12218 this.compositions.push(comp);
12219 }
12220
12221 return function(){
12222 function _thisProjectFunction(name){
12223 var i = 0, len = this.compositions.length;
12224 while(i<len){
12225 if(this.compositions[i].data && this.compositions[i].data.nm === name){
12226 if(this.compositions[i].prepareFrame && this.compositions[i].data.xt) {
12227 this.compositions[i].prepareFrame(this.currentFrame);
12228 }
12229 return this.compositions[i].compInterface;
12230 }
12231 i+=1;
12232 }
12233 }
12234
12235 _thisProjectFunction.compositions = [];
12236 _thisProjectFunction.currentFrame = 0;
12237
12238 _thisProjectFunction.registerComposition = registerComposition;
12239
12240
12241
12242 return _thisProjectFunction;
12243 };
12244}());
12245var EffectsExpressionInterface = (function (){
12246 var ob = {
12247 createEffectsInterface: createEffectsInterface
12248 };
12249
12250 function createEffectsInterface(elem, propertyGroup){
12251 if(elem.effectsManager){
12252
12253 var effectElements = [];
12254 var effectsData = elem.data.ef;
12255 var i, len = elem.effectsManager.effectElements.length;
12256 for(i=0;i<len;i+=1){
12257 effectElements.push(createGroupInterface(effectsData[i],elem.effectsManager.effectElements[i],propertyGroup,elem));
12258 }
12259
12260 var effects = elem.data.ef || [];
12261 var groupInterface = function(name){
12262 i = 0, len = effects.length;
12263 while(i<len) {
12264 if(name === effects[i].nm || name === effects[i].mn || name === effects[i].ix){
12265 return effectElements[i];
12266 }
12267 i += 1;
12268 }
12269 };
12270 Object.defineProperty(groupInterface, 'numProperties', {
12271 get: function(){
12272 return effects.length;
12273 }
12274 });
12275 return groupInterface
12276 }
12277 }
12278
12279 function createGroupInterface(data,elements, propertyGroup, elem){
12280
12281 function groupInterface(name){
12282 var effects = data.ef, i = 0, len = effects.length;
12283 while(i<len) {
12284 if(name === effects[i].nm || name === effects[i].mn || name === effects[i].ix){
12285 if(effects[i].ty === 5){
12286 return effectElements[i];
12287 } else {
12288 return effectElements[i]();
12289 }
12290 }
12291 i += 1;
12292 }
12293 throw new Error();
12294 };
12295 var _propertyGroup = propertyGroupFactory(groupInterface, propertyGroup);
12296
12297 var effectElements = [];
12298 var i, len = data.ef.length;
12299 for(i=0;i<len;i+=1){
12300 if(data.ef[i].ty === 5){
12301 effectElements.push(createGroupInterface(data.ef[i],elements.effectElements[i],elements.effectElements[i].propertyGroup, elem));
12302 } else {
12303 effectElements.push(createValueInterface(elements.effectElements[i],data.ef[i].ty, elem, _propertyGroup));
12304 }
12305 }
12306
12307 if(data.mn === 'ADBE Color Control'){
12308 Object.defineProperty(groupInterface, 'color', {
12309 get: function(){
12310 return effectElements[0]();
12311 }
12312 });
12313 }
12314 Object.defineProperties(groupInterface, {
12315 numProperties: {
12316 get: function(){
12317 return data.np;
12318 }
12319 },
12320 _name: { value: data.nm },
12321 propertyGroup: {value: _propertyGroup},
12322 });
12323 groupInterface.active = groupInterface.enabled = data.en !== 0;
12324 return groupInterface;
12325 }
12326
12327 function createValueInterface(element, type, elem, propertyGroup){
12328 var expressionProperty = ExpressionPropertyInterface(element.p);
12329 function interfaceFunction(){
12330 if(type === 10){
12331 return elem.comp.compInterface(element.p.v);
12332 }
12333 return expressionProperty();
12334 }
12335
12336 if(element.p.setGroupProperty) {
12337 element.p.setGroupProperty(PropertyInterface('', propertyGroup));
12338 }
12339
12340 return interfaceFunction;
12341 }
12342
12343 return ob;
12344
12345}());
12346var MaskManagerInterface = (function(){
12347
12348 function MaskInterface(mask, data){
12349 this._mask = mask;
12350 this._data = data;
12351 }
12352 Object.defineProperty(MaskInterface.prototype, 'maskPath', {
12353 get: function(){
12354 if(this._mask.prop.k){
12355 this._mask.prop.getValue();
12356 }
12357 return this._mask.prop;
12358 }
12359 });
12360 Object.defineProperty(MaskInterface.prototype, 'maskOpacity', {
12361 get: function(){
12362 if(this._mask.op.k){
12363 this._mask.op.getValue();
12364 }
12365 return this._mask.op.v * 100;
12366 }
12367 });
12368
12369 var MaskManager = function(maskManager, elem){
12370 var _maskManager = maskManager;
12371 var _elem = elem;
12372 var _masksInterfaces = createSizedArray(maskManager.viewData.length);
12373 var i, len = maskManager.viewData.length;
12374 for(i = 0; i < len; i += 1) {
12375 _masksInterfaces[i] = new MaskInterface(maskManager.viewData[i], maskManager.masksProperties[i]);
12376 }
12377
12378 var maskFunction = function(name){
12379 i = 0;
12380 while(i<len){
12381 if(maskManager.masksProperties[i].nm === name){
12382 return _masksInterfaces[i];
12383 }
12384 i += 1;
12385 }
12386 };
12387 return maskFunction;
12388 };
12389 return MaskManager;
12390}());
12391
12392var ExpressionPropertyInterface = (function() {
12393
12394 var defaultUnidimensionalValue = {pv:0, v:0, mult: 1}
12395 var defaultMultidimensionalValue = {pv:[0,0,0], v:[0,0,0], mult: 1}
12396
12397 function completeProperty(expressionValue, property, type) {
12398 Object.defineProperty(expressionValue, 'velocity', {
12399 get: function(){
12400 return property.getVelocityAtTime(property.comp.currentFrame);
12401 }
12402 });
12403 expressionValue.numKeys = property.keyframes ? property.keyframes.length : 0;
12404 expressionValue.key = function(pos) {
12405 if (!expressionValue.numKeys) {
12406 return 0;
12407 } else {
12408 var value = '';
12409 if ('s' in property.keyframes[pos-1]) {
12410 value = property.keyframes[pos-1].s;
12411 } else if ('e' in property.keyframes[pos-2]) {
12412 value = property.keyframes[pos-2].e;
12413 } else {
12414 value = property.keyframes[pos-2].s;
12415 }
12416 var valueProp = type === 'unidimensional' ? new Number(value) : Object.assign({}, value);
12417 valueProp.time = property.keyframes[pos-1].t / property.elem.comp.globalData.frameRate;
12418 valueProp.value = type === 'unidimensional' ? value[0] : value;
12419 return valueProp;
12420 }
12421 };
12422 expressionValue.valueAtTime = property.getValueAtTime;
12423 expressionValue.speedAtTime = property.getSpeedAtTime;
12424 expressionValue.velocityAtTime = property.getVelocityAtTime;
12425 expressionValue.propertyGroup = property.propertyGroup;
12426 }
12427
12428 function UnidimensionalPropertyInterface(property) {
12429 if(!property || !('pv' in property)) {
12430 property = defaultUnidimensionalValue;
12431 }
12432 var mult = 1 / property.mult;
12433 var val = property.pv * mult;
12434 var expressionValue = new Number(val);
12435 expressionValue.value = val;
12436 completeProperty(expressionValue, property, 'unidimensional');
12437
12438 return function() {
12439 if (property.k) {
12440 property.getValue();
12441 }
12442 val = property.v * mult;
12443 if(expressionValue.value !== val) {
12444 expressionValue = new Number(val);
12445 expressionValue.value = val;
12446 completeProperty(expressionValue, property, 'unidimensional');
12447 }
12448 return expressionValue;
12449 }
12450 }
12451
12452 function MultidimensionalPropertyInterface(property) {
12453 if(!property || !('pv' in property)) {
12454 property = defaultMultidimensionalValue;
12455 }
12456 var mult = 1 / property.mult;
12457 var len = property.pv.length;
12458 var expressionValue = createTypedArray('float32', len);
12459 var arrValue = createTypedArray('float32', len);
12460 expressionValue.value = arrValue;
12461 completeProperty(expressionValue, property, 'multidimensional');
12462
12463 return function() {
12464 if (property.k) {
12465 property.getValue();
12466 }
12467 for (var i = 0; i < len; i += 1) {
12468 expressionValue[i] = arrValue[i] = property.v[i] * mult;
12469 }
12470 return expressionValue;
12471 }
12472 }
12473
12474 //TODO: try to avoid using this getter
12475 function defaultGetter() {
12476 return defaultUnidimensionalValue;
12477 }
12478
12479 return function(property) {
12480 if(!property) {
12481 return defaultGetter;
12482 } else if (property.propType === 'unidimensional') {
12483 return UnidimensionalPropertyInterface(property);
12484 } else {
12485 return MultidimensionalPropertyInterface(property);
12486 }
12487 }
12488}());
12489
12490(function(){
12491
12492 var TextExpressionSelectorProp = (function(){
12493
12494 function getValueProxy(index,total){
12495 this.textIndex = index+1;
12496 this.textTotal = total;
12497 this.v = this.getValue() * this.mult;
12498 return this.v;
12499 }
12500
12501 return function TextExpressionSelectorProp(elem,data){
12502 this.pv = 1;
12503 this.comp = elem.comp;
12504 this.elem = elem;
12505 this.mult = 0.01;
12506 this.propType = 'textSelector';
12507 this.textTotal = data.totalChars;
12508 this.selectorValue = 100;
12509 this.lastValue = [1,1,1];
12510 this.k = true;
12511 this.x = true;
12512 this.getValue = ExpressionManager.initiateExpression.bind(this)(elem,data,this);
12513 this.getMult = getValueProxy;
12514 this.getVelocityAtTime = expressionHelpers.getVelocityAtTime;
12515 if(this.kf){
12516 this.getValueAtTime = expressionHelpers.getValueAtTime.bind(this);
12517 } else {
12518 this.getValueAtTime = expressionHelpers.getStaticValueAtTime.bind(this);
12519 }
12520 this.setGroupProperty = expressionHelpers.setGroupProperty;
12521 };
12522 }());
12523
12524 var propertyGetTextProp = TextSelectorProp.getTextSelectorProp;
12525 TextSelectorProp.getTextSelectorProp = function(elem, data,arr){
12526 if(data.t === 1){
12527 return new TextExpressionSelectorProp(elem, data,arr);
12528 } else {
12529 return propertyGetTextProp(elem,data,arr);
12530 }
12531 };
12532}());
12533function SliderEffect(data,elem, container){
12534 this.p = PropertyFactory.getProp(elem,data.v,0,0,container);
12535}
12536function AngleEffect(data,elem, container){
12537 this.p = PropertyFactory.getProp(elem,data.v,0,0,container);
12538}
12539function ColorEffect(data,elem, container){
12540 this.p = PropertyFactory.getProp(elem,data.v,1,0,container);
12541}
12542function PointEffect(data,elem, container){
12543 this.p = PropertyFactory.getProp(elem,data.v,1,0,container);
12544}
12545function LayerIndexEffect(data,elem, container){
12546 this.p = PropertyFactory.getProp(elem,data.v,0,0,container);
12547}
12548function MaskIndexEffect(data,elem, container){
12549 this.p = PropertyFactory.getProp(elem,data.v,0,0,container);
12550}
12551function CheckboxEffect(data,elem, container){
12552 this.p = PropertyFactory.getProp(elem,data.v,0,0,container);
12553}
12554function NoValueEffect(){
12555 this.p = {};
12556}
12557function EffectsManager(){}
12558function EffectsManager(data,element){
12559 var effects = data.ef || [];
12560 this.effectElements = [];
12561 var i,len = effects.length;
12562 var effectItem;
12563 for(i=0;i<len;i++) {
12564 effectItem = new GroupEffect(effects[i],element);
12565 this.effectElements.push(effectItem);
12566 }
12567}
12568
12569function GroupEffect(data,element){
12570 this.init(data,element);
12571}
12572
12573extendPrototype([DynamicPropertyContainer], GroupEffect);
12574
12575GroupEffect.prototype.getValue = GroupEffect.prototype.iterateDynamicProperties;
12576
12577GroupEffect.prototype.init = function(data,element){
12578 this.data = data;
12579 this.effectElements = [];
12580 this.initDynamicPropertyContainer(element);
12581 var i, len = this.data.ef.length;
12582 var eff, effects = this.data.ef;
12583 for(i=0;i<len;i+=1){
12584 eff = null;
12585 switch(effects[i].ty){
12586 case 0:
12587 eff = new SliderEffect(effects[i],element,this);
12588 break;
12589 case 1:
12590 eff = new AngleEffect(effects[i],element,this);
12591 break;
12592 case 2:
12593 eff = new ColorEffect(effects[i],element,this);
12594 break;
12595 case 3:
12596 eff = new PointEffect(effects[i],element,this);
12597 break;
12598 case 4:
12599 case 7:
12600 eff = new CheckboxEffect(effects[i],element,this);
12601 break;
12602 case 10:
12603 eff = new LayerIndexEffect(effects[i],element,this);
12604 break;
12605 case 11:
12606 eff = new MaskIndexEffect(effects[i],element,this);
12607 break;
12608 case 5:
12609 eff = new EffectsManager(effects[i],element,this);
12610 break;
12611 //case 6:
12612 default:
12613 eff = new NoValueEffect(effects[i],element,this);
12614 break;
12615 }
12616 if(eff) {
12617 this.effectElements.push(eff);
12618 }
12619 }
12620};
12621
12622var lottie = {};
12623
12624var _isFrozen = false;
12625
12626function setLocationHref (href) {
12627 locationHref = href;
12628}
12629
12630function searchAnimations() {
12631 if (standalone === true) {
12632 animationManager.searchAnimations(animationData, standalone, renderer);
12633 } else {
12634 animationManager.searchAnimations();
12635 }
12636}
12637
12638function setSubframeRendering(flag) {
12639 subframeEnabled = flag;
12640}
12641
12642function loadAnimation(params) {
12643 if (standalone === true) {
12644 params.animationData = JSON.parse(animationData);
12645 }
12646 return animationManager.loadAnimation(params);
12647}
12648
12649function setQuality(value) {
12650 if (typeof value === 'string') {
12651 switch (value) {
12652 case 'high':
12653 defaultCurveSegments = 200;
12654 break;
12655 case 'medium':
12656 defaultCurveSegments = 50;
12657 break;
12658 case 'low':
12659 defaultCurveSegments = 10;
12660 break;
12661 }
12662 } else if (!isNaN(value) && value > 1) {
12663 defaultCurveSegments = value;
12664 }
12665 if (defaultCurveSegments >= 50) {
12666 roundValues(false);
12667 } else {
12668 roundValues(true);
12669 }
12670}
12671
12672function inBrowser() {
12673 return typeof navigator !== 'undefined';
12674}
12675
12676function installPlugin(type, plugin) {
12677 if (type === 'expressions') {
12678 expressionsPlugin = plugin;
12679 }
12680}
12681
12682function getFactory(name) {
12683 switch (name) {
12684 case "propertyFactory":
12685 return PropertyFactory;
12686 case "shapePropertyFactory":
12687 return ShapePropertyFactory;
12688 case "matrix":
12689 return Matrix;
12690 }
12691}
12692
12693lottie.play = animationManager.play;
12694lottie.pause = animationManager.pause;
12695lottie.setLocationHref = setLocationHref;
12696lottie.togglePause = animationManager.togglePause;
12697lottie.setSpeed = animationManager.setSpeed;
12698lottie.setDirection = animationManager.setDirection;
12699lottie.stop = animationManager.stop;
12700lottie.searchAnimations = searchAnimations;
12701lottie.registerAnimation = animationManager.registerAnimation;
12702lottie.loadAnimation = loadAnimation;
12703lottie.setSubframeRendering = setSubframeRendering;
12704lottie.resize = animationManager.resize;
12705//lottie.start = start;
12706lottie.goToAndStop = animationManager.goToAndStop;
12707lottie.destroy = animationManager.destroy;
12708lottie.setQuality = setQuality;
12709lottie.inBrowser = inBrowser;
12710lottie.installPlugin = installPlugin;
12711lottie.freeze = animationManager.freeze;
12712lottie.unfreeze = animationManager.unfreeze;
12713lottie.setVolume = animationManager.setVolume;
12714lottie.mute = animationManager.mute;
12715lottie.unmute = animationManager.unmute;
12716lottie.getRegisteredAnimations = animationManager.getRegisteredAnimations;
12717lottie.__getFactory = getFactory;
12718lottie.version = '5.7.3';
12719
12720function checkReady() {
12721 if (document.readyState === "complete") {
12722 clearInterval(readyStateCheckInterval);
12723 searchAnimations();
12724 }
12725}
12726
12727function getQueryVariable(variable) {
12728 var vars = queryString.split('&');
12729 for (var i = 0; i < vars.length; i++) {
12730 var pair = vars[i].split('=');
12731 if (decodeURIComponent(pair[0]) == variable) {
12732 return decodeURIComponent(pair[1]);
12733 }
12734 }
12735}
12736var standalone = '__[STANDALONE]__';
12737var animationData = '__[ANIMATIONDATA]__';
12738var renderer = '';
12739if (standalone) {
12740 var scripts = document.getElementsByTagName('script');
12741 var index = scripts.length - 1;
12742 var myScript = scripts[index] || {
12743 src: ''
12744 };
12745 var queryString = myScript.src.replace(/^[^\?]+\??/, '');
12746 renderer = getQueryVariable('renderer');
12747}
12748var readyStateCheckInterval = setInterval(checkReady, 100);
12749
12750return lottie;
12751}));