Canvas worker
diff --git a/player/index.html b/player/index.html
index dc7d02c..39998cf 100644
--- a/player/index.html
+++ b/player/index.html
@@ -38,7 +38,9 @@
     <script src="js/utils/functionExtensions.js"></script>
     <script src="js/utils/bez.js"></script>
     <script src="js/utils/DataManager.js"></script>
+    <script src="js/utils/DataManagerWorkerOverrides.js" data-builds="canvas_worker"></script>
     <script src="js/utils/FontManager.js"></script>
+    <script src="js/utils/FontManagerWorkerOverride.js" data-builds="canvas_worker"></script>
     <script src="js/utils/PropertyFactory.js"></script>
     <script src="js/utils/TransformProperty.js"></script>
     <script src="js/utils/shapes/ShapePath.js"></script>
@@ -51,10 +53,12 @@
     <script src="js/utils/shapes/DashProperty.js"></script>
     <script src="js/utils/shapes/GradientProperty.js"></script>
     <script src="js/utils/shapes/shapePathBuilder.js"></script>
-    <script src="js/utils/imagePreloader.js"></script>
+    <script src="js/utils/imagePreloader.js" data-builds="full,canvas,canvas_light,html,html_light,svg,svg_light"></script>
+    <script src="js/utils/imagePreloaderWorkerOverride.js" data-builds="canvas_worker"></script>
     <script src="js/utils/featureSupport.js"></script>
     <script src="js/utils/filters.js"></script>
     <script src="js/utils/asset_loader.js"></script>
+    <script src="js/utils/asset_loader_worker_override.js" data-builds="canvas_worker"></script>
     <script src="js/utils/text/TextAnimatorProperty.js"></script>
     <script src="js/utils/text/TextAnimatorDataProperty.js"></script>
     <script src="js/utils/text/LetterProps.js"></script>
@@ -69,7 +73,8 @@
     <script src="js/utils/pooling/bezier_length_pool.js"></script>
     <script src="js/renderers/BaseRenderer.js"></script>
     <script src="js/renderers/SVGRenderer.js"></script>
-    <script src="js/renderers/CanvasRenderer.js" data-builds="full,canvas,canvas_light"></script>
+    <script src="js/renderers/CanvasRenderer.js" data-builds="full,canvas,canvas_light,canvas_worker"></script>
+    <script src="js/renderers/CanvasRendererWorkerOverride.js" data-builds="canvas_worker"></script>
     <script src="js/renderers/HybridRenderer.js" data-builds="full,html,html_light"></script>
     <script src="js/mask.js"></script>
     <script src="js/elements/helpers/HierarchyElement.js"></script>
@@ -88,7 +93,7 @@
     <script src="js/elements/helpers/shapes/ShapeGroupData.js"></script>
     <script src="js/elements/helpers/shapes/SVGElementsRenderer.js" data-builds="full,svg,svg_light,html,html_light"></script>
     <script src="js/elements/helpers/shapes/ShapeTransformManager.js"></script>
-    <script src="js/elements/helpers/shapes/CVShapeData.js" data-builds="full,canvas,canvas_light"></script>
+    <script src="js/elements/helpers/shapes/CVShapeData.js" data-builds="full,canvas,canvas_light,canvas_worker"></script>
     <script src="js/elements/BaseElement.js"></script>
     <script src="js/elements/NullElement.js"></script>
     <script src="js/elements/svgElements/SVGBaseElement.js"></script>
@@ -109,15 +114,15 @@
     <script src="js/elements/svgElements/effects/SVGDropShadowEffect.js" data-builds="full,svg,svg_light,html,html_light"></script>
     <script src="js/elements/svgElements/effects/SVGMatte3Effect.js" data-builds="full,svg,svg_light,html,html_light"></script>
     <script src="js/elements/svgElements/SVGEffects.js" data-builds="full,svg,svg_light,html,html_light"></script>
