(function() { var COMMA = ',', OPEN_PAREN = '(', CLOSE_PAREN = ')', OPEN_PAREN_BRACKET = '([', CLOSE_BRACKET_PAREN = '])', SEMICOLON = ';', DOUBLE_PAREN = '()', // EMPTY_STRING = '', EQUALS = '=', // SET = 'set', CONTEXT_METHODS = [ 'arc', 'arcTo', 'beginPath', 'bezierCurveTo', 'clearRect', 'clip', 'closePath', 'createLinearGradient', 'createPattern', 'createRadialGradient', 'drawImage', 'fill', 'fillText', 'getImageData', 'createImageData', 'lineTo', 'moveTo', 'putImageData', 'quadraticCurveTo', 'rect', 'restore', 'rotate', 'save', 'scale', 'setLineDash', 'setTransform', 'stroke', 'strokeText', 'transform', 'translate' ]; /** * Canvas Context constructor * @constructor * @abstract * @memberof Konva */ Konva.Context = function(canvas) { this.init(canvas); }; Konva.Context.prototype = { init: function(canvas) { this.canvas = canvas; this._context = canvas._canvas.getContext('2d'); if (Konva.enableTrace) { this.traceArr = []; this._enableTrace(); } }, /** * fill shape * @method * @memberof Konva.Context.prototype * @param {Konva.Shape} shape */ fillShape: function(shape) { if(shape.getFillEnabled()) { this._fill(shape); } }, /** * stroke shape * @method * @memberof Konva.Context.prototype * @param {Konva.Shape} shape */ strokeShape: function(shape) { if(shape.getStrokeEnabled()) { this._stroke(shape); } }, /** * fill then stroke * @method * @memberof Konva.Context.prototype * @param {Konva.Shape} shape */ fillStrokeShape: function(shape) { var fillEnabled = shape.getFillEnabled(); if(fillEnabled) { this._fill(shape); } if(shape.getStrokeEnabled()) { this._stroke(shape); } }, /** * get context trace if trace is enabled * @method * @memberof Konva.Context.prototype * @param {Boolean} relaxed if false, return strict context trace, which includes method names, method parameters * properties, and property values. If true, return relaxed context trace, which only returns method names and * properites. * @returns {String} */ getTrace: function(relaxed) { var traceArr = this.traceArr, len = traceArr.length, str = '', n, trace, method, args; for (n=0; n= Konva.traceArrMax) { traceArr.shift(); } }, /** * reset canvas context transform * @method * @memberof Konva.Context.prototype */ reset: function() { var pixelRatio = this.getCanvas().getPixelRatio(); this.setTransform(1 * pixelRatio, 0, 0, 1 * pixelRatio, 0, 0); }, /** * get canvas * @method * @memberof Konva.Context.prototype * @returns {Konva.Canvas} */ getCanvas: function() { return this.canvas; }, /** * clear canvas * @method * @memberof Konva.Context.prototype * @param {Object} [bounds] * @param {Number} [bounds.x] * @param {Number} [bounds.y] * @param {Number} [bounds.width] * @param {Number} [bounds.height] */ clear: function(bounds) { var canvas = this.getCanvas(); if (bounds) { this.clearRect(bounds.x || 0, bounds.y || 0, bounds.width || 0, bounds.height || 0); } else { this.clearRect(0, 0, canvas.getWidth(), canvas.getHeight()); } }, _applyLineCap: function(shape) { var lineCap = shape.getLineCap(); if(lineCap) { this.setAttr('lineCap', lineCap); } }, _applyOpacity: function(shape) { var absOpacity = shape.getAbsoluteOpacity(); if(absOpacity !== 1) { this.setAttr('globalAlpha', absOpacity); } }, _applyLineJoin: function(shape) { var lineJoin = shape.getLineJoin(); if(lineJoin) { this.setAttr('lineJoin', lineJoin); } }, setAttr: function(attr, val) { this._context[attr] = val; }, // context pass through methods arc: function() { var a = arguments; this._context.arc(a[0], a[1], a[2], a[3], a[4], a[5]); }, beginPath: function() { this._context.beginPath(); }, bezierCurveTo: function() { var a = arguments; this._context.bezierCurveTo(a[0], a[1], a[2], a[3], a[4], a[5]); }, clearRect: function() { var a = arguments; this._context.clearRect(a[0], a[1], a[2], a[3]); }, clip: function() { this._context.clip(); }, closePath: function() { this._context.closePath(); }, createImageData: function() { var a = arguments; if(a.length === 2) { return this._context.createImageData(a[0], a[1]); } else if(a.length === 1) { return this._context.createImageData(a[0]); } }, createLinearGradient: function() { var a = arguments; return this._context.createLinearGradient(a[0], a[1], a[2], a[3]); }, createPattern: function() { var a = arguments; return this._context.createPattern(a[0], a[1]); }, createRadialGradient: function() { var a = arguments; return this._context.createRadialGradient(a[0], a[1], a[2], a[3], a[4], a[5]); }, drawImage: function() { var a = arguments, _context = this._context; if(a.length === 3) { _context.drawImage(a[0], a[1], a[2]); } else if(a.length === 5) { _context.drawImage(a[0], a[1], a[2], a[3], a[4]); } else if(a.length === 9) { _context.drawImage(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]); } }, fill: function() { this._context.fill(); }, fillText: function() { var a = arguments; this._context.fillText(a[0], a[1], a[2]); }, getImageData: function() { var a = arguments; return this._context.getImageData(a[0], a[1], a[2], a[3]); }, lineTo: function() { var a = arguments; this._context.lineTo(a[0], a[1]); }, moveTo: function() { var a = arguments; this._context.moveTo(a[0], a[1]); }, rect: function() { var a = arguments; this._context.rect(a[0], a[1], a[2], a[3]); }, putImageData: function() { var a = arguments; this._context.putImageData(a[0], a[1], a[2]); }, quadraticCurveTo: function() { var a = arguments; this._context.quadraticCurveTo(a[0], a[1], a[2], a[3]); }, restore: function() { this._context.restore(); }, rotate: function() { var a = arguments; this._context.rotate(a[0]); }, save: function() { this._context.save(); }, scale: function() { var a = arguments; this._context.scale(a[0], a[1]); }, setLineDash: function() { var a = arguments, _context = this._context; // works for Chrome and IE11 if(this._context.setLineDash) { _context.setLineDash(a[0]); } // verified that this works in firefox else if('mozDash' in _context) { _context.mozDash = a[0]; } // does not currently work for Safari else if('webkitLineDash' in _context) { _context.webkitLineDash = a[0]; } // no support for IE9 and IE10 }, setTransform: function() { var a = arguments; this._context.setTransform(a[0], a[1], a[2], a[3], a[4], a[5]); }, stroke: function() { this._context.stroke(); }, strokeText: function() { var a = arguments; this._context.strokeText(a[0], a[1], a[2]); }, transform: function() { var a = arguments; this._context.transform(a[0], a[1], a[2], a[3], a[4], a[5]); }, translate: function() { var a = arguments; this._context.translate(a[0], a[1]); }, _enableTrace: function() { var that = this, len = CONTEXT_METHODS.length, _simplifyArray = Konva.Util._simplifyArray, origSetter = this.setAttr, n, args; // to prevent creating scope function at each loop var func = function(methodName) { var origMethod = that[methodName], ret; that[methodName] = function() { args = _simplifyArray(Array.prototype.slice.call(arguments, 0)); ret = origMethod.apply(that, arguments); that._trace({ method: methodName, args: args }); return ret; }; }; // methods for (n=0; n