merge with master
diff --git a/player/index.html b/player/index.html
index cb85320..9c0b10a 100644
--- a/player/index.html
+++ b/player/index.html
@@ -12,8 +12,8 @@
 
         #bodymovin{
             background-color:#333;
-            width:100%;
-            height:100%;
+            width:1024px;
+            height:768px;
             /*width:800px;
             height:500px;*/
             display:block;
@@ -128,6 +128,10 @@
         path: 'exports/render/data.json'
     };
     anim = bodymovin.loadAnimation(animData);
+    anim.addEventListener('complete', function(){
+        console.log('compeded');
+        anim.goToAndStop(0);
+    });
 
 </script>
 </body>
diff --git a/player/js/animation/AnimationItem.js b/player/js/animation/AnimationItem.js
index 7df5f96..0ad6e82 100644
--- a/player/js/animation/AnimationItem.js
+++ b/player/js/animation/AnimationItem.js
@@ -134,6 +134,7 @@
     if(prerender === 'false'){
         params.prerender = false;
     }
+    console.log('animElements:', params)
     this.setParams(params);
 };
 
diff --git a/player/js/elements/BaseElement.js b/player/js/elements/BaseElement.js
index 833c499..72b0931 100644
--- a/player/js/elements/BaseElement.js
+++ b/player/js/elements/BaseElement.js
@@ -108,7 +108,7 @@
     if(this.data.ty === 0 || this.data.xt){
         this.compInterface = CompExpressionInterface(this);
     } else if(this.data.ty === 4){
-        this.layerInterface.shapeInterface = ShapeExpressionInterface.createShapeInterface(this.shapesData,this.viewData,this.layerInterface);
+        this.layerInterface.shapeInterface = ShapeExpressionInterface.createShapeInterface(this.shapesData,this.itemsData,this.layerInterface);
     } else if(this.data.ty === 5){
         this.layerInterface.textInterface = TextExpressionInterface(this);
     }
diff --git a/player/js/elements/ShapeElement.js b/player/js/elements/ShapeElement.js
index 46e624b..51cc575 100644
--- a/player/js/elements/ShapeElement.js
+++ b/player/js/elements/ShapeElement.js
@@ -2,8 +2,10 @@
     this.shapes = [];
     this.shapesData = data.shapes;
     this.stylesList = [];
-    this.viewData = [];
+    this.itemsData = [];
+    this.prevViewData = [];
     this.shapeModifiers = [];
+    this.processedElements = [];
     this._parent.constructor.call(this,data,parentContainer,globalData,comp, placeholder);
 }
 createElement(SVGBaseElement, IShapeElement);
@@ -22,16 +24,43 @@
     '3': 'butt'
 }
 
+IShapeElement.prototype.searchProcessedElement = function(elem){
+    var i = this.processedElements.length;
+    while(i){
+        i -= 1;
+        if(this.processedElements[i].elem === elem){
+            return this.processedElements[i].pos;
+        }
+    }
+    return 0;
+};
+
+IShapeElement.prototype.addProcessedElement = function(elem, pos){
+    var i = this.processedElements.length;
+    while(i){
+        i -= 1;
+        if(this.processedElements[i].elem === elem){
+            this.processedElements[i].pos = pos;
+            break;
+        }
+    }
+    if(i === 0){
+        this.processedElements.push({
+            elem: elem,
+            pos: pos
+        })
+    }
+};
+
 IShapeElement.prototype.buildExpressionInterface = function(){};
 
 IShapeElement.prototype.createElements = function(){
     //TODO check if I can use symbol so i can set its viewBox
     this._parent.createElements.call(this);
-    this.searchShapes(this.shapesData,this.viewData,this.layerElement,this.dynamicProperties, 0);
+    this.searchShapes(this.shapesData,this.itemsData,this.prevViewData,this.layerElement,this.dynamicProperties, 0, [], true);
     if(!this.data.hd || this.data.td){
         styleUnselectableDiv(this.layerElement);
     }
-    //this.elemInterface.registerShapeExpressionInterface(ShapeExpressionInterface.createShapeInterface(this.shapesData,this.viewData,this.elemInterface));
 };
 
 IShapeElement.prototype.setGradientData = function(pathElement,arr,data){
@@ -98,140 +127,229 @@
     }
 };
 
