applying matrix to path nodes
diff --git a/player/index.html b/player/index.html
index de1e4ad..0375fc1 100644
--- a/player/index.html
+++ b/player/index.html
@@ -36,6 +36,6 @@
     <!-- endbuild -->
 </head>
 <body style="background-color:#fff; margin: 0px;height: 100%; font-family: sans-serif;font-size: 10px">
-<div style="width:600px;height:550px;background-color:#ddd;display:inline-block" class="bodymovin" data-bm-path="exports/ellipse" data-bm-type="svg" data-bm-loop="false" data-bm-prerender="true"></div>
+<div style="width:500px;height:500px;background-color:#000;display:inline-block" class="bodymovin" data-bm-path="exports/ninja" data-bm-type="svg" data-bm-loop="true" data-bm-prerender="true"></div>
 </body>
 </html>
diff --git a/player/js/animation/AnimationItem.js b/player/js/animation/AnimationItem.js
index 1674d6e..f74bc9a 100644
--- a/player/js/animation/AnimationItem.js
+++ b/player/js/animation/AnimationItem.js
@@ -124,8 +124,8 @@
     this.totalFrames = this.animationData.animation.totalFrames;
     this.frameRate = this.animationData.animation.frameRate;
     this.firstFrame = Math.round(this.animationData.animation.ff*this.frameRate);
-    /*this.firstFrame = 40;
-    this.totalFrames = 1;*/
+    this.firstFrame = 23;
+    this.totalFrames = 1;
     this.frameMult = this.animationData.animation.frameRate / 1000;
     dataManager.completeData(this.animationData);
     this.renderer.buildItems(this.animationData.animation.layers);
diff --git a/player/js/elements/ShapeElement.js b/player/js/elements/ShapeElement.js
index beaab3d..4e4b41e 100644
--- a/player/js/elements/ShapeElement.js
+++ b/player/js/elements/ShapeElement.js
@@ -32,7 +32,6 @@
     if(this.data.hasMask){
         this.mainShape.renderShape(num);
     }else{
-        console.log('this.finalTransform:',this.finalTransform);
         this.mainShape.renderShape(num,this.finalTransform);
     }
 };
\ No newline at end of file
diff --git a/player/js/elements/ShapeItemElement.js b/player/js/elements/ShapeItemElement.js
index abca9aa..0c44ac0 100644
--- a/player/js/elements/ShapeItemElement.js
+++ b/player/js/elements/ShapeItemElement.js
@@ -31,10 +31,10 @@
                     w: ''
                 }
             };
+            var pathElement = document.createElementNS(svgNS, "path");
+            this.shape.appendChild(pathElement);
             this.stylesList.push({
-                elements: [],
-                datas: [],
-                pathElement: document.createElementNS(svgNS, "path"),
+                pathElement: pathElement,
                 type: arr[i].ty,
                 d: ''
             });
@@ -52,10 +52,11 @@
                     opacity: 1
                 }
             };
