markers partial
diff --git a/extension/jsx/initializer.jsx b/extension/jsx/initializer.jsx
index 959cc22..e1c3ca7 100644
--- a/extension/jsx/initializer.jsx
+++ b/extension/jsx/initializer.jsx
@@ -15,4 +15,5 @@
 $.evalFile(extensionPath + 'utils/keyframeHelper.jsx');
 $.evalFile(extensionPath + 'utils/maskHelper.jsx');
 $.evalFile(extensionPath + 'utils/timeremapHelper.jsx');
-$.evalFile(extensionPath + 'utils/shapeHelper.jsx');
\ No newline at end of file
+$.evalFile(extensionPath + 'utils/shapeHelper.jsx');
+$.evalFile(extensionPath + 'utils/markerHelper.jsx');
\ No newline at end of file
diff --git a/extension/jsx/renderManager.jsx b/extension/jsx/renderManager.jsx
index 7985494..f763e05 100644
--- a/extension/jsx/renderManager.jsx
+++ b/extension/jsx/renderManager.jsx
@@ -1,5 +1,5 @@
 /*jslint vars: true , plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */
-/*global bm_layerElement, bm_eventDispatcher, bm_sourceHelper, bm_generalUtils, bm_compsManager, app, File*/
+/*global bm_layerElement, bm_eventDispatcher, bm_sourceHelper, bm_generalUtils, bm_compsManager, bm_markerHelper, app, File*/
 var bm_renderManager = (function () {
     'use strict';
     
@@ -88,6 +88,7 @@
         exportData.animation.compWidth = comp.width;
         exportData.animation.compHeight = comp.height;
         ob.renderData.firstFrame = exportData.animation.ff * comp.frameRate;
+        bm_markerHelper.searchMarkers(comp, exportData);
         createLayers(comp, exportData.animation.layers, exportData.animation.frameRate);
         totalLayers = pendingLayers.length;
         currentLayer = 0;
diff --git a/extension/jsx/utils/markerHelper.jsx b/extension/jsx/utils/markerHelper.jsx
new file mode 100644
index 0000000..28ce27b
--- /dev/null
+++ b/extension/jsx/utils/markerHelper.jsx
@@ -0,0 +1,25 @@
+/*jslint vars: true , plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */
+/*global bm_eventDispatcher*/
+var bm_markerHelper = (function () {
+    'use strict';
+    var ob = {};
+    
+    function searchMarkers(comp, ob) {
+        bm_eventDispatcher.log('searching');
+        bm_eventDispatcher.log(comp.marker);
+        if (!(comp.marker && comp.marker.numProperties > 0)) {
+            return;
+        }
+        var markersData = [], markerData, markers = comp.marker, i, len = markers.numProperties, markerElement;
+        for (i = 0; i < len; i += 1) {
+            markerData = {};
+            markerElement = markers(i + 1);
+            bm_eventDispatcher.log(markerElement.duration);
+            markersData.push(markerData);
+        }
+    }
+    
+    ob.searchMarkers = searchMarkers;
+    
+    return ob;
+}());
\ No newline at end of file
diff --git a/player/index.html b/player/index.html
index b1c875d..10e0c41 100644
--- a/player/index.html
+++ b/player/index.html
@@ -37,6 +37,19 @@
 </head>
 <body style="background-color:#ccc; margin: 0px;height: 100%; font-family: sans-serif;font-size: 10px">
 
-<div style="width:800px;height:800px;background-color:#333;display:inline-block;" class="bodymovin" data-bm-path="exports/render/vizual_edge_data.json" data-bm-type="svg" data-bm-loop="true" data-bm-prerender="false"></div>
+<!-- <div style="width:1350px;height:650px;background-color:#faf5d3;display:inline-block;" class="bodymovin" data-bm-path="exports/render/" data-bm-type="svg" data-bm-loop="true" data-bm-prerender="false"></div> -->
+<div style="width:100%;height:100%;background-color:#faf5d3;display:inline-block;" id="bodymovin"></div>
+
+<script>
+    var animData = {
+        wrapper: document.getElementById('bodymovin'),
+        animType: 'svg',
+        loop: true,
+        prerender: false,
+        path: 'exports/letters/full'
+
+    };
+    var anim = bodymovin.loadAnimation(animData);
+</script>
 </body>
 </html>
diff --git a/player/js/animation/AnimationItem.js b/player/js/animation/AnimationItem.js
index 209c9a5..5e2c090 100644
--- a/player/js/animation/AnimationItem.js
+++ b/player/js/animation/AnimationItem.js
@@ -26,6 +26,7 @@
     this.scaleMode = 'fit';
     this.math = Math;
     this.removed = false;
+    this.segments = [];
 };
 
 AnimationItem.prototype.setParams = function(params) {
@@ -126,7 +127,7 @@
     this.totalFrames = Math.floor(this.animationData.animation.totalFrames);
     this.frameRate = this.animationData.animation.frameRate;
     this.firstFrame = Math.round(this.animationData.animation.ff*this.frameRate);
-    /*this.firstFrame = 114;
+    /*this.firstFrame = 211;
     this.totalFrames = 1;*/
     this.frameMult = this.animationData.animation.frameRate / 1000;
     dataManager.completeData(this.animationData);
@@ -272,6 +273,29 @@
     this.setCurrentRawFrameValue(this.currentRawFrame+value);
 };
 
+AnimationItem.prototype.adjustSegment = function(arr){
+    this.totalFrames = arr[1] - arr[0];
+    this.firstFrame = arr[0];
+    this.currentRawFrame = this.firstFrame;
+};
+
+AnimationItem.prototype.playSegments = function (arr,forceFlag) {
+    var i, len = arr.length;
+    for(i=0;i<len;i+=1){
+        this.segments.push(arr[i]);
+    }
+    if(forceFlag){
+        this.adjustSegment(this.segments.shift());
+    }
+};
+
+AnimationItem.prototype.resetSegments = function (forceFlag) {
+    this.segments.push([Math.round(this.animationData.animation.ff*this.frameRate),Math.floor(this.animationData.animation.totalFrames+this.animationData.animation.ff*this.frameRate)]);
+    if(forceFlag){
+        this.adjustSegment(this.segments.shift());
+    }
+};
+
 AnimationItem.prototype.remove = function (name) {
     if(name && this.name != name){
         return;
@@ -289,6 +313,9 @@
 AnimationItem.prototype.setCurrentRawFrameValue = function(value){
     this.currentRawFrame = value;
     if (this.currentRawFrame >= this.totalFrames) {
+        if(this.segments.length){
+            this.adjustSegment(this.segments.shift());
+        }
         if(this.loop === false){
             this.currentRawFrame = this.totalFrames - 1;
             this.gotoFrame();
diff --git a/player/js/elements/ShapeItemElement.js b/player/js/elements/ShapeItemElement.js
index 8225861..51f2a12 100644
--- a/player/js/elements/ShapeItemElement.js
+++ b/player/js/elements/ShapeItemElement.js
@@ -181,27 +181,27 @@
         var pathStringTransformed = '';
         for(i=1;i<len;i+=1){
             if(stops[i-1]){
-                //pathStringTransformed += " M"+transform.mat.applyToPointStringified(stops[i-1][0],stops[i-1][1]);
-                pathStringTransformed += " M"+stops[i-1][0]+','+stops[i-1][1];
+                pathStringTransformed += " M"+bm_rnd(stops[i-1][0])+','+bm_rnd(stops[i-1][1]);
+                //pathStringTransformed += " M"+stops[i-1][0]+','+stops[i-1][1];
             }else if(i==1){
-                //pathStringTransformed += " M"+transform.mat.applyToPointStringified(pathNodes.v[0][0],pathNodes.v[0][1]);
-                pathStringTransformed += " M"+pathNodes.v[0][0]+','+pathNodes.v[0][1];
+                pathStringTransformed += " M"+bm_rnd(pathNodes.v[0][0])+','+bm_rnd(pathNodes.v[0][1]);
+                //pathStringTransformed += " M"+pathNodes.v[0][0]+','+pathNodes.v[0][1];
             }
-            //pathStringTransformed += " C"+transform.mat.applyToPointStringified(pathNodes.o[i-1][0],pathNodes.o[i-1][1]) + " "+transform.mat.applyToPointStringified(pathNodes.i[i][0],pathNodes.i[i][1]) + " "+transform.mat.applyToPointStringified(pathNodes.v[i][0],pathNodes.v[i][1]);
-            pathStringTransformed += " 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];
+            pathStringTransformed += " C"+bm_rnd(pathNodes.o[i-1][0])+','+bm_rnd(pathNodes.o[i-1][1]) + " "+bm_rnd(pathNodes.i[i][0])+','+bm_rnd(pathNodes.i[i][1]) + " "+bm_rnd(pathNodes.v[i][0])+','+bm_rnd(pathNodes.v[i][1]);
+            //pathStringTransformed += " 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];
         }
         if(len == 1){
             if(stops[0]){
-                //pathStringTransformed += " M"+transform.mat.applyToPointStringified(stops[i-1][0],stops[0][1]);
-                pathStringTransformed += " M"+stops[0][0]+','+stops[0][1];
+                pathStringTransformed += " M"+bm_rnd(stops[0][0])+','+bm_rnd(stops[0][1]);
+                //pathStringTransformed += " M"+stops[0][0]+','+stops[0][1];
             }else{
-                //pathStringTransformed += " M"+transform.mat.applyToPointStringified(pathNodes.v[0][0],pathNodes.v[0][1]);
-                pathStringTransformed += " M"+pathNodes.v[0][0]+','+pathNodes.v[0][1];
+                pathStringTransformed += " M"+bm_rnd(pathNodes.v[0][0])+','+bm_rnd(pathNodes.v[0][1]);
+                //pathStringTransformed += " M"+pathNodes.v[0][0]+','+pathNodes.v[0][1];
             }
         }
         if(pathData.closed && !(pathData.trimmed && !pathNodes.c)){
-            //pathStringTransformed += " C"+transform.mat.applyToPointStringified(pathNodes.o[i-1][0],pathNodes.o[i-1][1]) + " "+transform.mat.applyToPointStringified(pathNodes.i[0][0],pathNodes.i[0][1]) + " "+transform.mat.applyToPointStringified(pathNodes.v[0][0],pathNodes.v[0][1]);
-            pathStringTransformed += " 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];
+            pathStringTransformed += " C"+bm_rnd(pathNodes.o[i-1][0])+','+bm_rnd(pathNodes.o[i-1][1]) + " "+bm_rnd(pathNodes.i[0][0])+','+bm_rnd(pathNodes.i[0][1]) + " "+bm_rnd(pathNodes.v[0][0])+','+bm_rnd(pathNodes.v[0][1]);
+            //pathStringTransformed += " 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];
         }
 
         viewData.renderedFrames[this.globalData.frameNum] = {
diff --git a/player/js/elements/canvasElements/CVMaskElement.js b/player/js/elements/canvasElements/CVMaskElement.js
index bf9d5e7..60f5c79 100644
--- a/player/js/elements/canvasElements/CVMaskElement.js
+++ b/player/js/elements/canvasElements/CVMaskElement.js
@@ -35,11 +35,14 @@
 
 CVMaskElement.prototype.drawShape = function (path, data) {
     var j, jLen = data.v.length;
-    path.moveTo(data.v[0][0], data.v[0][1]);
+    path.moveTo(bm_rnd(data.v[0][0]), bm_rnd(data.v[0][1]));
+    //path.moveTo(data.v[0][0], data.v[0][1]);
     for (j = 1; j < jLen; j++) {
-        path.bezierCurveTo(data.o[j - 1][0], data.o[j - 1][1], data.i[j][0], data.i[j][1], data.v[j][0], data.v[j][1]);
+        //path.bezierCurveTo(data.o[j - 1][0], data.o[j - 1][1], data.i[j][0], data.i[j][1], data.v[j][0], data.v[j][1]);
+        path.bezierCurveTo(bm_rnd(data.o[j - 1][0]), bm_rnd(data.o[j - 1][1]), bm_rnd(data.i[j][0]), bm_rnd(data.i[j][1]), bm_rnd(data.v[j][0]), bm_rnd(data.v[j][1]));
     }
-    path.bezierCurveTo(data.o[j - 1][0], data.o[j - 1][1], data.i[0][0], data.i[0][1], data.v[0][0], data.v[0][1]);
+    //path.bezierCurveTo(data.o[j - 1][0], data.o[j - 1][1], data.i[0][0], data.i[0][1], data.v[0][0], data.v[0][1]);
+    path.bezierCurveTo(bm_rnd(data.o[j - 1][0]), bm_rnd(data.o[j - 1][1]), bm_rnd(data.i[0][0]), bm_rnd(data.i[0][1]), bm_rnd(data.v[0][0]), bm_rnd(data.v[0][1]));
 };
 
 CVMaskElement.prototype.createInvertedMask = function(path){
diff --git a/player/js/elements/canvasElements/CVShapeItemElement.js b/player/js/elements/canvasElements/CVShapeItemElement.js
index 8d00ad7..8f3a10c 100644
--- a/player/js/elements/canvasElements/CVShapeItemElement.js
+++ b/player/js/elements/canvasElements/CVShapeItemElement.js
@@ -1,4 +1,14 @@
 function CVShapeItemElement(data,mainFlag,globalData){
+    this.lcEnum = {
+        '1': 'butt',
+        '2': 'round',
+        '3': 'butt'
+    };
+    this.ljEnum = {
+        '1': 'miter',
+        '2': 'round',
+        '3': 'bevel'
+    };
     this.data = data;
     this.globalData = globalData;
     this.canvasContext = globalData.canvasContext;
@@ -34,6 +44,11 @@
             }else{
                 styleData.type = 'stroke';
                 styleData.width = 0;
+                styleData.lc = this.lcEnum[this.data[i].lc] || 'round';
+                styleData.lj = this.ljEnum[this.data[i].lj] || 'round';
+                if(this.data[i].lj == 1) {
+                    styleData.ml = this.data[i].ml;
+                }
             }
             this.stylesPool.push(styleData);
         }
@@ -51,8 +66,6 @@
     var i, len = stylesList.length;
     var ctx = this.canvasContext;
     this.globalData.renderer.save();
-    ctx.lineCap = 'round';
-    ctx.lineJoin = 'round';
     for(i=0;i<len;i+=1){
         if(stylesList[i].type == 'stroke'){
             if(stylesList[i].opacity != 1){
@@ -60,6 +73,9 @@
                 this.globalData.renderer.ctxOpacity(stylesList[i].opacity);
                 ///ctx.globalAlpha *= stylesList[i].opacity;
             }
+            ctx.lineCap = stylesList[i].lc;
+            ctx.lineJoin = stylesList[i].lj;
+            ctx.miterLimit = stylesList[i].ml;
             ctx.strokeStyle = stylesList[i].value;
             ctx.lineWidth = stylesList[i].width;
             if(stylesList[i].dasharray){
@@ -209,21 +225,27 @@
     var stops = pathNodes.s ? pathNodes.s : [];
     for(i=1;i<len;i+=1){
         if(stops[i-1]){
-            path2d.moveTo(stops[i-1][0],stops[i-1][1]);
+            path2d.moveTo(bm_rnd(stops[i-1][0]),bm_rnd(stops[i-1][1]));
+            //path2d.moveTo(stops[i-1][0],stops[i-1][1]);
         }else if(i==1){
-            path2d.moveTo(pathNodes.v[0][0],pathNodes.v[0][1]);
+            path2d.moveTo(bm_rnd(pathNodes.v[0][0]),bm_rnd(pathNodes.v[0][1]));
+            //path2d.moveTo(pathNodes.v[0][0],pathNodes.v[0][1]);
         }
-        path2d.bezierCurveTo(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]);
+        path2d.bezierCurveTo(bm_rnd(pathNodes.o[i-1][0]),bm_rnd(pathNodes.o[i-1][1]),bm_rnd(pathNodes.i[i][0]),bm_rnd(pathNodes.i[i][1]),bm_rnd(pathNodes.v[i][0]),bm_rnd(pathNodes.v[i][1]));
+        //path2d.bezierCurveTo(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]);
     }
     if(len == 1){
         if(stops[0]){
-            path2d.moveTo(stops[0][0],stops[0][1]);
+            path2d.moveTo(bm_rnd(stops[0][0]),bm_rnd(stops[0][1]));
+            //path2d.moveTo(stops[0][0],stops[0][1]);
         }else{
-            path2d.moveTo(pathNodes.v[0][0],pathNodes.v[0][1]);
+            path2d.moveTo(bm_rnd(pathNodes.v[0][0]),bm_rnd(pathNodes.v[0][1]));
+            //path2d.moveTo(pathNodes.v[0][0],pathNodes.v[0][1]);
         }
     }
     if(data.closed && !(data.trimmed && !pathNodes.c)){
-        path2d.bezierCurveTo(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]);
+        path2d.bezierCurveTo(bm_rnd(pathNodes.o[i-1][0]),bm_rnd(pathNodes.o[i-1][1]),bm_rnd(pathNodes.i[0][0]),bm_rnd(pathNodes.i[0][1]),bm_rnd(pathNodes.v[0][0]),bm_rnd(pathNodes.v[0][1]));
+        //path2d.bezierCurveTo(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]);
     }
     this.addPathToStyles(path2d);
 };
diff --git a/player/js/mask.js b/player/js/mask.js
index afcd868..bb5b3ea 100644
--- a/player/js/mask.js
+++ b/player/js/mask.js
@@ -141,12 +141,15 @@
         len = pathNodes.v.length;
             for(i=1;i<len;i+=1){
                 if(i==1){
-                    pathString += " M"+pathNodes.v[0][0]+','+pathNodes.v[0][1];
+                    //pathString += " M"+pathNodes.v[0][0]+','+pathNodes.v[0][1];
+                    pathString += " M"+bm_rnd(pathNodes.v[0][0])+','+bm_rnd(pathNodes.v[0][1]);
                 }
-                pathString += " C"+pathNodes.o[i-1][0]+','+pathNodes.o[i-1][1] + " "+pathNodes.i[i][0]+','+pathNodes.i[i][1] + " "+pathNodes.v[i][0]+','+pathNodes.v[i][1];
+                //pathString += " C"+pathNodes.o[i-1][0]+','+pathNodes.o[i-1][1] + " "+pathNodes.i[i][0]+','+pathNodes.i[i][1] + " "+pathNodes.v[i][0]+','+pathNodes.v[i][1];
+                pathString += " C"+bm_rnd(pathNodes.o[i-1][0])+','+bm_rnd(pathNodes.o[i-1][1]) + " "+bm_rnd(pathNodes.i[i][0])+','+bm_rnd(pathNodes.i[i][1]) + " "+bm_rnd(pathNodes.v[i][0])+','+bm_rnd(pathNodes.v[i][1]);
             }
             if(pathData.cl){
-                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];
+                //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];
+                pathString += " C"+bm_rnd(pathNodes.o[i-1][0])+','+bm_rnd(pathNodes.o[i-1][1]) + " "+bm_rnd(pathNodes.i[0][0])+','+bm_rnd(pathNodes.i[0][1]) + " "+bm_rnd(pathNodes.v[0][0])+','+bm_rnd(pathNodes.v[0][1]);
             }
         pathNodes.__renderedString = pathString;
     }else{
diff --git a/player/js/utils/DataManager.js b/player/js/utils/DataManager.js
index 174d7a5..e6ae6b3 100644
--- a/player/js/utils/DataManager.js
+++ b/player/js/utils/DataManager.js
@@ -53,9 +53,9 @@
             lastFrame = -1;
             if(layerData.tm){
                 layerData.trmp = layerData.tm;
-                var timeValues = new Array(layerFrames);
+                var timeValues = new Array(Math.round(layerFrames));
                 for(j=0 ; j<layerFrames; j+=1){
-                    timeValues.push(Math.floor(getInterpolatedValue(layerData.tm,j,offsetFrame)*frameRate));
+                    timeValues[j] = Math.floor(getInterpolatedValue(layerData.tm,j,offsetFrame)*frameRate);
                 }
                 layerData.tm = timeValues;
             }
diff --git a/player/js/utils/common.js b/player/js/utils/common.js
index c5f923b..157d628 100644
--- a/player/js/utils/common.js
+++ b/player/js/utils/common.js
@@ -1,5 +1,6 @@
 var subframeEnabled = false;
 var cachedColors = {};
+var bm_rnd = Math.round;
 
 function styleDiv(element){
     element.style.position = 'absolute';