fabric 5.1.0 → 5.2.2-browser

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/HEADER.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*! Fabric.js Copyright 2008-2015, Printio (Juriy Zaytsev, Maxim Chernyak) */
2
2
 
3
- var fabric = fabric || { version: '5.1.0' };
3
+ var fabric = fabric || { version: '5.2.1' };
4
4
  if (typeof exports !== 'undefined') {
5
5
  exports.fabric = fabric;
6
6
  }
package/dist/fabric.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /* build: `node build.js modules=ALL exclude=gestures,accessors,erasing requirejs minifier=uglifyjs` */
2
2
  /*! Fabric.js Copyright 2008-2015, Printio (Juriy Zaytsev, Maxim Chernyak) */
3
3
 
4
- var fabric = fabric || { version: '5.1.0' };
4
+ var fabric = fabric || { version: '5.2.1' };
5
5
  if (typeof exports !== 'undefined') {
6
6
  exports.fabric = fabric;
7
7
  }
@@ -1274,6 +1274,9 @@ fabric.CommonMethods = {
1274
1274
  groupSVGElements: function(elements, options, path) {
1275
1275
  var object;
1276
1276
  if (elements && elements.length === 1) {
1277
+ if (typeof path !== 'undefined') {
1278
+ elements[0].sourcePath = path;
1279
+ }
1277
1280
  return elements[0];
1278
1281
  }
1279
1282
  if (options) {
@@ -1304,7 +1307,7 @@ fabric.CommonMethods = {
1304
1307
  * @return {Array} properties Properties names to include
1305
1308
  */
1306
1309
  populateWithProperties: function(source, destination, properties) {
1307
- if (properties && Object.prototype.toString.call(properties) === '[object Array]') {
1310
+ if (properties && Array.isArray(properties)) {
1308
1311
  for (var i = 0, len = properties.length; i < len; i++) {
1309
1312
  if (properties[i] in source) {
1310
1313
  destination[properties[i]] = source[properties[i]];
@@ -1838,6 +1841,113 @@ fabric.CommonMethods = {
1838
1841
  }
1839
1842
  return new fabric.Group([a], { clipPath: b, inverted: inverted });
1840
1843
  },
1844
+
1845
+ /**
1846
+ * @memberOf fabric.util
1847
+ * @param {Object} prevStyle first style to compare
1848
+ * @param {Object} thisStyle second style to compare
1849
+ * @param {boolean} forTextSpans whether to check overline, underline, and line-through properties
1850
+ * @return {boolean} true if the style changed
1851
+ */
1852
+ hasStyleChanged: function(prevStyle, thisStyle, forTextSpans) {
1853
+ forTextSpans = forTextSpans || false;
1854
+ return (prevStyle.fill !== thisStyle.fill ||
1855
+ prevStyle.stroke !== thisStyle.stroke ||
1856
+ prevStyle.strokeWidth !== thisStyle.strokeWidth ||
1857
+ prevStyle.fontSize !== thisStyle.fontSize ||
1858
+ prevStyle.fontFamily !== thisStyle.fontFamily ||
1859
+ prevStyle.fontWeight !== thisStyle.fontWeight ||
1860
+ prevStyle.fontStyle !== thisStyle.fontStyle ||
1861
+ prevStyle.deltaY !== thisStyle.deltaY) ||
1862
+ (forTextSpans &&
1863
+ (prevStyle.overline !== thisStyle.overline ||
1864
+ prevStyle.underline !== thisStyle.underline ||
1865
+ prevStyle.linethrough !== thisStyle.linethrough));
1866
+ },
1867
+
1868
+ /**
1869
+ * Returns the array form of a text object's inline styles property with styles grouped in ranges
1870
+ * rather than per character. This format is less verbose, and is better suited for storage
1871
+ * so it is used in serialization (not during runtime).
1872
+ * @memberOf fabric.util
1873
+ * @param {object} styles per character styles for a text object
1874
+ * @param {String} text the text string that the styles are applied to
1875
+ * @return {{start: number, end: number, style: object}[]}
1876
+ */
1877
+ stylesToArray: function(styles, text) {
1878
+ // clone style structure to prevent mutation
1879
+ var styles = fabric.util.object.clone(styles, true),
1880
+ textLines = text.split('\n'),
1881
+ charIndex = -1, prevStyle = {}, stylesArray = [];
1882
+ //loop through each textLine
1883
+ for (var i = 0; i < textLines.length; i++) {
1884
+ if (!styles[i]) {
1885
+ //no styles exist for this line, so add the line's length to the charIndex total
1886
+ charIndex += textLines[i].length;
1887
+ continue;
1888
+ }
1889
+ //loop through each character of the current line
1890
+ for (var c = 0; c < textLines[i].length; c++) {
1891
+ charIndex++;
1892
+ var thisStyle = styles[i][c];
1893
+ //check if style exists for this character
1894
+ if (thisStyle) {
1895
+ var styleChanged = fabric.util.hasStyleChanged(prevStyle, thisStyle, true);
1896
+ if (styleChanged) {
1897
+ stylesArray.push({
1898
+ start: charIndex,
1899
+ end: charIndex + 1,
1900
+ style: thisStyle
1901
+ });
1902
+ }
1903
+ else {
1904
+ //if style is the same as previous character, increase end index
1905
+ stylesArray[stylesArray.length - 1].end++;
1906
+ }
1907
+ }
1908
+ prevStyle = thisStyle || {};
1909
+ }
1910
+ }
1911
+ return stylesArray;
1912
+ },
1913
+
1914
+ /**
1915
+ * Returns the object form of the styles property with styles that are assigned per
1916
+ * character rather than grouped by range. This format is more verbose, and is
1917
+ * only used during runtime (not for serialization/storage)
1918
+ * @memberOf fabric.util
1919
+ * @param {Array} styles the serialized form of a text object's styles
1920
+ * @param {String} text the text string that the styles are applied to
1921
+ * @return {Object}
1922
+ */
1923
+ stylesFromArray: function(styles, text) {
1924
+ if (!Array.isArray(styles)) {
1925
+ return styles;
1926
+ }
1927
+ var textLines = text.split('\n'),
1928
+ charIndex = -1, styleIndex = 0, stylesObject = {};
1929
+ //loop through each textLine
1930
+ for (var i = 0; i < textLines.length; i++) {
1931
+ //loop through each character of the current line
1932
+ for (var c = 0; c < textLines[i].length; c++) {
1933
+ charIndex++;
1934
+ //check if there's a style collection that includes the current character
1935
+ if (styles[styleIndex]
1936
+ && styles[styleIndex].start <= charIndex
1937
+ && charIndex < styles[styleIndex].end) {
1938
+ //create object for line index if it doesn't exist
1939
+ stylesObject[i] = stylesObject[i] || {};
1940
+ //assign a style at this character's index
1941
+ stylesObject[i][c] = Object.assign({}, styles[styleIndex].style);
1942
+ //if character is at the end of the current style collection, move to the next
1943
+ if (charIndex === styles[styleIndex].end - 1) {
1944
+ styleIndex++;
1945
+ }
1946
+ }
1947
+ }
1948
+ }
1949
+ return stylesObject;
1950
+ }
1841
1951
  };
1842
1952
  })(typeof exports !== 'undefined' ? exports : this);
1843
1953
 
@@ -3155,7 +3265,7 @@ fabric.CommonMethods = {
3155
3265
  var normalizedProperty = (property === 'float' || property === 'cssFloat')
3156
3266
  ? (typeof elementStyle.styleFloat === 'undefined' ? 'cssFloat' : 'styleFloat')
3157
3267
  : property;
3158
- elementStyle[normalizedProperty] = styles[property];
3268
+ elementStyle.setProperty(normalizedProperty, styles[property]);
3159
3269
  }
3160
3270
  }
3161
3271
  return element;
@@ -4382,8 +4492,7 @@ fabric.warn = console.warn;
4382
4492
  }
4383
4493
 
4384
4494
  function normalizeValue(attr, value, parentAttributes, fontSize) {
4385
- var isArray = Object.prototype.toString.call(value) === '[object Array]',
4386
- parsed;
4495
+ var isArray = Array.isArray(value), parsed;
4387
4496
 
4388
4497
  if ((attr === 'fill' || attr === 'stroke') && value === 'none') {
4389
4498
  value = '';
@@ -4781,7 +4890,7 @@ fabric.warn = console.warn;
4781
4890
  return;
4782
4891
  }
4783
4892
 
4784
- var xlink = xlinkAttribute.substr(1),
4893
+ var xlink = xlinkAttribute.slice(1),
4785
4894
  x = el.getAttribute('x') || 0,
4786
4895
  y = el.getAttribute('y') || 0,
4787
4896
  el2 = elementById(doc, xlink).cloneNode(true),
@@ -5053,7 +5162,7 @@ fabric.warn = console.warn;
5053
5162
  function recursivelyParseGradientsXlink(doc, gradient) {
5054
5163
  var gradientsAttrs = ['gradientTransform', 'x1', 'x2', 'y1', 'y2', 'gradientUnits', 'cx', 'cy', 'r', 'fx', 'fy'],
5055
5164
  xlinkAttr = 'xlink:href',
5056
- xLink = gradient.getAttribute(xlinkAttr).substr(1),
5165
+ xLink = gradient.getAttribute(xlinkAttr).slice(1),
5057
5166
  referencedGradient = elementById(doc, xLink);
5058
5167
  if (referencedGradient && referencedGradient.getAttribute(xlinkAttr)) {
5059
5168
  recursivelyParseGradientsXlink(doc, referencedGradient);
@@ -9793,6 +9902,7 @@ fabric.ElementsParser = function(elements, callback, options, reviver, parsingOp
9793
9902
  * Returns coordinates of a center of canvas.
9794
9903
  * Returned value is an object with top and left properties
9795
9904
  * @return {Object} object with "top" and "left" number values
9905
+ * @deprecated migrate to `getCenterPoint`
9796
9906
  */
9797
9907
  getCenter: function () {
9798
9908
  return {
@@ -9801,13 +9911,21 @@ fabric.ElementsParser = function(elements, callback, options, reviver, parsingOp
9801
9911
  };
9802
9912
  },
9803
9913
 
9914
+ /**
9915
+ * Returns coordinates of a center of canvas.
9916
+ * @return {fabric.Point}
9917
+ */
9918
+ getCenterPoint: function () {
9919
+ return new fabric.Point(this.width / 2, this.height / 2);
9920
+ },
9921
+
9804
9922
  /**
9805
9923
  * Centers object horizontally in the canvas
9806
9924
  * @param {fabric.Object} object Object to center horizontally
9807
9925
  * @return {fabric.Canvas} thisArg
9808
9926
  */
9809
9927
  centerObjectH: function (object) {
9810
- return this._centerObject(object, new fabric.Point(this.getCenter().left, object.getCenterPoint().y));
9928
+ return this._centerObject(object, new fabric.Point(this.getCenterPoint().x, object.getCenterPoint().y));
9811
9929
  },
9812
9930
 
9813
9931
  /**
@@ -9817,7 +9935,7 @@ fabric.ElementsParser = function(elements, callback, options, reviver, parsingOp
9817
9935
  * @chainable
9818
9936
  */
9819
9937
  centerObjectV: function (object) {
9820
- return this._centerObject(object, new fabric.Point(object.getCenterPoint().x, this.getCenter().top));
9938
+ return this._centerObject(object, new fabric.Point(object.getCenterPoint().x, this.getCenterPoint().y));
9821
9939
  },
9822
9940
 
9823
9941
  /**
@@ -9827,9 +9945,8 @@ fabric.ElementsParser = function(elements, callback, options, reviver, parsingOp
9827
9945
  * @chainable
9828
9946
  */
9829
9947
  centerObject: function(object) {
9830
- var center = this.getCenter();
9831
-
9832
- return this._centerObject(object, new fabric.Point(center.left, center.top));
9948
+ var center = this.getCenterPoint();
9949
+ return this._centerObject(object, center);
9833
9950
  },
9834
9951
 
9835
9952
  /**
@@ -9840,7 +9957,6 @@ fabric.ElementsParser = function(elements, callback, options, reviver, parsingOp
9840
9957
  */
9841
9958
  viewportCenterObject: function(object) {
9842
9959
  var vpCenter = this.getVpCenter();
9843
-
9844
9960
  return this._centerObject(object, vpCenter);
9845
9961
  },
9846
9962
 
@@ -9874,9 +9990,9 @@ fabric.ElementsParser = function(elements, callback, options, reviver, parsingOp
9874
9990
  * @chainable
9875
9991
  */
9876
9992
  getVpCenter: function() {
9877
- var center = this.getCenter(),
9993
+ var center = this.getCenterPoint(),
9878
9994
  iVpt = invertTransform(this.viewportTransform);
9879
- return transformPoint({ x: center.left, y: center.top }, iVpt);
9995
+ return transformPoint(center, iVpt);
9880
9996
  },
9881
9997
 
9882
9998
  /**
@@ -12033,7 +12149,7 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
12033
12149
  _isSelectionKeyPressed: function(e) {
12034
12150
  var selectionKeyPressed = false;
12035
12151
 
12036
- if (Object.prototype.toString.call(this.selectionKey) === '[object Array]') {
12152
+ if (Array.isArray(this.selectionKey)) {
12037
12153
  selectionKeyPressed = !!this.selectionKey.find(function(key) { return e[key] === true; });
12038
12154
  }
12039
12155
  else {
@@ -12459,6 +12575,14 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
12459
12575
  this.contextTop = upperCanvasEl.getContext('2d');
12460
12576
  },
12461
12577
 
12578
+ /**
12579
+ * Returns context of top canvas where interactions are drawn
12580
+ * @returns {CanvasRenderingContext2D}
12581
+ */
12582
+ getTopContext: function () {
12583
+ return this.contextTop;
12584
+ },
12585
+
12462
12586
  /**
12463
12587
  * @private
12464
12588
  */
@@ -12984,14 +13108,6 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
12984
13108
  _target && target.fire('mouseout', { e: e });
12985
13109
  });
12986
13110
  this._hoveredTargets = [];
12987
-
12988
- if (this._iTextInstances) {
12989
- this._iTextInstances.forEach(function(obj) {
12990
- if (obj.isEditing) {
12991
- obj.hiddenTextarea.focus();
12992
- }
12993
- });
12994
- }
12995
13111
  },
12996
13112
 
12997
13113
  /**
@@ -15236,11 +15352,9 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
15236
15352
  if (object[prop] === prototype[prop]) {
15237
15353
  delete object[prop];
15238
15354
  }
15239
- var isArray = Object.prototype.toString.call(object[prop]) === '[object Array]' &&
15240
- Object.prototype.toString.call(prototype[prop]) === '[object Array]';
15241
-
15242
15355
  // basically a check for [] === []
15243
- if (isArray && object[prop].length === 0 && prototype[prop].length === 0) {
15356
+ if (Array.isArray(object[prop]) && Array.isArray(prototype[prop])
15357
+ && object[prop].length === 0 && prototype[prop].length === 0) {
15244
15358
  delete object[prop];
15245
15359
  }
15246
15360
  });
@@ -15416,7 +15530,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
15416
15530
 
15417
15531
  renderCache: function(options) {
15418
15532
  options = options || {};
15419
- if (!this._cacheCanvas) {
15533
+ if (!this._cacheCanvas || !this._cacheContext) {
15420
15534
  this._createCacheCanvas();
15421
15535
  }
15422
15536
  if (this.isCacheDirty()) {
@@ -15431,6 +15545,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
15431
15545
  */
15432
15546
  _removeCacheCanvas: function() {
15433
15547
  this._cacheCanvas = null;
15548
+ this._cacheContext = null;
15434
15549
  this.cacheWidth = 0;
15435
15550
  this.cacheHeight = 0;
15436
15551
  },
@@ -15589,7 +15704,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
15589
15704
  if (this.isNotVisible()) {
15590
15705
  return false;
15591
15706
  }
15592
- if (this._cacheCanvas && !skipCanvas && this._updateCacheCanvas()) {
15707
+ if (this._cacheCanvas && this._cacheContext && !skipCanvas && this._updateCacheCanvas()) {
15593
15708
  // in this case the context is already cleared.
15594
15709
  return true;
15595
15710
  }
@@ -15598,7 +15713,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
15598
15713
  (this.clipPath && this.clipPath.absolutePositioned) ||
15599
15714
  (this.statefullCache && this.hasStateChanged('cacheProperties'))
15600
15715
  ) {
15601
- if (this._cacheCanvas && !skipCanvas) {
15716
+ if (this._cacheCanvas && this._cacheContext && !skipCanvas) {
15602
15717
  var width = this.cacheWidth / this.zoomX;
15603
15718
  var height = this.cacheHeight / this.zoomY;
15604
15719
  this._cacheContext.clearRect(-width / 2, -height / 2, width, height);
@@ -16132,7 +16247,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
16132
16247
  * @return {Boolean}
16133
16248
  */
16134
16249
  isType: function(type) {
16135
- return this.type === type;
16250
+ return arguments.length > 1 ? Array.from(arguments).includes(this.type) : this.type === type;
16136
16251
  },
16137
16252
 
16138
16253
  /**
@@ -18070,7 +18185,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
18070
18185
  return fabric.util.animate({
18071
18186
  target: this,
18072
18187
  startValue: object.left,
18073
- endValue: this.getCenter().left,
18188
+ endValue: this.getCenterPoint().x,
18074
18189
  duration: this.FX_DURATION,
18075
18190
  onChange: function(value) {
18076
18191
  object.set('left', value);
@@ -18103,7 +18218,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
18103
18218
  return fabric.util.animate({
18104
18219
  target: this,
18105
18220
  startValue: object.top,
18106
- endValue: this.getCenter().top,
18221
+ endValue: this.getCenterPoint().y,
18107
18222
  duration: this.FX_DURATION,
18108
18223
  onChange: function(value) {
18109
18224
  object.set('top', value);
@@ -19642,7 +19757,6 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
19642
19757
  max = fabric.util.array.max,
19643
19758
  extend = fabric.util.object.extend,
19644
19759
  clone = fabric.util.object.clone,
19645
- _toString = Object.prototype.toString,
19646
19760
  toFixed = fabric.util.toFixed;
19647
19761
 
19648
19762
  if (fabric.Path) {
@@ -19696,10 +19810,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
19696
19810
  * @param {Object} [options] Options object
19697
19811
  */
19698
19812
  _setPath: function (path, options) {
19699
- var fromArray = _toString.call(path) === '[object Array]';
19700
-
19701
19813
  this.path = fabric.util.makePathSimpler(
19702
- fromArray ? path : fabric.util.parsePath(path)
19814
+ Array.isArray(path) ? path : fabric.util.parsePath(path)
19703
19815
  );
19704
19816
 
19705
19817
  fabric.Polyline.prototype._setPositionDimensions.call(this, options || {});
@@ -19978,7 +20090,15 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
19978
20090
  fabric.loadSVGFromURL(pathUrl, function (elements) {
19979
20091
  var path = elements[0];
19980
20092
  path.setOptions(object);
19981
- callback && callback(path);
20093
+ if (object.clipPath) {
20094
+ fabric.util.enlivenObjects([object.clipPath], function(elivenedObjects) {
20095
+ path.clipPath = elivenedObjects[0];
20096
+ callback && callback(path);
20097
+ });
20098
+ }
20099
+ else {
20100
+ callback && callback(path);
20101
+ }
19982
20102
  });
19983
20103
  }
19984
20104
  else {
@@ -20585,20 +20705,27 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
20585
20705
  // it has to be an url or something went wrong.
20586
20706
  fabric.loadSVGFromURL(objects, function (elements) {
20587
20707
  var group = fabric.util.groupSVGElements(elements, object, objects);
20708
+ var clipPath = options.clipPath;
20709
+ delete options.clipPath;
20588
20710
  group.set(options);
20589
- callback && callback(group);
20711
+ if (clipPath) {
20712
+ fabric.util.enlivenObjects([clipPath], function(elivenedObjects) {
20713
+ group.clipPath = elivenedObjects[0];
20714
+ callback && callback(group);
20715
+ });
20716
+ }
20717
+ else {
20718
+ callback && callback(group);
20719
+ }
20590
20720
  });
20591
20721
  return;
20592
20722
  }
20593
20723
  fabric.util.enlivenObjects(objects, function (enlivenedObjects) {
20594
- var options = fabric.util.object.clone(object, true);
20595
- delete options.objects;
20596
20724
  fabric.util.enlivenObjectEnlivables(object, options, function () {
20597
20725
  callback && callback(new fabric.Group(enlivenedObjects, options, true));
20598
20726
  });
20599
20727
  });
20600
20728
  };
20601
-
20602
20729
  })(typeof exports !== 'undefined' ? exports : this);
20603
20730
 
20604
20731
 
@@ -26846,7 +26973,7 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
26846
26973
  // if we have charSpacing, we render char by char
26847
26974
  actualStyle = actualStyle || this.getCompleteStyleDeclaration(lineIndex, i);
26848
26975
  nextStyle = this.getCompleteStyleDeclaration(lineIndex, i + 1);
26849
- timeToRender = this._hasStyleChanged(actualStyle, nextStyle);
26976
+ timeToRender = fabric.util.hasStyleChanged(actualStyle, nextStyle, false);
26850
26977
  }
26851
26978
  if (timeToRender) {
26852
26979
  if (path) {
@@ -27016,34 +27143,6 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
27016
27143
  return this;
27017
27144
  },
27018
27145
 
27019
- /**
27020
- * @private
27021
- * @param {Object} prevStyle
27022
- * @param {Object} thisStyle
27023
- */
27024
- _hasStyleChanged: function(prevStyle, thisStyle) {
27025
- return prevStyle.fill !== thisStyle.fill ||
27026
- prevStyle.stroke !== thisStyle.stroke ||
27027
- prevStyle.strokeWidth !== thisStyle.strokeWidth ||
27028
- prevStyle.fontSize !== thisStyle.fontSize ||
27029
- prevStyle.fontFamily !== thisStyle.fontFamily ||
27030
- prevStyle.fontWeight !== thisStyle.fontWeight ||
27031
- prevStyle.fontStyle !== thisStyle.fontStyle ||
27032
- prevStyle.deltaY !== thisStyle.deltaY;
27033
- },
27034
-
27035
- /**
27036
- * @private
27037
- * @param {Object} prevStyle
27038
- * @param {Object} thisStyle
27039
- */
27040
- _hasStyleChangedForSvg: function(prevStyle, thisStyle) {
27041
- return this._hasStyleChanged(prevStyle, thisStyle) ||
27042
- prevStyle.overline !== thisStyle.overline ||
27043
- prevStyle.underline !== thisStyle.underline ||
27044
- prevStyle.linethrough !== thisStyle.linethrough;
27045
- },
27046
-
27047
27146
  /**
27048
27147
  * @private
27049
27148
  * @param {Number} lineIndex index text line
@@ -27305,8 +27404,7 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
27305
27404
  toObject: function(propertiesToInclude) {
27306
27405
  var allProperties = additionalProps.concat(propertiesToInclude);
27307
27406
  var obj = this.callSuper('toObject', allProperties);
27308
- // styles will be overridden with a properly cloned structure
27309
- obj.styles = clone(this.styles, true);
27407
+ obj.styles = fabric.util.stylesToArray(this.styles, this.text);
27310
27408
  if (obj.path) {
27311
27409
  obj.path = this.path.toObject();
27312
27410
  }
@@ -27472,6 +27570,7 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
27472
27570
  var objectCopy = clone(object), path = object.path;
27473
27571
  delete objectCopy.path;
27474
27572
  return fabric.Object._fromObject('Text', objectCopy, function(textInstance) {
27573
+ textInstance.styles = fabric.util.stylesFromArray(object.styles, object.text);
27475
27574
  if (path) {
27476
27575
  fabric.Object._fromObject('Path', path, function(pathInstance) {
27477
27576
  textInstance.set('path', pathInstance);
@@ -28329,15 +28428,18 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
28329
28428
  * @param {function} [callback] invoked with new instance as argument
28330
28429
  */
28331
28430
  fabric.IText.fromObject = function(object, callback) {
28332
- parseDecoration(object);
28333
- if (object.styles) {
28334
- for (var i in object.styles) {
28335
- for (var j in object.styles[i]) {
28336
- parseDecoration(object.styles[i][j]);
28431
+ var styles = fabric.util.stylesFromArray(object.styles, object.text);
28432
+ //copy object to prevent mutation
28433
+ var objCopy = Object.assign({}, object, { styles: styles });
28434
+ parseDecoration(objCopy);
28435
+ if (objCopy.styles) {
28436
+ for (var i in objCopy.styles) {
28437
+ for (var j in objCopy.styles[i]) {
28438
+ parseDecoration(objCopy.styles[i][j]);
28337
28439
  }
28338
28440
  }
28339
28441
  }
28340
- fabric.Object._fromObject('IText', object, callback, 'text');
28442
+ fabric.Object._fromObject('IText', objCopy, callback, 'text');
28341
28443
  };
28342
28444
  })();
28343
28445
 
@@ -28730,6 +28832,9 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
28730
28832
  return;
28731
28833
  }
28732
28834
 
28835
+ // regain focus
28836
+ document.activeElement !== this.hiddenTextarea && this.hiddenTextarea.focus();
28837
+
28733
28838
  var newSelectionStart = this.getSelectionStartFromPointer(options.e),
28734
28839
  currentStart = this.selectionStart,
28735
28840
  currentEnd = this.selectionEnd;
@@ -30083,7 +30188,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
30083
30188
  this[prop] += direction === 'Left' ? -1 : 1;
30084
30189
  return true;
30085
30190
  }
30086
- if (typeof newValue !== undefined && this[prop] !== newValue) {
30191
+ if (typeof newValue !== 'undefined' && this[prop] !== newValue) {
30087
30192
  this[prop] = newValue;
30088
30193
  return true;
30089
30194
  }
@@ -30401,7 +30506,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
30401
30506
  // if we have charSpacing, we render char by char
30402
30507
  actualStyle = actualStyle || this.getCompleteStyleDeclaration(lineIndex, i);
30403
30508
  nextStyle = this.getCompleteStyleDeclaration(lineIndex, i + 1);
30404
- timeToRender = this._hasStyleChangedForSvg(actualStyle, nextStyle);
30509
+ timeToRender = fabric.util.hasStyleChanged(actualStyle, nextStyle, true);
30405
30510
  }
30406
30511
  if (timeToRender) {
30407
30512
  style = this._getStyleDeclaration(lineIndex, i) || { };
@@ -30955,7 +31060,10 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
30955
31060
  * @param {Function} [callback] Callback to invoke when an fabric.Textbox instance is created
30956
31061
  */
30957
31062
  fabric.Textbox.fromObject = function(object, callback) {
30958
- return fabric.Object._fromObject('Textbox', object, callback, 'text');
31063
+ var styles = fabric.util.stylesFromArray(object.styles, object.text);
31064
+ //copy object to prevent mutation
31065
+ var objCopy = Object.assign({}, object, { styles: styles });
31066
+ return fabric.Object._fromObject('Textbox', objCopy, callback, 'text');
30959
31067
  };
30960
31068
  })(typeof exports !== 'undefined' ? exports : this);
30961
31069