From 673d8584d975ebd1bbeffbbdf10caa4b3c80402b Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Sun, 21 Sep 2014 20:54:21 +0200 Subject: [PATCH 1/2] Update object.class.js --- src/shapes/object.class.js | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/src/shapes/object.class.js b/src/shapes/object.class.js index 7649941d..b2db5dcc 100644 --- a/src/shapes/object.class.js +++ b/src/shapes/object.class.js @@ -461,7 +461,14 @@ * @type String * @default */ - fillRule: 'source-over', + fillRule: 'nonzero', + + /** + * Composite rule used for canvas globalCompositeOperation + * @type String + * @default + */ + compositeRule: 'source-over', /** * Background color of an object. Only works with text objects at the moment. @@ -674,7 +681,7 @@ stateProperties: ( 'top left width height scaleX scaleY flipX flipY originX originY transformMatrix ' + 'stroke strokeWidth strokeDashArray strokeLineCap strokeLineJoin strokeMiterLimit ' + - 'angle opacity fill fillRule shadow clipTo visible backgroundColor' + 'angle opacity fill fillRule compositeRule shadow clipTo visible backgroundColor' ).split(' '), /** @@ -788,7 +795,9 @@ shadow: (this.shadow && this.shadow.toObject) ? this.shadow.toObject() : this.shadow, visible: this.visible, clipTo: this.clipTo && String(this.clipTo), - backgroundColor: this.backgroundColor + backgroundColor: this.backgroundColor, + fillRule: this.fillRule, + compositeRule: this.compositeRule }; if (!this.includeDefaultValues) { @@ -959,7 +968,7 @@ ctx.save(); //setup fill rule for current object - this._setupFillRule(ctx); + this._setupCompositeRule(ctx); this._transform(ctx, noTransform); this._setStrokeStyles(ctx); @@ -977,7 +986,7 @@ this._render(ctx, noTransform); this.clipTo && ctx.restore(); this._removeShadow(ctx); - this._restoreFillRule(ctx); + this._restoreCompositeRule(ctx); ctx.restore(); }, @@ -1099,7 +1108,7 @@ -this.width / 2 + this.fill.offsetX || 0, -this.height / 2 + this.fill.offsetY || 0); } - if (this.fillRule === 'destination-over') { + if (this.fillRule === 'evenodd') { ctx.fill('evenodd'); } else { @@ -1476,13 +1485,13 @@ /** * Sets canvas globalCompositeOperation for specific object - * custom composition operation for the particular object can be specifed using fillRule property + * custom composition operation for the particular object can be specifed using compositeRule property * @param {CanvasRenderingContext2D} ctx Rendering canvas context */ - _setupFillRule: function (ctx) { - if (this.fillRule) { - this._prevFillRule = ctx.globalCompositeOperation; - ctx.globalCompositeOperation = this.fillRule; + _setupCompositeRule: function (ctx) { + if (this.compositeRule) { + this._prevCompositeRule = ctx.globalCompositeOperation; + ctx.globalCompositeOperation = this.compositeRule; } }, @@ -1490,9 +1499,9 @@ * Restores previously saved canvas globalCompositeOperation after obeject rendering * @param {CanvasRenderingContext2D} ctx Rendering canvas context */ - _restoreFillRule: function (ctx) { - if (this.fillRule && this._prevFillRule) { - ctx.globalCompositeOperation = this._prevFillRule; + _restoreCompositeRule: function (ctx) { + if (this.compositeRule && this._prevCompositeRule) { + ctx.globalCompositeOperation = this._prevCompositeRule; } } }); From af1138a6860a021be385fca63453f825525a7033 Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Sun, 21 Sep 2014 20:55:00 +0200 Subject: [PATCH 2/2] Divided FillRule from globalCompositeOperation --- src/mixins/object.svg_export.js | 2 +- src/parser.js | 3 - src/shapes/object.class.js | 78 ++++++++++++------------ src/shapes/text.class.js | 4 +- test/unit/canvas.js | 4 +- test/unit/canvas_static.js | 62 ++++++++++--------- test/unit/circle.js | 56 ++++++++--------- test/unit/ellipse.js | 54 +++++++++-------- test/unit/group.js | 54 +++++++++-------- test/unit/image.js | 56 ++++++++--------- test/unit/itext.js | 74 ++++++++++++----------- test/unit/line.js | 58 +++++++++--------- test/unit/object.js | 104 +++++++++++++++++--------------- test/unit/parser.js | 2 +- test/unit/path.js | 54 +++++++++-------- test/unit/path_group.js | 52 ++++++++-------- test/unit/polygon.js | 52 ++++++++-------- test/unit/polyline.js | 52 ++++++++-------- test/unit/rect.js | 56 ++++++++--------- test/unit/text.js | 74 ++++++++++++----------- 20 files changed, 490 insertions(+), 461 deletions(-) diff --git a/src/mixins/object.svg_export.js b/src/mixins/object.svg_export.js index 8d327781..ead156b7 100644 --- a/src/mixins/object.svg_export.js +++ b/src/mixins/object.svg_export.js @@ -10,7 +10,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot var fill = this.fill ? (this.fill.toLive ? 'url(#SVGID_' + this.fill.id + ')' : this.fill) : 'none', - fillRule = (this.fillRule === 'destination-over' ? 'evenodd' : this.fillRule), + fillRule = this.fillRule, stroke = this.stroke ? (this.stroke.toLive ? 'url(#SVGID_' + this.stroke.id + ')' : this.stroke) : 'none', diff --git a/src/parser.js b/src/parser.js index 7c4e9956..0bd39570 100644 --- a/src/parser.js +++ b/src/parser.js @@ -63,9 +63,6 @@ if ((attr === 'fill' || attr === 'stroke') && value === 'none') { value = ''; } - else if (attr === 'fillRule') { - value = (value === 'evenodd') ? 'destination-over' : value; - } else if (attr === 'strokeDashArray') { value = value.replace(/,/g, ' ').split(/\s+/).map(function(n) { return parseInt(n); diff --git a/src/shapes/object.class.js b/src/shapes/object.class.js index b2db5dcc..baca2e25 100644 --- a/src/shapes/object.class.js +++ b/src/shapes/object.class.js @@ -458,6 +458,8 @@ /** * Fill rule used to fill an object + * accepted values are nonzero, evenodd + * Backwards incompatibility note: This property was used for setting globalCompositeOperation until v1.4.12 (use `fabric.Object#globalCompositeOperation` instead) * @type String * @default */ @@ -468,7 +470,7 @@ * @type String * @default */ - compositeRule: 'source-over', + globalCompositeOperation: 'source-over', /** * Background color of an object. Only works with text objects at the moment. @@ -681,7 +683,7 @@ stateProperties: ( 'top left width height scaleX scaleY flipX flipY originX originY transformMatrix ' + 'stroke strokeWidth strokeDashArray strokeLineCap strokeLineJoin strokeMiterLimit ' + - 'angle opacity fill fillRule compositeRule shadow clipTo visible backgroundColor' + 'angle opacity fill fillRule globalCompositeOperation shadow clipTo visible backgroundColor' ).split(' '), /** @@ -772,32 +774,32 @@ var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS, object = { - type: this.type, - originX: this.originX, - originY: this.originY, - left: toFixed(this.left, NUM_FRACTION_DIGITS), - top: toFixed(this.top, NUM_FRACTION_DIGITS), - width: toFixed(this.width, NUM_FRACTION_DIGITS), - height: toFixed(this.height, NUM_FRACTION_DIGITS), - fill: (this.fill && this.fill.toObject) ? this.fill.toObject() : this.fill, - stroke: (this.stroke && this.stroke.toObject) ? this.stroke.toObject() : this.stroke, - strokeWidth: toFixed(this.strokeWidth, NUM_FRACTION_DIGITS), - strokeDashArray: this.strokeDashArray, - strokeLineCap: this.strokeLineCap, - strokeLineJoin: this.strokeLineJoin, - strokeMiterLimit: toFixed(this.strokeMiterLimit, NUM_FRACTION_DIGITS), - scaleX: toFixed(this.scaleX, NUM_FRACTION_DIGITS), - scaleY: toFixed(this.scaleY, NUM_FRACTION_DIGITS), - angle: toFixed(this.getAngle(), NUM_FRACTION_DIGITS), - flipX: this.flipX, - flipY: this.flipY, - opacity: toFixed(this.opacity, NUM_FRACTION_DIGITS), - shadow: (this.shadow && this.shadow.toObject) ? this.shadow.toObject() : this.shadow, - visible: this.visible, - clipTo: this.clipTo && String(this.clipTo), - backgroundColor: this.backgroundColor, - fillRule: this.fillRule, - compositeRule: this.compositeRule + type: this.type, + originX: this.originX, + originY: this.originY, + left: toFixed(this.left, NUM_FRACTION_DIGITS), + top: toFixed(this.top, NUM_FRACTION_DIGITS), + width: toFixed(this.width, NUM_FRACTION_DIGITS), + height: toFixed(this.height, NUM_FRACTION_DIGITS), + fill: (this.fill && this.fill.toObject) ? this.fill.toObject() : this.fill, + stroke: (this.stroke && this.stroke.toObject) ? this.stroke.toObject() : this.stroke, + strokeWidth: toFixed(this.strokeWidth, NUM_FRACTION_DIGITS), + strokeDashArray: this.strokeDashArray, + strokeLineCap: this.strokeLineCap, + strokeLineJoin: this.strokeLineJoin, + strokeMiterLimit: toFixed(this.strokeMiterLimit, NUM_FRACTION_DIGITS), + scaleX: toFixed(this.scaleX, NUM_FRACTION_DIGITS), + scaleY: toFixed(this.scaleY, NUM_FRACTION_DIGITS), + angle: toFixed(this.getAngle(), NUM_FRACTION_DIGITS), + flipX: this.flipX, + flipY: this.flipY, + opacity: toFixed(this.opacity, NUM_FRACTION_DIGITS), + shadow: (this.shadow && this.shadow.toObject) ? this.shadow.toObject() : this.shadow, + visible: this.visible, + clipTo: this.clipTo && String(this.clipTo), + backgroundColor: this.backgroundColor, + fillRule: this.fillRule, + globalCompositeOperation: this.globalCompositeOperation }; if (!this.includeDefaultValues) { @@ -968,7 +970,7 @@ ctx.save(); //setup fill rule for current object - this._setupCompositeRule(ctx); + this._setupCompositeOperation(ctx); this._transform(ctx, noTransform); this._setStrokeStyles(ctx); @@ -986,7 +988,7 @@ this._render(ctx, noTransform); this.clipTo && ctx.restore(); this._removeShadow(ctx); - this._restoreCompositeRule(ctx); + this._restoreCompositeOperation(ctx); ctx.restore(); }, @@ -1485,13 +1487,13 @@ /** * Sets canvas globalCompositeOperation for specific object - * custom composition operation for the particular object can be specifed using compositeRule property + * custom composition operation for the particular object can be specifed using globalCompositeOperation property * @param {CanvasRenderingContext2D} ctx Rendering canvas context */ - _setupCompositeRule: function (ctx) { - if (this.compositeRule) { - this._prevCompositeRule = ctx.globalCompositeOperation; - ctx.globalCompositeOperation = this.compositeRule; + _setupCompositeOperation: function (ctx) { + if (this.globalCompositeOperation) { + this._prevGlobalCompositeOperation = ctx.globalCompositeOperation; + ctx.globalCompositeOperation = this.globalCompositeOperation; } }, @@ -1499,9 +1501,9 @@ * Restores previously saved canvas globalCompositeOperation after obeject rendering * @param {CanvasRenderingContext2D} ctx Rendering canvas context */ - _restoreCompositeRule: function (ctx) { - if (this.compositeRule && this._prevCompositeRule) { - ctx.globalCompositeOperation = this._prevCompositeRule; + _restoreCompositeOperation: function (ctx) { + if (this.globalCompositeOperation && this._prevGlobalCompositeOperation) { + ctx.globalCompositeOperation = this._prevGlobalCompositeOperation; } } }); diff --git a/src/shapes/text.class.js b/src/shapes/text.class.js index 2f158a56..efc203d2 100644 --- a/src/shapes/text.class.js +++ b/src/shapes/text.class.js @@ -392,10 +392,10 @@ _renderText: function(ctx, textLines) { ctx.save(); this._setShadow(ctx); - this._setupFillRule(ctx); + this._setupCompositeOperation(ctx); this._renderTextFill(ctx, textLines); this._renderTextStroke(ctx, textLines); - this._restoreFillRule(ctx); + this._restoreCompositeOperation(ctx); this._removeShadow(ctx); ctx.restore(); }, diff --git a/test/unit/canvas.js b/test/unit/canvas.js index 15103077..3b66ec3d 100644 --- a/test/unit/canvas.js +++ b/test/unit/canvas.js @@ -41,12 +41,12 @@ var PATH_DATALESS_JSON = '{"objects":[{"type":"path","originX":"left","originY":"top","left":100,"top":100,"width":200,"height":200,"fill":"rgb(0,0,0)",'+ '"stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,'+ '"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,'+ - '"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","path":"http://example.com/","pathOffset":{"x":200,"y":200}}],"background":""}'; + '"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","globalCompositeOperation":"source-over","path":"http://example.com/","pathOffset":{"x":200,"y":200}}],"background":""}'; var RECT_JSON = '{"objects":[{"type":"rect","originX":"left","originY":"top","left":0,"top":0,"width":10,"height":10,"fill":"rgb(0,0,0)",'+ '"stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,'+ '"shadow":null,'+ - '"visible":true,"clipTo":null,"backgroundColor":"","rx":0,"ry":0}],"background":"#ff5555","overlay":"rgba(0,0,0,0.2)"}'; + '"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","globalCompositeOperation":"source-over","rx":0,"ry":0}],"background":"#ff5555","overlay":"rgba(0,0,0,0.2)"}'; var el = fabric.document.createElement('canvas'); el.width = 600; el.height = 600; diff --git a/test/unit/canvas_static.js b/test/unit/canvas_static.js index bc178a42..172df76e 100644 --- a/test/unit/canvas_static.js +++ b/test/unit/canvas_static.js @@ -28,17 +28,17 @@ var PATH_DATALESS_JSON = '{"objects":[{"type":"path","originX":"left","originY":"top","left":100,"top":100,"width":200,"height":200,"fill":"rgb(0,0,0)",'+ '"stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,'+ '"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,'+ - '"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","path":"http://example.com/","pathOffset":{"x":200,"y":200}}],"background":""}'; + '"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","globalCompositeOperation":"source-over","path":"http://example.com/","pathOffset":{"x":200,"y":200}}],"background":""}'; var RECT_JSON = '{"objects":[{"type":"rect","originX":"left","originY":"top","left":0,"top":0,"width":10,"height":10,"fill":"rgb(0,0,0)",'+ '"stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,'+ '"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,'+ - '"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","rx":0,"ry":0}],"background":"#ff5555","overlay":"rgba(0,0,0,0.2)"}'; + '"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","globalCompositeOperation":"source-over","rx":0,"ry":0}],"background":"#ff5555","overlay":"rgba(0,0,0,0.2)"}'; var RECT_JSON_WITH_PADDING = '{"objects":[{"type":"rect","originX":"left","originY":"top","left":0,"top":0,"width":10,"height":20,"fill":"rgb(0,0,0)",'+ '"stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,'+ '"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,'+ - '"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","padding":123,"foo":"bar","rx":0,"ry":0}],"background":""}'; + '"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","globalCompositeOperation":"source-over","padding":123,"foo":"bar","rx":0,"ry":0}],"background":""}'; function getAbsolutePath(path) { var isAbsolute = /^https?:/.test(path); @@ -55,33 +55,35 @@ IMG_HEIGHT = 110; var REFERENCE_IMG_OBJECT = { - 'type': 'image', - 'originX': 'left', - 'originY': 'top', - 'left': 0, - 'top': 0, - 'width': IMG_WIDTH, // node-canvas doesn't seem to allow setting width/height on image objects - 'height': IMG_HEIGHT, // or does it now? - 'fill': 'rgb(0,0,0)', - 'stroke': null, - 'strokeWidth': 1, - 'strokeDashArray': null, - 'strokeLineCap': 'butt', - 'strokeLineJoin': 'miter', - 'strokeMiterLimit': 10, - 'scaleX': 1, - 'scaleY': 1, - 'angle': 0, - 'flipX': false, - 'flipY': false, - 'opacity': 1, - 'src': fabric.isLikelyNode ? undefined : IMG_SRC, - 'shadow': null, - 'visible': true, - 'backgroundColor': '', - 'clipTo': null, - 'filters': [], - 'crossOrigin': '' + 'type': 'image', + 'originX': 'left', + 'originY': 'top', + 'left': 0, + 'top': 0, + 'width': IMG_WIDTH, // node-canvas doesn't seem to allow setting width/height on image objects + 'height': IMG_HEIGHT, // or does it now? + 'fill': 'rgb(0,0,0)', + 'stroke': null, + 'strokeWidth': 1, + 'strokeDashArray': null, + 'strokeLineCap': 'butt', + 'strokeLineJoin': 'miter', + 'strokeMiterLimit': 10, + 'scaleX': 1, + 'scaleY': 1, + 'angle': 0, + 'flipX': false, + 'flipY': false, + 'opacity': 1, + 'src': fabric.isLikelyNode ? undefined : IMG_SRC, + 'shadow': null, + 'visible': true, + 'backgroundColor': '', + 'clipTo': null, + 'filters': [], + 'crossOrigin': '', + 'fillRule': 'nonzero', + 'globalCompositeOperation': 'source-over' }; function _createImageElement() { diff --git a/test/unit/circle.js b/test/unit/circle.js index f780cca6..e79863e5 100644 --- a/test/unit/circle.js +++ b/test/unit/circle.js @@ -79,33 +79,35 @@ test('toObject', function() { var circle = new fabric.Circle(); var defaultProperties = { - 'type': 'circle', - 'originX': 'left', - 'originY': 'top', - 'left': 0, - 'top': 0, - 'width': 0, - 'height': 0, - 'fill': 'rgb(0,0,0)', - 'stroke': null, - 'strokeWidth': 1, - 'strokeDashArray': null, - 'strokeLineCap': 'butt', - 'strokeLineJoin': 'miter', - 'strokeMiterLimit': 10, - 'scaleX': 1, - 'scaleY': 1, - 'angle': 0, - 'flipX': false, - 'flipY': false, - 'opacity': 1, - 'shadow': null, - 'visible': true, - 'backgroundColor': '', - 'clipTo': null, - 'radius': 0, - 'startAngle': 0, - 'endAngle': 2 * Math.PI + 'type': 'circle', + 'originX': 'left', + 'originY': 'top', + 'left': 0, + 'top': 0, + 'width': 0, + 'height': 0, + 'fill': 'rgb(0,0,0)', + 'stroke': null, + 'strokeWidth': 1, + 'strokeDashArray': null, + 'strokeLineCap': 'butt', + 'strokeLineJoin': 'miter', + 'strokeMiterLimit': 10, + 'scaleX': 1, + 'scaleY': 1, + 'angle': 0, + 'flipX': false, + 'flipY': false, + 'opacity': 1, + 'shadow': null, + 'visible': true, + 'backgroundColor': '', + 'clipTo': null, + 'fillRule': 'nonzero', + 'globalCompositeOperation': 'source-over', + 'radius': 0, + 'startAngle': 0, + 'endAngle': 2 * Math.PI }; ok(typeof circle.toObject == 'function'); deepEqual(circle.toObject(), defaultProperties); diff --git a/test/unit/ellipse.js b/test/unit/ellipse.js index 88f43e1b..814fd753 100644 --- a/test/unit/ellipse.js +++ b/test/unit/ellipse.js @@ -22,32 +22,34 @@ test('toObject', function() { var ellipse = new fabric.Ellipse(); var defaultProperties = { - 'type': 'ellipse', - 'originX': 'left', - 'originY': 'top', - 'left': 0, - 'top': 0, - 'width': 0, - 'height': 0, - 'fill': 'rgb(0,0,0)', - 'stroke': null, - 'strokeWidth': 1, - 'strokeDashArray': null, - 'strokeLineCap': 'butt', - 'strokeLineJoin': 'miter', - 'strokeMiterLimit': 10, - 'scaleX': 1, - 'scaleY': 1, - 'angle': 0, - 'flipX': false, - 'flipY': false, - 'opacity': 1, - 'rx': 0, - 'ry': 0, - 'shadow': null, - 'visible': true, - 'backgroundColor': '', - 'clipTo': null + 'type': 'ellipse', + 'originX': 'left', + 'originY': 'top', + 'left': 0, + 'top': 0, + 'width': 0, + 'height': 0, + 'fill': 'rgb(0,0,0)', + 'stroke': null, + 'strokeWidth': 1, + 'strokeDashArray': null, + 'strokeLineCap': 'butt', + 'strokeLineJoin': 'miter', + 'strokeMiterLimit': 10, + 'scaleX': 1, + 'scaleY': 1, + 'angle': 0, + 'flipX': false, + 'flipY': false, + 'opacity': 1, + 'rx': 0, + 'ry': 0, + 'shadow': null, + 'visible': true, + 'backgroundColor': '', + 'fillRule': 'nonzero', + 'globalCompositeOperation': 'source-over', + 'clipTo': null }; ok(typeof ellipse.toObject == 'function'); deepEqual(ellipse.toObject(), defaultProperties); diff --git a/test/unit/group.js b/test/unit/group.js index 047d3282..7f6d7319 100644 --- a/test/unit/group.js +++ b/test/unit/group.js @@ -154,31 +154,33 @@ var clone = group.toObject(); var expectedObject = { - 'type': 'group', - 'originX': 'left', - 'originY': 'top', - 'left': 90, - 'top': 130, - 'width': 80, - 'height': 60, - 'fill': 'rgb(0,0,0)', - 'stroke': null, - 'strokeWidth': 1, - 'strokeDashArray': null, - 'strokeLineCap': 'butt', - 'strokeLineJoin': 'miter', - 'strokeMiterLimit': 10, - 'scaleX': 1, - 'scaleY': 1, - 'shadow': null, - 'visible': true, - 'backgroundColor': '', - 'clipTo': null, - 'angle': 0, - 'flipX': false, - 'flipY': false, - 'opacity': 1, - 'objects': clone.objects + 'type': 'group', + 'originX': 'left', + 'originY': 'top', + 'left': 90, + 'top': 130, + 'width': 80, + 'height': 60, + 'fill': 'rgb(0,0,0)', + 'stroke': null, + 'strokeWidth': 1, + 'strokeDashArray': null, + 'strokeLineCap': 'butt', + 'strokeLineJoin': 'miter', + 'strokeMiterLimit': 10, + 'scaleX': 1, + 'scaleY': 1, + 'shadow': null, + 'visible': true, + 'backgroundColor': '', + 'clipTo': null, + 'angle': 0, + 'flipX': false, + 'flipY': false, + 'opacity': 1, + 'fillRule': 'nonzero', + 'globalCompositeOperation': 'source-over', + 'objects': clone.objects }; deepEqual(clone, expectedObject); @@ -384,7 +386,7 @@ test('toObject without default values', function() { var group = makeGroupWith2Objects(); ok(typeof group.toSVG == 'function'); - var expectedSVG = '\n\n\n\n'; + var expectedSVG = '\n\n\n\n'; equal(group.toSVG(), expectedSVG); }); diff --git a/test/unit/image.js b/test/unit/image.js index 24134a58..6076b45a 100644 --- a/test/unit/image.js +++ b/test/unit/image.js @@ -15,33 +15,35 @@ IMG_HEIGHT = 110; var REFERENCE_IMG_OBJECT = { - 'type': 'image', - 'originX': 'left', - 'originY': 'top', - 'left': 0, - 'top': 0, - 'width': IMG_WIDTH, // node-canvas doesn't seem to allow setting width/height on image objects - 'height': IMG_HEIGHT, // or does it now? - 'fill': 'rgb(0,0,0)', - 'stroke': null, - 'strokeWidth': 1, - 'strokeDashArray': null, - 'strokeLineCap': 'butt', - 'strokeLineJoin': 'miter', - 'strokeMiterLimit': 10, - 'scaleX': 1, - 'scaleY': 1, - 'angle': 0, - 'flipX': false, - 'flipY': false, - 'opacity': 1, - 'src': fabric.isLikelyNode ? undefined : IMG_SRC, - 'shadow': null, - 'visible': true, - 'backgroundColor': '', - 'clipTo': null, - 'filters': [], - 'crossOrigin': '' + 'type': 'image', + 'originX': 'left', + 'originY': 'top', + 'left': 0, + 'top': 0, + 'width': IMG_WIDTH, // node-canvas doesn't seem to allow setting width/height on image objects + 'height': IMG_HEIGHT, // or does it now? + 'fill': 'rgb(0,0,0)', + 'stroke': null, + 'strokeWidth': 1, + 'strokeDashArray': null, + 'strokeLineCap': 'butt', + 'strokeLineJoin': 'miter', + 'strokeMiterLimit': 10, + 'scaleX': 1, + 'scaleY': 1, + 'angle': 0, + 'flipX': false, + 'flipY': false, + 'opacity': 1, + 'src': fabric.isLikelyNode ? undefined : IMG_SRC, + 'shadow': null, + 'visible': true, + 'backgroundColor': '', + 'clipTo': null, + 'filters': [], + 'crossOrigin': '', + 'fillRule': 'nonzero', + 'globalCompositeOperation': 'source-over' }; function _createImageElement() { diff --git a/test/unit/itext.js b/test/unit/itext.js index d7b306ea..114566ae 100644 --- a/test/unit/itext.js +++ b/test/unit/itext.js @@ -3,42 +3,44 @@ QUnit.module('fabric.IText'); var ITEXT_OBJECT = { - 'type': 'text', - 'originX': 'left', - 'originY': 'top', - 'left': 0, - 'top': 0, - 'width': 20, - 'height': 52, - 'fill': 'rgb(0,0,0)', - 'stroke': null, - 'strokeWidth': 1, - 'strokeDashArray': null, - 'strokeLineCap': 'butt', - 'strokeLineJoin': 'miter', - 'strokeMiterLimit': 10, - 'scaleX': 1, - 'scaleY': 1, - 'angle': 0, - 'flipX': false, - 'flipY': false, - 'opacity': 1, - 'shadow': null, - 'visible': true, - 'clipTo': null, - 'text': 'x', - 'fontSize': 40, - 'fontWeight': 'normal', - 'fontFamily': 'Times New Roman', - 'fontStyle': '', - 'lineHeight': 1.3, - 'textDecoration': '', - 'textAlign': 'left', - 'path': null, - 'backgroundColor': '', - 'textBackgroundColor': '', - 'useNative': true, - styles: { } + 'type': 'text', + 'originX': 'left', + 'originY': 'top', + 'left': 0, + 'top': 0, + 'width': 20, + 'height': 52, + 'fill': 'rgb(0,0,0)', + 'stroke': null, + 'strokeWidth': 1, + 'strokeDashArray': null, + 'strokeLineCap': 'butt', + 'strokeLineJoin': 'miter', + 'strokeMiterLimit': 10, + 'scaleX': 1, + 'scaleY': 1, + 'angle': 0, + 'flipX': false, + 'flipY': false, + 'opacity': 1, + 'shadow': null, + 'visible': true, + 'clipTo': null, + 'text': 'x', + 'fontSize': 40, + 'fontWeight': 'normal', + 'fontFamily': 'Times New Roman', + 'fontStyle': '', + 'lineHeight': 1.3, + 'textDecoration': '', + 'textAlign': 'left', + 'path': null, + 'backgroundColor': '', + 'textBackgroundColor': '', + 'useNative': true, + 'fillRule': 'nonzero', + 'globalCompositeOperation': 'source-over', + styles: { } }; test('constructor', function() { diff --git a/test/unit/line.js b/test/unit/line.js index 1c0ced12..4d1f37ca 100644 --- a/test/unit/line.js +++ b/test/unit/line.js @@ -1,34 +1,36 @@ (function(){ var LINE_OBJECT = { - 'type': 'line', - 'originX': 'left', - 'originY': 'top', - 'left': 11, - 'top': 12, - 'width': 2, - 'height': 2, - 'fill': 'rgb(0,0,0)', - 'stroke': null, - 'strokeWidth': 1, - 'strokeDashArray': null, - 'strokeLineCap': 'butt', - 'strokeLineJoin': 'miter', - 'strokeMiterLimit': 10, - 'scaleX': 1, - 'scaleY': 1, - 'angle': 0, - 'flipX': false, - 'flipY': false, - 'opacity': 1, - 'x1': 11, - 'y1': 12, - 'x2': 13, - 'y2': 14, - 'shadow': null, - 'visible': true, - 'clipTo': null, - 'backgroundColor': '' + 'type': 'line', + 'originX': 'left', + 'originY': 'top', + 'left': 11, + 'top': 12, + 'width': 2, + 'height': 2, + 'fill': 'rgb(0,0,0)', + 'stroke': null, + 'strokeWidth': 1, + 'strokeDashArray': null, + 'strokeLineCap': 'butt', + 'strokeLineJoin': 'miter', + 'strokeMiterLimit': 10, + 'scaleX': 1, + 'scaleY': 1, + 'angle': 0, + 'flipX': false, + 'flipY': false, + 'opacity': 1, + 'x1': 11, + 'y1': 12, + 'x2': 13, + 'y2': 14, + 'shadow': null, + 'visible': true, + 'clipTo': null, + 'backgroundColor': '', + 'fillRule': 'nonzero', + 'globalCompositeOperation': 'source-over' }; QUnit.module('fabric.Line'); diff --git a/test/unit/object.js b/test/unit/object.js index 984a55c4..d54acb90 100644 --- a/test/unit/object.js +++ b/test/unit/object.js @@ -153,12 +153,12 @@ var emptyObjectJSON = '{"type":"object","originX":"left","originY":"top","left":0,"top":0,"width":0,"height":0,"fill":"rgb(0,0,0)",'+ '"stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,'+ '"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,'+ - '"shadow":null,"visible":true,"clipTo":null,"backgroundColor":""}'; + '"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","globalCompositeOperation":"source-over"}'; var augmentedJSON = '{"type":"object","originX":"left","originY":"top","left":0,"top":0,"width":122,"height":0,"fill":"rgb(0,0,0)",'+ '"stroke":null,"strokeWidth":1,"strokeDashArray":[5,2],"strokeLineCap":"round","strokeLineJoin":"bevil","strokeMiterLimit":5,'+ '"scaleX":1.3,"scaleY":1,"angle":0,"flipX":false,"flipY":true,"opacity":0.88,'+ - '"shadow":null,"visible":true,"clipTo":null,"backgroundColor":""}'; + '"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","globalCompositeOperation":"source-over"}'; var cObj = new fabric.Object(); ok(typeof cObj.toJSON == 'function'); @@ -178,57 +178,61 @@ test('toObject', function() { var emptyObjectRepr = { - 'type': 'object', - 'originX': 'left', - 'originY': 'top', - 'left': 0, - 'top': 0, - 'width': 0, - 'height': 0, - 'fill': 'rgb(0,0,0)', - 'stroke': null, - 'strokeWidth': 1, - 'strokeDashArray': null, - 'strokeLineCap': 'butt', - 'strokeLineJoin': 'miter', - 'strokeMiterLimit': 10, - 'scaleX': 1, - 'scaleY': 1, - 'angle': 0, - 'flipX': false, - 'flipY': false, - 'opacity': 1, - 'shadow': null, - 'visible': true, - 'backgroundColor': '', - 'clipTo': null + 'type': 'object', + 'originX': 'left', + 'originY': 'top', + 'left': 0, + 'top': 0, + 'width': 0, + 'height': 0, + 'fill': 'rgb(0,0,0)', + 'stroke': null, + 'strokeWidth': 1, + 'strokeDashArray': null, + 'strokeLineCap': 'butt', + 'strokeLineJoin': 'miter', + 'strokeMiterLimit': 10, + 'scaleX': 1, + 'scaleY': 1, + 'angle': 0, + 'flipX': false, + 'flipY': false, + 'opacity': 1, + 'shadow': null, + 'visible': true, + 'backgroundColor': '', + 'clipTo': null, + 'fillRule': 'nonzero', + 'globalCompositeOperation': 'source-over' }; var augmentedObjectRepr = { - 'type': 'object', - 'originX': 'left', - 'originY': 'top', - 'left': 10, - 'top': 20, - 'width': 30, - 'height': 40, - 'fill': 'rgb(0,0,0)', - 'stroke': null, - 'strokeWidth': 1, - 'strokeDashArray': [5, 2], - 'strokeLineCap': 'round', - 'strokeLineJoin': 'bevil', - 'strokeMiterLimit': 5, - 'scaleX': 1, - 'scaleY': 1, - 'angle': 0, - 'flipX': true, - 'flipY': false, - 'opacity': 0.13, - 'shadow': null, - 'visible': true, - 'backgroundColor': '', - 'clipTo': null + 'type': 'object', + 'originX': 'left', + 'originY': 'top', + 'left': 10, + 'top': 20, + 'width': 30, + 'height': 40, + 'fill': 'rgb(0,0,0)', + 'stroke': null, + 'strokeWidth': 1, + 'strokeDashArray': [5, 2], + 'strokeLineCap': 'round', + 'strokeLineJoin': 'bevil', + 'strokeMiterLimit': 5, + 'scaleX': 1, + 'scaleY': 1, + 'angle': 0, + 'flipX': true, + 'flipY': false, + 'opacity': 0.13, + 'shadow': null, + 'visible': true, + 'backgroundColor': '', + 'clipTo': null, + 'fillRule': 'nonzero', + 'globalCompositeOperation': 'source-over' }; var cObj = new fabric.Object(); diff --git a/test/unit/parser.js b/test/unit/parser.js index 9c62f04e..a1c71f88 100644 --- a/test/unit/parser.js +++ b/test/unit/parser.js @@ -51,7 +51,7 @@ var element = fabric.document.createElement('path'); element.setAttribute('fill-rule', 'evenodd'); - deepEqual(fabric.parseAttributes(element, ['fill-rule']), { fillRule: 'destination-over' }); + deepEqual(fabric.parseAttributes(element, ['fill-rule']), { fillRule: 'evenodd' }); }); test('parseAttributesFillRuleWithoutTransformation', function() { diff --git a/test/unit/path.js b/test/unit/path.js index 358c879e..becc842d 100644 --- a/test/unit/path.js +++ b/test/unit/path.js @@ -1,32 +1,34 @@ (function() { var REFERENCE_PATH_OBJECT = { - 'type': 'path', - 'originX': 'left', - 'originY': 'top', - 'left': 100, - 'top': 100, - 'width': 200, - 'height': 200, - 'fill': 'red', - 'stroke': 'blue', - 'strokeWidth': 1, - 'strokeDashArray': null, - 'strokeLineCap': 'butt', - 'strokeLineJoin': 'miter', - 'strokeMiterLimit': 10, - 'scaleX': 1, - 'scaleY': 1, - 'angle': 0, - 'flipX': false, - 'flipY': false, - 'opacity': 1, - 'path': [['M', 100, 100], ['L', 300, 100], ['L', 200, 300], ['z']], - 'pathOffset': { x: 200, y: 200 }, - 'shadow': null, - 'visible': true, - 'backgroundColor': '', - 'clipTo': null + 'type': 'path', + 'originX': 'left', + 'originY': 'top', + 'left': 100, + 'top': 100, + 'width': 200, + 'height': 200, + 'fill': 'red', + 'stroke': 'blue', + 'strokeWidth': 1, + 'strokeDashArray': null, + 'strokeLineCap': 'butt', + 'strokeLineJoin': 'miter', + 'strokeMiterLimit': 10, + 'scaleX': 1, + 'scaleY': 1, + 'angle': 0, + 'flipX': false, + 'flipY': false, + 'opacity': 1, + 'path': [['M', 100, 100], ['L', 300, 100], ['L', 200, 300], ['z']], + 'pathOffset': { x: 200, y: 200 }, + 'shadow': null, + 'visible': true, + 'backgroundColor': '', + 'clipTo': null, + 'fillRule': 'nonzero', + 'globalCompositeOperation': 'source-over' }; function getPathElement(path) { diff --git a/test/unit/path_group.js b/test/unit/path_group.js index 29e5e190..ebcfa38b 100644 --- a/test/unit/path_group.js +++ b/test/unit/path_group.js @@ -1,31 +1,33 @@ (function(){ var REFERENCE_PATH_GROUP_OBJECT = { - 'type': 'path-group', - 'originX': 'left', - 'originY': 'top', - 'left': 0, - 'top': 0, - 'width': 0, - 'height': 0, - 'fill': '', - 'stroke': null, - 'strokeWidth': 1, - 'strokeDashArray': null, - 'strokeLineCap': 'butt', - 'strokeLineJoin': 'miter', - 'strokeMiterLimit': 10, - 'scaleX': 1, - 'scaleY': 1, - 'angle': 0, - 'flipX': false, - 'flipY': false, - 'opacity': 1, - 'shadow': null, - 'visible': true, - 'clipTo': null, - 'backgroundColor': '', - 'paths': getPathObjects() + 'type': 'path-group', + 'originX': 'left', + 'originY': 'top', + 'left': 0, + 'top': 0, + 'width': 0, + 'height': 0, + 'fill': '', + 'stroke': null, + 'strokeWidth': 1, + 'strokeDashArray': null, + 'strokeLineCap': 'butt', + 'strokeLineJoin': 'miter', + 'strokeMiterLimit': 10, + 'scaleX': 1, + 'scaleY': 1, + 'angle': 0, + 'flipX': false, + 'flipY': false, + 'opacity': 1, + 'shadow': null, + 'visible': true, + 'clipTo': null, + 'backgroundColor': '', + 'fillRule': 'nonzero', + 'globalCompositeOperation': 'source-over', + 'paths': getPathObjects() }; function getPathElement(path) { diff --git a/test/unit/polygon.js b/test/unit/polygon.js index 8df2a557..787d1f0f 100644 --- a/test/unit/polygon.js +++ b/test/unit/polygon.js @@ -8,31 +8,33 @@ } var REFERENCE_OBJECT = { - 'type': 'polygon', - 'originX': 'left', - 'originY': 'top', - 'left': 10, - 'top': 12, - 'width': 10, - 'height': 10, - 'fill': 'rgb(0,0,0)', - 'stroke': null, - 'strokeWidth': 1, - 'strokeDashArray': null, - 'strokeLineCap': 'butt', - 'strokeLineJoin': 'miter', - 'strokeMiterLimit': 10, - 'scaleX': 1, - 'scaleY': 1, - 'angle': 0, - 'flipX': false, - 'flipY': false, - 'opacity': 1, - 'points': getPoints(), - 'shadow': null, - 'visible': true, - 'backgroundColor': '', - 'clipTo': null + 'type': 'polygon', + 'originX': 'left', + 'originY': 'top', + 'left': 10, + 'top': 12, + 'width': 10, + 'height': 10, + 'fill': 'rgb(0,0,0)', + 'stroke': null, + 'strokeWidth': 1, + 'strokeDashArray': null, + 'strokeLineCap': 'butt', + 'strokeLineJoin': 'miter', + 'strokeMiterLimit': 10, + 'scaleX': 1, + 'scaleY': 1, + 'angle': 0, + 'flipX': false, + 'flipY': false, + 'opacity': 1, + 'points': getPoints(), + 'shadow': null, + 'visible': true, + 'backgroundColor': '', + 'clipTo': null, + 'fillRule': 'nonzero', + 'globalCompositeOperation': 'source-over' }; QUnit.module('fabric.Polygon'); diff --git a/test/unit/polyline.js b/test/unit/polyline.js index bf3f5d63..7ba51daf 100644 --- a/test/unit/polyline.js +++ b/test/unit/polyline.js @@ -8,31 +8,33 @@ } var REFERENCE_OBJECT = { - 'type': 'polyline', - 'originX': 'left', - 'originY': 'top', - 'left': 10, - 'top': 12, - 'width': 10, - 'height': 10, - 'fill': 'rgb(0,0,0)', - 'stroke': null, - 'strokeWidth': 1, - 'strokeDashArray': null, - 'strokeLineCap': 'butt', - 'strokeLineJoin': 'miter', - 'strokeMiterLimit': 10, - 'scaleX': 1, - 'scaleY': 1, - 'angle': 0, - 'flipX': false, - 'flipY': false, - 'opacity': 1, - 'points': getPoints(), - 'shadow': null, - 'visible': true, - 'backgroundColor': '', - 'clipTo': null + 'type': 'polyline', + 'originX': 'left', + 'originY': 'top', + 'left': 10, + 'top': 12, + 'width': 10, + 'height': 10, + 'fill': 'rgb(0,0,0)', + 'stroke': null, + 'strokeWidth': 1, + 'strokeDashArray': null, + 'strokeLineCap': 'butt', + 'strokeLineJoin': 'miter', + 'strokeMiterLimit': 10, + 'scaleX': 1, + 'scaleY': 1, + 'angle': 0, + 'flipX': false, + 'flipY': false, + 'opacity': 1, + 'points': getPoints(), + 'shadow': null, + 'visible': true, + 'backgroundColor': '', + 'clipTo': null, + 'fillRule': 'nonzero', + 'globalCompositeOperation': 'source-over' }; QUnit.module('fabric.Polyline'); diff --git a/test/unit/rect.js b/test/unit/rect.js index 5addeeec..67b76cb0 100644 --- a/test/unit/rect.js +++ b/test/unit/rect.js @@ -1,32 +1,34 @@ (function() { var REFERENCE_RECT = { - 'type': 'rect', - 'originX': 'left', - 'originY': 'top', - 'left': 0, - 'top': 0, - 'width': 0, - 'height': 0, - 'fill': 'rgb(0,0,0)', - 'stroke': null, - 'strokeWidth': 1, - 'strokeDashArray': null, - 'strokeLineCap': 'butt', - 'strokeLineJoin': 'miter', - 'strokeMiterLimit': 10, - 'scaleX': 1, - 'scaleY': 1, - 'angle': 0, - 'flipX': false, - 'flipY': false, - 'opacity': 1, - 'shadow': null, - 'visible': true, - 'backgroundColor': '', - 'clipTo': null, - 'rx': 0, - 'ry': 0, + 'type': 'rect', + 'originX': 'left', + 'originY': 'top', + 'left': 0, + 'top': 0, + 'width': 0, + 'height': 0, + 'fill': 'rgb(0,0,0)', + 'stroke': null, + 'strokeWidth': 1, + 'strokeDashArray': null, + 'strokeLineCap': 'butt', + 'strokeLineJoin': 'miter', + 'strokeMiterLimit': 10, + 'scaleX': 1, + 'scaleY': 1, + 'angle': 0, + 'flipX': false, + 'flipY': false, + 'opacity': 1, + 'shadow': null, + 'visible': true, + 'backgroundColor': '', + 'clipTo': null, + 'fillRule': 'nonzero', + 'globalCompositeOperation': 'source-over', + 'rx': 0, + 'ry': 0, }; QUnit.module('fabric.Rect'); @@ -131,7 +133,7 @@ var rect = new fabric.Rect({ width: 100, height: 100, rx: 20, ry: 30 }); var svg = rect.toSVG(); - equal(svg, '\n'); + equal(svg, '\n'); }); test('toObject without default values', function() { diff --git a/test/unit/text.js b/test/unit/text.js index d5c32366..682e5bdd 100644 --- a/test/unit/text.js +++ b/test/unit/text.js @@ -9,44 +9,46 @@ var CHAR_WIDTH = 20; var REFERENCE_TEXT_OBJECT = { - 'type': 'text', - 'originX': 'left', - 'originY': 'top', - 'left': 0, - 'top': 0, - 'width': CHAR_WIDTH, - 'height': 52, - 'fill': 'rgb(0,0,0)', - 'stroke': null, - 'strokeWidth': 1, - 'strokeDashArray': null, - 'strokeLineCap': 'butt', - 'strokeLineJoin': 'miter', - 'strokeMiterLimit': 10, - 'scaleX': 1, - 'scaleY': 1, - 'angle': 0, - 'flipX': false, - 'flipY': false, - 'opacity': 1, - 'shadow': null, - 'visible': true, - 'clipTo': null, - 'backgroundColor': '', - 'text': 'x', - 'fontSize': 40, - 'fontWeight': 'normal', - 'fontFamily': 'Times New Roman', - 'fontStyle': '', - 'lineHeight': 1.3, - 'textDecoration': '', - 'textAlign': 'left', - 'path': null, - 'textBackgroundColor': '', - 'useNative': true + 'type': 'text', + 'originX': 'left', + 'originY': 'top', + 'left': 0, + 'top': 0, + 'width': CHAR_WIDTH, + 'height': 52, + 'fill': 'rgb(0,0,0)', + 'stroke': null, + 'strokeWidth': 1, + 'strokeDashArray': null, + 'strokeLineCap': 'butt', + 'strokeLineJoin': 'miter', + 'strokeMiterLimit': 10, + 'scaleX': 1, + 'scaleY': 1, + 'angle': 0, + 'flipX': false, + 'flipY': false, + 'opacity': 1, + 'shadow': null, + 'visible': true, + 'clipTo': null, + 'backgroundColor': '', + 'text': 'x', + 'fontSize': 40, + 'fontWeight': 'normal', + 'fontFamily': 'Times New Roman', + 'fontStyle': '', + 'lineHeight': 1.3, + 'textDecoration': '', + 'textAlign': 'left', + 'path': null, + 'textBackgroundColor': '', + 'useNative': true, + 'fillRule': 'nonzero', + 'globalCompositeOperation': 'source-over' }; - var TEXT_SVG = '\nx\n\n'; + var TEXT_SVG = '\nx\n\n'; test('constructor', function() { ok(fabric.Text);