-        }else if(arr[i].ty == 'sh'){
+        }else if(arr[i].ty == 'sh' || arr[i].ty == 'rc' || arr[i].ty == 'el'){
             data[i] = {
                 elements : [],
                 renderedFrames : [],
+                styles : [],
                 lastData : {
                     d: '',
                     o:'',
@@ -63,96 +64,16 @@
                 }
             };
             jLen = this.stylesList.length;
-            //kLen = arr[i].ks.v ? arr[i].ks.v.length :  arr[i].ks[0].s[0].v.length;
             for(j=0;j<jLen;j+=1){
                 if(!this.stylesList[j].closed){
-                    pathNode = document.createElementNS(svgNS, "path");
-                    /*pathNode.__items = [];
-                    pathNode.__items.push(pathNode.createSVGPathSegMovetoAbs(0,0));
-                    pathNode.pathSegList.appendItem(pathNode.__items[0]);
-                    if(arr[i].closed){
-                        kLen += 1;
-                    }
-                    for(k=1;k<kLen;k+=1){
-                        pathNode.__items.push(pathNode.createSVGPathSegCurvetoCubicAbs(0,0,0,0,0,0));
-                        pathNode.pathSegList.appendItem(pathNode.__items[k]);
-                    }*/
-                    data[i].elements.push(pathNode);
-                    this.shape.appendChild(pathNode);
-                    this.stylesList[j].elements.push(pathNode);
-                    this.stylesList[j].datas.push(data[i]);
+                    data[i].styles.push(this.stylesList[j]);
                     if(this.stylesList[j].type == 'st'){
-                        pathNode.setAttribute('fill-opacity',0);
-                        pathNode.setAttribute('stroke-linejoin','round');
-                        pathNode.setAttribute('stroke-linecap','round');
+                        this.stylesList[j].pathElement.setAttribute('fill-opacity',0);
+                        this.stylesList[j].pathElement.setAttribute('stroke-linejoin','round');
+                        this.stylesList[j].pathElement.setAttribute('stroke-linecap','round');
                     }
                 }
             }
-
-        }else if(arr[i].ty == 'rc'){
-            data[i] = {
-                elements : [],
-                renderedFrames : [],
-                lastData : {
-                    roundness: '',
-                    w: '',
-                    h: '',
-                    x: '',
-                    y:'',
-                    o:'',
-                    tr:''
-                }
-            }
-            jLen = this.stylesList.length;
-            for(j=0;j<jLen;j+=1){
-                if(!this.stylesList[j].closed){
-                    if(arr[i].trimmed){
-                        pathNode = document.createElementNS(svgNS, "path");
-                    }else{
-                        pathNode = document.createElementNS(svgNS, "rect");
-                    }
-                    data[i].elements.push(pathNode);
-                    this.shape.appendChild(pathNode);
-                    this.stylesList[j].elements.push(pathNode);
-                    this.stylesList[j].datas.push(data[i]);
-                    if(this.stylesList[j].type == 'st'){
-                        pathNode.setAttribute('fill-opacity',0);
-                        if(arr[i].trimmed){
-                            pathNode.setAttribute('stroke-linejoin','round');
-                            pathNode.setAttribute('stroke-linecap','round');
-                        }
-                    }
-                }
-            }
-
-        }else if(arr[i].ty == 'el'){
-            data[i] = {
-                elements : [],
-                renderedFrames : [],
-                lastData : {
-                    cx: '',
-                    cy: '',
-                    rx: '',
-                    ry: '',
-                    o:'',
-                    tr:''
-                }
-            };
-            jLen = this.stylesList.length;
-            for(j=0;j<jLen;j+=1){
-                if(!this.stylesList[j].closed){
-                    pathNode = document.createElementNS(svgNS, "path");
-                    //pathNode = document.createElementNS(svgNS, "ellipse");
-                    data[i].elements.push(pathNode);
-                    this.shape.appendChild(pathNode);
-                    this.stylesList[j].elements.push(pathNode);
-                    this.stylesList[j].datas.push(data[i]);
-                    if(this.stylesList[j].type == 'st'){
-                        pathNode.setAttribute('fill-opacity',0);
-                    }
-                }
-            }
-
         }
     }
     len = ownArrays.length;
@@ -165,37 +86,21 @@
     return this.shape;
 };
 
