fabric 5.2.1-browser → 5.2.2
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 +152 -54
- package/dist/fabric.min.js +1 -1
- package/package.json +91 -88
- package/src/mixins/canvas_events.mixin.js +0 -8
- package/src/mixins/itext.svg_export.js +1 -1
- package/src/mixins/itext_behavior.mixin.js +3 -0
- package/src/mixins/itext_key_behavior.mixin.js +1 -1
- package/src/shapes/group.class.js +11 -4
- package/src/shapes/itext.class.js +9 -6
- package/src/shapes/path.class.js +9 -1
- package/src/shapes/text.class.js +3 -31
- package/src/shapes/textbox.class.js +4 -1
- package/src/util/dom_style.js +1 -1
- package/src/util/misc.js +110 -0
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
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
28343
|
-
|
|
28344
|
-
|
|
28345
|
-
|
|
28346
|
-
|
|
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',
|
|
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 =
|
|
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
|
-
|
|
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
|
|