diff --git a/README.md b/README.md
index f0da35c2..35a41fe9 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-### Fabric
+### Fabric
[](http://travis-ci.org/#!/kangax/fabric.js)
@@ -12,7 +12,7 @@ Using Fabric.js, you can create and populate objects on canvas; objects like sim
### Goals
-- Unit tested (1500+ tests at the moment)
+- Unit tested (1570+ tests at the moment)
- Modular (~40 small "classes", modules, mixins)
- Cross-browser
- [Fast](https://github.com/kangax/fabric.js/wiki/Focus-on-speed)
diff --git a/dist/all.js b/dist/all.js
index b48dbdbd..771190c0 100644
--- a/dist/all.js
+++ b/dist/all.js
@@ -4182,6 +4182,34 @@ fabric.util.string = {
return parsedPoints;
}
+ function parseFontDeclaration(value, oStyle) {
+
+ // TODO: support non-px font size
+ var match = value.match(/(normal|italic)?\s*(normal|small-caps)?\s*(normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900)?\s*(\d+)px\s+(.*)/);
+
+ if (!match) return;
+
+ var fontStyle = match[1];
+ // Font variant is not used
+ // var fontVariant = match[2];
+ var fontWeight = match[3];
+ var fontSize = match[4];
+ var fontFamily = match[5];
+
+ if (fontStyle) {
+ oStyle.fontStyle = fontStyle;
+ }
+ if (fontWeight) {
+ oStyle.fontSize = isNaN(parseFloat(fontWeight)) ? fontWeight : parseFloat(fontWeight);
+ }
+ if (fontSize) {
+ oStyle.fontSize = parseFloat(fontSize);
+ }
+ if (fontFamily) {
+ oStyle.fontFamily = fontFamily;
+ }
+ }
+
/**
* Parses "style" attribute, retuning an object with values
* @static
@@ -4196,16 +4224,20 @@ fabric.util.string = {
if (!style) return oStyle;
if (typeof style === 'string') {
- style = style.replace(/;$/, '').split(';').forEach(function (current) {
+ style.replace(/;$/, '').split(';').forEach(function (chunk) {
- var pair = current.split(':');
+ var pair = chunk.split(':');
var attr = normalizeAttr(pair[0].trim().toLowerCase());
var value = normalizeValue(attr, pair[1].trim());
- // TODO: need to normalize em, %, pt, etc. to px (!)
- var parsed = parseFloat(value);
-
- oStyle[attr] = isNaN(parsed) ? value : parsed;
+ if (attr === 'font') {
+ parseFontDeclaration(value, oStyle);
+ }
+ else {
+ // TODO: need to normalize em, %, pt, etc. to px (!)
+ var parsed = parseFloat(value);
+ oStyle[attr] = isNaN(parsed) ? value : parsed;
+ }
});
}
else {
@@ -4214,9 +4246,15 @@ fabric.util.string = {
var attr = normalizeAttr(prop.toLowerCase());
var value = normalizeValue(attr, style[prop]);
- var parsed = parseFloat(value);
- oStyle[attr] = isNaN(parsed) ? value : parsed;
+ if (attr === 'font') {
+ parseFontDeclaration(value, oStyle);
+ }
+ else {
+ // TODO: need to normalize em, %, pt, etc. to px (!)
+ var parsed = parseFloat(value);
+ oStyle[attr] = isNaN(parsed) ? value : parsed;
+ }
}
}
@@ -8845,6 +8883,7 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
/**
* @private
+ * @param {Event} e Event object fired on mousedown
*/
_onMouseDown: function (e) {
this.__onMouseDown(e);
@@ -8861,6 +8900,7 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
/**
* @private
+ * @param {Event} e Event object fired on mouseup
*/
_onMouseUp: function (e) {
this.__onMouseUp(e);
@@ -8877,6 +8917,7 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
/**
* @private
+ * @param {Event} e Event object fired on mousemove
*/
_onMouseMove: function (e) {
e.preventDefault && e.preventDefault();
@@ -8969,7 +9010,7 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
* canvas so the current image can be placed on the top canvas and the rest
* in on the container one.
* @private
- * @param e {Event} Event object fired on mousedown
+ * @param {Event} e Event object fired on mousedown
*/
__onMouseDown: function (e) {
@@ -9004,6 +9045,10 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
this.deactivateAllWithDispatch();
target && target.selectable && this.setActiveObject(target, e);
}
+ else if (this._shouldHandleGroupLogic(e, target)) {
+ this._handleGroupLogic(e, target);
+ target = this.getActiveGroup();
+ }
else {
// determine if it's a drag or rotate case
this.stateful && target.saveState();
@@ -9012,15 +9057,9 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
this.onBeforeScaleRotate(target);
}
- if (this._shouldHandleGroupLogic(e, target)) {
- this._handleGroupLogic(e, target);
- target = this.getActiveGroup();
- }
- else {
- if (target !== this.getActiveGroup() && target !== this.getActiveObject()) {
- this.deactivateAll();
- this.setActiveObject(target, e);
- }
+ if (target !== this.getActiveGroup() && target !== this.getActiveObject()) {
+ this.deactivateAll();
+ this.setActiveObject(target, e);
}
this._setupCurrentTransform(e, target);
@@ -9047,7 +9086,7 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
* all any other type of action.
* In case of an image transformation only the top canvas will be rendered.
* @private
- * @param e {Event} Event object fired on mousemove
+ * @param {Event} e Event object fired on mousemove
*/
__onMouseMove: function (e) {
@@ -9174,8 +9213,8 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
/**
* Sets the cursor depending on where the canvas is being hovered.
* Note: very buggy in Opera
- * @param e {Event} Event object
- * @param target {Object} Object that the mouse is hovering, if so.
+ * @param {Event} e Event object
+ * @param {Object} target Object that the mouse is hovering, if so.
*/
_setCursorFromEvent: function (e, target) {
var s = this.upperCanvasEl.style;
@@ -15269,23 +15308,17 @@ fabric.Image.filters.Grayscale = fabric.util.createClass( /** @lends fabric.Imag
var context = canvasEl.getContext('2d'),
imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
data = imageData.data,
- iLen = imageData.width,
- jLen = imageData.height,
- index, average, i, j;
-
- for (i = 0; i < iLen; i++) {
- for (j = 0; j < jLen; j++) {
-
- index = (i * 4) * jLen + (j * 4);
- average = (data[index] + data[index + 1] + data[index + 2]) / 3;
-
- data[index] = average;
- data[index + 1] = average;
- data[index + 2] = average;
- }
- }
-
- context.putImageData(imageData, 0, 0);
+ len = imageData.width * imageData.height * 4,
+ index = 0,
+ average;
+ while (index < len) {
+ average = (data[index] + data[index + 1] + data[index + 2]) / 3;
+ data[index] = average;
+ data[index + 1] = average;
+ data[index + 2] = average;
+ index += 4;
+ }
+ context.putImageData(imageData, 0, 0);
},
/**
diff --git a/dist/all.min.js b/dist/all.min.js
index 4ed48b61..10704a49 100644
--- a/dist/all.min.js
+++ b/dist/all.min.js
@@ -1,6 +1,6 @@
/* build: `node build.js modules=ALL exclude=gestures` *//*! Fabric.js Copyright 2008-2013, Printio (Juriy Zaytsev, Maxim Chernyak) */var fabric=fabric||{version:"1.1.13"};typeof exports!="undefined"&&(exports.fabric=fabric),typeof document!="undefined"&&typeof window!="undefined"?(fabric.document=document,fabric.window=window):(fabric.document=require("jsdom").jsdom("
-1},complexity:function(){return this.getObjects().reduce(function(e,t){return e+=t.complexity?t.complexity():0,e},0)},toGrayscale:function(){return this.forEachObject(function(e){e.toGrayscale()})}},function(){function n(e,t){var n=e.indexOf(t);return n!==-1&&e.splice(n,1),e}function r(e,t){return Math.floor(Math.random()*(t-e+1))+e}function s(e){return e*i}function o(e){return e/i}function u(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)}function a(e,t){return parseFloat(Number(e).toFixed(t))}function f(){return!1}function l(e){e||(e={});var t=+(new Date),n=e.duration||500,r=t+n,i,s=e.onChange||function(){},o=e.abort||function(){return!1},u=e.easing||function(e,t,n,r){return-n*Math.cos(e/r*(Math.PI/2))+n+t},a="startValue"in e?e.startValue:0,f="endValue"in e?e.endValue:100,l=e.byValue||f-a;e.onStart&&e.onStart(),function c(){i=+(new Date);var f=i>r?n:i-t;s(u(f,a,l,n));if(i>r||o()){e.onComplete&&e.onComplete();return}h(c)}()}function p(e,t,n){if(e){var r=fabric.util.createImage();r.onload=function(){t&&t.call(n,r),r=r.onload=null},r.src=e}else t&&t.call(n,e)}function d(e,t){function n(e){return fabric[fabric.util.string.camelize(fabric.util.string.capitalize(e))]}function r(){++s===o&&t&&t(i)}var i=[],s=0,o=e.length;e.forEach(function(e,t){if(!e.type)return;var s=n(e.type);s.async?s.fromObject(e,function(e,n){n||(i[t]=e),r()}):(i[t]=s.fromObject(e),r())})}function v(e,t,n){var r;return e.length>1?r=new fabric.PathGroup(e,t):r=e[0],typeof n!="undefined"&&r.setSourcePath(n),r}function m(e,t,n){if(n&&Object.prototype.toString.call(n)==="[object Array]")for(var r=0,i=n.length;rr)r+=u[p++%h],r>l&&(r=l),n[d?"lineTo":"moveTo"](r,0),d=!d;n.restore()}function y(e){return e||(e=fabric.document.createElement("canvas")),!e.getContext&&typeof G_vmlCanvasManager!="undefined"&&G_vmlCanvasManager.initElement(e),e}function b(){return fabric.isLikelyNode?new(require("canvas").Image):fabric.document.createElement("img")}function w(e){var t=e.prototype;for(var n=t.stateProperties.length;n--;){var r=t.stateProperties[n],i=r.charAt(0).toUpperCase()+r.slice(1),s="set"+i,o="get"+i;t[o]||(t[o]=function(e){return new Function('return this.get("'+e+'")')}(r)),t[s]||(t[s]=function(e){return new Function("value",'return this.set("'+e+'", value)')}(r))}}function E(e,t){t.save(),t.beginPath(),e.clipTo(t),t.clip()}function S(e,t){var n=[[e[0],e[2],e[4]],[e[1],e[3],e[5]],[0,0,1]],r=[[t[0],t[2],t[4]],[t[1],t[3],t[5]],[0,0,1]],i=[];for(var s=0;s<3;s++){i[s]=[];for(var o=0;o<3;o++){var u=0;for(var a=0;a<3;a++)u+=n[s][a]*r[a][o];i[s][o]=u}}return[i[0][0],i[1][0],i[0][1],i[1][1],i[0][2],i[1][2]]}var e=Math.sqrt,t=Math.atan2;fabric.util={};var i=Math.PI/180,c=fabric.window.requestAnimationFrame||fabric.window.webkitRequestAnimationFrame||fabric.window.mozRequestAnimationFrame||fabric.window.oRequestAnimationFrame||fabric.window.msRequestAnimationFrame||function(e){fabric.window.setTimeout(e,1e3/60)},h=function(){return c.apply(fabric.window,arguments)};fabric.util.removeFromArray=n,fabric.util.degreesToRadians=s,fabric.util.radiansToDegrees=o,fabric.util.rotatePoint=u,fabric.util.toFixed=a,fabric.util.getRandomInt=r,fabric.util.falseFunction=f,fabric.util.animate=l,fabric.util.requestAnimFrame=h,fabric.util.loadImage=p,fabric.util.enlivenObjects=d,fabric.util.groupSVGElements=v,fabric.util.populateWithProperties=m,fabric.util.drawDashedLine=g,fabric.util.createCanvasElement=y,fabric.util.createImage=b,fabric.util.createAccessors=w,fabric.util.clipContext=E,fabric.util.multiplyTransformMatrices=S}(),function(){function t(t,n){var r=e.call(arguments,2),i=[];for(var s=0,o=t.length;s>>0,n=0,r;if(arguments.length>1)r=arguments[1];else do{if(n in this){r=this[n++];break}if(++n>=t)throw new TypeError}while(!0);for(;n0&&(i.status="Intersection"),i},t.Intersection.intersectPolygonPolygon=function(e,t){var r=new n("No Intersection"),i=e.length;for(var s=0;s0&&(r.status="Intersection"),r},t.Intersection.intersectPolygonRectangle=function(e,r,i){var s=r.min(i),o=r.max(i),u=new t.Point(o.x,s.y),a=new t.Point(s.x,o.y),f=n.intersectLinePolygon(s,u,e),l=n.intersectLinePolygon(u,o,e),c=n.intersectLinePolygon(o,a,e),h=n.intersectLinePolygon(a,s,e),p=new n("No Intersection");return p.appendPoints(f.points),p.appendPoints(l.points),p.appendPoints(c.points),p.appendPoints(h.points),p.points.length>0&&(p.status="Intersection"),p}}(typeof exports!="undefined"?exports:this),function(e){"use strict";function n(e){e?this._tryParsingColor(e):this.setSource([0,0,0,1])}var t=e.fabric||(e.fabric={});if(t.Color){t.warn("fabric.Color is already defined.");return}t.Color=n,t.Color.prototype={_tryParsingColor:function(e){var t;e in n.colorNameMap&&(e=n.colorNameMap[e]),t=n.sourceFromHex(e),t||(t=n.sourceFromRgb(e)),t&&this.setSource(t)},getSource:function(){return this._source},setSource:function(e){this._source=e},toRgb:function(){var e=this.getSource();return"rgb("+e[0]+","+e[1]+","+e[2]+")"},toRgba:function(){var e=this.getSource();return"rgba("+e[0]+","+e[1]+","+e[2]+","+e[3]+")"},toHex:function(){var e=this.getSource(),t=e[0].toString(16);t=t.length===1?"0"+t:t;var n=e[1].toString(16);n=n.length===1?"0"+n:n;var r=e[2].toString(16);return r=r.length===1?"0"+r:r,t.toUpperCase()+n.toUpperCase()+r.toUpperCase()},getAlpha:function(){return this.getSource()[3]},setAlpha:function(e){var t=this.getSource();return t[3]=e,this.setSource(t),this},toGrayscale:function(){var e=this.getSource(),t=parseInt((e[0]*.3+e[1]*.59+e[2]*.11).toFixed(0),10),n=e[3];return this.setSource([t,t,t,n]),this},toBlackWhite:function(e){var t=this.getSource(),n=(t[0]*.3+t[1]*.59+t[2]*.11).toFixed(0),r=t[3];return e=e||127,n=Number(n)