-ShapeItemElement.prototype.hideShape = function(items,data){
-    if(!items){
-        items = this.data;
-    }
-    if(!data){
-        data = this.viewData;
-    }
+ShapeItemElement.prototype.hideShape = function(){
     var i, len = this.stylesList.length;
-    var j, jLen;
-    var elements;
-    len = items.length - 1;
-    for(i=len;i>=0;i-=1){
-        if(items[i].ty == 'sh' || items[i].ty == 'el' || items[i].ty == 'rc'){
-            data[i].lastData.o = -1;
-            elements = data[i].elements;
-            jLen = elements.length;
-            for(j=0;j<jLen;j+=1){
-                elements[j].setAttribute('opacity','0');
-                /*elements[i].setAttribute('fill-opacity','0');
-                 elements[i].setAttribute('stroke-opacity','0');*/
-            }
-
-        }else if(items[i].ty == 'gr'){
-            this.hideShape(items[i].it,data[i].it);
-        }
+    for(i=len-1;i>=0;i-=1){
+        this.stylesList[i].pathElement.setAttribute('d','');
     }
 };
 
 ShapeItemElement.prototype.renderShape = function(num,parentTransform,items,data){
+    var i, len;
     if(!items){
         items = this.data;
+        len = this.stylesList.length;
+        for(i=0;i<len;i+=1){
+            this.stylesList[i].d = '';
+        }
     }
     if(!data){
         data = this.viewData;
@@ -203,9 +108,9 @@
     if(this.currentTrim.active){
         this.currentTrim.active = false;
     }
-    this.posCount = 0;
     this.frameNum = num;
-    var i, len;
+    ///
+    ///
     len = items.length - 1;
     var groupTransform,groupMatrix;
     groupTransform = parentTransform;
@@ -245,222 +150,45 @@
             //
         }
     }
+    len = this.stylesList.length;
+    for(i=0;i<len;i+=1){
+        this.stylesList[i].pathElement.setAttribute('d',this.stylesList[i].d);
+    }
+
 };
 
 ShapeItemElement.prototype.renderPath = function(pathData,viewData,num,transform){
     if(!viewData.renderedFrames[this.globalData.frameNum]){
+        ////
+
+        var pathNodes = pathData.renderedData[num].path.pathNodes;
+        if(!pathNodes.v || !pathNodes.v[0]){
+            return;
+        }
+        var pathV = pathNodes.v;
+        var pathO = pathNodes.o;
+        var pathI = pathNodes.i;
+        var k,kLen = pathV.length;
+        var pathStringTransformed = " M"+transform.mat.applyToPointStringified(pathV[0][0],pathV[0][1]);
+        for(k=1;k<kLen;k++){
+            pathStringTransformed += " C"+transform.mat.applyToPointStringified(pathO[k-1][0],pathO[k-1][1]) + " "+transform.mat.applyToPointStringified(pathI[k][0],pathI[k][1]) + " "+transform.mat.applyToPointStringified(pathV[k][0],pathV[k][1]);
+        }
+        if(pathData.closed !== false){
+            pathStringTransformed += " C"+transform.mat.applyToPointStringified(pathO[k-1][0],pathO[k-1][1]) + " "+transform.mat.applyToPointStringified(pathI[0][0],pathI[0][1]) + " "+transform.mat.applyToPointStringified(pathV[0][0],pathV[0][1]);
+        }
+
+        ////
         viewData.renderedFrames[this.globalData.frameNum] = {
-            d: pathData.renderedData[num].path.pathString,
-            tr: 'matrix('+transform.mat.props.join(',')+')',
-            o: transform.opacity
+            dTr: pathStringTransformed
         };
     }
     var renderedFrameData = viewData.renderedFrames[this.globalData.frameNum];
-    var pathString = renderedFrameData.d;
-    var transformString = renderedFrameData.tr;
-    var opacity = renderedFrameData.o;
-    var elements = viewData.elements;
-    var i, len = elements.length;
-    var pathNodes = pathData.renderedData[num].path.pathNodes;
-    var j, jLen = pathNodes.v.length;
-    ////
+    var i, len;
 
-    console.log(transform.mat);
-
-    var pathV = pathNodes.v;
-    var pathO = pathNodes.o;
-    var pathI = pathNodes.i;
-    var k,kLen = pathV.length;
-    var pathStringTransformed = "M"+transform.mat.applyToPointStringified(pathV[0][0],pathV[0][1]);
-    for(k=1;k<kLen;k++){
-        pathStringTransformed += " C"+transform.mat.applyToPointStringified(pathO[k-1][0],pathO[k-1][1]) + " "+transform.mat.applyToPointStringified(pathI[k][0],pathI[k][1]) + " "+transform.mat.applyToPointStringified(pathV[k][0],pathV[k][1]);
-    }
-    if(pathData.closed !== false){
-        pathStringTransformed += " C"+transform.mat.applyToPointStringified(pathO[k-1][0],pathO[k-1][1]) + " "+transform.mat.applyToPointStringified(pathI[0][0],pathI[0][1]) + " "+transform.mat.applyToPointStringified(pathV[0][0],pathV[0][1]);
-    }
-
-    ////
-    var elem, item;
+    len = viewData.styles.length;
     for(i=0;i<len;i+=1){
-        elem = elements[i];
-        /*item = elem.__items[0];
-        if(item.x != pathNodes.v[0][0]){
-            item.x = pathNodes.v[0][0];
-        }
-        if(item.y != pathNodes.v[0][1]){
-            item.y = pathNodes.v[0][1];
-        }
-        for(j = 1; j < jLen ; j +=1){
-            item = elem.__items[j];
-            if(item.x != pathNodes.v[j][0]){
-                item.x = pathNodes.v[j][0];
-            }
-            if(item.y != pathNodes.v[j][1]){
-                item.y = pathNodes.v[j][1];
-            }
-            if(item.x1 != pathNodes.o[j-1][0]){
-                item.x1 = pathNodes.o[j-1][0];
-            }
-            if(item.y1 != pathNodes.o[j-1][1]){
-                item.y1 = pathNodes.o[j-1][1];
-            }
-            if(item.x2 != pathNodes.i[j][0]){
-                item.x2 = pathNodes.i[j][0];
-            }
-            if(item.y2 != pathNodes.i[j][1]){
-                item.y2 = pathNodes.i[j][1];
-            }
-        }
-        if(pathData.closed){
-            item = elem.__items[j];
-            if(item.x != pathNodes.v[0][0]){
-                item.x = pathNodes.v[0][0];
-            }
-            if(item.y != pathNodes.v[0][1]){
-                item.y = pathNodes.v[0][1];
-            }
-            if(item.x1 != pathNodes.o[j-1][0]){
-                item.x1 = pathNodes.o[j-1][0];
-            }
-            if(item.y1 != pathNodes.o[j-1][1]){
-                item.y1 = pathNodes.o[j-1][1];
-            }
-            if(item.x2 != pathNodes.i[0][0]){
-                item.x2 = pathNodes.i[0][0];
-            }
-            if(item.y2 != pathNodes.i[0][1]){
-                item.y2 = pathNodes.i[0][1];
-            }
-        }*/
-        if(viewData.lastData.d != pathString){
-            //elements[i].setAttribute('d',pathString);
-            elements[i].setAttribute('d',pathStringTransformed);
-        }
-        if(viewData.lastData.tr != transformString){
-            //elements[i].setAttribute('transform',transformString);
-        }
-        if(viewData.lastData.o !== opacity){
-            elements[i].setAttribute('opacity',opacity);
-        }
+        viewData.styles[i].d += renderedFrameData.dTr;
     }
-    viewData.lastData.d = pathString;
-    viewData.lastData.tr = transformString;
-    viewData.lastData.o = opacity;
-};
-
-
-ShapeItemElement.prototype.renderEllipse = function(ellipseData,viewData,num,transform){
-    var ellipseAttrs = ellipseData.renderedData[num];
-    if(!viewData.renderedFrames[this.globalData.frameNum]){
-        viewData.renderedFrames[this.globalData.frameNum] = {
-            cx: ellipseAttrs.p[0],
-            cy: ellipseAttrs.p[1],
-            rx: ellipseAttrs.size[0]/2,
-            ry: ellipseAttrs.size[1]/2,
-            tr: 'matrix('+transform.mat.props.join(',')+')',
-            o: transform.opacity
-        };
-    }
-    var renderedFrameData = viewData.renderedFrames[this.globalData.frameNum];
-    var cx = renderedFrameData.cx;
-    var cy = renderedFrameData.cy;
-    var rx = renderedFrameData.rx;
-    var ry = renderedFrameData.ry;
-    var tr = renderedFrameData.tr;
-    var o = renderedFrameData.o;
-
-    var elements = viewData.elements;
-    var i, len = elements.length;
-    for(i=0;i<len;i+=1){
-        if(viewData.lastData.cx != cx){
-            elements[i].setAttribute('cx',cx);
-        }
-        if(viewData.lastData.cy != cy){
-            elements[i].setAttribute('cy',cy);
-        }
-        if(viewData.lastData.rx != rx){
-            elements[i].setAttribute('rx',rx);
-        }
-        if(viewData.lastData.ry != ry){
-            elements[i].setAttribute('ry',ry);
-        }
-        if(viewData.lastData.tr != tr){
-            elements[i].setAttribute('transform',tr);
-        }
-        if(viewData.lastData.o != o){
-            elements[i].setAttribute('opacity',o);
-        }
-    }
-    viewData.lastData.cx = cx;
-    viewData.lastData.cy = cy;
-    viewData.lastData.rx = rx;
-    viewData.lastData.ry = ry;
-    viewData.lastData.tr = tr;
-    viewData.lastData.o = o;
-};
-
-ShapeItemElement.prototype.renderRect = function(rectData,viewData,num,transform){
-    var elements = viewData.elements;
-    var rectAttrs = rectData.renderedData[num];
-    var roundness;
-    if(!viewData.renderedFrames[this.globalData.frameNum]){
-        roundness = rectAttrs.roundness;
-
-        if(roundness > rectAttrs.size[0]/2){
-            roundness = rectAttrs.size[0]/2;
-        }
-        if(roundness > rectAttrs.size[1]/2){
-            roundness = rectAttrs.size[1]/2;
-        }
-        viewData.renderedFrames[this.globalData.frameNum] = {
-            round: roundness,
-            w: rectAttrs.size[0],
-            h: rectAttrs.size[1],
-            x: rectAttrs.position[0] - rectAttrs.size[0]/2,
-            y: rectAttrs.position[1] - rectAttrs.size[1]/2,
-            tr: 'matrix('+transform.mat.props.join(',')+')',
-            o: transform.opacity
-        };
-    }
-    var renderedFrameData = viewData.renderedFrames[this.globalData.frameNum];
-    roundness = renderedFrameData.round;
-    var w = renderedFrameData.w;
-    var h = renderedFrameData.h;
-    var x = renderedFrameData.x;
-    var y = renderedFrameData.y;
-    var tr = renderedFrameData.tr;
-    var o = renderedFrameData.o;
-    var i, len = elements.length;
-    for(i=0;i<len;i+=1){
-        if(viewData.lastData.roundness != roundness){
-            elements[i].setAttribute('rx',roundness);
-            elements[i].setAttribute('ry',roundness);
-        }
-        if(viewData.lastData.w != w){
-            elements[i].setAttribute('width',w);
-        }
-        if(viewData.lastData.h != h){
-            elements[i].setAttribute('height',h);
-        }
-        if(viewData.lastData.x != x){
-            elements[i].setAttribute('x',x);
-        }
-        if(viewData.lastData.y != y){
-            elements[i].setAttribute('y',y);
-        }
-        if(viewData.lastData.tr != tr){
-            elements[i].setAttribute('transform',tr);
-        }
-        if(viewData.lastData.o != o){
-            elements[i].setAttribute('opacity',o);
-        }
-    }
-    viewData.lastData.roundness = roundness;
-    viewData.lastData.w = w;
-    viewData.lastData.h = h;
-    viewData.lastData.x = x;
-    viewData.lastData.y = y;
-    viewData.lastData.o = o;
 };
 
 ShapeItemElement.prototype.renderFill = function(styleData,viewData,num){
@@ -476,17 +204,11 @@
     var renderedFrameData = viewData.renderedFrames[this.globalData.frameNum];
     var c = renderedFrameData.c;
     var o = renderedFrameData.o;
-    var elements = styleElem.elements;
-    var i, len = elements.length;
-    styleElem.pathElement.setAttribute('fill',c);
-    styleElem.pathElement.setAttribute('fill-opacity',o);
-    for(i=0;i<len;i+=1){
-        if(viewData.lastData.c != c){
-            elements[i].setAttribute('fill',c);
-        }
-        if(viewData.lastData.o != o){
-            elements[i].setAttribute('fill-opacity',o);
-        }
+    if(viewData.lastData.c != c){
+        styleElem.pathElement.setAttribute('fill',c);
+    }
+    if(viewData.lastData.o != o){
+        styleElem.pathElement.setAttribute('fill-opacity',o);
     }
     viewData.lastData.c = c;
     viewData.lastData.o = o;
@@ -523,29 +245,21 @@
             }
         }
     }
