diff --git a/src/mixins/itext_click_behavior.mixin.js b/src/mixins/itext_click_behavior.mixin.js index d865c7a7411..e654e5d4b12 100644 --- a/src/mixins/itext_click_behavior.mixin.js +++ b/src/mixins/itext_click_behavior.mixin.js @@ -84,7 +84,9 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot */ initMousedownHandler: function() { this.on('mousedown', function(options) { - + if (!this.editable) { + return; + } var pointer = this.canvas.getPointer(options.e); this.__mousedownX = pointer.x; @@ -122,7 +124,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot initMouseupHandler: function() { this.on('mouseup', function(options) { this.__isMousedown = false; - if (this._isObjectMoved(options.e)) { + if (!this.editable || this._isObjectMoved(options.e)) { return; } diff --git a/src/mixins/object.svg_export.js b/src/mixins/object.svg_export.js index acb86998616..20e85462027 100644 --- a/src/mixins/object.svg_export.js +++ b/src/mixins/object.svg_export.js @@ -60,8 +60,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot angle = this.getAngle(), skewX = (this.getSkewX() % 360), skewY = (this.getSkewY() % 360), - vpt = !this.canvas || this.canvas.svgViewportTransformation ? this.getViewportTransform() : [1, 0, 0, 1, 0, 0], - center = fabric.util.transformPoint(this.getCenterPoint(), vpt), + center = this.getCenterPoint(), NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS, @@ -75,23 +74,23 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot ? (' rotate(' + toFixed(angle, NUM_FRACTION_DIGITS) + ')') : '', - scalePart = (this.scaleX === 1 && this.scaleY === 1 && vpt[0] === 1 && vpt[3] === 1) + scalePart = (this.scaleX === 1 && this.scaleY === 1) ? '' : (' scale(' + - toFixed(this.scaleX * vpt[0], NUM_FRACTION_DIGITS) + + toFixed(this.scaleX, NUM_FRACTION_DIGITS) + ' ' + - toFixed(this.scaleY * vpt[3], NUM_FRACTION_DIGITS) + + toFixed(this.scaleY, NUM_FRACTION_DIGITS) + ')'), skewXPart = skewX !== 0 ? ' skewX(' + toFixed(skewX, NUM_FRACTION_DIGITS) + ')' : '', skewYPart = skewY !== 0 ? ' skewY(' + toFixed(skewY, NUM_FRACTION_DIGITS) + ')' : '', - addTranslateX = this.type === 'path-group' ? this.width * vpt[0] : 0, + addTranslateX = this.type === 'path-group' ? this.width : 0, flipXPart = this.flipX ? ' matrix(-1 0 0 1 ' + addTranslateX + ' 0) ' : '', - addTranslateY = this.type === 'path-group' ? this.height * vpt[3] : 0, + addTranslateY = this.type === 'path-group' ? this.height : 0, flipYPart = this.flipY ? ' matrix(1 0 0 -1 0 ' + addTranslateY + ')' : ''; diff --git a/src/parser.js b/src/parser.js index 6b42c0630fb..adddcc5ecec 100644 --- a/src/parser.js +++ b/src/parser.js @@ -130,12 +130,16 @@ */ fabric.parseTransformAttribute = (function() { function rotateMatrix(matrix, args) { - var angle = args[0]; + var angle = args[0], + x = (args.length === 3) ? args[1] : 0, + y = (args.length === 3) ? args[2] : 0; matrix[0] = Math.cos(angle); matrix[1] = Math.sin(angle); matrix[2] = -Math.sin(angle); matrix[3] = Math.cos(angle); + matrix[4] = x - (matrix[0] * x + matrix[2] * y); + matrix[5] = y - (matrix[1] * x + matrix[3] * y); } function scaleMatrix(matrix, args) { diff --git a/src/shapes/group.class.js b/src/shapes/group.class.js index 5c0e7979144..21e8a51c5f5 100644 --- a/src/shapes/group.class.js +++ b/src/shapes/group.class.js @@ -209,7 +209,8 @@ */ delegatedProperties: { fill: true, - opacity: true, + stroke: true, + strokeWidth: true, fontFamily: true, fontWeight: true, fontSize: true, diff --git a/src/static_canvas.class.js b/src/static_canvas.class.js index 57565a02db7..2823fdab4e5 100644 --- a/src/static_canvas.class.js +++ b/src/static_canvas.class.js @@ -11,6 +11,7 @@ var extend = fabric.util.object.extend, getElementOffset = fabric.util.getElementOffset, removeFromArray = fabric.util.removeFromArray, + toFixed = fabric.util.toFixed, CANVAS_INIT_ERROR = new Error('Could not initialize `canvas` element'); @@ -1183,6 +1184,8 @@ * @param {Number} [options.viewBox.width] Width of viewbox * @param {Number} [options.viewBox.height] Height of viewbox * @param {String} [options.encoding=UTF-8] Encoding of SVG output + * @param {String} [options.width] desired width of svg with or without units + * @param {String} [options.height] desired height of svg with or without units * @param {Function} [reviver] Method for further parsing of svg elements, called after each fabric object converted into svg representation. * @return {String} SVG string * @tutorial {@link http://fabricjs.com/fabric-intro-part-3/#serialization} @@ -1232,32 +1235,40 @@ * @private */ _setSVGPreamble: function(markup, options) { - if (!options.suppressPreamble) { - markup.push( - '\n', - '\n' - ); + if (options.suppressPreamble) { + return; } + markup.push( + '\n', + '\n' + ); }, /** * @private */ _setSVGHeader: function(markup, options) { - var width, height, vpt; + var width = options.width || this.width, + height = options.height || this.height, + vpt, viewBox = 'viewBox="0 0 ' + this.width + ' ' + this.height + '" ', + NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS; if (options.viewBox) { - width = options.viewBox.width; - height = options.viewBox.height; + viewBox = 'viewBox="' + + options.viewBox.x + ' ' + + options.viewBox.y + ' ' + + options.viewBox.width + ' ' + + options.viewBox.height + '" '; } else { - width = this.width; - height = this.height; - if (!this.svgViewportTransformation) { + if (this.svgViewportTransformation) { vpt = this.viewportTransform; - width /= vpt[0]; - height /= vpt[3]; + viewBox = 'viewBox="' + + toFixed(-vpt[4] / vpt[0], NUM_FRACTION_DIGITS) + ' ' + + toFixed(-vpt[5] / vpt[3], NUM_FRACTION_DIGITS) + ' ' + + toFixed(this.width / vpt[0], NUM_FRACTION_DIGITS) + ' ' + + toFixed(this.height / vpt[3], NUM_FRACTION_DIGITS) + '" '; } } @@ -1271,13 +1282,7 @@ (this.backgroundColor && !this.backgroundColor.toLive ? 'style="background-color: ' + this.backgroundColor + '" ' : null), - (options.viewBox - ? 'viewBox="' + - options.viewBox.x + ' ' + - options.viewBox.y + ' ' + - options.viewBox.width + ' ' + - options.viewBox.height + '" ' - : null), + viewBox, 'xml:space="preserve">\n', 'Created with Fabric.js ', fabric.version, '\n', '', diff --git a/test/unit/canvas_static.js b/test/unit/canvas_static.js index 8029671e325..359b63a37b2 100644 --- a/test/unit/canvas_static.js +++ b/test/unit/canvas_static.js @@ -3,10 +3,10 @@ // var emptyImageCanvasData = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAfQAAAH0CAYAAADL1t+KAAAH7ElEQVR4nO3VMQ0AMAzAsPInvYHoMS2yEeTLHADge/M6AADYM3QACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIMHQACDB0AAgwdAAIuMjH4b7osLFBAAAAAElFTkSuQmCC"; var CANVAS_SVG = '\n\n'+ - '\nCreated with Fabric.js ' + fabric.version + '\n\n'; + '\nCreated with Fabric.js ' + fabric.version + '\n\n'; var CANVAS_SVG_VIEWBOX = '\n\n'+ - '\nCreated with Fabric.js ' + fabric.version + '\n\n'; + '\nCreated with Fabric.js ' + fabric.version + '\n\n'; var PATH_JSON = '{"objects": [{"type": "path", "originX": "left", "originY": "top", "left": 268, "top": 266, "width": 51, "height": 49,'+ ' "fill": "rgb(0,0,0)", "stroke": null, "strokeWidth": 1, "scaleX": 1, "scaleY": 1, '+ diff --git a/test/unit/shadow.js b/test/unit/shadow.js index 9f0fe6365bc..3fa28c7462f 100644 --- a/test/unit/shadow.js +++ b/test/unit/shadow.js @@ -132,15 +132,17 @@ ok(typeof shadow.toObject == 'function'); var object = shadow.toObject(); - equal(JSON.stringify(object), '{"color":"rgb(0,0,0)","blur":0,"offsetX":0,"offsetY":0}'); + equal(JSON.stringify(object), '{"color":"rgb(0,0,0)","blur":0,"offsetX":0,"offsetY":0,"affectStroke":false}'); }); test('clone with affectStroke', function() { var shadow = new fabric.Shadow({affectStroke: true, blur: 5}); ok(typeof shadow.toObject == 'function'); var object = shadow.toObject(), - shadow2 = new fabric.Shadow(object); - deepEqual(shadow, shadow2); + shadow2 = new fabric.Shadow(object), + object2 = shadow2.toObject(); + equal(shadow.affectStroke, shadow2.affectStroke) + deepEqual(object, object2); }); test('toObject without default value', function() {