fabric 5.2.1 → 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/dist/fabric.js CHANGED
@@ -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) {
@@ -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;
@@ -12998,14 +13108,6 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
12998
13108
  _target && target.fire('mouseout', { e: e });
12999
13109
  });
13000
13110
  this._hoveredTargets = [];
13001
-
13002
- if (this._iTextInstances) {
13003
- this._iTextInstances.forEach(function(obj) {
13004
- if (obj.isEditing) {
13005
- obj.hiddenTextarea.focus();
13006
- }
13007
- });
13008
- }
13009
13111
  },
13010
13112
 
13011
13113
  /**
@@ -19988,7 +20090,15 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
19988
20090
  fabric.loadSVGFromURL(pathUrl, function (elements) {
19989
20091
  var path = elements[0];
19990
20092
  path.setOptions(object);
19991
- 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
+ }
19992
20102
  });
19993
20103
  }
19994
20104
  else {
@@ -20595,20 +20705,27 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
20595
20705
  // it has to be an url or something went wrong.
20596
20706
  fabric.loadSVGFromURL(objects, function (elements) {
20597
20707
  var group = fabric.util.groupSVGElements(elements, object, objects);
20708
+ var clipPath = options.clipPath;
20709
+ delete options.clipPath;
20598
20710
  group.set(options);
20599
- 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
+ }
20600
20720
  });
20601
20721
  return;
20602
20722
  }
20603
20723
  fabric.util.enlivenObjects(objects, function (enlivenedObjects) {
20604
- var options = fabric.util.object.clone(object, true);
20605
- delete options.objects;
20606
20724
  fabric.util.enlivenObjectEnlivables(object, options, function () {
20607
20725
  callback && callback(new fabric.Group(enlivenedObjects, options, true));
20608
20726
  });
20609
20727
  });
20610
20728
  };
20611
-
20612
20729
  })(typeof exports !== 'undefined' ? exports : this);
20613
20730
 
20614
20731
 
@@ -26856,7 +26973,7 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
26856
26973
  // if we have charSpacing, we render char by char
26857
26974
  actualStyle = actualStyle || this.getCompleteStyleDeclaration(lineIndex, i);
26858
26975
  nextStyle = this.getCompleteStyleDeclaration(lineIndex, i + 1);
26859
- timeToRender = this._hasStyleChanged(actualStyle, nextStyle);
26976
+ timeToRender = fabric.util.hasStyleChanged(actualStyle, nextStyle, false);
26860
26977
  }
26861
26978
  if (timeToRender) {
26862
26979
  if (path) {
@@ -27026,34 +27143,6 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
27026
27143
  return this;
27027
27144
  },
27028
27145
 
27029
- /**
27030
- * @private
27031
- * @param {Object} prevStyle
27032
- * @param {Object} thisStyle
27033
- */
27034
- _hasStyleChanged: function(prevStyle, thisStyle) {
27035
- return prevStyle.fill !== thisStyle.fill ||
27036
- prevStyle.stroke !== thisStyle.stroke ||
27037
- prevStyle.strokeWidth !== thisStyle.strokeWidth ||
27038
- prevStyle.fontSize !== thisStyle.fontSize ||
27039
- prevStyle.fontFamily !== thisStyle.fontFamily ||
27040
- prevStyle.fontWeight !== thisStyle.fontWeight ||
27041
- prevStyle.fontStyle !== thisStyle.fontStyle ||
27042
- prevStyle.deltaY !== thisStyle.deltaY;
27043
- },
27044
-
27045
- /**
27046
- * @private
27047
- * @param {Object} prevStyle
27048
- * @param {Object} thisStyle
27049
- */
27050
- _hasStyleChangedForSvg: function(prevStyle, thisStyle) {
27051
- return this._hasStyleChanged(prevStyle, thisStyle) ||
27052
- prevStyle.overline !== thisStyle.overline ||
27053
- prevStyle.underline !== thisStyle.underline ||
27054
- prevStyle.linethrough !== thisStyle.linethrough;
27055
- },
27056
-
27057
27146
  /**
27058
27147
  * @private
27059
27148
  * @param {Number} lineIndex index text line
@@ -27315,8 +27404,7 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
27315
27404
  toObject: function(propertiesToInclude) {
27316
27405
  var allProperties = additionalProps.concat(propertiesToInclude);
27317
27406
  var obj = this.callSuper('toObject', allProperties);
27318
- // styles will be overridden with a properly cloned structure
27319
- obj.styles = clone(this.styles, true);
27407
+ obj.styles = fabric.util.stylesToArray(this.styles, this.text);
27320
27408
  if (obj.path) {
27321
27409
  obj.path = this.path.toObject();
27322
27410
  }
@@ -27482,6 +27570,7 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
27482
27570
  var objectCopy = clone(object), path = object.path;
27483
27571
  delete objectCopy.path;
27484
27572
  return fabric.Object._fromObject('Text', objectCopy, function(textInstance) {
27573
+ textInstance.styles = fabric.util.stylesFromArray(object.styles, object.text);
27485
27574
  if (path) {
27486
27575
  fabric.Object._fromObject('Path', path, function(pathInstance) {
27487
27576
  textInstance.set('path', pathInstance);
@@ -28339,15 +28428,18 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
28339
28428
  * @param {function} [callback] invoked with new instance as argument
28340
28429
  */