-
-    var elements = styleElem.elements;
-    var i, len = elements.length;
-    styleElem.pathElement.setAttribute('stroke',c);
-    styleElem.pathElement.setAttribute('stroke-opacity',o);
-    styleElem.pathElement.setAttribute('stroke-width',w);
-    for(i=0;i<len;i+=1){
-        if(viewData.lastData.c != c){
-            elements[i].setAttribute('stroke',c);
+    if(viewData.lastData.c != c){
+        styleElem.pathElement.setAttribute('stroke',c);
+    }
+    if(viewData.lastData.o != o){
+        styleElem.pathElement.setAttribute('stroke-opacity',o);
+    }
+    if(viewData.lastData.w != w){
+        styleElem.pathElement.setAttribute('stroke-width',w);
+    }
+    if(d){
+        if(viewData.lastData.da != dasharray){
+            styleElem.pathElement.setAttribute('stroke-dasharray',dasharray);
         }
-        if(viewData.lastData.o != o){
-            elements[i].setAttribute('stroke-opacity',o);
-        }
-        if(viewData.lastData.w != w){
-            elements[i].setAttribute('stroke-width',w);
-        }
-        if(d){
-            if(viewData.lastData.da != dasharray){
-                elements[i].setAttribute('stroke-dasharray',dasharray);
-            }
-            if(viewData.lastData.do != dashoffset){
-                elements[i].setAttribute('stroke-dashoffset',dashoffset);
-            }
+        if(viewData.lastData.do != dashoffset){
+            styleElem.pathElement.setAttribute('stroke-dashoffset',dashoffset);
         }
     }
     viewData.lastData.c = c;