diff --git a/HEADER.js b/HEADER.js index 3386fcf4..39493e56 100644 --- a/HEADER.js +++ b/HEADER.js @@ -1,6 +1,6 @@ /*! Fabric.js Copyright 2008-2014, Printio (Juriy Zaytsev, Maxim Chernyak) */ -var fabric = fabric || { version: "1.4.9" }; +var fabric = fabric || { version: "1.4.10" }; if (typeof exports !== 'undefined') { exports.fabric = fabric; } diff --git a/bower.json b/bower.json index 0b5208bd..577ea6bf 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "fabric.js", - "version": "1.4.9", + "version": "1.4.10", "homepage": "http://fabricjs.com", "authors": [ "kangax", "Kienz" diff --git a/dist/fabric.js b/dist/fabric.js index c7d87b71..9c788e51 100644 --- a/dist/fabric.js +++ b/dist/fabric.js @@ -1,7 +1,7 @@ /* build: `node build.js modules=ALL exclude=gestures,cufon,json minifier=uglifyjs` */ /*! Fabric.js Copyright 2008-2014, Printio (Juriy Zaytsev, Maxim Chernyak) */ -var fabric = fabric || { version: "1.4.9" }; +var fabric = fabric || { version: "1.4.10" }; if (typeof exports !== 'undefined') { exports.fabric = fabric; } @@ -3151,10 +3151,9 @@ if (typeof console !== 'undefined') { if (!(matrix[0] !== 1 || matrix[3] !== 1 || matrix[4] !== 0 || matrix[5] !== 0)) return; // default is to preserve aspect ratio // preserveAspectRatio attribute to be implemented - var el = document.createElement('g'); + var el = doc.ownerDocument.createElement('g'); while (doc.firstChild != null) { - var node = doc.firstChild; - el.appendChild(node); + el.appendChild(doc.firstChild); } el.setAttribute('transform','matrix(' + matrix[0] + ' ' + matrix[1] + ' ' + matrix[2] + ' ' + matrix[3] + ' ' + matrix[4] + ' ' + matrix[5] + ')'); doc.appendChild(el); @@ -3254,8 +3253,8 @@ if (typeof console !== 'undefined') { heightAttr: heightAttr }; - fabric.gradientDefs = extend(fabric.getGradientDefs(doc), fabric.gradientDefs); - fabric.cssRules = extend(fabric.getCSSRules(doc), fabric.cssRules); + fabric.gradientDefs = fabric.getGradientDefs(doc); + fabric.cssRules = fabric.getCSSRules(doc); // Precedence of rules: style > class > attribute fabric.parseElements(elements, function(instances) { @@ -5847,36 +5846,65 @@ fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ /** * Sets width of this canvas instance - * @param {Number} width value to set width to + * @param {Number|String} width value to set width to + * @param {Object} [options] Options object + * @param {Boolean} [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions + * @param {Boolean} [options.cssOnly=false] Set the given dimensions only as css dimensions * @return {fabric.Canvas} instance * @chainable true */ - setWidth: function (width) { - return this._setDimension('width', width); + setWidth: function (value, options) { + return this.setDimensions({ width: value }, options); }, /** * Sets height of this canvas instance - * @param {Number} height value to set height to + * @param {Number|String} height value to set height to + * @param {Object} [options] Options object + * @param {Boolean} [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions + * @param {Boolean} [options.cssOnly=false] Set the given dimensions only as css dimensions * @return {fabric.Canvas} instance * @chainable true */ - setHeight: function (height) { - return this._setDimension('height', height); + setHeight: function (value, options) { + return this.setDimensions({ height: value }, options); }, /** - * Sets dimensions (width, height) of this canvas instance - * @param {Object} dimensions Object with width/height properties - * @param {Number} [dimensions.width] Width of canvas element - * @param {Number} [dimensions.height] Height of canvas element + * Sets dimensions (width, height) of this canvas instance. when options.cssOnly flag active you should also supply the unit of measure (px/%/em) + * @param {Object} dimensions Object with width/height properties + * @param {Number|String} [dimensions.width] Width of canvas element + * @param {Number|String} [dimensions.height] Height of canvas element + * @param {Object} [options] Options object + * @param {Boolean} [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions + * @param {Boolean} [options.cssOnly=false] Set the given dimensions only as css dimensions * @return {fabric.Canvas} thisArg * @chainable */ - setDimensions: function(dimensions) { + setDimensions: function (dimensions, options) { + var cssValue; + + options = options || {}; + for (var prop in dimensions) { - this._setDimension(prop, dimensions[prop]); + cssValue = dimensions[prop]; + + if (!options.cssOnly) { + this._setBackstoreDimension(prop, dimensions[prop]); + cssValue += 'px'; + } + + if (!options.backstoreOnly) { + this._setCssDimension(prop, cssValue); + } } + + if (!options.cssOnly) { + this.renderAll(); + } + + this.calcOffset(); + return this; }, @@ -5888,27 +5916,40 @@ fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ * @return {fabric.Canvas} instance * @chainable true */ - _setDimension: function (prop, value) { + _setBackstoreDimension: function (prop, value) { this.lowerCanvasEl[prop] = value; - this.lowerCanvasEl.style[prop] = value + 'px'; if (this.upperCanvasEl) { this.upperCanvasEl[prop] = value; - this.upperCanvasEl.style[prop] = value + 'px'; } if (this.cacheCanvasEl) { this.cacheCanvasEl[prop] = value; } - if (this.wrapperEl) { - this.wrapperEl.style[prop] = value + 'px'; - } - this[prop] = value; - this.calcOffset(); - this.renderAll(); + return this; + }, + + /** + * Helper for setting css width/height + * @private + * @param {String} prop property (width|height) + * @param {String} value value to set property to + * @return {fabric.Canvas} instance + * @chainable true + */ + _setCssDimension: function (prop, value) { + this.lowerCanvasEl.style[prop] = value; + + if (this.upperCanvasEl) { + this.upperCanvasEl.style[prop] = value; + } + + if (this.wrapperEl) { + this.wrapperEl.style[prop] = value; + } return this; }, @@ -8417,6 +8458,8 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab bounds = upperCanvasEl.getBoundingClientRect(), cssScale; + this.calcOffset(); + pointer.x = pointer.x - this._offset.left; pointer.y = pointer.y - this._offset.top; if (!ignoreZoom) { @@ -8436,6 +8479,7 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab height: upperCanvasEl.height / bounds.height }; } + return { x: pointer.x * cssScale.width, y: pointer.y * cssScale.height @@ -18135,6 +18179,118 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag })(typeof exports !== 'undefined' ? exports : this); +(function(global){ + 'use strict'; + + var fabric = global.fabric; + + /** + * Color Blend filter class + * @class fabric.Image.filter.Blend + * @memberOf fabric.Image.filters + * @extends fabric.Image.filters.BaseFilter + * @example + * var filter = new fabric.Image.filters.Blend({ + * color: '#000', + * mode: 'multiply' + * }); + * + * var filter = new fabric.Image.filters.Blend({ + * image: fabricImageObject, + * mode: 'multiply', + * alpha: 0.5 + * }); + + * object.filters.push(filter); + * object.applyFilters(canvas.renderAll.bind(canvas)); + */ + fabric.Image.filters.Blend = fabric.util.createClass({ + type: 'Blend', + + initialize: function(options){ + options = options || {}; + this.color = options.color || '#000'; + this.image = options.image || false; + this.mode = options.mode || 'multiply'; + this.alpha = options.alpha || 1; + }, + + applyTo: function(canvasEl) { + var context = canvasEl.getContext('2d'), + imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), + data = imageData.data, + tr, tg, tb, + r, g, b, + source, + isImage = false; + + if(this.image){ + // Blend images + isImage = true; + + var _el = fabric.util.createCanvasElement(); + _el.width = this.image.width; + _el.height = this.image.height; + + var _tmp_canvas = new fabric.StaticCanvas(_el); + _tmp_canvas.add(this.image); + var context2 = _tmp_canvas.getContext('2d'); + source = context2.getImageData(0, 0, _tmp_canvas.width, _tmp_canvas.height).data; + } else { + // Blend color + source = new fabric.Color(this.color).getSource(); + + tr = source[0] * this.alpha; + tg = source[1] * this.alpha; + tb = source[2] * this.alpha; + } + + for (var i = 0, len = data.length; i < len; i += 4) { + + r = data[i]; + g = data[i + 1]; + b = data[i + 2]; + + if(isImage){ + tr = source[i] * this.alpha; + tg = source[i + 1] * this.alpha; + tb = source[i + 2] * this.alpha; + } + + switch(this.mode){ + case 'multiply': + data[i] = r * tr / 255; + data[i + 1] = g * tg / 255; + data[i + 2] = b * tb / 255; + break; + case 'screen': + data[i] = 1 - (1-r) * (1-tr); + data[i + 1] = 1 - (1-g) * (1-tg); + data[i + 2] = 1 - (1-b) * (1-tb); + break; + case 'add': + data[i] = Math.min(255, r + tr); + data[i + 1] = Math.min(255, g + tg); + data[i + 2] = Math.min(255, b + tb); + break; + case 'diff': + data[i] = Math.abs(r - tr); + data[i + 1] = Math.abs(g - tg); + data[i + 2] = Math.abs(b - tb); + break; + } + } + + context.putImageData(imageData, 0, 0); + } + }); + + fabric.Image.filters.Blend.fromObject = function(object) { + return new fabric.Image.filters.Blend(object); + }; +})(typeof exports !== 'undefined' ? exports : this); + + (function(global) { 'use strict'; @@ -21350,7 +21506,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot if (mouseOffset.y < height) { return this._getNewSelectionStartFromOffset( - mouseOffset, prevWidth, width, charIndex + i, jlen, j); + mouseOffset, prevWidth, width, charIndex + i, jlen); } } @@ -21363,7 +21519,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot /** * @private */ - _getNewSelectionStartFromOffset: function(mouseOffset, prevWidth, width, index, jlen, j) { + _getNewSelectionStartFromOffset: function(mouseOffset, prevWidth, width, index, jlen) { var distanceBtwLastCharAndCursor = mouseOffset.x - prevWidth, distanceBtwNextCharAndCursor = width - mouseOffset.x, @@ -21379,10 +21535,6 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot newSelectionStart = this.text.length; } - if (j === jlen) { - newSelectionStart--; - } - return newSelectionStart; } }); @@ -22326,8 +22478,8 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot }; var origSetWidth = fabric.StaticCanvas.prototype.setWidth; - fabric.StaticCanvas.prototype.setWidth = function(width) { - origSetWidth.call(this, width); + fabric.StaticCanvas.prototype.setWidth = function(width, options) { + origSetWidth.call(this, width, options); this.nodeCanvas.width = width; return this; }; @@ -22336,8 +22488,8 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot } var origSetHeight = fabric.StaticCanvas.prototype.setHeight; - fabric.StaticCanvas.prototype.setHeight = function(height) { - origSetHeight.call(this, height); + fabric.StaticCanvas.prototype.setHeight = function(height, options) { + origSetHeight.call(this, height, options); this.nodeCanvas.height = height; return this; }; diff --git a/dist/fabric.min.js b/dist/fabric.min.js index 9562abb2..2d173827 100644 --- a/dist/fabric.min.js +++ b/dist/fabric.min.js @@ -1,7 +1,7 @@ -/* build: `node build.js modules=ALL exclude=gestures,cufon,json minifier=uglifyjs` *//*! Fabric.js Copyright 2008-2014, Printio (Juriy Zaytsev, Maxim Chernyak) */var fabric=fabric||{version:"1.4.9"};typeof exports!="undefined"&&(exports.fabric=fabric),typeof document!="undefined"&&typeof window!="undefined"?(fabric.document=document,fabric.window=window):(fabric.document=require("jsdom").jsdom("
"),fabric.window=fabric.document.createWindow()),fabric.isTouchSupported="ontouchstart"in fabric.document.documentElement,fabric.isLikelyNode=typeof Buffer!="undefined"&&typeof window=="undefined",fabric.SHARED_ATTRIBUTES=["display","transform","fill","fill-opacity","fill-rule","opacity","stroke","stroke-dasharray","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width"],fabric.DPI=96,function(){function e(e,t){if(!this.__eventListeners[e])return;t?fabric.util.removeFromArray(this.__eventListeners[e],t):this.__eventListeners[e].length=0}function t(e,t){this.__eventListeners||(this.__eventListeners={});if(arguments.length===1)for(var n in e)this.on(n,e[n]);else this.__eventListeners[e]||(this.__eventListeners[e]=[]),this.__eventListeners[e].push(t);return this}function n(t,n){if(!this.__eventListeners)return;if(arguments.length===0)this.__eventListeners={};else if(arguments.length===1&&typeof arguments[0]=="object")for(var r in t)e.call(this,r,t[r]);else e.call(this,t,n);return this}function r(e,t){if(!this.__eventListeners)return;var n=this.__eventListeners[e];if(!n)return;for(var r=0,i=n.length;r-1},complexity:function(){return this.getObjects().reduce(function(e,t){return e+=t.complexity?t.complexity():0,e},0)}},function(e){var t=Math.sqrt,n=Math.atan2,r=Math.PI/180;fabric.util={removeFromArray:function(e,t){var n=e.indexOf(t);return n!==-1&&e.splice(n,1),e},getRandomInt:function(e,t){return Math.floor(Math.random()*(t-e+1))+e},degreesToRadians:function(e){return e*r},radiansToDegrees:function(e){return e/r},rotatePoint:function(e,t,n){var r=Math.sin(n),i=Math.cos(n);e.subtractEquals(t);var s=e.x*i-e.y*r,o=e.x*r+e.y*i;return(new fabric.Point(s,o)).addEquals(t)},transformPoint:function(e,t,n){return n?new fabric.Point(t[0]*e.x+t[1]*e.y,t[2]*e.x+t[3]*e.y):new fabric.Point(t[0]*e.x+t[1]*e.y+t[4],t[2]*e.x+t[3]*e.y+t[5])},invertTransform:function(e){var t=e.slice(),n=1/(e[0]*e[3]-e[1]*e[2]);t=[n*e[3],-n*e[1],-n*e[2],n*e[0],0,0];var r=fabric.util.transformPoint({x:e[4],y:e[5]},t);return t[4]=-r.x,t[5]=-r.y,t},toFixed:function(e,t){return parseFloat(Number(e).toFixed(t))},parseUnit:function(e){var t=/\D{0,2}$/.exec(e),n=parseFloat(e);switch(t[0]){case"mm":return n*fabric.DPI/25.4;case"cm":return n*fabric.DPI/2.54;case"in":return n*fabric.DPI;case"pt":return n*fabric.DPI/72;case"pc":return n*fabric.DPI/72*12;default:return n}},falseFunction:function(){return!1},getKlass:function(e,t){return e=fabric.util.string.camelize(e.charAt(0).toUpperCase()+e.slice(1)),fabric.util.resolveNamespace(t)[e]},resolveNamespace:function(t){if(!t)return fabric;var n=t.split("."),r=n.length,i=e||fabric.window;for(var s=0;s