28341
28430
  fabric.IText.fromObject = function(object, callback) {
28342
- parseDecoration(object);
28343
- if (object.styles) {
28344
- for (var i in object.styles) {
28345
- for (var j in object.styles[i]) {
28346
- 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]);
28347
28439
  }
28348
28440
  }
28349
28441
  }
28350
- fabric.Object._fromObject('IText', object, callback, 'text');
28442
+ fabric.Object._fromObject('IText', objCopy, callback, 'text');
28351
28443
  };
28352
28444
  })();
28353
28445
 
@@ -28740,6 +28832,9 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
28740
28832
  return;
28741
28833
  }
28742
28834
 
28835
+ // regain focus
28836
+ document.activeElement !== this.hiddenTextarea && this.hiddenTextarea.focus();
28837
+
28743
28838
  var newSelectionStart = this.getSelectionStartFromPointer(options.e),
28744
28839
  currentStart = this.selectionStart,
28745
28840
  currentEnd = this.selectionEnd;
@@ -30093,7 +30188,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
30093
30188
  this[prop] += direction === 'Left' ? -1 : 1;
30094
30189
  return true;
30095
30190
  }
30096
- if (typeof newValue !== undefined && this[prop] !== newValue) {
30191
+ if (typeof newValue !== 'undefined' && this[prop] !== newValue) {
30097
30192
  this[prop] = newValue;
30098
30193
  return true;
30099
30194
  }
@@ -30411,7 +30506,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
30411
30506
  // if we have charSpacing, we render char by char
30412
30507
  actualStyle = actualStyle || this.getCompleteStyleDeclaration(lineIndex, i);
30413
30508
  nextStyle = this.getCompleteStyleDeclaration(lineIndex, i + 1);
30414
- timeToRender = this._hasStyleChangedForSvg(actualStyle, nextStyle);
30509
+ timeToRender = fabric.util.hasStyleChanged(actualStyle, nextStyle, true);
30415
30510
  }
30416
30511
  if (timeToRender) {
30417
30512
  style = this._getStyleDeclaration(lineIndex, i) || { };
@@ -30965,7 +31060,10 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
30965
31060
  * @param {Function} [callback] Callback to invoke when an fabric.Textbox instance is created
30966
31061
  */
30967
31062
  fabric.Textbox.fromObject = function(object, callback) {
30968
- 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');
30969
31067
  };
30970
31068
  })(typeof exports !== 'undefined' ? exports : this);
30971
31069