-IShapeElement.prototype.searchShapes = function(arr,data,container,dynamicProperties, level, transformers){
-    transformers = transformers || [];
+IShapeElement.prototype.createStyleElement = function(data, level, dynamicProperties){
+    var elementData = {
+    };
+    styleOb = {
+        data: data,
+        type: data.ty,
+        d: '',
+        ld: '',
+        lvl: level,
+        mdf: false,
+        closed: false
+    };
+    var pathElement = document.createElementNS(svgNS, "path");
+    elementData.o = PropertyFactory.getProp(this,data.o,0,0.01,dynamicProperties);
+    if(data.ty == 'st' || data.ty == 'gs') {
+        pathElement.setAttribute('stroke-linecap', this.lcEnum[data.lc] || 'round');
+        ////pathElement.style.strokeLinecap = this.lcEnum[data.lc] || 'round';
+        pathElement.setAttribute('stroke-linejoin',this.ljEnum[data.lj] || 'round');
+        ////pathElement.style.strokeLinejoin = this.ljEnum[data.lj] || 'round';
+        pathElement.setAttribute('fill-opacity','0');
+        ////pathElement.style.fillOpacity = 0;
+        if(data.lj == 1) {
+            pathElement.setAttribute('stroke-miterlimit',data.ml);
+            ////pathElement.style.strokeMiterlimit = data.ml;
+        }
+
+        elementData.w = PropertyFactory.getProp(this,data.w,0,null,dynamicProperties);
+        if(data.d){
+            var d = PropertyFactory.getDashProp(this,data.d,'svg',dynamicProperties);
+            if(!d.k){
+                pathElement.setAttribute('stroke-dasharray', d.dasharray);
+                ////pathElement.style.strokeDasharray = d.dasharray;
+                pathElement.setAttribute('stroke-dashoffset', d.dashoffset);
+                ////pathElement.style.strokeDashoffset = d.dashoffset;
+            }
+            elementData.d = d;
+        }
+
+    }
+    if(data.ty == 'fl' || data.ty == 'st'){
+        elementData.c = PropertyFactory.getProp(this,data.c,1,255,dynamicProperties);
+    } else {
+        elementData.g = PropertyFactory.getGradientProp(this,data.g,dynamicProperties);
+        if(data.t == 2){
+            elementData.h = PropertyFactory.getProp(this,data.h,1,0.01,dynamicProperties);
+            elementData.a = PropertyFactory.getProp(this,data.a,1,degToRads,dynamicProperties);
+        }
+        elementData.s = PropertyFactory.getProp(this,data.s,1,null,dynamicProperties);
+        elementData.e = PropertyFactory.getProp(this,data.e,1,null,dynamicProperties);
+        this.setGradientData(pathElement,data,elementData, styleOb);
+        var maskId = this.setGradientOpacity(data,elementData, styleOb);
+        if(maskId){
+            pathElement.setAttribute('mask','url(#'+maskId+')');
+        }
+    }
+    elementData.elem = pathElement;
+    //container.appendChild(pathElement);
+    if(data.r === 2) {
+        pathElement.setAttribute('fill-rule', 'evenodd');
+    }
+
+    if(data.ln){
+        pathElement.setAttribute('id',data.ln);
+    }
+    if(data.cl){
+        pathElement.setAttribute('class',data.cl);
+    }
+    styleOb.pElem = pathElement;
+    this.stylesList.push(styleOb);
+    elementData.style = styleOb;
+    return elementData;
+}
+
+IShapeElement.prototype.createGroupElement = function(data) {
+    var elementData = {
+        it: [],
+        prevViewData: []
+    };
+    var g = document.createElementNS(svgNS,'g');
+    elementData.gr = g;
+    if(data.ln){
+        elementData.gr.setAttribute('id',data.ln);
+    }
+    return elementData;
+}
+
+IShapeElement.prototype.createTransformElement = function(data, dynamicProperties) {
+    var elementData = {
+        transform : {
+            op: PropertyFactory.getProp(this,data.o,0,0.01,dynamicProperties),
+            mProps: PropertyFactory.getProp(this,data,2,null,dynamicProperties)
+        },
+        elements: []
+    };
+    return elementData;
+}
+
+IShapeElement.prototype.createShapeElement = function(data, ownTransformers, level, dynamicProperties) {
+    var elementData = {
+        elements : [],
+        caches:[],
+        styles : [],
+        transformers: ownTransformers,
+        lStr: ''
+    };
+    var ty = 4;
+    if(data.ty == 'rc'){
+        ty = 5;
+    }else if(data.ty == 'el'){
+        ty = 6;
+    }else if(data.ty == 'sr'){
+        ty = 7;
+    }
+    elementData.sh = ShapePropertyFactory.getShapeProp(this,data,ty,dynamicProperties);
+    elementData.lvl = level;
+    this.shapes.push(elementData.sh);
+    this.addShapeToModifiers(elementData);
+    return elementData;
+}
+
+var cont = 0;
+
+IShapeElement.prototype.setElementStyles = function(){
+    var j, jLen = this.stylesList.length;
+    var arr = [];
+    for(j=0;j<jLen;j+=1){
+        if(!this.stylesList[j].closed){
+            arr.push(this.stylesList[j]);
+        }
+    }
+    return arr;
+}
+
+IShapeElement.prototype.reloadShapes = function(){
+    this.firstFrame = true;
+    var i, len = this.itemsData.length;
+    for(i=0;i<len;i+=1){
+        this.prevViewData[i] = this.itemsData[i];
+    }
+    this.searchShapes(this.shapesData,this.itemsData,this.prevViewData,this.layerElement,this.dynamicProperties, 0, [], true);
+    var i, len = this.dynamicProperties.length;
+    for(i=0;i<len;i+=1){
+        this.dynamicProperties[i].getValue();
+    }
+    this.renderModifiers();
+}
+
+IShapeElement.prototype.searchShapes = function(arr,itemsData,prevViewData,container,dynamicProperties, level, transformers, render){
     var ownTransformers = [].concat(transformers);
     var i, len = arr.length - 1;
     var j, jLen;
-    var ownArrays = [], ownModifiers = [], styleOb, currentTransform;
+    var ownStyles = [], ownModifiers = [], styleOb, currentTransform, modifier, processedPos;
     for(i=len;i>=0;i-=1){
+        processedPos = this.searchProcessedElement(arr[i]);
+        if(!processedPos){
+            arr[i]._render = render;
+        } else {
+            itemsData[i] = prevViewData[processedPos - 1];
+        }
         if(arr[i].ty == 'fl' || arr[i].ty == 'st' || arr[i].ty == 'gf' || arr[i].ty == 'gs'){
-            data[i] = {};
-            styleOb = {
-                type: arr[i].ty,
-                d: '',
-                ld: '',
-                lvl: level,
-                mdf: false
-            };
-            var pathElement = document.createElementNS(svgNS, "path");
-            data[i].o = PropertyFactory.getProp(this,arr[i].o,0,0.01,dynamicProperties);
-            if(arr[i].ty == 'st' || arr[i].ty == 'gs') {
-                pathElement.setAttribute('stroke-linecap', this.lcEnum[arr[i].lc] || 'round');
-                ////pathElement.style.strokeLinecap = this.lcEnum[arr[i].lc] || 'round';
-                pathElement.setAttribute('stroke-linejoin',this.ljEnum[arr[i].lj] || 'round');
-                ////pathElement.style.strokeLinejoin = this.ljEnum[arr[i].lj] || 'round';
-                pathElement.setAttribute('fill-opacity','0');
-                ////pathElement.style.fillOpacity = 0;
-                if(arr[i].lj == 1) {
-                    pathElement.setAttribute('stroke-miterlimit',arr[i].ml);
-                    ////pathElement.style.strokeMiterlimit = arr[i].ml;
-                }
-
-                data[i].w = PropertyFactory.getProp(this,arr[i].w,0,null,dynamicProperties);
-                if(arr[i].d){
-                    var d = PropertyFactory.getDashProp(this,arr[i].d,'svg',dynamicProperties);
-                    if(!d.k){
-                        pathElement.setAttribute('stroke-dasharray', d.dasharray);
-                        ////pathElement.style.strokeDasharray = d.dasharray;
-                        pathElement.setAttribute('stroke-dashoffset', d.dashoffset);
-                        ////pathElement.style.strokeDashoffset = d.dashoffset;
-                    }
-                    data[i].d = d;
-                }
-
-            }
-            if(arr[i].ty == 'fl' || arr[i].ty == 'st'){
-                data[i].c = PropertyFactory.getProp(this,arr[i].c,1,255,dynamicProperties);
-                container.appendChild(pathElement);
+            if(!processedPos){
+                itemsData[i] = this.createStyleElement(arr[i], level, dynamicProperties);
             } else {
-                data[i].g = PropertyFactory.getGradientProp(this,arr[i].g,dynamicProperties);
-                if(arr[i].t == 2){
-                    data[i].h = PropertyFactory.getProp(this,arr[i].h,1,0.01,dynamicProperties);
-                    data[i].a = PropertyFactory.getProp(this,arr[i].a,1,degToRads,dynamicProperties);
-                }
-                data[i].s = PropertyFactory.getProp(this,arr[i].s,1,null,dynamicProperties);
-                data[i].e = PropertyFactory.getProp(this,arr[i].e,1,null,dynamicProperties);
-                this.setGradientData(pathElement,arr[i],data[i], styleOb);
-                var maskId = this.setGradientOpacity(arr[i],data[i], styleOb);
-                if(maskId){
-                    pathElement.setAttribute('mask','url(#'+maskId+')');
-                }
-                data[i].elem = pathElement;
-                container.appendChild(pathElement);
+                itemsData[i].style.closed = false;
             }
-            if(arr[i].r === 2) {
-                pathElement.setAttribute('fill-rule', 'evenodd');
+            if(arr[i]._render){
+                container.appendChild(itemsData[i].elem);
             }
-
-            if(arr[i].ln){
-                pathElement.setAttribute('id',arr[i].ln);
-            }
-            if(arr[i].cl){
-                pathElement.setAttribute('class',arr[i].cl);
-            }
-            styleOb.pElem = pathElement;
-            this.stylesList.push(styleOb);
-            data[i].style = styleOb;
-            ownArrays.push(styleOb);
+            ownStyles.push(itemsData[i].style);
         }else if(arr[i].ty == 'gr'){
-            data[i] = {
-                it: []
-            };
-            var g = document.createElementNS(svgNS,'g');
-            container.appendChild(g);
-            data[i].gr = g;
-            this.searchShapes(arr[i].it,data[i].it,g,dynamicProperties, level + 1, ownTransformers);
+            if(!processedPos){
+                itemsData[i] = this.createGroupElement(arr[i]);
+            } else {
+                jLen = itemsData[i].it.length;
+                for(j=0;j<jLen;j+=1){
+                    itemsData[i].prevViewData[j] = itemsData[i].it[j];
+                }
+            }
+            this.searchShapes(arr[i].it,itemsData[i].it,itemsData[i].prevViewData,itemsData[i].gr,dynamicProperties, level + 1, ownTransformers, render);
+            if(arr[i]._render){
+                container.appendChild(itemsData[i].gr);
+            }
         }else if(arr[i].ty == 'tr'){
-            data[i] = {
-                transform : {
-                    op: PropertyFactory.getProp(this,arr[i].o,0,0.01,dynamicProperties),
-                    mProps: PropertyFactory.getProp(this,arr[i],2,null,dynamicProperties)
-                },
-                elements: []
-            };
-            currentTransform = data[i].transform;
+            if(!processedPos){
+                itemsData[i] = this.createTransformElement(arr[i], dynamicProperties);
+            }
+            currentTransform = itemsData[i].transform;
             ownTransformers.push(currentTransform);
         }else if(arr[i].ty == 'sh' || arr[i].ty == 'rc' || arr[i].ty == 'el' || arr[i].ty == 'sr'){
-            data[i] = {
-                elements : [],
-                caches:[],
-                styles : [],
-                transformers: ownTransformers,
-                lStr: ''
-            };
-            var ty = 4;
-            if(arr[i].ty == 'rc'){
-                ty = 5;
-            }else if(arr[i].ty == 'el'){
-                ty = 6;
-            }else if(arr[i].ty == 'sr'){
-                ty = 7;
+            if(!processedPos){
+                itemsData[i] = this.createShapeElement(arr[i], ownTransformers, level, dynamicProperties);
             }
-            data[i].sh = ShapePropertyFactory.getShapeProp(this,arr[i],ty,dynamicProperties);
-            data[i].lvl = level;
-            this.shapes.push(data[i].sh);
-            this.addShapeToModifiers(data[i]);
-            jLen = this.stylesList.length;
-            for(j=0;j<jLen;j+=1){
-                if(!this.stylesList[j].closed){
-                    data[i].elements.push({
-                        ty:this.stylesList[j].type,
-                        st: this.stylesList[j]
-                    });
-                }
+            itemsData[i].elements = this.setElementStyles();
+
+        }else if(arr[i].ty == 'tm' || arr[i].ty == 'rd' || arr[i].ty == 'ms'){
+            if(!processedPos){
+                modifier = ShapeModifiers.getModifier(arr[i].ty);
+                modifier.init(this,arr[i],dynamicProperties);
+                itemsData[i] = modifier;
+                this.shapeModifiers.push(modifier);
+            } else {
+                modifier = itemsData[i];
+                modifier.closed = false;
             }
-        }else if(arr[i].ty == 'tm' || arr[i].ty == 'rd' || arr[i].ty == 'ms' || arr[i].ty == 'rp'){
-            var modifier = ShapeModifiers.getModifier(arr[i].ty);
-            modifier.init(this,arr[i],dynamicProperties);
-            this.shapeModifiers.push(modifier);
             ownModifiers.push(modifier);
-            data[i] = modifier;
+        }else if(arr[i].ty == 'rp'){
+            if(!processedPos){
+                modifier = ShapeModifiers.getModifier(arr[i].ty);
+                itemsData[i] = modifier;
+                modifier.init(this,arr,i,itemsData,dynamicProperties);
+                this.shapeModifiers.push(modifier);
+                render = false;
+            }else{
+                modifier = itemsData[i];
+                modifier.closed = true;
+            }
+            ownModifiers.push(modifier);
         }
+        this.addProcessedElement(arr[i], i + 1);
     }
-    len = ownArrays.length;
+    len = ownStyles.length;
     for(i=0;i<len;i+=1){
-        ownArrays[i].closed = true;
+        ownStyles[i].closed = true;
     }
     len = ownModifiers.length;
     for(i=0;i<len;i+=1){
@@ -264,18 +382,40 @@
 };
 
 IShapeElement.prototype.renderFrame = function(parentMatrix){
+    //this.reloadShapes();
     var renderParent = this._parent.renderFrame.call(this,parentMatrix);
     if(renderParent===false){
         this.hide();
         return;
     }
-    this.globalToLocal([0,0,0]);
     if(this.hidden){
         this.layerElement.style.display = 'block';
         this.hidden = false;
     }
     this.renderModifiers();
-    this.renderShape(null,null,true, null);
+    var i, len = this.stylesList.length;
+    for(i=0;i<len;i+=1){
+        this.stylesList[i].d = '';
+        this.stylesList[i].mdf = false;
+    }
+    this.renderShape(this.shapesData,this.itemsData, null);
+
+    for (i = 0; i < len; i += 1) {
+        if (this.stylesList[i].ld === '0') {
+            this.stylesList[i].ld = '1';
+            this.stylesList[i].pElem.style.display = 'block';
+            //this.stylesList[i].parent.appendChild(this.stylesList[i].pElem);
+        }
+        if (this.stylesList[i].mdf || this.firstFrame) {
+            this.stylesList[i].pElem.setAttribute('d', this.stylesList[i].d);
+            if(this.stylesList[i].msElem){
+                this.stylesList[i].msElem.setAttribute('d', this.stylesList[i].d);
+            }
+        }
+    }
+    if (this.firstFrame) {
+        this.firstFrame = false;
+    }
 };
 
 IShapeElement.prototype.hide = function(){
@@ -296,22 +436,8 @@
     }
 };
 
-IShapeElement.prototype.renderShape = function(items,data,isMain, container){
-    var i, len;
-    if(!items){
-        items = this.shapesData;
-        len = this.stylesList.length;
-        for(i=0;i<len;i+=1){
-            this.stylesList[i].d = '';
-            this.stylesList[i].mdf = false;
-        }
-    }
-    if(!data){
-        data = this.viewData;
-    }
-    ///
-    ///
-    len = items.length - 1;
+IShapeElement.prototype.renderShape = function(items,data, container){
+    var i, len = items.length - 1;
     var ty;
     for(i=len;i>=0;i-=1){
         ty = items[i].ty;
@@ -334,30 +460,11 @@
         }else if(ty == 'st'){
             this.renderStroke(items[i],data[i]);
         }else if(ty == 'gr'){
-            this.renderShape(items[i].it,data[i].it,false, data[i].gr);
+            this.renderShape(items[i].it,data[i].it, data[i].gr);
         }else if(ty == 'tm'){
             //
         }
     }
-    if(isMain) {
-        len = this.stylesList.length;
-        for (i = 0; i < len; i += 1) {
-            if (this.stylesList[i].ld === '0') {
-                this.stylesList[i].ld = '1';
-                this.stylesList[i].pElem.style.display = 'block';
-                //this.stylesList[i].parent.appendChild(this.stylesList[i].pElem);
-            }
-            if (this.stylesList[i].mdf || this.firstFrame) {
-                this.stylesList[i].pElem.setAttribute('d', this.stylesList[i].d);
-                if(this.stylesList[i].msElem){
-                    this.stylesList[i].msElem.setAttribute('d', this.stylesList[i].d);
-                }
-            }
-        }
-        if (this.firstFrame) {
-            this.firstFrame = false;
-        }
-    }
 
 };
 
@@ -377,80 +484,86 @@
         shapeString += 'z';
     }
     return shapeString;
-}
+};
 
-IShapeElement.prototype.renderPath = function(pathData,viewData){
-    var len, i, j, jLen,pathStringTransformed,redraw,pathNodes,l, lLen = viewData.elements.length;
-    var lvl = viewData.lvl;
+IShapeElement.prototype.renderPath = function(pathData,itemData){
+    var len, i, j, jLen,pathStringTransformed,redraw,pathNodes,l, lLen = itemData.elements.length;
+    var lvl = itemData.lvl;
+    if(!pathData._render){
+        return;
+    }
     for(l=0;l<lLen;l+=1){
-        redraw = viewData.sh.mdf || this.firstFrame;
-        pathStringTransformed = 'M0 0';
-        var paths = viewData.sh.paths;
-        jLen = paths._length;
-        if(viewData.elements[l].st.lvl < lvl){
-            var mat = this.mHelper.reset(), props;
-            var iterations = lvl - viewData.elements[l].st.lvl;
-            var k = viewData.transformers.length-1;
-            while(iterations > 0) {
-                redraw = viewData.transformers[k].mProps.mdf || redraw;
-                props = viewData.transformers[k].mProps.v.props;
-                mat.transform(props[0],props[1],props[2],props[3],props[4],props[5],props[6],props[7],props[8],props[9],props[10],props[11],props[12],props[13],props[14],props[15]);
-                iterations --;
-                k --;
-            }
-            if(redraw){
-                for(j=0;j<jLen;j+=1){
-                    pathNodes = paths.shapes[j];
-                    if(pathNodes && pathNodes._length){
-                        pathStringTransformed += this.buildShapeString(pathNodes, pathNodes._length, pathNodes.c, mat);
-                    }
+        if(itemData.elements[l].data._render){
+            redraw = itemData.sh.mdf || this.firstFrame;
+            pathStringTransformed = 'M0 0';
+            var paths = itemData.sh.paths;
+            jLen = paths._length;
+            if(itemData.elements[l].lvl < lvl){
+                var mat = this.mHelper.reset(), props;
+                var iterations = lvl - itemData.elements[l].lvl;
+                var k = itemData.transformers.length-1;
+                while(iterations > 0) {
+                    redraw = itemData.transformers[k].mProps.mdf || redraw;
+                    props = itemData.transformers[k].mProps.v.props;
+                    mat.transform(props[0],props[1],props[2],props[3],props[4],props[5],props[6],props[7],props[8],props[9],props[10],props[11],props[12],props[13],props[14],props[15]);
+                    iterations --;
+                    k --;
                 }
-                viewData.caches[l] = pathStringTransformed;
+                if(redraw){
+                    for(j=0;j<jLen;j+=1){
+                        pathNodes = paths.shapes[j];
+                        if(pathNodes && pathNodes._length){
+                            pathStringTransformed += this.buildShapeString(pathNodes, pathNodes._length, pathNodes.c, mat);
+                        }
+                    }
+                    itemData.caches[l] = pathStringTransformed;
+                } else {
+                    pathStringTransformed = itemData.caches[l];
+                }
             } else {
-                pathStringTransformed = viewData.caches[l];
+                if(redraw){
+                    for(j=0;j<jLen;j+=1){
+                        pathNodes = paths.shapes[j];
+                        if(pathNodes && pathNodes._length){
+                            pathStringTransformed += this.buildShapeString(pathNodes, pathNodes._length, pathNodes.c, this.identityMatrix);
+                        }
+                    }
+                    itemData.caches[l] = pathStringTransformed;
+                } else {
+                    pathStringTransformed = itemData.caches[l];
+                }
             }
+            itemData.elements[l].d += pathStringTransformed;
+            itemData.elements[l].mdf = redraw || itemData.elements[l].mdf;
         } else {
-            if(redraw){
-                for(j=0;j<jLen;j+=1){
-                    pathNodes = paths.shapes[j];
-                    if(pathNodes && pathNodes._length){
-                        pathStringTransformed += this.buildShapeString(pathNodes, pathNodes._length, pathNodes.c, this.identityMatrix);
-                    }
-                }
-                viewData.caches[l] = pathStringTransformed;
-            } else {
-                pathStringTransformed = viewData.caches[l];
-            }
+            itemData.elements[l].mdf = true;
         }
-        viewData.elements[l].st.d += pathStringTransformed;
-        viewData.elements[l].st.mdf = redraw || viewData.elements[l].st.mdf;
-    }
-
-};
-
-IShapeElement.prototype.renderFill = function(styleData,viewData){
-    var styleElem = viewData.style;
-
-    if(viewData.c.mdf || this.firstFrame){
-        styleElem.pElem.setAttribute('fill','rgb('+bm_floor(viewData.c.v[0])+','+bm_floor(viewData.c.v[1])+','+bm_floor(viewData.c.v[2])+')');
-        ////styleElem.pElem.style.fill = 'rgb('+bm_floor(viewData.c.v[0])+','+bm_floor(viewData.c.v[1])+','+bm_floor(viewData.c.v[2])+')';
-    }
-    if(viewData.o.mdf || this.firstFrame){
-        styleElem.pElem.setAttribute('fill-opacity',viewData.o.v);
     }
 };
 
-IShapeElement.prototype.renderGradient = function(styleData,viewData){
-    var gfill = viewData.gf;
-    var opFill = viewData.of;
-    var pt1 = viewData.s.v,pt2 = viewData.e.v;
+IShapeElement.prototype.renderFill = function(styleData,itemData){
+    var styleElem = itemData.style;
 
-    if(viewData.o.mdf || this.firstFrame){
+    if(itemData.c.mdf || this.firstFrame){
+        styleElem.pElem.setAttribute('fill','rgb('+bm_floor(itemData.c.v[0])+','+bm_floor(itemData.c.v[1])+','+bm_floor(itemData.c.v[2])+')');
+        ////styleElem.pElem.style.fill = 'rgb('+bm_floor(itemData.c.v[0])+','+bm_floor(itemData.c.v[1])+','+bm_floor(itemData.c.v[2])+')';
+    }
+    if(itemData.o.mdf || this.firstFrame){
+        styleElem.pElem.setAttribute('fill-opacity',itemData.o.v);
+    }
+};
+
+IShapeElement.prototype.renderGradient = function(styleData,itemData){
+    var gfill = itemData.gf;
+    var opFill = itemData.of;
+    var pt1 = itemData.s.v,pt2 = itemData.e.v;
+
+    if(itemData.o.mdf || this.firstFrame){
         var attr = styleData.ty === 'gf' ? 'fill-opacity':'stroke-opacity';
-        viewData.elem.setAttribute(attr,viewData.o.v);
+        itemData.elem.setAttribute(attr,itemData.o.v);
     }
     //clippedElement.setAttribute('transform','matrix(1,0,0,1,-100,0)');
-    if(viewData.s.mdf || this.firstFrame){
+    if(itemData.s.mdf || this.firstFrame){
         var attr1 = styleData.t === 1 ? 'x1':'cx';
         var attr2 = attr1 === 'x1' ? 'y1':'cy';
         gfill.setAttribute(attr1,pt1[0]);
@@ -461,9 +574,9 @@
         }
     }
     var stops, i, len, stop;
-    if(viewData.g.cmdf || this.firstFrame){
-        stops = viewData.cst;
-        var cValues = viewData.g.c;
+    if(itemData.g.cmdf || this.firstFrame){
+        stops = itemData.cst;
+        var cValues = itemData.g.c;
         len = stops.length;
         for(i=0;i<len;i+=1){
             stop = stops[i];
@@ -471,9 +584,9 @@
             stop.setAttribute('stop-color','rgb('+cValues[i*4+1]+','+cValues[i*4+2]+','+cValues[i*4+3]+')');
         }
     }
-    if(opFill && (viewData.g.omdf || this.firstFrame)){
-        stops = viewData.ost;
-        var oValues = viewData.g.o;
+    if(opFill && (itemData.g.omdf || this.firstFrame)){
+        stops = itemData.ost;
+        var oValues = itemData.g.o;
         len = stops.length;
         for(i=0;i<len;i+=1){
             stop = stops[i];
@@ -482,7 +595,7 @@
         }
     }
     if(styleData.t === 1){
-        if(viewData.e.mdf  || this.firstFrame){
+        if(itemData.e.mdf  || this.firstFrame){
             gfill.setAttribute('x2',pt2[0]);
             gfill.setAttribute('y2',pt2[1]);
             if(opFill){
@@ -492,23 +605,23 @@
         }
     } else {
         var rad;
-        if(viewData.s.mdf || viewData.e.mdf || this.firstFrame){
+        if(itemData.s.mdf || itemData.e.mdf || this.firstFrame){
             rad = Math.sqrt(Math.pow(pt1[0]-pt2[0],2)+Math.pow(pt1[1]-pt2[1],2));
             gfill.setAttribute('r',rad);
             if(opFill){
                 opFill.setAttribute('r',rad);
             }
         }
-        if(viewData.e.mdf || viewData.h.mdf || viewData.a.mdf || this.firstFrame){
+        if(itemData.e.mdf || itemData.h.mdf || itemData.a.mdf || this.firstFrame){
             if(!rad){
                 rad = Math.sqrt(Math.pow(pt1[0]-pt2[0],2)+Math.pow(pt1[1]-pt2[1],2));
             }
             var ang = Math.atan2(pt2[1]-pt1[1], pt2[0]-pt1[0]);
 
-            var percent = viewData.h.v >= 1 ? 0.99 : viewData.h.v <= -1 ? -0.99:viewData.h.v;
+            var percent = itemData.h.v >= 1 ? 0.99 : itemData.h.v <= -1 ? -0.99:itemData.h.v;
             var dist = rad*percent;
-            var x = Math.cos(ang + viewData.a.v)*dist + pt1[0];
-            var y = Math.sin(ang + viewData.a.v)*dist + pt1[1];
+            var x = Math.cos(ang + itemData.a.v)*dist + pt1[0];
+            var y = Math.sin(ang + itemData.a.v)*dist + pt1[1];
             gfill.setAttribute('fx',x);
             gfill.setAttribute('fy',y);
             if(opFill){
@@ -520,10 +633,10 @@
     }
 };
 
-IShapeElement.prototype.renderStroke = function(styleData,viewData){
-    var styleElem = viewData.style;
+IShapeElement.prototype.renderStroke = function(styleData,itemData){
+    var styleElem = itemData.style;
     //TODO fix dashes
-    var d = viewData.d;
+    var d = itemData.d;
     var dasharray,dashoffset;
     if(d && d.k && (d.mdf || this.firstFrame)){
         styleElem.pElem.setAttribute('stroke-dasharray', d.dasharray);
@@ -531,26 +644,26 @@
         styleElem.pElem.setAttribute('stroke-dashoffset', d.dashoffset);
         ////styleElem.pElem.style.strokeDashoffset = d.dashoffset;
     }
-    if(viewData.c && (viewData.c.mdf || this.firstFrame)){
-        styleElem.pElem.setAttribute('stroke','rgb('+bm_floor(viewData.c.v[0])+','+bm_floor(viewData.c.v[1])+','+bm_floor(viewData.c.v[2])+')');
-        ////styleElem.pElem.style.stroke = 'rgb('+bm_floor(viewData.c.v[0])+','+bm_floor(viewData.c.v[1])+','+bm_floor(viewData.c.v[2])+')';
+    if(itemData.c && (itemData.c.mdf || this.firstFrame)){
+        styleElem.pElem.setAttribute('stroke','rgb('+bm_floor(itemData.c.v[0])+','+bm_floor(itemData.c.v[1])+','+bm_floor(itemData.c.v[2])+')');
+        ////styleElem.pElem.style.stroke = 'rgb('+bm_floor(itemData.c.v[0])+','+bm_floor(itemData.c.v[1])+','+bm_floor(itemData.c.v[2])+')';
     }
-    if(viewData.o.mdf || this.firstFrame){
-        styleElem.pElem.setAttribute('stroke-opacity',viewData.o.v);
+    if(itemData.o.mdf || this.firstFrame){
+        styleElem.pElem.setAttribute('stroke-opacity',itemData.o.v);
     }
-    if(viewData.w.mdf || this.firstFrame){
-        styleElem.pElem.setAttribute('stroke-width',viewData.w.v);
+    if(itemData.w.mdf || this.firstFrame){
+        styleElem.pElem.setAttribute('stroke-width',itemData.w.v);
         if(styleElem.msElem){
-            styleElem.msElem.setAttribute('stroke-width',viewData.w.v);
+            styleElem.msElem.setAttribute('stroke-width',itemData.w.v);
         }
-        ////styleElem.pElem.style.strokeWidth = viewData.w.v;
+        ////styleElem.pElem.style.strokeWidth = itemData.w.v;
     }
 };
 
 IShapeElement.prototype.destroy = function(){
     this._parent.destroy.call(this._parent);
     this.shapeData = null;
-    this.viewData = null;
+    this.itemsData = null;
     this.parentContainer = null;
     this.placeholder = null;
 };
diff --git a/player/js/elements/canvasElements/CVShapeElement.js b/player/js/elements/canvasElements/CVShapeElement.js
index c09a6dd..5c9cd53 100644
--- a/player/js/elements/canvasElements/CVShapeElement.js
+++ b/player/js/elements/canvasElements/CVShapeElement.js
@@ -1,25 +1,15 @@
 function CVShapeElement(data, comp,globalData){
     this.shapes = [];
-    this.stylesList = [];
-    this.viewData = [];
-    this.shapeModifiers = [];
     this.shapesData = data.shapes;
-    this.firstFrame = true;
+    this.stylesList = [];
+    this.itemsData = [];
+    this.prevViewData = [];
+    this.shapeModifiers = [];
+    this.processedElements = [];
     this._parent.constructor.call(this,data, comp,globalData);
 }
 createElement(CVBaseElement, CVShapeElement);
 
-CVShapeElement.prototype.lcEnum = {
-    '1': 'butt',
-    '2': 'round',
-    '3': 'butt'
-}
-
-CVShapeElement.prototype.ljEnum = {
-    '1': 'miter',
-    '2': 'round',
-    '3': 'butt'
-};
 CVShapeElement.prototype.transformHelper = {opacity:1,mat:new Matrix(),matMdf:false,opMdf:false};
 
 CVShapeElement.prototype.dashResetter = [];
@@ -27,107 +17,185 @@
 CVShapeElement.prototype.createElements = function(){
 
     this._parent.createElements.call(this);
-    this.searchShapes(this.shapesData,this.viewData,this.dynamicProperties);
+    this.searchShapes(this.shapesData,this.itemsData,this.prevViewData,this.dynamicProperties, true);
 };
-CVShapeElement.prototype.searchShapes = function(arr,data,dynamicProperties){
+
+CVShapeElement.prototype.createStyleElement = function(data, dynamicProperties){
+    var styleElem = {
+        data: data,
+        type: data.ty,
+        elements: []
+    };
+    var elementData = {};
+    if(data.ty == 'fl' || data.ty == 'st'){
+        elementData.c = PropertyFactory.getProp(this,data.c,1,255,dynamicProperties);
+        if(!elementData.c.k){
+            styleElem.co = 'rgb('+bm_floor(elementData.c.v[0])+','+bm_floor(elementData.c.v[1])+','+bm_floor(elementData.c.v[2])+')';
+        }
+    }
+    elementData.o = PropertyFactory.getProp(this,data.o,0,0.01,dynamicProperties);
+    if(data.ty == 'st') {
+        styleElem.lc = this.lcEnum[data.lc] || 'round';
+        styleElem.lj = this.ljEnum[data.lj] || 'round';
+        if(data.lj == 1) {
+            styleElem.ml = data.ml;
+        }
+        elementData.w = PropertyFactory.getProp(this,data.w,0,null,dynamicProperties);
+        if(!elementData.w.k){
+            styleElem.wi = elementData.w.v;
+        }
+        if(data.d){
+            var d = PropertyFactory.getDashProp(this,data.d,'canvas',dynamicProperties);
+            elementData.d = d;
+            if(!elementData.d.k){
+                styleElem.da = elementData.d.dasharray;
+                styleElem.do = elementData.d.dashoffset;
+            }
+        }
+
+    } else {
+
+        styleElem.r = data.r === 2 ? 'evenodd' : 'nonzero';
+    }
+    this.stylesList.push(styleElem);
+    elementData.style = styleElem;
+    return elementData;
+}
+
+CVShapeElement.prototype.createGroupElement = function(data) {
+    var elementData = {
+        it: [],
+        prevViewData: []
+    };
+    return elementData;
+}
+
+CVShapeElement.prototype.createTransformElement = function(data, dynamicProperties) {
+    var elementData = {
+        transform : {
+            mat: new Matrix(),
+            opacity: 1,
+            matMdf:false,
+            opMdf:false,
+            op: PropertyFactory.getProp(this,data.o,0,0.01,dynamicProperties),
+            mProps: PropertyFactory.getProp(this,data,2,null,dynamicProperties)
+        },
+        elements: []
+    };
+    return elementData;
+}
+
+CVShapeElement.prototype.createShapeElement = function(data, dynamicProperties) {
+    var elementData = {
+        nodes:[],
+        trNodes:[],
+        tr:[0,0,0,0,0,0]
+    };
+    var ty = 4;
+    if(data.ty == 'rc'){
+        ty = 5;
+    }else if(data.ty == 'el'){
+        ty = 6;
+    }else if(data.ty == 'sr'){
+        ty = 7;
+    }
+    elementData.sh = ShapePropertyFactory.getShapeProp(this,data,ty,dynamicProperties);
+    this.shapes.push(elementData.sh);
+    this.addShapeToModifiers(elementData);
+    jLen = this.stylesList.length;
+    var hasStrokes = false, hasFills = false;
+    for(j=0;j<jLen;j+=1){
+        if(!this.stylesList[j].closed){
+            this.stylesList[j].elements.push(elementData);
+            if(this.stylesList[j].type === 'st'){
+                hasStrokes = true;
+            }else{
+                hasFills = true;
+            }
+        }
+    }
+    elementData.st = hasStrokes;
+    elementData.fl = hasFills;
+    return elementData;
+}
+
+CVShapeElement.prototype.reloadShapes = function(){
+    this.firstFrame = true;
+    var i, len = this.itemsData.length;
+    for(i=0;i<len;i+=1){
+        this.prevViewData[i] = this.itemsData[i];
+    }
+    this.searchShapes(this.shapesData,this.itemsData,this.prevViewData,this.dynamicProperties, true);
+    var i, len = this.dynamicProperties.length;
+    for(i=0;i<len;i+=1){
+        this.dynamicProperties[i].getValue();
+    }
+    this.renderModifiers();
+}
+
+CVShapeElement.prototype.searchShapes = function(arr,itemsData, prevViewData,dynamicProperties, render){
     var i, len = arr.length - 1;
     var j, jLen;
-    var ownArrays = [], ownModifiers = [], styleElem;
+    var ownArrays = [], ownModifiers = [], processedPos;
     for(i=len;i>=0;i-=1){
-        if(arr[i].ty == 'fl' || arr[i].ty == 'st'){
-            styleElem = {
-                type: arr[i].ty,
-                elements: []
-            };
-            data[i] = {};
-            if(arr[i].ty == 'fl' || arr[i].ty == 'st'){
-                data[i].c = PropertyFactory.getProp(this,arr[i].c,1,255,dynamicProperties);
-                if(!data[i].c.k){
-                    styleElem.co = 'rgb('+bm_floor(data[i].c.v[0])+','+bm_floor(data[i].c.v[1])+','+bm_floor(data[i].c.v[2])+')';
-                }
-            }
-            data[i].o = PropertyFactory.getProp(this,arr[i].o,0,0.01,dynamicProperties);
-            if(arr[i].ty == 'st') {
-                styleElem.lc = this.lcEnum[arr[i].lc] || 'round';
-                styleElem.lj = this.ljEnum[arr[i].lj] || 'round';
-                if(arr[i].lj == 1) {
-                    styleElem.ml = arr[i].ml;
-                }
-                data[i].w = PropertyFactory.getProp(this,arr[i].w,0,null,dynamicProperties);
-                if(!data[i].w.k){
-                    styleElem.wi = data[i].w.v;
-                }
-                if(arr[i].d){
-                    var d = PropertyFactory.getDashProp(this,arr[i].d,'canvas',dynamicProperties);
-                    data[i].d = d;
-                    if(!data[i].d.k){
-                        styleElem.da = data[i].d.dasharray;
-                        styleElem.do = data[i].d.dashoffset;
-                    }
-                }
-
-            } else {
-
-                styleElem.r = arr[i].r === 2 ? 'evenodd' : 'nonzero';
-            }
-            this.stylesList.push(styleElem);
-            data[i].style = styleElem;
-            ownArrays.push(data[i].style);
-        }else if(arr[i].ty == 'gr'){
-            data[i] = {
-                it: []
-            };
-            this.searchShapes(arr[i].it,data[i].it,dynamicProperties);
-        }else if(arr[i].ty == 'tr'){
-            data[i] = {
-                transform : {
-                    mat: new Matrix(),
-                    opacity: 1,
-                    matMdf:false,
-                    opMdf:false,
-                    op: PropertyFactory.getProp(this,arr[i].o,0,0.01,dynamicProperties),
-                    mProps: PropertyFactory.getProp(this,arr[i],2,null,dynamicProperties)
-                },
-                elements: []
-            };
-        }else if(arr[i].ty == 'sh' || arr[i].ty == 'rc' || arr[i].ty == 'el' || arr[i].ty == 'sr'){
-            data[i] = {
-                nodes:[],
-                trNodes:[],
-                tr:[0,0,0,0,0,0]
-            };
-            var ty = 4;
-            if(arr[i].ty == 'rc'){
-                ty = 5;
-            }else if(arr[i].ty == 'el'){
-                ty = 6;
-            }else if(arr[i].ty == 'sr'){
-                ty = 7;
-            }
-            data[i].sh = ShapePropertyFactory.getShapeProp(this,arr[i],ty,dynamicProperties);
-            this.shapes.push(data[i].sh);
-            this.addShapeToModifiers(data[i]);
-            jLen = this.stylesList.length;
-            var hasStrokes = false, hasFills = false;
-            for(j=0;j<jLen;j+=1){
-                if(!this.stylesList[j].closed){
-                    this.stylesList[j].elements.push(data[i]);
-                    if(this.stylesList[j].type === 'st'){
-                        hasStrokes = true;
-                    }else{
-                        hasFills = true;
-                    }
-                }
-            }
-            data[i].st = hasStrokes;
-            data[i].fl = hasFills;
-        }else if(arr[i].ty == 'tm' || arr[i].ty == 'rd' || arr[i].ty == 'rp'){
-            var modifier = ShapeModifiers.getModifier(arr[i].ty);
-            modifier.init(this,arr[i],dynamicProperties);
-            this.shapeModifiers.push(modifier);
-            ownModifiers.push(modifier);
-            data[i] = modifier;
+        processedPos = this.searchProcessedElement(arr[i]);
+        if(!processedPos){
+            arr[i]._render = render;
+        } else {
+            itemsData[i] = prevViewData[processedPos - 1];
         }
+        if(arr[i].ty == 'fl' || arr[i].ty == 'st'){
+            if(!processedPos){
+                itemsData[i] = this.createStyleElement(arr[i], dynamicProperties);
+            } else {
+                itemsData[i].style.closed = false;
+            }
+            
+            ownArrays.push(itemsData[i].style);
+        }else if(arr[i].ty == 'gr'){
+            if(!processedPos){
+                itemsData[i] = this.createGroupElement(arr[i]);
+            } else {
+                jLen = itemsData[i].it.length;
+                for(j=0;j<jLen;j+=1){
+                    itemsData[i].prevViewData[j] = itemsData[i].it[j];
+                }
+            }
+            this.searchShapes(arr[i].it,itemsData[i].it,itemsData[i].prevViewData,dynamicProperties, render);
+        }else if(arr[i].ty == 'tr'){
+            if(!processedPos){
+                itemsData[i] = this.createTransformElement(arr[i], dynamicProperties);
+            }
+        }else if(arr[i].ty == 'sh' || arr[i].ty == 'rc' || arr[i].ty == 'el' || arr[i].ty == 'sr'){
+            if(!processedPos){
+                itemsData[i] = this.createShapeElement(arr[i], dynamicProperties);
+            }
+            
+        }else if(arr[i].ty == 'tm' || arr[i].ty == 'rd'){
+            if(!processedPos){
+                var modifier = ShapeModifiers.getModifier(arr[i].ty);
+                modifier.init(this,arr[i],dynamicProperties);
+                itemsData[i] = modifier;
+                this.shapeModifiers.push(modifier);
+            } else {
+                modifier = itemsData[i];
+                modifier.closed = false;
+            }
+            ownModifiers.push(modifier);
+        } else if(arr[i].ty == 'rp'){
+            if(!processedPos){
+                modifier = ShapeModifiers.getModifier(arr[i].ty);
+                itemsData[i] = modifier;
+                modifier.init(this,arr,i,itemsData,dynamicProperties);
+                this.shapeModifiers.push(modifier);
+                render = false;
+            }else{
+                modifier = itemsData[i];
+                modifier.closed = true;
+            }
+            ownModifiers.push(modifier);
+        }
+        this.addProcessedElement(arr[i], i + 1);
     }
     len = ownArrays.length;
     for(i=0;i<len;i+=1){
@@ -141,6 +209,10 @@
 
 CVShapeElement.prototype.addShapeToModifiers = IShapeElement.prototype.addShapeToModifiers;
 CVShapeElement.prototype.renderModifiers = IShapeElement.prototype.renderModifiers;
+CVShapeElement.prototype.lcEnum = IShapeElement.prototype.lcEnum;
+CVShapeElement.prototype.ljEnum = IShapeElement.prototype.ljEnum;
+CVShapeElement.prototype.searchProcessedElement = IShapeElement.prototype.searchProcessedElement;
+CVShapeElement.prototype.addProcessedElement = IShapeElement.prototype.addProcessedElement;
 
 CVShapeElement.prototype.renderFrame = function(parentMatrix){
     if(this._parent.renderFrame.call(this, parentMatrix)===false){
@@ -168,7 +240,7 @@
         }
     }
     if(!data){
-        data = this.viewData;
+        data = this.itemsData;
     }
     ///
     ///
@@ -214,7 +286,7 @@
     renderer.ctxTransform(this.finalTransform.mat.props);
     for(i=0;i<len;i+=1){
         type = this.stylesList[i].type;
-        if(type === 'st' && this.stylesList[i].wi === 0){
+        if((type === 'st' && this.stylesList[i].wi === 0) || !this.stylesList[i].data._render){
             continue;
         }
         renderer.save();
@@ -271,13 +343,13 @@
         this.firstFrame = false;
     }
 };
-CVShapeElement.prototype.renderPath = function(pathData,viewData,groupTransform){
+CVShapeElement.prototype.renderPath = function(pathData,itemData,groupTransform){
     var len, i, j,jLen;
-    var redraw = groupTransform.matMdf || viewData.sh.mdf || this.firstFrame;
+    var redraw = groupTransform.matMdf || itemData.sh.mdf || this.firstFrame;
     if(redraw) {
-        var paths = viewData.sh.paths;
+        var paths = itemData.sh.paths;
         jLen = paths._length;
-        var pathStringTransformed = viewData.trNodes;
+        var pathStringTransformed = itemData.trNodes;
         pathStringTransformed.length = 0;
         for(j=0;j<jLen;j+=1){
             var pathNodes = paths.shapes[j];
@@ -314,51 +386,51 @@
                         t: 'z'
                     });
                 }
-                viewData.lStr = pathStringTransformed;
+                itemData.lStr = pathStringTransformed;
             }
 
         }
 
-        if (viewData.st) {
+        if (itemData.st) {
             for (i = 0; i < 16; i += 1) {
-                viewData.tr[i] = groupTransform.mat.props[i];
+                itemData.tr[i] = groupTransform.mat.props[i];
             }
         }
-        viewData.trNodes = pathStringTransformed;
+        itemData.trNodes = pathStringTransformed;
 
     }
 };
 
 
 
-CVShapeElement.prototype.renderFill = function(styleData,viewData, groupTransform){
-    var styleElem = viewData.style;
+CVShapeElement.prototype.renderFill = function(styleData,itemData, groupTransform){
+    var styleElem = itemData.style;
 
-    if(viewData.c.mdf || this.firstFrame){
-        styleElem.co = 'rgb('+bm_floor(viewData.c.v[0])+','+bm_floor(viewData.c.v[1])+','+bm_floor(viewData.c.v[2])+')';
+    if(itemData.c.mdf || this.firstFrame){
+        styleElem.co = 'rgb('+bm_floor(itemData.c.v[0])+','+bm_floor(itemData.c.v[1])+','+bm_floor(itemData.c.v[2])+')';
     }
-    if(viewData.o.mdf || groupTransform.opMdf || this.firstFrame){
-        styleElem.coOp = viewData.o.v*groupTransform.opacity;
+    if(itemData.o.mdf || groupTransform.opMdf || this.firstFrame){
+        styleElem.coOp = itemData.o.v*groupTransform.opacity;
     }
 };
 
-CVShapeElement.prototype.renderStroke = function(styleData,viewData, groupTransform){
-    var styleElem = viewData.style;
+CVShapeElement.prototype.renderStroke = function(styleData,itemData, groupTransform){
+    var styleElem = itemData.style;
     //TODO fix dashes
-    var d = viewData.d;
+    var d = itemData.d;
     var dasharray,dashoffset;
     if(d && (d.mdf  || this.firstFrame)){
         styleElem.da = d.dasharray;
         styleElem.do = d.dashoffset;
     }
-    if(viewData.c.mdf || this.firstFrame){
-        styleElem.co = 'rgb('+bm_floor(viewData.c.v[0])+','+bm_floor(viewData.c.v[1])+','+bm_floor(viewData.c.v[2])+')';
+    if(itemData.c.mdf || this.firstFrame){
+        styleElem.co = 'rgb('+bm_floor(itemData.c.v[0])+','+bm_floor(itemData.c.v[1])+','+bm_floor(itemData.c.v[2])+')';
     }
-    if(viewData.o.mdf || groupTransform.opMdf || this.firstFrame){
-        styleElem.coOp = viewData.o.v*groupTransform.opacity;
+    if(itemData.o.mdf || groupTransform.opMdf || this.firstFrame){
+        styleElem.coOp = itemData.o.v*groupTransform.opacity;
     }
-    if(viewData.w.mdf || this.firstFrame){
-        styleElem.wi = viewData.w.v;
+    if(itemData.w.mdf || this.firstFrame){
+        styleElem.wi = itemData.w.v;
     }
 };
 
@@ -368,7 +440,7 @@
     this.globalData = null;
     this.canvasContext = null;
     this.stylesList.length = 0;
-    this.viewData.length = 0;
+    this.itemData.length = 0;
     this._parent.destroy.call(this._parent);
 };
 
diff --git a/player/js/elements/htmlElements/HShapeElement.js b/player/js/elements/htmlElements/HShapeElement.js
index a00e2c8..f6aef9d 100644
--- a/player/js/elements/htmlElements/HShapeElement.js
+++ b/player/js/elements/htmlElements/HShapeElement.js
@@ -1,14 +1,12 @@
 function HShapeElement(data,parentContainer,globalData,comp, placeholder){
     this.shapes = [];
-    this.shapeModifiers = [];
     this.shapesData = data.shapes;
     this.stylesList = [];
-    this.viewData = [];
+    this.itemsData = [];
+    this.prevViewData = [];
+    this.shapeModifiers = [];
+    this.processedElements = [];
     this._parent.constructor.call(this,data,parentContainer,globalData,comp, placeholder);
-    this.addedTransforms = {
-        mdf: false,
-        mats: [this.finalTransform.mat]
-    };
     this.currentBBox = {
         x:999999,
         y: -999999,
@@ -20,6 +18,7 @@
 var parent = HShapeElement.prototype._parent;
 extendPrototype(IShapeElement, HShapeElement);
 HShapeElement.prototype._parent = parent;
+HShapeElement.prototype._renderShapeFrame = HShapeElement.prototype.renderFrame;
 
 HShapeElement.prototype.createElements = function(){
     var parent = document.createElement('div');
@@ -50,7 +49,8 @@
     if(this.data.ln){
         this.innerElem.setAttribute('id',this.data.ln);
     }
-    this.searchShapes(this.shapesData,this.viewData,this.layerElement,this.dynamicProperties,0);
+
+    this.searchShapes(this.shapesData,this.itemsData,this.prevViewData,this.layerElement,this.dynamicProperties,0, [], true);
     this.buildExpressionInterface();
     this.layerElement = parent;
     this.transformedElement = parent;
@@ -62,22 +62,10 @@
 };
 
 HShapeElement.prototype.renderFrame = function(parentMatrix){
-    var renderParent = this._parent.renderFrame.call(this,parentMatrix);
-    if(renderParent===false){
-        this.hide();
-        return;
-    }
-    if(this.hidden){
-        this.layerElement.style.display = 'block';
-        this.hidden = false;
-    }
-    this.renderModifiers();
-    this.addedTransforms.mdf = this.finalTransform.matMdf;
-    this.addedTransforms.mats.length = 1;
-    this.addedTransforms.mats[0] = this.finalTransform.mat;
-    this.renderShape(null,null,true, null);
+    var firstFrame = this.firstFrame;
+    this._renderShapeFrame();
 
-    if(this.isVisible && (this.elemMdf || this.firstFrame)){
+    if(this.isVisible && (this.elemMdf || firstFrame)){
         var boundingBox = this.shapeCont.getBBox();
         var changed = false;
         if(this.currentBBox.w !== boundingBox.width){
diff --git a/player/js/utils/DataManager.js b/player/js/utils/DataManager.js
index 8719af6..5b3375b 100644
--- a/player/js/utils/DataManager.js
+++ b/player/js/utils/DataManager.js
@@ -52,7 +52,11 @@
         var i = 0, len = comps.length;
         while(i<len){
             if(comps[i].id === id){
-                return comps[i].layers;
+                if(!comps[i].layers.__used) {
+                    comps[i].layers.__used = true;
+                    return comps[i].layers;
+                }
+                return JSON.parse(JSON.stringify(comps[i].layers));
             }
             i += 1;
         }
diff --git a/player/js/utils/common.js b/player/js/utils/common.js
index 05a3632..a5452f0 100644
--- a/player/js/utils/common.js
+++ b/player/js/utils/common.js
@@ -1,4 +1,4 @@
-var subframeEnabled = true;
+var subframeEnabled = false;
 var expressionsPlugin;
 var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
 var cachedColors = {};
diff --git a/player/js/utils/shapes/RepeaterModifier.js b/player/js/utils/shapes/RepeaterModifier.js
index 87cb7cc..a78b937 100644
--- a/player/js/utils/shapes/RepeaterModifier.js
+++ b/player/js/utils/shapes/RepeaterModifier.js
@@ -1,11 +1,9 @@
 function RepeaterModifier(){};
-extendPrototype(ShapeModifier,RepeaterModifier);
 RepeaterModifier.prototype.processKeys = function(forceRender){
     if(this.elem.globalData.frameId === this.frameId && !forceRender){
         return;
     }
     this.mdf = forceRender ? true : false;
-    this.frameId = this.elem.globalData.frameId;
     var i, len = this.dynamicProperties.length;
 
     for(i=0;i<len;i+=1){
@@ -15,11 +13,13 @@
         }
     }
 };
+
 RepeaterModifier.prototype.initModifierProperties = function(elem,data){
     this.getValue = this.processKeys;
     this.c = PropertyFactory.getProp(elem,data.c,0,null,this.dynamicProperties);
     this.o = PropertyFactory.getProp(elem,data.o,0,null,this.dynamicProperties);
     this.tr = PropertyFactory.getProp(elem,data.tr,2,null,this.dynamicProperties);
+    this.data = data;
     if(!this.dynamicProperties.length){
         this.getValue(true);
     }
@@ -43,98 +43,164 @@
     sMatrix.translate(transform.a.v[0], transform.a.v[1], transform.a.v[2]);
 }
 
+RepeaterModifier.prototype.init = function(elem, arr, pos, elemsData, dynamicProperties) {
+    this.elem = elem;
+    this.arr = arr;
+    this.pos = pos;
+    this.elemsData = elemsData;
+    this._currentCopies = 0;
+    this._elements = [];
+    this._groups = [];
+    this.dynamicProperties = [];
+    this.frameId = -1;
+    this.initModifierProperties(elem,arr[pos]);
+    var cont = 0;
+    while(pos>0){
+        pos -= 1;
+        //this._elements.unshift(arr.splice(pos,1)[0]);
+        this._elements.unshift(arr[pos]);
+        cont += 1;
+    }
+    if(this.dynamicProperties.length){
+        this.k = true;
+        dynamicProperties.push(this);
+    }else{
+        this.getValue(true);
+    }
+}
+
+RepeaterModifier.prototype.resetElements = function(elements){
+    var i, len = elements.length;
+    for(i = 0; i < len; i += 1) {
+        elements[i]._processed = false;
+        if(elements[i].ty === 'gr'){
+            this.resetElements(elements[i].it);
+        }
+    }
+}
+
+RepeaterModifier.prototype.cloneElements = function(elements){
+    var i, len = elements.length;
+    var newElements = JSON.parse(JSON.stringify(elements));
+    this.resetElements(newElements);
+    return newElements;
+}
+
+RepeaterModifier.prototype.changeGroupRender = function(elements, renderFlag) {
+    var i, len = elements.length;
+    for(i = 0; i < len ; i += 1) {
+        elements[i]._render = renderFlag;
+        if(elements[i].ty === 'gr') {
+            this.changeGroupRender(elements[i].it, renderFlag);
+        }
+    }
+}
+
 RepeaterModifier.prototype.processShapes = function(firstFrame){
-    if(!this.dynamicProperties.length){
+
+    if(this.elem.globalData.frameId === this.frameId){
+        return;
+    }
+    this.frameId = this.elem.globalData.frameId;
+    if(!this.dynamicProperties.length && !firstFrame){
         this.mdf = false;
     }
-    var i, len = this.shapes.length;
-    var j, jLen;
-    var shapeData, localShapeCollection, currentPath;
-    var copies = Math.ceil(this.c.v);
-    var offset = this.o.v;
-    var offsetModulo = offset%1;
-    var roundOffset = offset > 0 ? Math.floor(offset) : Math.ceil(offset);
-    var k, pathData, shapeCollection, shapeCollectionList;
-    var tMat = this.tr.v.props;
-    var pProps = this.pMatrix.props;
-    var rProps = this.rMatrix.props;
-    var sProps = this.sMatrix.props;
-    var iteration = 0;
-    var l, lLen, tProps,transformers, maxLvl;
-    for(i=0;i<len;i+=1){
-        shapeData = this.shapes[i];
-        localShapeCollection = shapeData.localShapeCollection;
-        if(!(!shapeData.shape.mdf && !this.mdf && !firstFrame)){
-            localShapeCollection.releaseShapes();
-            shapeData.shape.mdf = true;
-            shapeCollection = shapeData.shape.paths;
-            shapeCollectionList = shapeCollection.shapes;
-            jLen = shapeCollection._length;
-            iteration = 0;
-            this.pMatrix.reset();
-            this.rMatrix.reset();
-            this.sMatrix.reset();
-            this.tMatrix.reset();
-            this.matrix.reset();
-
-            if(offset > 0) {
-                while(iteration<roundOffset){
-                    this.applyTransforms(this.pMatrix, this.rMatrix, this.sMatrix, this.tr, 1, false);
-                    iteration += 1;
+    if(this.mdf){
+        var copies = Math.ceil(this.c.v);
+        if(this._groups.length < copies){
+            while(this._groups.length < copies){
+                var group = {
+                    it:this.cloneElements(this._elements),
+                    ty:'gr'
                 }
-                if(offsetModulo){
-                    this.applyTransforms(this.pMatrix, this.rMatrix, this.sMatrix, this.tr, offsetModulo, false);
-                    iteration += offsetModulo;
-                }
-            } else if(roundOffset < 0) {
-                while(iteration>roundOffset){
-                    this.applyTransforms(this.pMatrix, this.rMatrix, this.sMatrix, this.tr, 1, true);
-                    iteration -= 1;
-                }
-                if(offsetModulo){
-                    this.applyTransforms(this.pMatrix, this.rMatrix, this.sMatrix, this.tr, - offsetModulo, true);
-                    iteration -= offsetModulo;
-                }
+                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":0,"ix":6,"k":0},"s":{"a":0,"ix":3,"k":[100,100]},"sa":{"a":0,"ix":5,"k":0},"sk":{"a":0,"ix":4,"k":0},"ty":"tr"});
+                
+                this.arr.splice(0,0,group);
+                this._groups.splice(0,0,group);
+                this._currentCopies += 1;
             }
-            for(j=0;j<jLen;j+=1){
-                currentPath = shapeCollectionList[j];
-                for(k=0;k<copies;k+=1) {
-                    if(k !== 0) {
-                        this.applyTransforms(this.pMatrix, this.rMatrix, this.sMatrix, this.tr, 1, false);
-                    }
-                    if(shapeData.data.transformers) {
-                        shapeData.data.lvl = 0;
-                        maxLvl = 0;
-                        lLen = shapeData.data.elements.length;
-                        for(l = 0; l < lLen; l += 1) {
-                            maxLvl = Math.max(maxLvl, shapeData.data.elements[l].st.lvl);
-                        } 
-                        transformers = shapeData.data.transformers;
-                        lLen = transformers.length;
-                        for(l = lLen - 1; l >= maxLvl; l -= 1) {
-                            tProps = transformers[l].mProps.v.props;
-                            this.matrix.transform(tProps[0],tProps[1],tProps[2],tProps[3],tProps[4],tProps[5],tProps[6],tProps[7],tProps[8],tProps[9],tProps[10],tProps[11],tProps[12],tProps[13],tProps[14],tProps[15]);
-                        }
-                    }
-                    if(iteration !== 0){
-                        this.matrix.transform(rProps[0],rProps[1],rProps[2],rProps[3],rProps[4],rProps[5],rProps[6],rProps[7],rProps[8],rProps[9],rProps[10],rProps[11],rProps[12],rProps[13],rProps[14],rProps[15]);
-                        this.matrix.transform(sProps[0],sProps[1],sProps[2],sProps[3],sProps[4],sProps[5],sProps[6],sProps[7],sProps[8],sProps[9],sProps[10],sProps[11],sProps[12],sProps[13],sProps[14],sProps[15]);
-                        this.matrix.transform(pProps[0],pProps[1],pProps[2],pProps[3],pProps[4],pProps[5],pProps[6],pProps[7],pProps[8],pProps[9],pProps[10],pProps[11],pProps[12],pProps[13],pProps[14],pProps[15]);
-                    }
-                    localShapeCollection.addShape(this.processPath(currentPath, this.matrix));
-                    this.matrix.reset();
-                    iteration += 1;
-                }
+            this.elem.reloadShapes();
+        }
+        var i, cont = 0, renderFlag;
+        for(i = 0; i  <= this._groups.length - 1; i += 1){
+            renderFlag = cont < copies;
+            this._groups[i]._render = renderFlag;
+            this.changeGroupRender(this._groups[i].it, renderFlag);
+            cont += 1;
+        }
+        
+        this._currentCopies = copies;
+        this.elem.firstFrame = true;
+        ////
+
+        var offset = this.o.v;
+        var offsetModulo = offset%1;
+        var roundOffset = offset > 0 ? Math.floor(offset) : Math.ceil(offset);
+        var k;
+        var tMat = this.tr.v.props;
+        var pProps = this.pMatrix.props;
+        var rProps = this.rMatrix.props;
+        var sProps = this.sMatrix.props;
+        this.pMatrix.reset();
+        this.rMatrix.reset();
+        this.sMatrix.reset();
+        this.tMatrix.reset();
+        this.matrix.reset();
+        var iteration = 0;
+
+        if(offset > 0) {
+            while(iteration<roundOffset){
+                this.applyTransforms(this.pMatrix, this.rMatrix, this.sMatrix, this.tr, 1, false);
+                iteration += 1;
+            }
+            if(offsetModulo){
+                this.applyTransforms(this.pMatrix, this.rMatrix, this.sMatrix, this.tr, offsetModulo, false);
+                iteration += offsetModulo;
+            }
+        } else if(offset < 0) {
+            while(iteration>roundOffset){
+                this.applyTransforms(this.pMatrix, this.rMatrix, this.sMatrix, this.tr, 1, true);
+                iteration -= 1;
+            }
+            if(offsetModulo){
+                this.applyTransforms(this.pMatrix, this.rMatrix, this.sMatrix, this.tr, - offsetModulo, true);
+                iteration -= offsetModulo;
             }
         }
-        shapeData.shape.paths = localShapeCollection;
+        i = this.data.m === 1 ? 0 : this._currentCopies - 1;
+        var dir = this.data.m === 1 ? 1 : -1;
+        cont = this._currentCopies;
+        while(cont){
+            if(iteration !== 0){
+                if((i !== 0 && dir === 1) || (i !== this._currentCopies - 1 && dir === -1)){
+                    this.applyTransforms(this.pMatrix, this.rMatrix, this.sMatrix, this.tr, 1, false);
+                }
+                this.matrix.transform(rProps[0],rProps[1],rProps[2],rProps[3],rProps[4],rProps[5],rProps[6],rProps[7],rProps[8],rProps[9],rProps[10],rProps[11],rProps[12],rProps[13],rProps[14],rProps[15]);
+                this.matrix.transform(sProps[0],sProps[1],sProps[2],sProps[3],sProps[4],sProps[5],sProps[6],sProps[7],sProps[8],sProps[9],sProps[10],sProps[11],sProps[12],sProps[13],sProps[14],sProps[15]);
+                this.matrix.transform(pProps[0],pProps[1],pProps[2],pProps[3],pProps[4],pProps[5],pProps[6],pProps[7],pProps[8],pProps[9],pProps[10],pProps[11],pProps[12],pProps[13],pProps[14],pProps[15]);
+                var items = this.elemsData[i].it;
+                var itemsTransform = items[items.length - 1].transform.mProps.v.props;
+                var j, jLen = itemsTransform.length;
+                for(j=0;j<jLen;j+=1) {
+                    itemsTransform[j] = this.matrix.props[j];
+                }
+                this.matrix.reset();
+            } else {
+                this.matrix.reset();
+                var items = this.elemsData[i].it;
+                var itemsTransform = items[items.length - 1].transform.mProps.v.props;
+                var j, jLen = itemsTransform.length;
+                for(j=0;j<jLen;j+=1) {
+                    itemsTransform[j] = this.matrix.props[j];
+                }
+            }
+            iteration += 1;
+            cont -= 1;
+            i += dir;
+        }
     }
-};
+}
 
-RepeaterModifier.prototype.processPath = function(path, transform) {
-    var clonedPath = shape_pool.clone(path, transform);
-    return clonedPath;
-};
-
+RepeaterModifier.prototype.addShape = function(){}
 
 ShapeModifiers.registerModifier('rp',RepeaterModifier);
\ No newline at end of file
diff --git a/player/js/utils/shapes/ShapeModifiers.js b/player/js/utils/shapes/ShapeModifiers.js
index 9f44740..00cf36b 100644
--- a/player/js/utils/shapes/ShapeModifiers.js
+++ b/player/js/utils/shapes/ShapeModifiers.js
@@ -34,7 +34,6 @@
     this.mdf = false;
     this.closed = false;
     this.k = false;
-    this.isTrimming = false;
     this.comp = elem.comp;
     this.initModifierProperties(elem,data);
     if(this.dynamicProperties.length){