-    <script src="js/elements/canvasElements/CVContextData.js" data-builds="full,canvas,canvas_light"></script>
-    <script src="js/elements/canvasElements/CVBaseElement.js" data-builds="full,canvas,canvas_light"></script>
+    <script src="js/elements/canvasElements/CVContextData.js" data-builds="full,canvas,canvas_light,canvas_worker"></script>
+    <script src="js/elements/canvasElements/CVBaseElement.js" data-builds="full,canvas,canvas_light,canvas_worker"></script>
     <script src="js/elements/canvasElements/CVImageElement.js" data-builds="full,canvas,canvas_light"></script>
-    <script src="js/elements/canvasElements/CVCompElement.js" data-builds="full,canvas,canvas_light"></script>
-    <script src="js/elements/canvasElements/CVMaskElement.js" data-builds="full,canvas,canvas_light"></script>
-    <script src="js/elements/canvasElements/CVShapeElement.js" data-builds="full,canvas,canvas_light"></script>
-    <script src="js/elements/canvasElements/CVSolidElement.js" data-builds="full,canvas,canvas_light"></script>
+    <script src="js/elements/canvasElements/CVCompElement.js" data-builds="full,canvas,canvas_light,canvas_worker"></script>
+    <script src="js/elements/canvasElements/CVMaskElement.js" data-builds="full,canvas,canvas_light,canvas_worker"></script>
+    <script src="js/elements/canvasElements/CVShapeElement.js" data-builds="full,canvas,canvas_light,canvas_worker"></script>
+    <script src="js/elements/canvasElements/CVSolidElement.js" data-builds="full,canvas,canvas_light,canvas_worker"></script>
     <script src="js/elements/canvasElements/CVTextElement.js" data-builds="full,canvas,canvas_light"></script>
-    <script src="js/elements/canvasElements/CVEffects.js" data-builds="full,canvas,canvas_light,html,html_light"></script>
+    <script src="js/elements/canvasElements/CVEffects.js" data-builds="full,canvas,canvas_light,html,html_light,canvas_worker"></script>
     <script src="js/elements/htmlElements/HBaseElement.js" data-builds="full,html,html_light"></script>
     <script src="js/elements/htmlElements/HSolidElement.js" data-builds="full,html,html_light"></script>
     <script src="js/elements/htmlElements/HCompElement.js" data-builds="full,html,html_light"></script>
@@ -127,26 +132,28 @@
     <script src="js/elements/htmlElements/HCameraElement.js" data-builds="full,html,html_light"></script>
     <script src="js/elements/htmlElements/HEffects.js" data-builds="full,html,html_light"></script>
     <script src="js/animation/AnimationManager.js"></script>
+    <script src="js/animation/AnimationManagerWorkerOverride.js" data-builds="canvas_worker"></script>
     <script src="js/animation/AnimationItem.js"></script>
+    <script src="js/animation/AnimationItemWorkerOverride.js" data-builds="canvas_worker"></script>
     <!-- Expressions -->
