From b661774a3d392713e6db491c11eb8ff7054164eb Mon Sep 17 00:00:00 2001 From: Brian Hernandez Date: Mon, 22 Feb 2016 14:06:24 -0500 Subject: [PATCH 01/28] Add a non-technical intro to Fabric --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index d2f85ff2..20f9f29a 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,11 @@ Using Fabric.js, you can create and populate objects on canvas; objects like simple geometrical shapes — rectangles, circles, ellipses, polygons, or more complex shapes consisting of hundreds or thousands of simple paths. You can then scale, move, and rotate these objects with the mouse; modify their properties — color, transparency, z-index, etc. You can also manipulate these objects altogether — grouping them with a simple mouse selection. +### Non-Technical Introduction to Fabric + +Fabric.js allows you to easily create simple shapes like rectangles, circles, triangles and other polygons or more complex shapes made up of many paths, onto the HTML `` element on a webpage using JavaScript. Fabric.js will then allow you to manipulate the size, position and rotation of these objects with a mouse. It’s also possible to change some of the attributes of these objects such as their color, transparency, depth position on the webpage or selecting groups of these objects using the Fabric.js library. Fabric.js will even allow you to convert an SVG image into JavaScript data that can be using for putting it onto the `` element. + + [Contributions](https://github.com/kangax/fabric.js/wiki/Love-Fabric%3F-Help-us-by...) are very much welcome! ### Goals From 381f959f545ce5b170e6384a81c8a8aecbdef6e6 Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Wed, 24 Feb 2016 08:44:21 +0100 Subject: [PATCH 02/28] move retina logic check in a function --- src/static_canvas.class.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/static_canvas.class.js b/src/static_canvas.class.js index 71743faf..4737a858 100644 --- a/src/static_canvas.class.js +++ b/src/static_canvas.class.js @@ -191,11 +191,18 @@ this.calcOffset(); }, + /** + * @private + */ + _isRetinaScaling: function() { + return (fabric.devicePixelRatio !== 1 && this.enableRetinaScaling); + }, + /** * @private */ _initRetinaScaling: function() { - if (fabric.devicePixelRatio === 1 || !this.enableRetinaScaling) { + if (!this._isRetinaScaling()) { return; } From db068d59c93bda1395770ca428a51fc90250dbe7 Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Wed, 24 Feb 2016 08:45:15 +0100 Subject: [PATCH 03/28] enlarge shadow if retina scaling is active --- src/shapes/object.class.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/shapes/object.class.js b/src/shapes/object.class.js index 51314cb0..f6c327ba 100644 --- a/src/shapes/object.class.js +++ b/src/shapes/object.class.js @@ -1109,7 +1109,10 @@ var multX = (this.canvas && this.canvas.viewportTransform[0]) || 1, multY = (this.canvas && this.canvas.viewportTransform[3]) || 1; - + if (this._isRetinaScaling()) { + multX *= fabric.devicePixelRatio; + multY *= fabric.devicePixelRatio; + } ctx.shadowColor = this.shadow.color; ctx.shadowBlur = this.shadow.blur * (multX + multY) * (this.scaleX + this.scaleY) / 4; ctx.shadowOffsetX = this.shadow.offsetX * multX * this.scaleX; From df1cffaadee9bbc34d9a56f1a43689ef395637ab Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Wed, 24 Feb 2016 08:47:27 +0100 Subject: [PATCH 04/28] add retina scaling effect to dataUrl exporter Add retina scaling as a normal dataurl multiplier. Removed setWidth and setHeight in favor of setDimensions Removed rescaling back of canvas because setDimension will clear the transform anyway. --- src/mixins/canvas_dataurl_exporter.mixin.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/mixins/canvas_dataurl_exporter.mixin.js b/src/mixins/canvas_dataurl_exporter.mixin.js index f65775b8..2f30fec8 100644 --- a/src/mixins/canvas_dataurl_exporter.mixin.js +++ b/src/mixins/canvas_dataurl_exporter.mixin.js @@ -44,6 +44,10 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati height: options.height }; + if (this._isRetinaScaling()) { + multiplier *= fabric.devicePixelRatio; + } + if (multiplier !== 1) { return this.__toDataURLWithMultiplier(format, quality, cropping, multiplier); } @@ -111,16 +115,18 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati var origWidth = this.getWidth(), origHeight = this.getHeight(), + origRetinaScaling = this.enableRetinaScaling, scaledWidth = origWidth * multiplier, scaledHeight = origHeight * multiplier, activeObject = this.getActiveObject(), activeGroup = this.getActiveGroup(), - ctx = this.contextContainer; + this.enableRetinaScaling = false; if (multiplier > 1) { - this.setWidth(scaledWidth).setHeight(scaledHeight); + this.setDimensions({width: scaledWidth, height: scaledHeight}); } + ctx.save(); ctx.scale(multiplier, multiplier); if (cropping.left) { @@ -156,9 +162,8 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati // background properly (while context is scaled) this.width = origWidth; this.height = origHeight; - - ctx.scale(1 / multiplier, 1 / multiplier); - this.setWidth(origWidth).setHeight(origHeight); + this.enableRetinaScaling = origRetinaScaling; + this.setDimensions({width: origWidth, height: origHeight}); if (activeGroup) { this._restoreBordersControlsOnGroup(activeGroup); From 873abee42231e42e544b773e40e3b4d228c57189 Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Thu, 25 Feb 2016 00:30:49 +0100 Subject: [PATCH 05/28] fixes lint --- src/mixins/canvas_dataurl_exporter.mixin.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mixins/canvas_dataurl_exporter.mixin.js b/src/mixins/canvas_dataurl_exporter.mixin.js index 2f30fec8..ab47d95d 100644 --- a/src/mixins/canvas_dataurl_exporter.mixin.js +++ b/src/mixins/canvas_dataurl_exporter.mixin.js @@ -124,7 +124,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati this.enableRetinaScaling = false; if (multiplier > 1) { - this.setDimensions({width: scaledWidth, height: scaledHeight}); + this.setDimensions({ width: scaledWidth, height: scaledHeight }); } ctx.save(); ctx.scale(multiplier, multiplier); @@ -163,7 +163,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati this.width = origWidth; this.height = origHeight; this.enableRetinaScaling = origRetinaScaling; - this.setDimensions({width: origWidth, height: origHeight}); + this.setDimensions({ width: origWidth, height: origHeight }); if (activeGroup) { this._restoreBordersControlsOnGroup(activeGroup); From bd345a39d5e960a27cde63de0c007ab3990dcd9f Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Thu, 25 Feb 2016 00:50:10 +0100 Subject: [PATCH 06/28] Update object.class.js --- src/shapes/object.class.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shapes/object.class.js b/src/shapes/object.class.js index f6c327ba..62d3b941 100644 --- a/src/shapes/object.class.js +++ b/src/shapes/object.class.js @@ -1109,7 +1109,7 @@ var multX = (this.canvas && this.canvas.viewportTransform[0]) || 1, multY = (this.canvas && this.canvas.viewportTransform[3]) || 1; - if (this._isRetinaScaling()) { + if (this.canvas && this.canvas.isRetinaScaling()) { multX *= fabric.devicePixelRatio; multY *= fabric.devicePixelRatio; } From b4f99d96a9ad74e72345e6b35e47b50958971ca6 Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Thu, 25 Feb 2016 00:52:51 +0100 Subject: [PATCH 07/28] Update canvas_dataurl_exporter.mixin.js --- src/mixins/canvas_dataurl_exporter.mixin.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/mixins/canvas_dataurl_exporter.mixin.js b/src/mixins/canvas_dataurl_exporter.mixin.js index ab47d95d..566026a4 100644 --- a/src/mixins/canvas_dataurl_exporter.mixin.js +++ b/src/mixins/canvas_dataurl_exporter.mixin.js @@ -115,19 +115,17 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati var origWidth = this.getWidth(), origHeight = this.getHeight(), - origRetinaScaling = this.enableRetinaScaling, scaledWidth = origWidth * multiplier, scaledHeight = origHeight * multiplier, activeObject = this.getActiveObject(), activeGroup = this.getActiveGroup(), ctx = this.contextContainer; - this.enableRetinaScaling = false; if (multiplier > 1) { this.setDimensions({ width: scaledWidth, height: scaledHeight }); } ctx.save(); - ctx.scale(multiplier, multiplier); + ctx.scale(multiplier / fabric.devicePixelRatio, multiplier / fabric.devicePixelRatio); if (cropping.left) { cropping.left *= multiplier; @@ -162,7 +160,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati // background properly (while context is scaled) this.width = origWidth; this.height = origHeight; - this.enableRetinaScaling = origRetinaScaling; this.setDimensions({ width: origWidth, height: origHeight }); if (activeGroup) { From f15b7f5d3c1aafb9afc28927c5872d0e705cefe6 Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Thu, 25 Feb 2016 02:46:05 +0100 Subject: [PATCH 08/28] Update text.class.js --- src/shapes/text.class.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/shapes/text.class.js b/src/shapes/text.class.js index fb448ccd..e4e2d968 100644 --- a/src/shapes/text.class.js +++ b/src/shapes/text.class.js @@ -624,7 +624,9 @@ this.width, this.height ); - + // if there is background color no other shadows + // should be casted + this._removeShadow(ctx); }, /** @@ -635,11 +637,12 @@ if (!this.textBackgroundColor) { return; } - var lineTopOffset = 0, heightOfLine = this._getHeightOfLine(), + var lineTopOffset = 0, heightOfLine, lineWidth, lineLeftOffset; ctx.fillStyle = this.textBackgroundColor; for (var i = 0, len = this._textLines.length; i < len; i++) { + heightOfLine = this._getHeightOfLine(ctx, i); if (this._textLines[i] !== '') { lineWidth = this.textAlign === 'justify' ? this.width : this._getLineWidth(ctx, i); lineLeftOffset = this._getLineLeftOffset(lineWidth); @@ -647,11 +650,14 @@ this._getLeftOffset() + lineLeftOffset, this._getTopOffset() + lineTopOffset, lineWidth, - this.fontSize * this._fontSizeMult + heightOfLine / this.lineHeight ); } lineTopOffset += heightOfLine; } + // if there is text background color no + // other shadows should be casted + this._removeShadow(ctx); }, /** From 2f19e25ef28f49b66b521049d3d44a45e5a715f1 Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Thu, 25 Feb 2016 02:48:20 +0100 Subject: [PATCH 09/28] Update itext.class.js --- src/shapes/itext.class.js | 85 +++++++++++---------------------------- 1 file changed, 23 insertions(+), 62 deletions(-) diff --git a/src/shapes/itext.class.js b/src/shapes/itext.class.js index b7c0ceb7..583f8281 100644 --- a/src/shapes/itext.class.js +++ b/src/shapes/itext.class.js @@ -743,60 +743,43 @@ * @param {CanvasRenderingContext2D} ctx Context to render on */ _renderTextLinesBackground: function(ctx) { - if (!this.textBackgroundColor && !this.styles) { - return; - } + this.callSuper('_renderTextLinesBackground', ctx); - ctx.save(); - - if (this.textBackgroundColor) { - ctx.fillStyle = this.textBackgroundColor; - } - - var lineHeights = 0; + var lineTopOffset = 0, heightOfLine, + lineWidth, lineLeftOffset, + leftOffset = this._getLeftOffset(), + topOffset = this._getTopOffset(), + line, _char, style; for (var i = 0, len = this._textLines.length; i < len; i++) { + heightOfLine = this._getHeightOfLine(ctx, i); + line = this._textLines[i]; - var heightOfLine = this._getHeightOfLine(ctx, i); - if (this._textLines[i] === '') { - lineHeights += heightOfLine; + if (line === '' || !this.styles || !this._getLineStyle(i)) { + lineTopOffset += heightOfLine; continue; } - var lineWidth = this._getLineWidth(ctx, i), - lineLeftOffset = this._getLineLeftOffset(lineWidth); + lineWidth = this._getLineWidth(ctx, i); + lineLeftOffset = this._getLineLeftOffset(lineWidth); - if (this.textBackgroundColor) { - ctx.fillStyle = this.textBackgroundColor; + for (var j = 0, jlen = line.length; j < jlen; j++) { + style = this._getStyleDeclaration(i, j); + if (!style || !style.textBackgroundColor) { + continue; + } + _char = line[j]; + + ctx.fillStyle = style.textBackgroundColor; ctx.fillRect( - this._getLeftOffset() + lineLeftOffset, - this._getTopOffset() + lineHeights, - lineWidth, + leftOffset + lineLeftOffset + this._getWidthOfCharsAt(ctx, i, j), + topOffset + lineTopOffset, + this._getWidthOfChar(ctx, _char, i, j) + 1, heightOfLine / this.lineHeight ); } - if (this._getLineStyle(i)) { - for (var j = 0, jlen = this._textLines[i].length; j < jlen; j++) { - var style = this._getStyleDeclaration(i, j); - if (style && style.textBackgroundColor) { - - var _char = this._textLines[i][j]; - - ctx.fillStyle = style.textBackgroundColor; - - ctx.fillRect( - this._getLeftOffset() + lineLeftOffset + this._getWidthOfCharsAt(ctx, i, j), - this._getTopOffset() + lineHeights, - this._getWidthOfChar(ctx, _char, i, j) + 1, - heightOfLine / this.lineHeight - ); - } - } - } - lineHeights += heightOfLine; } - ctx.restore(); }, /** @@ -1070,28 +1053,6 @@ return height; }, - /** - * This method is overwritten to account for different top offset - * @private - */ - _renderTextBoxBackground: function(ctx) { - if (!this.backgroundColor) { - return; - } - - ctx.save(); - ctx.fillStyle = this.backgroundColor; - - ctx.fillRect( - this._getLeftOffset(), - this._getTopOffset(), - this.width, - this.height - ); - - ctx.restore(); - }, - /** * Returns object representation of an instance * @method toObject From d5ad13fa6e17479708ff2a9b452108ad445acd2e Mon Sep 17 00:00:00 2001 From: Brandon Hernandez Date: Wed, 24 Feb 2016 20:52:07 -0500 Subject: [PATCH 10/28] Fixed spacing changed even to also --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 20f9f29a..dc374650 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Using Fabric.js, you can create and populate objects on canvas; objects like sim ### Non-Technical Introduction to Fabric -Fabric.js allows you to easily create simple shapes like rectangles, circles, triangles and other polygons or more complex shapes made up of many paths, onto the HTML `` element on a webpage using JavaScript. Fabric.js will then allow you to manipulate the size, position and rotation of these objects with a mouse. It’s also possible to change some of the attributes of these objects such as their color, transparency, depth position on the webpage or selecting groups of these objects using the Fabric.js library. Fabric.js will even allow you to convert an SVG image into JavaScript data that can be using for putting it onto the `` element. +Fabric.js allows you to easily create simple shapes like rectangles, circles, triangles and other polygons or more complex shapes made up of many paths, onto the HTML `` element on a webpage using JavaScript. Fabric.js will then allow you to manipulate the size, position and rotation of these objects with a mouse. It’s also possible to change some of the attributes of these objects such as their color, transparency, depth position on the webpage or selecting groups of these objects using the Fabric.js library. Fabric.js will also allow you to convert an SVG image into JavaScript data that can be using for putting it onto the `` element. [Contributions](https://github.com/kangax/fabric.js/wiki/Love-Fabric%3F-Help-us-by...) are very much welcome! From 9c41f0923d7fd68538232b3b8c855d6ee43f318b Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Thu, 25 Feb 2016 02:59:04 +0100 Subject: [PATCH 11/28] Update itext.class.js --- src/shapes/itext.class.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/shapes/itext.class.js b/src/shapes/itext.class.js index 583f8281..b5edd508 100644 --- a/src/shapes/itext.class.js +++ b/src/shapes/itext.class.js @@ -657,6 +657,9 @@ charWidth = this._applyCharStylesGetWidth(ctx, _char, lineIndex, i, decl || {}); textDecoration = textDecoration || this.textDecoration; + if (decl && decl.textBackgroundColor) { + this._removeShadow(ctx); + } shouldFill && ctx.fillText(_char, left, top); shouldStroke && ctx.strokeText(_char, left, top); From 328194551d9e593814039ed33aacde691dd7d8d7 Mon Sep 17 00:00:00 2001 From: Brian Hernandez Date: Wed, 24 Feb 2016 21:35:14 -0500 Subject: [PATCH 12/28] Fix small typo Fixed a small typo in the non-technical introduction paragraph. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dc374650..8790fe4d 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Using Fabric.js, you can create and populate objects on canvas; objects like sim ### Non-Technical Introduction to Fabric -Fabric.js allows you to easily create simple shapes like rectangles, circles, triangles and other polygons or more complex shapes made up of many paths, onto the HTML `` element on a webpage using JavaScript. Fabric.js will then allow you to manipulate the size, position and rotation of these objects with a mouse. It’s also possible to change some of the attributes of these objects such as their color, transparency, depth position on the webpage or selecting groups of these objects using the Fabric.js library. Fabric.js will also allow you to convert an SVG image into JavaScript data that can be using for putting it onto the `` element. +Fabric.js allows you to easily create simple shapes like rectangles, circles, triangles and other polygons or more complex shapes made up of many paths, onto the HTML `` element on a webpage using JavaScript. Fabric.js will then allow you to manipulate the size, position and rotation of these objects with a mouse. It’s also possible to change some of the attributes of these objects such as their color, transparency, depth position on the webpage or selecting groups of these objects using the Fabric.js library. Fabric.js will also allow you to convert an SVG image into JavaScript data that can be used for putting it onto the `` element. [Contributions](https://github.com/kangax/fabric.js/wiki/Love-Fabric%3F-Help-us-by...) are very much welcome! From 91bf1fbacff4e24ae4f6e77becbf4594d0221d55 Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Thu, 25 Feb 2016 08:10:38 +0100 Subject: [PATCH 13/28] Update object.class.js --- src/shapes/object.class.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shapes/object.class.js b/src/shapes/object.class.js index 62d3b941..21bd737d 100644 --- a/src/shapes/object.class.js +++ b/src/shapes/object.class.js @@ -1109,7 +1109,7 @@ var multX = (this.canvas && this.canvas.viewportTransform[0]) || 1, multY = (this.canvas && this.canvas.viewportTransform[3]) || 1; - if (this.canvas && this.canvas.isRetinaScaling()) { + if (this.canvas && this.canvas._isRetinaScaling()) { multX *= fabric.devicePixelRatio; multY *= fabric.devicePixelRatio; } From 47776c55fd38b45800641df6226cf4dffb6ebc83 Mon Sep 17 00:00:00 2001 From: asteriskman Date: Fri, 26 Feb 2016 22:51:56 -0500 Subject: [PATCH 14/28] Change location of rect in 1x1 case As can be seen in this jsfiddle, https://jsfiddle.net/asteriskman/kk6v0tu4/ , the 1x1 rectangle was being placed incorrectly. It must be offset by -0.5 in the x and y direction to line up with other rects. --- src/shapes/rect.class.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shapes/rect.class.js b/src/shapes/rect.class.js index c753c99a..92b7a6f1 100644 --- a/src/shapes/rect.class.js +++ b/src/shapes/rect.class.js @@ -90,7 +90,7 @@ // optimize 1x1 case (used in spray brush) if (this.width === 1 && this.height === 1) { - ctx.fillRect(0, 0, 1, 1); + ctx.fillRect(-0.5, -0.5, 1, 1); return; } From a3fd9061efd29918bbc2cc272756a4ae99f53199 Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Fri, 11 Mar 2016 06:14:40 +0100 Subject: [PATCH 15/28] Add shadow to outer group of text --- src/shapes/text.class.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/shapes/text.class.js b/src/shapes/text.class.js index fb448ccd..87b350d5 100644 --- a/src/shapes/text.class.js +++ b/src/shapes/text.class.js @@ -881,8 +881,10 @@ * @private */ _wrapSVGTextAndBg: function(markup, textAndBg) { + var noShadow = true; markup.push( - '\t\n', + '\t\n', textAndBg.textBgRects.join(''), '\t\t\n', + 'style="', this.getSvgStyles(noShadow), '" >\n', textAndBg.textSpans.join(''), '\t\t\n', '\t\n' From cc9d826d4c6b9171777dc94470f88711caeb759d Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Fri, 11 Mar 2016 06:16:42 +0100 Subject: [PATCH 16/28] add ability to skip shadow to style export This is necessary for text now. --- src/mixins/object.svg_export.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mixins/object.svg_export.js b/src/mixins/object.svg_export.js index 20e85462..5e01cf04 100644 --- a/src/mixins/object.svg_export.js +++ b/src/mixins/object.svg_export.js @@ -5,7 +5,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot * Returns styles-string for svg-export * @return {String} */ - getSvgStyles: function() { + getSvgStyles: function(skipShadow) { var fill = this.fill ? (this.fill.toLive ? 'url(#SVGID_' + this.fill.id + ')' : this.fill) @@ -23,7 +23,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot opacity = typeof this.opacity !== 'undefined' ? this.opacity : '1', visibility = this.visible ? '' : ' visibility: hidden;', - filter = this.getSvgFilter(); + filter = skipShadow ? '' : this.getSvgFilter(); return [ 'stroke: ', stroke, '; ', From bb9aef97264d76ba4667829f42c7dda8418fb35e Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Fri, 11 Mar 2016 06:37:23 +0100 Subject: [PATCH 17/28] do not output useless empty style declaration --- src/shapes/text.class.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/shapes/text.class.js b/src/shapes/text.class.js index 87b350d5..984bf363 100644 --- a/src/shapes/text.class.js +++ b/src/shapes/text.class.js @@ -881,10 +881,12 @@ * @private */ _wrapSVGTextAndBg: function(markup, textAndBg) { - var noShadow = true; + var noShadow = true, filter = this.getSvgFilter(), + style = filter === '' ? '' : ' style="' + this.getSvgFilter() + '"'; + markup.push( - '\t\n', + '\t\n', textAndBg.textBgRects.join(''), '\t\t Date: Fri, 11 Mar 2016 10:52:20 +0100 Subject: [PATCH 18/28] Do not call 2 times this.getSvgFilter() --- src/shapes/text.class.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shapes/text.class.js b/src/shapes/text.class.js index 984bf363..7b9f4177 100644 --- a/src/shapes/text.class.js +++ b/src/shapes/text.class.js @@ -882,7 +882,7 @@ */ _wrapSVGTextAndBg: function(markup, textAndBg) { var noShadow = true, filter = this.getSvgFilter(), - style = filter === '' ? '' : ' style="' + this.getSvgFilter() + '"'; + style = filter === '' ? '' : ' style="' + filter + '"'; markup.push( '\t Date: Fri, 11 Mar 2016 11:09:12 +0100 Subject: [PATCH 19/28] improved docs --- src/mixins/object.svg_export.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mixins/object.svg_export.js b/src/mixins/object.svg_export.js index 5e01cf04..4bcc008a 100644 --- a/src/mixins/object.svg_export.js +++ b/src/mixins/object.svg_export.js @@ -3,6 +3,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot /** * Returns styles-string for svg-export + * @param {Boolean} skipShadow a boolean to skip shadow filter output * @return {String} */ getSvgStyles: function(skipShadow) { From 84107968728e11e330cad007fbd2bbba149260df Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Thu, 17 Mar 2016 09:07:47 +0100 Subject: [PATCH 20/28] drw controls and borders just if you are in active group ora active --- src/shapes/object.class.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/shapes/object.class.js b/src/shapes/object.class.js index 51314cb0..4dc941dd 100644 --- a/src/shapes/object.class.js +++ b/src/shapes/object.class.js @@ -1075,7 +1075,8 @@ * @param {Boolean} [noTransform] When true, context is not transformed */ _renderControls: function(ctx, noTransform) { - if (!this.active || noTransform) { + if (!this.active || noTransform + || (this.group && this.group !== this.canvas.getActiveGroup())) { return; } From 2a1842af02d95dfc3456a3e638e3da022ec62b5e Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Sat, 26 Mar 2016 11:41:49 +0100 Subject: [PATCH 21/28] adding lineStarted logic to _wrapLine function The error was considering line === '' as a line that just started. This messed up consecutive spaces. Consecutive spaces create words with 0 lenght and they leave the line with no infix and no characters. --- src/shapes/textbox.class.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/shapes/textbox.class.js b/src/shapes/textbox.class.js index f28a0695..8e2ada9f 100644 --- a/src/shapes/textbox.class.js +++ b/src/shapes/textbox.class.js @@ -262,29 +262,32 @@ infix = ' ', wordWidth = 0, infixWidth = 0, - largestWordWidth = 0; + largestWordWidth = 0, + lineJustStarted = true; for (var i = 0; i < words.length; i++) { word = words[i]; wordWidth = this._measureText(ctx, word, lineIndex, offset); + offset += word.length; lineWidth += infixWidth + wordWidth; - if (lineWidth >= this.width && line !== '') { + if (lineWidth >= this.width && !lineJustStarted) { lines.push(line); line = ''; lineWidth = wordWidth; + lineJustStarted = true; } - if (line !== '' || i === 1) { + if (!lineJustStarted) { line += infix; } line += word; infixWidth = this._measureText(ctx, infix, lineIndex, offset); offset++; - + lineJustStarted = false; // keep track of largest word if (wordWidth > largestWordWidth) { largestWordWidth = wordWidth; @@ -299,7 +302,6 @@ return lines; }, - /** * Gets lines of text to render in the Textbox. This function calculates * text wrapping on the fly everytime it is called. From f5f51938f72359dd9a48036be62730a881cfb670 Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Sat, 26 Mar 2016 12:42:03 +0100 Subject: [PATCH 22/28] add check for this.styles[i] --- src/shapes/itext.class.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/shapes/itext.class.js b/src/shapes/itext.class.js index b7c0ceb7..d7575b37 100644 --- a/src/shapes/itext.class.js +++ b/src/shapes/itext.class.js @@ -879,6 +879,16 @@ } }, + /** + * This function is a TEMPORARY fix before restyling svg export + * and tspan generation + * @param {Number} lineIndex + * @private + */ + hasStyleOnLine: function(lineIndex) { + return this.styles[lineIndex]; + }, + /** * @param {Number} lineIndex * @param {Number} charIndex From 55da566d3731ebfd2b0660655ed8bc0d1e39a674 Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Sat, 26 Mar 2016 12:44:11 +0100 Subject: [PATCH 23/28] Update textbox.class.js --- src/shapes/textbox.class.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/shapes/textbox.class.js b/src/shapes/textbox.class.js index 8e2ada9f..226e10e2 100644 --- a/src/shapes/textbox.class.js +++ b/src/shapes/textbox.class.js @@ -131,6 +131,23 @@ return map; }, + /** + * This function is a TEMPORARY fix before restyling svg export + * and tspan generation + * @param {Number} lineIndex + * @private + */ + hasStyleOnLine: function(lineIndex) { + if (this._styleMap) { + var map = this._styleMap[lineIndex]; + if (!map) { + return null; + } + lineIndex = map.line; + } + return this.styles[lineIndex]; + }, + /** * @param {Number} lineIndex * @param {Number} charIndex From 0785bd9a320b27e9e3c3ce959503b13b01530c26 Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Sat, 26 Mar 2016 12:47:20 +0100 Subject: [PATCH 24/28] check properly if there is style on the line --- src/mixins/itext.svg_export.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mixins/itext.svg_export.js b/src/mixins/itext.svg_export.js index 5b7f83de..3017d4ea 100644 --- a/src/mixins/itext.svg_export.js +++ b/src/mixins/itext.svg_export.js @@ -9,7 +9,7 @@ * @private */ _setSVGTextLineText: function(lineIndex, textSpans, height, textLeftOffset, textTopOffset, textBgRects) { - if (!this.styles[lineIndex]) { + if (!this.hasStyleOnLine(lineIndex)) { fabric.Text.prototype._setSVGTextLineText.call(this, lineIndex, textSpans, height, textLeftOffset, textTopOffset); } From e3e8984ec9bb1ae83da5a7a0491d723ba6dadbdd Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Sat, 26 Mar 2016 13:00:37 +0100 Subject: [PATCH 25/28] fixes trailing spaces --- src/shapes/textbox.class.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shapes/textbox.class.js b/src/shapes/textbox.class.js index 226e10e2..0142b2c0 100644 --- a/src/shapes/textbox.class.js +++ b/src/shapes/textbox.class.js @@ -147,7 +147,7 @@ } return this.styles[lineIndex]; }, - + /** * @param {Number} lineIndex * @param {Number} charIndex From 6891d2cde7c30d4c739c5bcf08c7892511e1c121 Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Sat, 26 Mar 2016 13:41:34 +0100 Subject: [PATCH 26/28] Update shadow.class.js --- src/shadow.class.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/shadow.class.js b/src/shadow.class.js index db644b69..45ce75c9 100644 --- a/src/shadow.class.js +++ b/src/shadow.class.js @@ -123,7 +123,12 @@ fBoxX = toFixed((Math.abs(offset.x) + this.blur) / object.width, NUM_FRACTION_DIGITS) * 100 + BLUR_BOX; fBoxY = toFixed((Math.abs(offset.y) + this.blur) / object.height, NUM_FRACTION_DIGITS) * 100 + BLUR_BOX; } - + if (object.flipX) { + offset.x *= -1; + } + if (object.flipY) { + offset.y *= -1; + } return ( '\n' + From 4dd392ca56c8df9cb15fa56b17989da17e9f2f93 Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Sun, 27 Mar 2016 22:58:02 +0200 Subject: [PATCH 27/28] Added tests for flipped object --- test/unit/shadow.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/unit/shadow.js b/test/unit/shadow.js index 4f7d4813..21421c4f 100644 --- a/test/unit/shadow.js +++ b/test/unit/shadow.js @@ -170,6 +170,17 @@ shadow.color = '#000000'; equal(shadow.toSVG(object), '\n\t\n\t\n\t\n\t\n\t\n\t\t\n\t\t\n\t\n\n'); }); + + test('toSVG with flipped object', function() { + // reset uid + fabric.Object.__uid = 0; + + var shadow = new fabric.Shadow({color: '#FF0000', offsetX: 10, offsetY: -10, blur: 2}); + var object = new fabric.Object({fill: '#FF0000', flipX: true, flipY: true}); + + equal(shadow.toSVG(object), '\n\t\n\t\n\t\n\t\n\t\n\t\t\n\t\t\n\t\n\n'); + + }); test('toSVG with rotated object', function() { // reset uid @@ -180,5 +191,15 @@ equal(shadow.toSVG(object), '\n\t\n\t\n\t\n\t\n\t\n\t\t\n\t\t\n\t\n\n'); }); + + test('toSVG with rotated flipped object', function() { + // reset uid + fabric.Object.__uid = 0; + + var shadow = new fabric.Shadow({color: '#FF0000', offsetX: 10, offsetY: 10, blur: 2}); + var object = new fabric.Object({fill: '#FF0000', angle: 45, flipX: true}); + + equal(shadow.toSVG(object), '\n\t\n\t\n\t\n\t\n\t\n\t\t\n\t\t\n\t\n\n'); + }); })(); From 719746e58d97c3fd3ef10037f719f7a985ba25c9 Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Sun, 27 Mar 2016 23:25:39 +0200 Subject: [PATCH 28/28] Revert "Textboxspaces" --- src/mixins/itext.svg_export.js | 2 +- src/shapes/itext.class.js | 10 ---------- src/shapes/textbox.class.js | 17 ----------------- 3 files changed, 1 insertion(+), 28 deletions(-) diff --git a/src/mixins/itext.svg_export.js b/src/mixins/itext.svg_export.js index 3017d4ea..5b7f83de 100644 --- a/src/mixins/itext.svg_export.js +++ b/src/mixins/itext.svg_export.js @@ -9,7 +9,7 @@ * @private */ _setSVGTextLineText: function(lineIndex, textSpans, height, textLeftOffset, textTopOffset, textBgRects) { - if (!this.hasStyleOnLine(lineIndex)) { + if (!this.styles[lineIndex]) { fabric.Text.prototype._setSVGTextLineText.call(this, lineIndex, textSpans, height, textLeftOffset, textTopOffset); } diff --git a/src/shapes/itext.class.js b/src/shapes/itext.class.js index 6a53c757..b5edd508 100644 --- a/src/shapes/itext.class.js +++ b/src/shapes/itext.class.js @@ -865,16 +865,6 @@ } }, - /** - * This function is a TEMPORARY fix before restyling svg export - * and tspan generation - * @param {Number} lineIndex - * @private - */ - hasStyleOnLine: function(lineIndex) { - return this.styles[lineIndex]; - }, - /** * @param {Number} lineIndex * @param {Number} charIndex diff --git a/src/shapes/textbox.class.js b/src/shapes/textbox.class.js index 0142b2c0..8e2ada9f 100644 --- a/src/shapes/textbox.class.js +++ b/src/shapes/textbox.class.js @@ -131,23 +131,6 @@ return map; }, - /** - * This function is a TEMPORARY fix before restyling svg export - * and tspan generation - * @param {Number} lineIndex - * @private - */ - hasStyleOnLine: function(lineIndex) { - if (this._styleMap) { - var map = this._styleMap[lineIndex]; - if (!map) { - return null; - } - lineIndex = map.line; - } - return this.styles[lineIndex]; - }, - /** * @param {Number} lineIndex * @param {Number} charIndex