fabric 4.6.0 → 5.0.0-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/CHANGELOG.md +42 -0
- package/HEADER.js +1 -1
- package/README.md +1 -6
- package/SECURITY.md +5 -0
- package/dist/fabric.js +652 -393
- package/dist/fabric.min.js +1 -1
- package/lib/event.js +7 -3
- package/package.json +87 -88
- package/src/brushes/base_brush.class.js +2 -2
- package/src/brushes/pattern_brush.class.js +7 -5
- package/src/brushes/pencil_brush.class.js +33 -4
- package/src/canvas.class.js +9 -17
- package/src/mixins/animation.mixin.js +16 -21
- package/src/mixins/canvas_events.mixin.js +27 -56
- package/src/mixins/eraser_brush.mixin.js +354 -420
- package/src/mixins/itext_behavior.mixin.js +7 -1
- package/src/mixins/object_geometry.mixin.js +3 -34
- package/src/mixins/object_straightening.mixin.js +4 -9
- package/src/parser.js +13 -9
- package/src/shapes/circle.class.js +20 -17
- package/src/shapes/group.class.js +13 -25
- package/src/shapes/image.class.js +3 -3
- package/src/shapes/object.class.js +45 -19
- package/src/shapes/path.class.js +13 -9
- package/src/shapes/polygon.class.js +9 -1
- package/src/shapes/polyline.class.js +33 -9
- package/src/shapes/text.class.js +38 -21
- package/src/static_canvas.class.js +15 -7
- package/src/util/animate.js +146 -22
- package/src/util/misc.js +193 -45
- package/src/util/path.js +2 -56
|
@@ -866,7 +866,13 @@
|
|
|
866
866
|
this.insertCharStyleObject(cursorLoc.lineIndex + i, 0, addedLines[i], copiedStyle);
|
|
867
867
|
}
|
|
868
868
|
else if (copiedStyle) {
|
|
869
|
-
this
|
|
869
|
+
// this test is required in order to close #6841
|
|
870
|
+
// when a pasted buffer begins with a newline then
|
|
871
|
+
// this.styles[cursorLoc.lineIndex + i] and copiedStyle[0]
|
|
872
|
+
// may be undefined for some reason
|
|
873
|
+
if (this.styles[cursorLoc.lineIndex + i] && copiedStyle[0]) {
|
|
874
|
+
this.styles[cursorLoc.lineIndex + i][0] = copiedStyle[0];
|
|
875
|
+
}
|
|
870
876
|
}
|
|
871
877
|
copiedStyle = copiedStyle && copiedStyle.slice(addedLines[i] + 1);
|
|
872
878
|
}
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
/**
|
|
46
46
|
* Describe object's corner position in canvas element coordinates.
|
|
47
47
|
* includes padding. Used of object detection.
|
|
48
|
-
* set and refreshed with setCoords
|
|
48
|
+
* set and refreshed with setCoords.
|
|
49
49
|
* @memberOf fabric.Object.prototype
|
|
50
50
|
*/
|
|
51
51
|
lineCoords: null,
|
|
@@ -429,21 +429,6 @@
|
|
|
429
429
|
return this.scale(value / this.height / boundingRectFactor);
|
|
430
430
|
},
|
|
431
431
|
|
|
432
|
-
/**
|
|
433
|
-
* Calculates and returns the .coords of an object.
|
|
434
|
-
* unused by the library, only for the end dev.
|
|
435
|
-
* @return {Object} Object with tl, tr, br, bl ....
|
|
436
|
-
* @chainable
|
|
437
|
-
* @deprecated
|
|
438
|
-
*/
|
|
439
|
-
calcCoords: function(absolute) {
|
|
440
|
-
// this is a compatibility function to avoid removing calcCoords now.
|
|
441
|
-
if (absolute) {
|
|
442
|
-
return this.calcACoords();
|
|
443
|
-
}
|
|
444
|
-
return this.calcOCoords();
|
|
445
|
-
},
|
|
446
|
-
|
|
447
432
|
calcLineCoords: function() {
|
|
448
433
|
var vpt = this.getViewportTransform(),
|
|
449
434
|
padding = this.padding, angle = degreesToRadians(this.angle),
|
|
@@ -518,7 +503,8 @@
|
|
|
518
503
|
* oCoords are used to find the corners
|
|
519
504
|
* aCoords are used to quickly find an object on the canvas
|
|
520
505
|
* lineCoords are used to quickly find object during pointer events.
|
|
521
|
-
* See {@link https://github.com/
|
|
506
|
+
* See {@link https://github.com/fabricjs/fabric.js/wiki/When-to-call-setCoords} and {@link http://fabricjs.com/fabric-gotchas}
|
|
507
|
+
*
|
|
522
508
|
* @param {Boolean} [skipCorners] skip calculation of oCoords.
|
|
523
509
|
* @return {fabric.Object} thisArg
|
|
524
510
|
* @chainable
|
|
@@ -615,23 +601,6 @@
|
|
|
615
601
|
return cache.value;
|
|
616
602
|
},
|
|
617
603
|
|
|
618
|
-
/*
|
|
619
|
-
* Calculate object dimensions from its properties
|
|
620
|
-
* @private
|
|
621
|
-
* @deprecated since 3.4.0, please use fabric.util._calcDimensionsTransformMatrix
|
|
622
|
-
* not including or including flipX, flipY to emulate the flipping boolean
|
|
623
|
-
* @return {Object} .x width dimension
|
|
624
|
-
* @return {Object} .y height dimension
|
|
625
|
-
*/
|
|
626
|
-
_calcDimensionsTransformMatrix: function(skewX, skewY, flipping) {
|
|
627
|
-
return util.calcDimensionsMatrix({
|
|
628
|
-
skewX: skewX,
|
|
629
|
-
skewY: skewY,
|
|
630
|
-
scaleX: this.scaleX * (flipping && this.flipX ? -1 : 1),
|
|
631
|
-
scaleY: this.scaleY * (flipping && this.flipY ? -1 : 1)
|
|
632
|
-
});
|
|
633
|
-
},
|
|
634
|
-
|
|
635
604
|
/*
|
|
636
605
|
* Calculate object dimensions from its properties
|
|
637
606
|
* @private
|
|
@@ -18,8 +18,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
18
18
|
* @chainable
|
|
19
19
|
*/
|
|
20
20
|
straighten: function() {
|
|
21
|
-
this.rotate(this._getAngleValueForStraighten());
|
|
22
|
-
return this;
|
|
21
|
+
return this.rotate(this._getAngleValueForStraighten());
|
|
23
22
|
},
|
|
24
23
|
|
|
25
24
|
/**
|
|
@@ -28,7 +27,6 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
28
27
|
* @param {Function} [callbacks.onComplete] Invoked on completion
|
|
29
28
|
* @param {Function} [callbacks.onChange] Invoked on every step of animation
|
|
30
29
|
* @return {fabric.Object} thisArg
|
|
31
|
-
* @chainable
|
|
32
30
|
*/
|
|
33
31
|
fxStraighten: function(callbacks) {
|
|
34
32
|
callbacks = callbacks || { };
|
|
@@ -38,7 +36,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
38
36
|
onChange = callbacks.onChange || empty,
|
|
39
37
|
_this = this;
|
|
40
38
|
|
|
41
|
-
fabric.util.animate({
|
|
39
|
+
return fabric.util.animate({
|
|
40
|
+
target: this,
|
|
42
41
|
startValue: this.get('angle'),
|
|
43
42
|
endValue: this._getAngleValueForStraighten(),
|
|
44
43
|
duration: this.FX_DURATION,
|
|
@@ -51,8 +50,6 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
51
50
|
onComplete();
|
|
52
51
|
},
|
|
53
52
|
});
|
|
54
|
-
|
|
55
|
-
return this;
|
|
56
53
|
}
|
|
57
54
|
});
|
|
58
55
|
|
|
@@ -74,12 +71,10 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
74
71
|
* Same as {@link fabric.Canvas.prototype.straightenObject}, but animated
|
|
75
72
|
* @param {fabric.Object} object Object to straighten
|
|
76
73
|
* @return {fabric.Canvas} thisArg
|
|
77
|
-
* @chainable
|
|
78
74
|
*/
|
|
79
75
|
fxStraightenObject: function (object) {
|
|
80
|
-
object.fxStraighten({
|
|
76
|
+
return object.fxStraighten({
|
|
81
77
|
onChange: this.requestRenderAllBound
|
|
82
78
|
});
|
|
83
|
-
return this;
|
|
84
79
|
}
|
|
85
80
|
});
|
package/src/parser.js
CHANGED
|
@@ -1001,22 +1001,26 @@
|
|
|
1001
1001
|
if (styleContents.trim() === '') {
|
|
1002
1002
|
continue;
|
|
1003
1003
|
}
|
|
1004
|
-
|
|
1005
|
-
rules =
|
|
1004
|
+
// recovers all the rule in this form `body { style code... }`
|
|
1005
|
+
// rules = styleContents.match(/[^{]*\{[\s\S]*?\}/g);
|
|
1006
|
+
rules = styleContents.split('}');
|
|
1007
|
+
// remove empty rules.
|
|
1008
|
+
rules = rules.filter(function(rule) { return rule.trim(); });
|
|
1009
|
+
// at this point we have hopefully an array of rules `body { style code... `
|
|
1006
1010
|
// eslint-disable-next-line no-loop-func
|
|
1007
1011
|
rules.forEach(function(rule) {
|
|
1008
1012
|
|
|
1009
|
-
var match = rule.
|
|
1010
|
-
ruleObj = { }, declaration = match[
|
|
1011
|
-
propertyValuePairs = declaration.
|
|
1013
|
+
var match = rule.split('{'),
|
|
1014
|
+
ruleObj = { }, declaration = match[1].trim(),
|
|
1015
|
+
propertyValuePairs = declaration.split(';').filter(function(pair) { return pair.trim(); });
|
|
1012
1016
|
|
|
1013
1017
|
for (i = 0, len = propertyValuePairs.length; i < len; i++) {
|
|
1014
|
-
var pair = propertyValuePairs[i].split(
|
|
1015
|
-
property = pair[0],
|
|
1016
|
-
value = pair[1];
|
|
1018
|
+
var pair = propertyValuePairs[i].split(':'),
|
|
1019
|
+
property = pair[0].trim(),
|
|
1020
|
+
value = pair[1].trim();
|
|
1017
1021
|
ruleObj[property] = value;
|
|
1018
1022
|
}
|
|
1019
|
-
rule = match[
|
|
1023
|
+
rule = match[0].trim();
|
|
1020
1024
|
rule.split(',').forEach(function(_rule) {
|
|
1021
1025
|
_rule = _rule.replace(/^svg/i, '').trim();
|
|
1022
1026
|
if (_rule === '') {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
5
5
|
var fabric = global.fabric || (global.fabric = { }),
|
|
6
|
-
|
|
6
|
+
degreesToRadians = fabric.util.degreesToRadians;
|
|
7
7
|
|
|
8
8
|
if (fabric.Circle) {
|
|
9
9
|
fabric.warn('fabric.Circle is already defined.');
|
|
@@ -33,22 +33,20 @@
|
|
|
33
33
|
radius: 0,
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
|
-
*
|
|
37
|
-
* deprecated type, this should be in degree, this was an oversight.
|
|
36
|
+
* degrees of start of the circle.
|
|
38
37
|
* probably will change to degrees in next major version
|
|
39
|
-
* @type Number
|
|
38
|
+
* @type Number 0 - 359
|
|
40
39
|
* @default 0
|
|
41
40
|
*/
|
|
42
41
|
startAngle: 0,
|
|
43
42
|
|
|
44
43
|
/**
|
|
45
44
|
* End angle of the circle
|
|
46
|
-
* deprecated type, this should be in degree, this was an oversight.
|
|
47
45
|
* probably will change to degrees in next major version
|
|
48
|
-
* @type Number
|
|
49
|
-
* @default
|
|
46
|
+
* @type Number 1 - 360
|
|
47
|
+
* @default 360
|
|
50
48
|
*/
|
|
51
|
-
endAngle:
|
|
49
|
+
endAngle: 360,
|
|
52
50
|
|
|
53
51
|
cacheProperties: fabric.Object.prototype.cacheProperties.concat('radius', 'startAngle', 'endAngle'),
|
|
54
52
|
|
|
@@ -86,7 +84,7 @@
|
|
|
86
84
|
*/
|
|
87
85
|
_toSVG: function() {
|
|
88
86
|
var svgString, x = 0, y = 0,
|
|
89
|
-
angle = (this.endAngle - this.startAngle) %
|
|
87
|
+
angle = (this.endAngle - this.startAngle) % 360;
|
|
90
88
|
|
|
91
89
|
if (angle === 0) {
|
|
92
90
|
svgString = [
|
|
@@ -97,14 +95,17 @@
|
|
|
97
95
|
];
|
|
98
96
|
}
|
|
99
97
|
else {
|
|
100
|
-
var
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
98
|
+
var start = degreesToRadians(this.startAngle),
|
|
99
|
+
end = degreesToRadians(this.endAngle),
|
|
100
|
+
radius = this.radius,
|
|
101
|
+
startX = fabric.util.cos(start) * radius,
|
|
102
|
+
startY = fabric.util.sin(start) * radius,
|
|
103
|
+
endX = fabric.util.cos(end) * radius,
|
|
104
|
+
endY = fabric.util.sin(end) * radius,
|
|
105
|
+
largeFlag = angle > 180 ? '1' : '0';
|
|
105
106
|
svgString = [
|
|
106
107
|
'<path d="M ' + startX + ' ' + startY,
|
|
107
|
-
' A ' +
|
|
108
|
+
' A ' + radius + ' ' + radius,
|
|
108
109
|
' 0 ', +largeFlag + ' 1', ' ' + endX + ' ' + endY,
|
|
109
110
|
'" ', 'COMMON_PARTS', ' />\n'
|
|
110
111
|
];
|
|
@@ -123,8 +124,10 @@
|
|
|
123
124
|
0,
|
|
124
125
|
0,
|
|
125
126
|
this.radius,
|
|
126
|
-
this.startAngle,
|
|
127
|
-
this.endAngle,
|
|
127
|
+
degreesToRadians(this.startAngle),
|
|
128
|
+
degreesToRadians(this.endAngle),
|
|
129
|
+
false
|
|
130
|
+
);
|
|
128
131
|
this._renderPaintInOrder(ctx);
|
|
129
132
|
},
|
|
130
133
|
|
|
@@ -343,7 +343,7 @@
|
|
|
343
343
|
for (var i = 0, len = this._objects.length; i < len; i++) {
|
|
344
344
|
this._objects[i].render(ctx);
|
|
345
345
|
}
|
|
346
|
-
this._drawClipPath(ctx);
|
|
346
|
+
this._drawClipPath(ctx, this.clipPath);
|
|
347
347
|
},
|
|
348
348
|
|
|
349
349
|
/**
|
|
@@ -389,25 +389,6 @@
|
|
|
389
389
|
return this;
|
|
390
390
|
},
|
|
391
391
|
|
|
392
|
-
/**
|
|
393
|
-
* Realises the transform from this group onto the supplied object
|
|
394
|
-
* i.e. it tells you what would happen if the supplied object was in
|
|
395
|
-
* the group, and then the group was destroyed. It mutates the supplied
|
|
396
|
-
* object.
|
|
397
|
-
* Warning: this method is not useful anymore, it has been kept to no break the api.
|
|
398
|
-
* is not used in the fabricJS codebase
|
|
399
|
-
* this method will be reduced to using the utility.
|
|
400
|
-
* @private
|
|
401
|
-
* @deprecated
|
|
402
|
-
* @param {fabric.Object} object
|
|
403
|
-
* @param {Array} parentMatrix parent transformation
|
|
404
|
-
* @return {fabric.Object} transformedObject
|
|
405
|
-
*/
|
|
406
|
-
realizeTransform: function(object, parentMatrix) {
|
|
407
|
-
fabric.util.addTransformToObject(object, parentMatrix);
|
|
408
|
-
return object;
|
|
409
|
-
},
|
|
410
|
-
|
|
411
392
|
/**
|
|
412
393
|
* Destroys a group (restoring state of its objects)
|
|
413
394
|
* @return {fabric.Group} thisArg
|
|
@@ -422,6 +403,14 @@
|
|
|
422
403
|
return this._restoreObjectsState();
|
|
423
404
|
},
|
|
424
405
|
|
|
406
|
+
dispose: function () {
|
|
407
|
+
this.callSuper('dispose');
|
|
408
|
+
this.forEachObject(function (object) {
|
|
409
|
+
object.dispose && object.dispose();
|
|
410
|
+
});
|
|
411
|
+
this._objects = [];
|
|
412
|
+
},
|
|
413
|
+
|
|
425
414
|
/**
|
|
426
415
|
* make a group an active selection, remove the group from canvas
|
|
427
416
|
* the group has to be on canvas for this to work.
|
|
@@ -585,11 +574,10 @@
|
|
|
585
574
|
});
|
|
586
575
|
return;
|
|
587
576
|
}
|
|
588
|
-
fabric.util.enlivenObjects(objects, function(enlivenedObjects) {
|
|
589
|
-
fabric.util.
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
delete options.objects;
|
|
577
|
+
fabric.util.enlivenObjects(objects, function (enlivenedObjects) {
|
|
578
|
+
var options = fabric.util.object.clone(object, true);
|
|
579
|
+
delete options.objects;
|
|
580
|
+
fabric.util.enlivenObjectEnlivables(object, options, function () {
|
|
593
581
|
callback && callback(new fabric.Group(enlivenedObjects, options, true));
|
|
594
582
|
});
|
|
595
583
|
});
|
|
@@ -202,7 +202,8 @@
|
|
|
202
202
|
/**
|
|
203
203
|
* Delete textures, reference to elements and eventually JSDOM cleanup
|
|
204
204
|
*/
|
|
205
|
-
dispose: function() {
|
|
205
|
+
dispose: function () {
|
|
206
|
+
this.callSuper('dispose');
|
|
206
207
|
this.removeTexture(this.cacheKey);
|
|
207
208
|
this.removeTexture(this.cacheKey + '_filtered');
|
|
208
209
|
this._cacheContext = undefined;
|
|
@@ -712,8 +713,7 @@
|
|
|
712
713
|
object.filters = filters || [];
|
|
713
714
|
fabric.Image.prototype._initFilters.call(object, [object.resizeFilter], function(resizeFilters) {
|
|
714
715
|
object.resizeFilter = resizeFilters[0];
|
|
715
|
-
fabric.util.
|
|
716
|
-
object.clipPath = enlivedProps[0];
|
|
716
|
+
fabric.util.enlivenObjectEnlivables(object, object, function () {
|
|
717
717
|
var image = new fabric.Image(img, object);
|
|
718
718
|
callback(image, false);
|
|
719
719
|
});
|
|
@@ -536,6 +536,7 @@
|
|
|
536
536
|
/**
|
|
537
537
|
* When `false`, the stoke width will scale with the object.
|
|
538
538
|
* When `true`, the stroke will always match the exact pixel size entered for stroke width.
|
|
539
|
+
* this Property does not work on Text classes or drawing call that uses strokeText,fillText methods
|
|
539
540
|
* default to false
|
|
540
541
|
* @since 2.6.0
|
|
541
542
|
* @type Boolean
|
|
@@ -1186,26 +1187,26 @@
|
|
|
1186
1187
|
/**
|
|
1187
1188
|
* Execute the drawing operation for an object clipPath
|
|
1188
1189
|
* @param {CanvasRenderingContext2D} ctx Context to render on
|
|
1190
|
+
* @param {fabric.Object} clipPath
|
|
1189
1191
|
*/
|
|
1190
|
-
drawClipPathOnCache: function(ctx) {
|
|
1191
|
-
var path = this.clipPath;
|
|
1192
|
+
drawClipPathOnCache: function(ctx, clipPath) {
|
|
1192
1193
|
ctx.save();
|
|
1193
1194
|
// DEBUG: uncomment this line, comment the following
|
|
1194
1195
|
// ctx.globalAlpha = 0.4
|
|
1195
|
-
if (
|
|
1196
|
+
if (clipPath.inverted) {
|
|
1196
1197
|
ctx.globalCompositeOperation = 'destination-out';
|
|
1197
1198
|
}
|
|
1198
1199
|
else {
|
|
1199
1200
|
ctx.globalCompositeOperation = 'destination-in';
|
|
1200
1201
|
}
|
|
1201
1202
|
//ctx.scale(1 / 2, 1 / 2);
|
|
1202
|
-
if (
|
|
1203
|
+
if (clipPath.absolutePositioned) {
|
|
1203
1204
|
var m = fabric.util.invertTransform(this.calcTransformMatrix());
|
|
1204
1205
|
ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
|
|
1205
1206
|
}
|
|
1206
|
-
|
|
1207
|
-
ctx.scale(1 /
|
|
1208
|
-
ctx.drawImage(
|
|
1207
|
+
clipPath.transform(ctx);
|
|
1208
|
+
ctx.scale(1 / clipPath.zoomX, 1 / clipPath.zoomY);
|
|
1209
|
+
ctx.drawImage(clipPath._cacheCanvas, -clipPath.cacheTranslationX, -clipPath.cacheTranslationY);
|
|
1209
1210
|
ctx.restore();
|
|
1210
1211
|
},
|
|
1211
1212
|
|
|
@@ -1224,22 +1225,26 @@
|
|
|
1224
1225
|
this._renderBackground(ctx);
|
|
1225
1226
|
}
|
|
1226
1227
|
this._render(ctx);
|
|
1227
|
-
this._drawClipPath(ctx);
|
|
1228
|
+
this._drawClipPath(ctx, this.clipPath);
|
|
1228
1229
|
this.fill = originalFill;
|
|
1229
1230
|
this.stroke = originalStroke;
|
|
1230
1231
|
},
|
|
1231
1232
|
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1233
|
+
/**
|
|
1234
|
+
* Prepare clipPath state and cache and draw it on instance's cache
|
|
1235
|
+
* @param {CanvasRenderingContext2D} ctx
|
|
1236
|
+
* @param {fabric.Object} clipPath
|
|
1237
|
+
*/
|
|
1238
|
+
_drawClipPath: function (ctx, clipPath) {
|
|
1239
|
+
if (!clipPath) { return; }
|
|
1235
1240
|
// needed to setup a couple of variables
|
|
1236
1241
|
// path canvas gets overridden with this one.
|
|
1237
1242
|
// TODO find a better solution?
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
this.drawClipPathOnCache(ctx);
|
|
1243
|
+
clipPath.canvas = this.canvas;
|
|
1244
|
+
clipPath.shouldCache();
|
|
1245
|
+
clipPath._transformDone = true;
|
|
1246
|
+
clipPath.renderCache({ forClipping: true });
|
|
1247
|
+
this.drawClipPathOnCache(ctx, clipPath);
|
|
1243
1248
|
},
|
|
1244
1249
|
|
|
1245
1250
|
/**
|
|
@@ -1383,6 +1388,7 @@
|
|
|
1383
1388
|
|
|
1384
1389
|
/**
|
|
1385
1390
|
* Renders controls and borders for the object
|
|
1391
|
+
* the context here is not transformed
|
|
1386
1392
|
* @param {CanvasRenderingContext2D} ctx Context to render on
|
|
1387
1393
|
* @param {Object} [styleOverride] properties to override the object style
|
|
1388
1394
|
*/
|
|
@@ -1401,7 +1407,10 @@
|
|
|
1401
1407
|
if (!this.group) {
|
|
1402
1408
|
ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;
|
|
1403
1409
|
}
|
|
1404
|
-
|
|
1410
|
+
if (this.flipX) {
|
|
1411
|
+
options.angle -= 180;
|
|
1412
|
+
}
|
|
1413
|
+
ctx.rotate(degreesToRadians(this.group ? options.angle : this.angle));
|
|
1405
1414
|
if (styleOverride.forActiveSelection || this.group) {
|
|
1406
1415
|
drawBorders && this.drawBordersInGroup(ctx, options, styleOverride);
|
|
1407
1416
|
}
|
|
@@ -1937,6 +1946,15 @@
|
|
|
1937
1946
|
if (this.globalCompositeOperation) {
|
|
1938
1947
|
ctx.globalCompositeOperation = this.globalCompositeOperation;
|
|
1939
1948
|
}
|
|
1949
|
+
},
|
|
1950
|
+
|
|
1951
|
+
/**
|
|
1952
|
+
* cancel instance's running animations
|
|
1953
|
+
*/
|
|
1954
|
+
dispose: function () {
|
|
1955
|
+
if (fabric.runningAnimations) {
|
|
1956
|
+
fabric.runningAnimations.cancelByTarget(this);
|
|
1957
|
+
}
|
|
1940
1958
|
}
|
|
1941
1959
|
});
|
|
1942
1960
|
|
|
@@ -1954,6 +1972,15 @@
|
|
|
1954
1972
|
*/
|
|
1955
1973
|
fabric.Object.NUM_FRACTION_DIGITS = 2;
|
|
1956
1974
|
|
|
1975
|
+
/**
|
|
1976
|
+
* Defines which properties should be enlivened from the object passed to {@link fabric.Object._fromObject}
|
|
1977
|
+
* @static
|
|
1978
|
+
* @memberOf fabric.Object
|
|
1979
|
+
* @constant
|
|
1980
|
+
* @type string[]
|
|
1981
|
+
*/
|
|
1982
|
+
fabric.Object.ENLIVEN_PROPS = ['clipPath'];
|
|
1983
|
+
|
|
1957
1984
|
fabric.Object._fromObject = function(className, object, callback, extraParam) {
|
|
1958
1985
|
var klass = fabric[className];
|
|
1959
1986
|
object = clone(object, true);
|
|
@@ -1964,8 +1991,7 @@
|
|
|
1964
1991
|
if (typeof patterns[1] !== 'undefined') {
|
|
1965
1992
|
object.stroke = patterns[1];
|
|
1966
1993
|
}
|
|
1967
|
-
fabric.util.
|
|
1968
|
-
object.clipPath = enlivedProps[0];
|
|
1994
|
+
fabric.util.enlivenObjectEnlivables(object, object, function () {
|
|
1969
1995
|
var instance = extraParam ? new klass(object[extraParam], object) : new klass(object);
|
|
1970
1996
|
callback && callback(instance);
|
|
1971
1997
|
});
|
package/src/shapes/path.class.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
min = fabric.util.array.min,
|
|
7
7
|
max = fabric.util.array.max,
|
|
8
8
|
extend = fabric.util.object.extend,
|
|
9
|
+
clone = fabric.util.object.clone,
|
|
9
10
|
_toString = Object.prototype.toString,
|
|
10
11
|
toFixed = fabric.util.toFixed;
|
|
11
12
|
|
|
@@ -47,23 +48,26 @@
|
|
|
47
48
|
* @param {Object} [options] Options object
|
|
48
49
|
* @return {fabric.Path} thisArg
|
|
49
50
|
*/
|
|
50
|
-
initialize: function(path, options) {
|
|
51
|
-
options = options || {
|
|
51
|
+
initialize: function (path, options) {
|
|
52
|
+
options = clone(options || {});
|
|
53
|
+
delete options.path;
|
|
52
54
|
this.callSuper('initialize', options);
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
55
|
+
this._setPath(path || [], options);
|
|
56
|
+
},
|
|
56
57
|
|
|
58
|
+
/**
|
|
59
|
+
* @private
|
|
60
|
+
* @param {Array|String} path Path data (sequence of coordinates and corresponding "command" tokens)
|
|
61
|
+
* @param {Object} [options] Options object
|
|
62
|
+
*/
|
|
63
|
+
_setPath: function (path, options) {
|
|
57
64
|
var fromArray = _toString.call(path) === '[object Array]';
|
|
58
65
|
|
|
59
66
|
this.path = fabric.util.makePathSimpler(
|
|
60
67
|
fromArray ? path : fabric.util.parsePath(path)
|
|
61
68
|
);
|
|
62
69
|
|
|
63
|
-
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
fabric.Polyline.prototype._setPositionDimensions.call(this, options);
|
|
70
|
+
fabric.Polyline.prototype._setPositionDimensions.call(this, options || {});
|
|
67
71
|
},
|
|
68
72
|
|
|
69
73
|
/**
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
5
|
-
var fabric = global.fabric || (global.fabric = {
|
|
5
|
+
var fabric = global.fabric || (global.fabric = {}),
|
|
6
|
+
projectStrokeOnPoints = fabric.util.projectStrokeOnPoints;
|
|
6
7
|
|
|
7
8
|
if (fabric.Polygon) {
|
|
8
9
|
fabric.warn('fabric.Polygon is already defined');
|
|
@@ -24,6 +25,13 @@
|
|
|
24
25
|
*/
|
|
25
26
|
type: 'polygon',
|
|
26
27
|
|
|
28
|
+
/**
|
|
29
|
+
* @private
|
|
30
|
+
*/
|
|
31
|
+
_projectStrokeOnPoints: function () {
|
|
32
|
+
return projectStrokeOnPoints(this.points, this);
|
|
33
|
+
},
|
|
34
|
+
|
|
27
35
|
/**
|
|
28
36
|
* @private
|
|
29
37
|
* @param {CanvasRenderingContext2D} ctx Context to render on
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
extend = fabric.util.object.extend,
|
|
7
7
|
min = fabric.util.array.min,
|
|
8
8
|
max = fabric.util.array.max,
|
|
9
|
-
toFixed = fabric.util.toFixed
|
|
9
|
+
toFixed = fabric.util.toFixed,
|
|
10
|
+
projectStrokeOnPoints = fabric.util.projectStrokeOnPoints;
|
|
10
11
|
|
|
11
12
|
if (fabric.Polyline) {
|
|
12
13
|
fabric.warn('fabric.Polyline is already defined');
|
|
@@ -35,6 +36,17 @@
|
|
|
35
36
|
*/
|
|
36
37
|
points: null,
|
|
37
38
|
|
|
39
|
+
/**
|
|
40
|
+
* WARNING: Feature in progress
|
|
41
|
+
* Calculate the exact bounding box taking in account strokeWidth on acute angles
|
|
42
|
+
* this will be turned to true by default on fabric 6.0
|
|
43
|
+
* maybe will be left in as an optimization since calculations may be slow
|
|
44
|
+
* @deprecated
|
|
45
|
+
* @type Boolean
|
|
46
|
+
* @default false
|
|
47
|
+
*/
|
|
48
|
+
exactBoundingBox: false,
|
|
49
|
+
|
|
38
50
|
cacheProperties: fabric.Object.prototype.cacheProperties.concat('points'),
|
|
39
51
|
|
|
40
52
|
/**
|
|
@@ -63,13 +75,25 @@
|
|
|
63
75
|
this._setPositionDimensions(options);
|
|
64
76
|
},
|
|
65
77
|
|
|
78
|
+
/**
|
|
79
|
+
* @private
|
|
80
|
+
*/
|
|
81
|
+
_projectStrokeOnPoints: function () {
|
|
82
|
+
return projectStrokeOnPoints(this.points, this, true);
|
|
83
|
+
},
|
|
84
|
+
|
|
66
85
|
_setPositionDimensions: function(options) {
|
|
67
|
-
var calcDim = this._calcDimensions(options), correctLeftTop
|
|
68
|
-
|
|
69
|
-
this.
|
|
86
|
+
var calcDim = this._calcDimensions(options), correctLeftTop,
|
|
87
|
+
correctSize = this.exactBoundingBox ? this.strokeWidth : 0;
|
|
88
|
+
this.width = calcDim.width - correctSize;
|
|
89
|
+
this.height = calcDim.height - correctSize;
|
|
70
90
|
if (!options.fromSVG) {
|
|
71
91
|
correctLeftTop = this.translateToGivenOrigin(
|
|
72
|
-
{
|
|
92
|
+
{
|
|
93
|
+
// this looks bad, but is one way to keep it optional for now.
|
|
94
|
+
x: calcDim.left - this.strokeWidth / 2 + correctSize / 2,
|
|
95
|
+
y: calcDim.top - this.strokeWidth / 2 + correctSize / 2
|
|
96
|
+
},
|
|
73
97
|
'left',
|
|
74
98
|
'top',
|
|
75
99
|
this.originX,
|
|
@@ -83,8 +107,8 @@
|
|
|
83
107
|
this.top = options.fromSVG ? calcDim.top : correctLeftTop.y;
|
|
84
108
|
}
|
|
85
109
|
this.pathOffset = {
|
|
86
|
-
x: calcDim.left + this.width / 2,
|
|
87
|
-
y: calcDim.top + this.height / 2
|
|
110
|
+
x: calcDim.left + this.width / 2 + correctSize / 2,
|
|
111
|
+
y: calcDim.top + this.height / 2 + correctSize / 2
|
|
88
112
|
};
|
|
89
113
|
},
|
|
90
114
|
|
|
@@ -100,7 +124,7 @@
|
|
|
100
124
|
*/
|
|
101
125
|
_calcDimensions: function() {
|
|
102
126
|
|
|
103
|
-
var points = this.points,
|
|
127
|
+
var points = this.exactBoundingBox ? this._projectStrokeOnPoints() : this.points,
|
|
104
128
|
minX = min(points, 'x') || 0,
|
|
105
129
|
minY = min(points, 'y') || 0,
|
|
106
130
|
maxX = max(points, 'x') || 0,
|
|
@@ -112,7 +136,7 @@
|
|
|
112
136
|
left: minX,
|
|
113
137
|
top: minY,
|
|
114
138
|
width: width,
|
|
115
|
-
height: height
|
|
139
|
+
height: height,
|
|
116
140
|
};
|
|
117
141
|
},
|
|
118
142
|
|