-    <script src="js/utils/expressions/Expressions.js" data-builds="full,svg,canvas,html"></script>
-    <script src="js/utils/expressions/ExpressionManager.js" data-builds="full,svg,canvas,html"></script>
-    <script src="js/utils/expressions/expressionHelpers.js" data-builds="full,svg,canvas,html"></script>
-    <script src="js/utils/expressions/ExpressionPropertyDecorator.js" data-builds="full,svg,canvas,html"></script>
-    <script src="js/utils/expressions/ExpressionTextPropertyDecorator.js" data-builds="full,svg,canvas,html"></script>
-    <script src="js/utils/expressions/ShapeInterface.js" data-builds="full,svg,canvas,html"></script>
-    <script src="js/utils/expressions/TextInterface.js" data-builds="full,svg,canvas,html"></script>
-    <script src="js/utils/expressions/LayerInterface.js" data-builds="full,svg,canvas,html"></script>
-    <script src="js/utils/expressions/CompInterface.js" data-builds="full,svg,canvas,html"></script>
-    <script src="js/utils/expressions/TransformInterface.js" data-builds="full,svg,canvas,html"></script>
-    <script src="js/utils/expressions/ProjectInterface.js" data-builds="full,svg,canvas,html"></script>
-    <script src="js/utils/expressions/EffectInterface.js" data-builds="full,svg,canvas,html"></script>
-    <script src="js/utils/expressions/MaskInterface.js" data-builds="full,svg,canvas,html"></script>
-    <script src="js/utils/expressions/ExpressionValueFactory.js" data-builds="full,svg,canvas,html"></script>
-    <script src="js/utils/expressions/TextSelectorPropertyDecorator.js" data-builds="full,svg,canvas,html"></script>
-    <script src="js/effects/SliderEffect.js" data-builds="full,svg,canvas,html"></script>
+    <script src="js/utils/expressions/Expressions.js" data-builds="full,svg,canvas,html,canvas_worker"></script>
+    <script src="js/utils/expressions/ExpressionManager.js" data-builds="full,svg,canvas,html,canvas_worker"></script>
+    <script src="js/utils/expressions/expressionHelpers.js" data-builds="full,svg,canvas,html,canvas_worker"></script>
+    <script src="js/utils/expressions/ExpressionPropertyDecorator.js" data-builds="full,svg,canvas,html,canvas_worker"></script>
+    <script src="js/utils/expressions/ExpressionTextPropertyDecorator.js" data-builds="full,svg,canvas,html,canvas_worker"></script>
+    <script src="js/utils/expressions/ShapeInterface.js" data-builds="full,svg,canvas,html,canvas_worker"></script>
+    <script src="js/utils/expressions/TextInterface.js" data-builds="full,svg,canvas,html,canvas_worker"></script>
+    <script src="js/utils/expressions/LayerInterface.js" data-builds="full,svg,canvas,html,canvas_worker"></script>
+    <script src="js/utils/expressions/CompInterface.js" data-builds="full,svg,canvas,html,canvas_worker"></script>
+    <script src="js/utils/expressions/TransformInterface.js" data-builds="full,svg,canvas,html,canvas_worker"></script>
+    <script src="js/utils/expressions/ProjectInterface.js" data-builds="full,svg,canvas,html,canvas_worker"></script>
+    <script src="js/utils/expressions/EffectInterface.js" data-builds="full,svg,canvas,html,canvas_worker"></script>
+    <script src="js/utils/expressions/MaskInterface.js" data-builds="full,svg,canvas,html,canvas_worker"></script>
+    <script src="js/utils/expressions/ExpressionValueFactory.js" data-builds="full,svg,canvas,html,canvas_worker"></script>
+    <script src="js/utils/expressions/TextSelectorPropertyDecorator.js" data-builds="full,svg,canvas,html,canvas_worker"></script>
+    <script src="js/effects/SliderEffect.js" data-builds="full,svg,canvas,html,canvas_worker"></script>
     <script src="js/effects/EffectsManagerPlaceholder.js" ></script>
-    <script src="js/EffectsManager.js" data-builds="full,svg,canvas,html"></script>
+    <script src="js/EffectsManager.js" data-builds="full,svg,canvas,html,canvas_worker"></script>
     <!-- end Expressions -->
     <!-- endbuild -->
     <script src="js/module.js" ></script>
diff --git a/player/js/animation/AnimationItemWorkerOverride.js b/player/js/animation/AnimationItemWorkerOverride.js
new file mode 100644
index 0000000..577d66b
--- /dev/null
+++ b/player/js/animation/AnimationItemWorkerOverride.js
@@ -0,0 +1,134 @@
+AnimationItem.prototype.setParams = function(params) {
+    if(params.context){
+        this.context = params.context;
+    }
+    var animType = params.animType ? params.animType : params.renderer ? params.renderer : 'svg';
+    switch(animType){
+        case 'canvas':
+            this.renderer = new CanvasRenderer(this, params.rendererSettings);
+            break;
+        default:
+            throw new Error('Only canvas renderer is supported when using worker.');
+            break;
+    }
+    this.renderer.setProjectInterface(this.projectInterface);
+    this.animType = animType;
+
+    if(params.loop === '' || params.loop === null){
+    }else if(params.loop === false){
+        this.loop = false;
+    }else if(params.loop === true){
+        this.loop = true;
+    }else{
+        this.loop = parseInt(params.loop);
+    }
+    this.autoplay = 'autoplay' in params ? params.autoplay : true;
+    this.name = params.name ? params.name :  '';
+    this.autoloadSegments = params.hasOwnProperty('autoloadSegments') ? params.autoloadSegments :  true;
+    this.assetsPath = null;
+    if(params.animationData){
+        this.configAnimation(params.animationData);
+    }else if(params.path){
+        throw new Error('Canvas worker renderer cannot load animation from url');
+    }
+};
+
+AnimationItem.prototype.setData = function (wrapper, animationData) {
+    throw new Error('Cannot set data on wrapper for canvas worker renderer');
+};
+
+AnimationItem.prototype.includeLayers = function(data) {
+    if(data.op > this.animationData.op){
+        this.animationData.op = data.op;
+        this.totalFrames = Math.floor(data.op - this.animationData.ip);
+    }
+    var layers = this.animationData.layers;
+    var i, len = layers.length;
+    var newLayers = data.layers;
+    var j, jLen = newLayers.length;
+    for(j=0;j<jLen;j+=1){
+        i = 0;
+        while(i<len){
+            if(layers[i].id == newLayers[j].id){
+                layers[i] = newLayers[j];
+                break;
+            }
+            i += 1;
+        }
+    }
+    this.animationData.__complete = false;
+    dataManager.completeData(this.animationData,this.renderer.globalData.fontManager);
+    this.renderer.includeLayers(data.layers);
+    if(expressionsPlugin){
+        expressionsPlugin.initExpressions(this);
+    }
+    this.loadNextSegment();
+};
+
+AnimationItem.prototype.loadNextSegment = function() {
+    var segments = this.animationData.segments;
+    if(!segments || segments.length === 0 || !this.autoloadSegments){
+        this.timeCompleted = this.totalFrames;
+        return;
+    }
+    throw new Error('Cannot load multiple segments in worker.');
+};
+
+AnimationItem.prototype.loadSegments = function() {
+    var segments = this.animationData.segments;
+    if(!segments) {
+        this.timeCompleted = this.totalFrames;
+    }
+    this.loadNextSegment();
+};
+
+AnimationItem.prototype.imagesLoaded = null;
+
+AnimationItem.prototype.preloadImages = null;
+
+AnimationItem.prototype.configAnimation = function (animData) {
+    if(!this.renderer){
+        return;
+    }
+    this.animationData = animData;
+    this.totalFrames = Math.floor(this.animationData.op - this.animationData.ip);
+    this.renderer.configAnimation(animData);
+    if(!animData.assets){
+        animData.assets = [];
+    }
+    this.renderer.searchExtraCompositions(animData.assets);
+
+    this.assets = this.animationData.assets;
+    this.frameRate = this.animationData.fr;
+    this.firstFrame = Math.round(this.animationData.ip);
+    this.frameMult = this.animationData.fr / 1000;
+    this.loadSegments();
+    this.updaFrameModifier();
+    this.checkLoaded();
+};
+
+AnimationItem.prototype.waitForFontsLoaded = null;
+
+AnimationItem.prototype.checkLoaded = function () {
+    if (!this.isLoaded) {
+        this.isLoaded = true;
+        dataManager.completeData(this.animationData, null);
+        if(expressionsPlugin){
+            expressionsPlugin.initExpressions(this);
+        }
+        this.renderer.initItems();
+        this.gotoFrame();
+    }
+};
+
+AnimationItem.prototype.destroy = function (name) {
+    if ((name && this.name != name) || !this.renderer) {
+        return;
+    }
+    this.renderer.destroy();
+    this._cbs = null;
+    this.onEnterFrame = this.onLoopComplete = this.onComplete = this.onSegmentStart = this.onDestroy = null;
+    this.renderer = null;
+};
+
+AnimationItem.prototype.getPath = null;
diff --git a/player/js/animation/AnimationManagerWorkerOverride.js b/player/js/animation/AnimationManagerWorkerOverride.js
new file mode 100644
index 0000000..136ab65
--- /dev/null
+++ b/player/js/animation/AnimationManagerWorkerOverride.js
@@ -0,0 +1,197 @@
+animationManager = (function(){
+    var moduleOb = {};
+    var registeredAnimations = [];
+    var initTime = 0;
+    var len = 0;
+    var playingAnimationsNum = 0;
+    var _stopped = true;
+    var _isFrozen = false;
+
+    function removeElement(ev){
+        var i = 0;
+        var animItem = ev.target;
+        while(i<len) {
+            if (registeredAnimations[i].animation === animItem) {
+                registeredAnimations.splice(i, 1);
+                i -= 1;
+                len -= 1;
+                if(!animItem.isPaused){
+                    subtractPlayingCount();
+                }
+            }
+            i += 1;
+        }
+    }
+
+    function registerAnimation(element, animationData){
+        if(!element){
+            return null;
+        }
+        var i=0;
+        while(i<len){
+            if(registeredAnimations[i].elem == element && registeredAnimations[i].elem !== null ){
+                return registeredAnimations[i].animation;
+            }
+            i+=1;
+        }
+        var animItem = new AnimationItem();
+        setupAnimation(animItem, element);
+        animItem.setData(element, animationData);
+        return animItem;
+    }
+
+    function getRegisteredAnimations() {
+        var i, len = registeredAnimations.length;
+        var animations = [];
+        for(i = 0; i < len; i += 1) {
+            animations.push(registeredAnimations[i].animation);
+        }
+        return animations;
+    }
+
+    function addPlayingCount(){
+        playingAnimationsNum += 1;
+        activate();
+    }
+
+    function subtractPlayingCount(){
+        playingAnimationsNum -= 1;
+    }
+
+    function setupAnimation(animItem, element){
+        animItem.addEventListener('destroy',removeElement);
+        animItem.addEventListener('_active',addPlayingCount);
+        animItem.addEventListener('_idle',subtractPlayingCount);
+        registeredAnimations.push({elem: element,animation:animItem});
+        len += 1;
+    }
+
+    function loadAnimation(params){
+        var animItem = new AnimationItem();
+        setupAnimation(animItem, null);
+        animItem.setParams(params);
+        return animItem;
+    }
+
+
+    function setSpeed(val,animation){
+        var i;
+        for(i=0;i<len;i+=1){
+            registeredAnimations[i].animation.setSpeed(val, animation);
+        }
+    }
+
+    function setDirection(val, animation){
+        var i;
+        for(i=0;i<len;i+=1){
+            registeredAnimations[i].animation.setDirection(val, animation);
+        }
+    }
+
+    function play(animation){
+        var i;
+        for(i=0;i<len;i+=1){
+            registeredAnimations[i].animation.play(animation);
+        }
+    }
+    function resume(nowTime) {
+        var elapsedTime = nowTime - initTime;
+        var i;
+        for(i=0;i<len;i+=1){
+            registeredAnimations[i].animation.advanceTime(elapsedTime);
+        }
+        initTime = nowTime;
+        if(playingAnimationsNum && !_isFrozen) {
+            requestAnimationFrame(resume);
+        } else {
+            _stopped = true;
+        }
+    }
+
+    function first(nowTime){
+        initTime = nowTime;
+        requestAnimationFrame(resume);
+    }
+
+    function pause(animation) {
+        var i;
+        for(i=0;i<len;i+=1){
+            registeredAnimations[i].animation.pause(animation);
+        }
+    }
+
+    function goToAndStop(value,isFrame,animation) {
+        var i;
+        for(i=0;i<len;i+=1){
+            registeredAnimations[i].animation.goToAndStop(value,isFrame,animation);
+        }
+    }
+
+    function stop(animation) {
+        var i;
+        for(i=0;i<len;i+=1){
+            registeredAnimations[i].animation.stop(animation);
+        }
+    }
+
+    function togglePause(animation) {
+        var i;
+        for(i=0;i<len;i+=1){
+            registeredAnimations[i].animation.togglePause(animation);
+        }
+    }
+
+    function destroy(animation) {
+        var i;
+        for(i=(len-1);i>=0;i-=1){
+            registeredAnimations[i].animation.destroy(animation);
+        }
+    }
+
+    function searchAnimations(animationData, standalone, renderer){
+        throw new Error('Cannot access DOM from worker thread');
+    }
+
+    function resize(){
+        var i;
+        for(i=0;i<len;i+=1){
+            registeredAnimations[i].animation.resize();
+        }
+    }
+
+    function activate(){
+        if(!_isFrozen && playingAnimationsNum){
+            if(_stopped) {
+                requestAnimationFrame(first);
+                _stopped = false;
+            }
+        }
+    }
+
+    function freeze() {
+        _isFrozen = true;
+    }
+
+    function unfreeze() {
+        _isFrozen = false;
+        activate();
+    }
+
+    moduleOb.registerAnimation = registerAnimation;
+    moduleOb.loadAnimation = loadAnimation;
+    moduleOb.setSpeed = setSpeed;
+    moduleOb.setDirection = setDirection;
+    moduleOb.play = play;
+    moduleOb.pause = pause;
+    moduleOb.stop = stop;
+    moduleOb.togglePause = togglePause;
+    moduleOb.searchAnimations = searchAnimations;
+    moduleOb.resize = resize;
+    //moduleOb.start = start;
+    moduleOb.goToAndStop = goToAndStop;
+    moduleOb.destroy = destroy;
+    moduleOb.freeze = freeze;
+    moduleOb.unfreeze = unfreeze;
+    moduleOb.getRegisteredAnimations = getRegisteredAnimations;
+    return moduleOb;
+}());
diff --git a/player/js/module_worker.js b/player/js/module_worker.js
new file mode 100644
index 0000000..12b1d58
--- /dev/null
+++ b/player/js/module_worker.js
@@ -0,0 +1,77 @@
+var lottiejs = (function(window) {
+    "use strict";
+    /*<%= contents %>*/
+    var lottiejs = {};
+
+    var _isFrozen = false;
+
+    function loadAnimation(params) {
+        return animationManager.loadAnimation(params);
+    }
+
+    function setQuality(value) {
+        if (typeof value === 'string') {
+            switch (value) {
+                case 'high':
+                    defaultCurveSegments = 200;
+                    break;
+                case 'medium':
+                    defaultCurveSegments = 50;
+                    break;
+                case 'low':
+                    defaultCurveSegments = 10;
+                    break;
+            }
+        } else if (!isNaN(value) && value > 1) {
+            defaultCurveSegments = value;
+        }
+        if (defaultCurveSegments >= 50) {
+            roundValues(false);
+        } else {
+            roundValues(true);
+        }
+    }
+
+    lottiejs.play = animationManager.play;
+    lottiejs.pause = animationManager.pause;
+    lottiejs.togglePause = animationManager.togglePause;
+    lottiejs.setSpeed = animationManager.setSpeed;
+    lottiejs.setDirection = animationManager.setDirection;
+    lottiejs.stop = animationManager.stop;
+    lottiejs.registerAnimation = animationManager.registerAnimation;
+    lottiejs.loadAnimation = loadAnimation;
+    lottiejs.resize = animationManager.resize;
+    lottiejs.goToAndStop = animationManager.goToAndStop;
+    lottiejs.destroy = animationManager.destroy;
+    lottiejs.setQuality = setQuality;
+    lottiejs.freeze = animationManager.freeze;
+    lottiejs.unfreeze = animationManager.unfreeze;
+    lottiejs.getRegisteredAnimations = animationManager.getRegisteredAnimations;
+    lottiejs.__getFactory = getFactory;
+    lottiejs.version = '[[BM_VERSION]]';
+
+    var renderer = '';
+    return lottiejs;
+})({});
+
+var animations = [];
+
+var onmessage = function(evt) {
+    var canvas = evt.data.canvas;
+    var params = evt.data.params;
+    var ctx = canvas.getContext("2d");
+    var animation = lottiejs.loadAnimation({
+        renderer: 'canvas',
+        loop: evt.data.loop,
+        autoplay: true,
+        animationData: evt.data.animationData,
+        rendererSettings: {
+            context: ctx,
+            scaleMode: 'noScale',
+            clearCanvas: true
+        }
+    });
+    animations.push(animation);
+    animation.play();
+};
+
diff --git a/player/js/renderers/CanvasRendererWorkerOverride.js b/player/js/renderers/CanvasRendererWorkerOverride.js
new file mode 100644
index 0000000..dd11758
--- /dev/null
+++ b/player/js/renderers/CanvasRendererWorkerOverride.js
@@ -0,0 +1,42 @@
+CanvasRenderer.prototype.configAnimation = function(animData){
+    if(this.animationItem.wrapper){
+        this.animationItem.container = createTag('canvas');
+        this.animationItem.container.style.width = '100%';
+        this.animationItem.container.style.height = '100%';
+        //this.animationItem.container.style.transform = 'translate3d(0,0,0)';
+        //this.animationItem.container.style.webkitTransform = 'translate3d(0,0,0)';
+        this.animationItem.container.style.transformOrigin = this.animationItem.container.style.mozTransformOrigin = this.animationItem.container.style.webkitTransformOrigin = this.animationItem.container.style['-webkit-transform'] = "0px 0px 0px";
+        this.animationItem.wrapper.appendChild(this.animationItem.container);
+        this.canvasContext = this.animationItem.container.getContext('2d');
+        if(this.renderConfig.className) {
+            this.animationItem.container.setAttribute('class', this.renderConfig.className);
+        }
+    }else{
+        this.canvasContext = this.renderConfig.context;
+    }
+    this.data = animData;
+    this.layers = animData.layers;
+    this.transformCanvas = {
+        w: animData.w,
+        h:animData.h,
+        sx:0,
+        sy:0,
+        tx:0,
+        ty:0
+    };
+    this.globalData.frameId = 0;
+    this.globalData.frameRate = animData.fr;
+    this.globalData.nm = animData.nm;
+    this.globalData.compSize = {
+        w: animData.w,
+        h: animData.h
+    }
+    this.globalData.canvasContext = this.canvasContext;
+    this.globalData.renderer = this;
+    this.globalData.isDashed = false;
+    this.globalData.progressiveLoad = this.renderConfig.progressiveLoad;
+    this.globalData.transformCanvas = this.transformCanvas;
+    this.elements = createSizedArray(animData.layers.length);
+
+    this.updateContainerSize();
+};
diff --git a/player/js/utils/DataManager.js b/player/js/utils/DataManager.js
index e3b0671..a0aa4be 100644
--- a/player/js/utils/DataManager.js
+++ b/player/js/utils/DataManager.js
@@ -353,8 +353,12 @@
 
     var moduleOb = {};
     moduleOb.completeData = completeData;
+    moduleOb.checkColors = checkColors;
+    moduleOb.checkChars = checkChars;
+    moduleOb.checkShapes = checkShapes;
+    moduleOb.completeLayers = completeLayers;
 
     return moduleOb;
 }
 
-var dataManager = dataFunctionManager();
\ No newline at end of file
+var dataManager = dataFunctionManager();
diff --git a/player/js/utils/DataManagerWorkerOverrides.js b/player/js/utils/DataManagerWorkerOverrides.js
new file mode 100644
index 0000000..800af9e
--- /dev/null
+++ b/player/js/utils/DataManagerWorkerOverrides.js
@@ -0,0 +1,10 @@
+dataManager.completeData = function(animationData, fontManager) {
+    if(animationData.__complete){
+            return;
+        }
+        this.checkColors(animationData);
+        this.checkChars(animationData);
+        this.checkShapes(animationData);
+        this.completeLayers(animationData.layers, animationData.assets, fontManager);
+        animationData.__complete = true;
+}
diff --git a/player/js/utils/FontManagerWorkerOverride.js b/player/js/utils/FontManagerWorkerOverride.js
new file mode 100644
index 0000000..2e37782
--- /dev/null
+++ b/player/js/utils/FontManagerWorkerOverride.js
@@ -0,0 +1,10 @@
+FontManager = (function(){
+    var Font = function(){
+        this.fonts = [];
+        this.chars = null;
+        this.typekitLoaded = 0;
+        this.isLoaded = false;
+        this.initTime = Date.now();
+    };
+    return Font;
+}());
diff --git a/player/js/utils/asset_loader_worker_override.js b/player/js/utils/asset_loader_worker_override.js
new file mode 100644
index 0000000..42a6fbe
--- /dev/null
+++ b/player/js/utils/asset_loader_worker_override.js
@@ -0,0 +1 @@
+var assetLoader = null;
diff --git a/player/js/utils/imagePreloaderWorkerOverride.js b/player/js/utils/imagePreloaderWorkerOverride.js
new file mode 100644
index 0000000..9bd5c5b
--- /dev/null
+++ b/player/js/utils/imagePreloaderWorkerOverride.js
@@ -0,0 +1 @@
+var ImagePreloader = function() {};
diff --git a/tasks/build.js b/tasks/build.js
index 1c3cc1d..2862436 100644
--- a/tasks/build.js
+++ b/tasks/build.js
@@ -33,7 +33,7 @@
 function getScripts($) {
 	return new Promise((resolve, reject)=> {
 		try {
-			const defaultBuilds = ['full','svg_light','svg','canvas','html', 'canvas_light', 'html_light']
+			const defaultBuilds = ['full','svg_light','svg','canvas','html', 'canvas_light', 'html_light', 'canvas_worker']
 			const scriptNodes = []
 			let shouldAddToScripts = false;
 			$("head").contents().each((index, node) => {
@@ -80,11 +80,12 @@
 	});
 }
 
-function wrapScriptWithModule(code) {
+function wrapScriptWithModule(code, build) {
 	return new Promise((resolve, reject)=>{
 		try {
 			// Wrapping with module
-			let wrappedCode = fs.readFileSync(`${rootFolder}js/module.js`, "utf8");
+			let moduleFileName = (build =='canvas_light') ? 'module_worker' : 'module';
+			let wrappedCode = fs.readFileSync(`${rootFolder}js/${moduleFileName}.js`, "utf8");
 			wrappedCode = wrappedCode.replace('/*<%= contents %>*/',code);
 			wrappedCode = wrappedCode.replace('[[BM_VERSION]]',bm_version);
 			resolve(wrappedCode);
@@ -111,7 +112,7 @@
 
 async function buildVersion(scripts, version) {
 	const code = await concatScripts(scripts, version.build)
-	const wrappedCode = await wrapScriptWithModule(code)
+	const wrappedCode = await wrapScriptWithModule(code, version.build)
 	const processedCode = await version.process(wrappedCode)
 	const saved = await save(processedCode, version.fileName)
 	return true
@@ -187,6 +188,11 @@
 			process: uglifyCode
 		},
 		{
+			fileName: 'lottie_canvas_worker.js',
+			build: 'canvas_worker',
+			process: noop
+		},
+		{
 			fileName: 'lottie_html.js',
 			build: 'html',
 			process: noop
@@ -237,4 +243,4 @@
 	}
 }
 
-build()
\ No newline at end of file
+build()