fabric 6.0.0-beta13 → 6.0.0-beta14

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.
Files changed (105) hide show
  1. package/.eslintrc.js +9 -0
  2. package/CHANGELOG.md +30 -1
  3. package/CONTRIBUTING.md +9 -9
  4. package/dist/fabric.d.ts +3 -3
  5. package/dist/index.js +234 -302
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.min.js +1 -1
  8. package/dist/index.mjs +231 -302
  9. package/dist/index.mjs.map +1 -1
  10. package/dist/index.node.cjs +234 -302
  11. package/dist/index.node.cjs.map +1 -1
  12. package/dist/index.node.mjs +231 -302
  13. package/dist/index.node.mjs.map +1 -1
  14. package/dist/src/Intersection.d.ts +8 -0
  15. package/dist/src/canvas/Canvas.d.ts +1 -1
  16. package/dist/src/canvas/CanvasOptions.d.ts +1 -1
  17. package/dist/src/canvas/DOMManagers/CanvasDOMManager.d.ts +1 -1
  18. package/dist/src/canvas/DOMManagers/StaticCanvasDOMManager.d.ts +2 -2
  19. package/dist/src/canvas/SelectableCanvas.d.ts +10 -15
  20. package/dist/src/canvas/StaticCanvas.d.ts +2 -2
  21. package/dist/src/controls/Control.d.ts +8 -8
  22. package/dist/src/controls/index.d.ts +1 -1
  23. package/dist/src/controls/polyControl.d.ts +25 -0
  24. package/dist/src/filters/BlendImage.d.ts +4 -4
  25. package/dist/src/shapes/Group.d.ts +5 -1
  26. package/dist/src/shapes/IText/ITextBehavior.d.ts +2 -2
  27. package/dist/src/shapes/Image.d.ts +19 -11
  28. package/dist/src/shapes/Object/FabricObject.d.ts +8 -0
  29. package/dist/src/shapes/Object/InteractiveObject.d.ts +2 -3
  30. package/dist/src/shapes/Object/Object.d.ts +4 -4
  31. package/dist/src/shapes/Object/ObjectGeometry.d.ts +3 -29
  32. package/dist/src/shapes/Object/types/FabricObjectProps.d.ts +1 -1
  33. package/dist/src/shapes/Path.d.ts +1 -1
  34. package/dist/src/shapes/Text/StyledText.d.ts +2 -2
  35. package/dist/src/shapes/Text/Text.d.ts +15 -7
  36. package/dist/src/shapes/Text/TextSVGExportMixin.d.ts +7 -7
  37. package/dist/src/shapes/Text/constants.d.ts +2 -2
  38. package/dist/src/util/animation/AnimationRegistry.d.ts +4 -4
  39. package/dist/src/util/internals/console.d.ts +8 -0
  40. package/dist/src/util/misc/dom.d.ts +1 -1
  41. package/dist/src/util/misc/svgParsing.d.ts +2 -1
  42. package/dist/src/util/typeAssertions.d.ts +2 -2
  43. package/fabric.ts +7 -3
  44. package/jest.extend.ts +3 -1
  45. package/package.json +5 -6
  46. package/playwright.setup.ts +82 -14
  47. package/src/ClassRegistry.ts +3 -1
  48. package/src/Collection.ts +2 -3
  49. package/src/Intersection.spec.ts +74 -0
  50. package/src/Intersection.ts +30 -0
  51. package/src/Pattern/Pattern.ts +2 -1
  52. package/src/benchmarks/README.md +7 -0
  53. package/src/benchmarks/calcCornerCoords.mjs +117 -0
  54. package/src/benchmarks/raycasting.mjs +154 -0
  55. package/src/canvas/Canvas.ts +23 -11
  56. package/src/canvas/CanvasOptions.ts +1 -1
  57. package/src/canvas/DOMManagers/CanvasDOMManager.ts +1 -1
  58. package/src/canvas/DOMManagers/StaticCanvasDOMManager.ts +7 -7
  59. package/src/canvas/SelectableCanvas.ts +30 -43
  60. package/src/canvas/StaticCanvas.ts +9 -7
  61. package/src/canvas/__tests__/SelectableCanvas.spec.ts +60 -0
  62. package/src/canvas/__tests__/__snapshots__/eventData.test.ts.snap +193 -2
  63. package/src/canvas/__tests__/eventData.test.ts +40 -1
  64. package/src/controls/Control.spec.ts +41 -0
  65. package/src/controls/Control.ts +36 -44
  66. package/src/controls/index.ts +1 -1
  67. package/src/controls/polyControl.ts +8 -5
  68. package/src/filters/BaseFilter.ts +8 -6
  69. package/src/filters/BlendImage.ts +4 -4
  70. package/src/filters/GLProbes/WebGLProbe.ts +2 -1
  71. package/src/parser/elements_parser.ts +2 -2
  72. package/src/parser/parseSVGDocument.ts +2 -1
  73. package/src/shapes/ActiveSelection.spec.ts +35 -1
  74. package/src/shapes/ActiveSelection.ts +3 -1
  75. package/src/shapes/Group.ts +7 -8
  76. package/src/shapes/IText/IText.test.ts +43 -0
  77. package/src/shapes/IText/IText.ts +1 -1
  78. package/src/shapes/IText/ITextBehavior.ts +2 -2
  79. package/src/shapes/IText/__snapshots__/IText.test.ts.snap +50 -0
  80. package/src/shapes/Image.ts +23 -14
  81. package/src/shapes/Object/FabricObject.spec.ts +16 -0
  82. package/src/shapes/Object/FabricObject.ts +8 -0
  83. package/src/shapes/Object/InteractiveObject.spec.ts +43 -0
  84. package/src/shapes/Object/InteractiveObject.ts +20 -30
  85. package/src/shapes/Object/Object.ts +6 -5
  86. package/src/shapes/Object/ObjectGeometry.ts +11 -126
  87. package/src/shapes/Object/types/FabricObjectProps.ts +1 -1
  88. package/src/shapes/Text/StyledText.ts +5 -2
  89. package/src/shapes/Text/Text.spec.ts +9 -9
  90. package/src/shapes/Text/Text.ts +24 -15
  91. package/src/shapes/Text/TextSVGExportMixin.spec.ts +29 -0
  92. package/src/shapes/Text/TextSVGExportMixin.ts +16 -13
  93. package/src/shapes/Text/__snapshots__/Text.spec.ts.snap +6 -6
  94. package/src/shapes/Text/constants.ts +2 -2
  95. package/src/util/animation/AnimationRegistry.ts +7 -6
  96. package/src/util/internals/console.ts +18 -0
  97. package/src/util/internals/dom_request.ts +2 -1
  98. package/src/util/misc/dom.ts +3 -2
  99. package/src/util/misc/objectEnlive.ts +3 -2
  100. package/src/util/misc/planeChange.ts +3 -2
  101. package/src/util/misc/svgParsing.ts +22 -9
  102. package/src/util/transform_matrix_removal.ts +3 -3
  103. package/src/util/typeAssertions.ts +2 -2
  104. package/typedoc.config.json +6 -0
  105. package/typedoc.json +3 -2
package/dist/index.js CHANGED
@@ -230,6 +230,26 @@
230
230
  }
231
231
  const config = new Configuration();
232
232
 
233
+ const log = function (severity) {
234
+ for (var _len = arguments.length, optionalParams = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
235
+ optionalParams[_key - 1] = arguments[_key];
236
+ }
237
+ return (
238
+ // eslint-disable-next-line no-restricted-syntax
239
+ console[severity]('fabric', ...optionalParams)
240
+ );
241
+ };
242
+ class FabricError extends Error {
243
+ constructor(message, options) {
244
+ super("fabric: ".concat(message), options);
245
+ }
246
+ }
247
+ class SignalAbortedError extends FabricError {
248
+ constructor(context) {
249
+ super("".concat(context, " 'options.signal' is in 'aborted' state"));
250
+ }
251
+ }
252
+
233
253
  class GLProbe {}
234
254
 
235
255
  /**
@@ -261,7 +281,7 @@
261
281
  if (gl) {
262
282
  this.maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);
263
283
  this.GLPrecision = ['highp', 'mediump', 'lowp'].find(precision => this.testPrecision(gl, precision));
264
- console.log("fabric: max texture size ".concat(this.maxTextureSize));
284
+ log('log', "WebGL: max texture size ".concat(this.maxTextureSize));
265
285
  }
266
286
  }
267
287
  isSupported(textureSize) {
@@ -399,7 +419,7 @@
399
419
  }
400
420
  const cache = new Cache();
401
421
 
402
- var version = "6.0.0-beta13";
422
+ var version = "6.0.0-beta14";
403
423
 
404
424
  // use this syntax so babel plugin see this import here
405
425
  const VERSION = version;
@@ -447,7 +467,7 @@
447
467
  getClass(classType) {
448
468
  const constructor = this[JSON$1].get(classType);
449
469
  if (!constructor) {
450
- throw new Error("No class registered for ".concat(classType));
470
+ throw new FabricError("No class registered for ".concat(classType));
451
471
  }
452
472
  return constructor;
453
473
  }
@@ -493,8 +513,8 @@
493
513
  }
494
514
 
495
515
  /**
496
- * Cancel all running animations attached to a Canvas on the next frame
497
- * @param {Canvas} canvas
516
+ * Cancel all running animations attached to a canvas on the next frame
517
+ * @param {StaticCanvas} canvas
498
518
  */
499
519
  cancelByCanvas(canvas) {
500
520
  if (!canvas) {
@@ -502,7 +522,7 @@
502
522
  }
503
523
  const animations = this.filter(animation => {
504
524
  var _animation$target;
505
- return typeof animation.target === 'object' && ((_animation$target = animation.target) === null || _animation$target === void 0 ? void 0 : _animation$target.canvas) === canvas;
525
+ return animation.target === canvas || typeof animation.target === 'object' && ((_animation$target = animation.target) === null || _animation$target === void 0 ? void 0 : _animation$target.canvas) === canvas;
506
526
  });
507
527
  animations.forEach(animation => animation.abort());
508
528
  return animations;
@@ -1439,7 +1459,7 @@
1439
1459
  // we iterate reverse order to collect top first in case of click.
1440
1460
  for (let i = this._objects.length - 1; i >= 0; i--) {
1441
1461
  const object = this._objects[i];
1442
- if (object.selectable && object.visible && (includeIntersecting && object.intersectsWithRect(tl, br, true) || object.isContainedWithinRect(tl, br, true) || includeIntersecting && object.containsPoint(tl, undefined, true) || includeIntersecting && object.containsPoint(br, undefined, true))) {
1462
+ if (object.selectable && object.visible && (includeIntersecting && object.intersectsWithRect(tl, br, true) || object.isContainedWithinRect(tl, br, true) || includeIntersecting && object.containsPoint(tl, true) || includeIntersecting && object.containsPoint(br, true))) {
1443
1463
  objects.push(object);
1444
1464
  }
1445
1465
  }
@@ -1529,7 +1549,7 @@
1529
1549
  const createCanvasElement = () => {
1530
1550
  const element = getFabricDocument().createElement('canvas');
1531
1551
  if (!element || typeof element.getContext === 'undefined') {
1532
- throw new Error('Failed to create `canvas` element');
1552
+ throw new FabricError('Failed to create `canvas` element');
1533
1553
  }
1534
1554
  return element;
1535
1555
  };
@@ -1817,7 +1837,7 @@
1817
1837
  } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1818
1838
  return new Promise(function (resolve, reject) {
1819
1839
  if (signal && signal.aborted) {
1820
- return reject(new Error('`options.signal` is in `aborted` state'));
1840
+ return reject(new SignalAbortedError('loadImage'));
1821
1841
  }
1822
1842
  const img = createImage();
1823
1843
  let abort;
@@ -1842,7 +1862,7 @@
1842
1862
  img.onload = done;
1843
1863
  img.onerror = function () {
1844
1864
  abort && (signal === null || signal === void 0 ? void 0 : signal.removeEventListener('abort', abort));
1845
- reject(new Error('Error loading ' + img.src));
1865
+ reject(new FabricError("Error loading ".concat(img.src)));
1846
1866
  };
1847
1867
  crossOrigin && (img.crossOrigin = crossOrigin);
1848
1868
  img.src = url;
@@ -2700,22 +2720,29 @@
2700
2720
  * we work around it by "moving" alpha channel into opacity attribute and setting fill's alpha to 1
2701
2721
  * @param prop
2702
2722
  * @param value
2723
+ * @param {boolean} inlineStyle The default is inline style, the separator used is ":", The other is "="
2703
2724
  * @returns
2704
2725
  */
2705
- const colorPropToSVG = (prop, value) => {
2726
+ const colorPropToSVG = function (prop, value) {
2727
+ let inlineStyle = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
2728
+ let colorValue;
2729
+ let opacityValue;
2706
2730
  if (!value) {
2707
- return "".concat(prop, ": none; ");
2731
+ colorValue = 'none';
2708
2732
  } else if (value.toLive) {
2709
- return "".concat(prop, ": url(#SVGID_").concat(value.id, "); ");
2733
+ colorValue = "url(#SVGID_".concat(value.id, ")");
2710
2734
  } else {
2711
2735
  const color = new Color(value),
2712
2736
  opacity = color.getAlpha();
2713
- let str = "".concat(prop, ": ").concat(color.toRgb(), "; ");
2737
+ colorValue = color.toRgb();
2714
2738
  if (opacity !== 1) {
2715
- //change the color in rgb + opacity
2716
- str += "".concat(prop, "-opacity: ").concat(opacity.toString(), "; ");
2739
+ opacityValue = opacity.toString();
2717
2740
  }
2718
- return str;
2741
+ }
2742
+ if (inlineStyle) {
2743
+ return "".concat(prop, ": ").concat(colorValue, "; ").concat(opacityValue ? "".concat(prop, "-opacity: ").concat(opacityValue, "; ") : '');
2744
+ } else {
2745
+ return "".concat(prop, "=\"").concat(colorValue, "\" ").concat(opacityValue ? "".concat(prop, "-opacity=\"").concat(opacityValue, "\" ") : '');
2719
2746
  }
2720
2747
  };
2721
2748
  const createSVGRect = function (color, _ref) {
@@ -2726,7 +2753,7 @@
2726
2753
  height
2727
2754
  } = _ref;
2728
2755
  let precision = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : config.NUM_FRACTION_DIGITS;
2729
- const svgColor = colorPropToSVG('fill', color);
2756
+ const svgColor = colorPropToSVG('fill', color, false);
2730
2757
  const [x, y, w, h] = [left, top, width, height].map(value => toFixed(value, precision));
2731
2758
  return "<rect ".concat(svgColor, " x=\"").concat(x, "\" y=\"").concat(y, "\" width=\"").concat(w, "\" height=\"").concat(h, "\"></rect>");
2732
2759
  };
@@ -2938,13 +2965,10 @@
2938
2965
  }
2939
2966
  createLowerCanvas(arg0) {
2940
2967
  // canvasEl === 'HTMLCanvasElement' does not work on jsdom/node
2941
- const el = isHTMLCanvas(arg0) ? arg0 : getFabricDocument().getElementById(arg0) || createCanvasElement();
2968
+ const el = isHTMLCanvas(arg0) ? arg0 : arg0 && getFabricDocument().getElementById(arg0) || createCanvasElement();
2942
2969
  if (el.hasAttribute('data-fabric')) {
2943
- /* _DEV_MODE_START_ */
2944
- throw new Error('fabric.js: trying to initialize a canvas that has already been initialized');
2945
- /* _DEV_MODE_END_ */
2970
+ throw new FabricError('Trying to initialize a canvas that has already been initialized. Did you forget to dispose the canvas?');
2946
2971
  }
2947
-
2948
2972
  this._originalCanvasStyle = el.style.cssText;
2949
2973
  el.setAttribute('data-fabric', 'main');
2950
2974
  el.classList.add('lower-canvas');
@@ -3113,9 +3137,7 @@
3113
3137
  }
3114
3138
  _onObjectAdded(obj) {
3115
3139
  if (obj.canvas && obj.canvas !== this) {
3116
- /* _DEV_MODE_START_ */
3117
- console.warn('fabric.Canvas: trying to add an object that belongs to a different canvas.\n' + 'Resulting to default behavior: removing object from previous canvas and adding to new canvas');
3118
- /* _DEV_MODE_END_ */
3140
+ log('warn', 'Canvas is trying to add an object that belongs to a different canvas.\n' + 'Resulting to default behavior: removing object from previous canvas and adding to new canvas');
3119
3141
  obj.canvas.remove(obj);
3120
3142
  }
3121
3143
  obj._set('canvas', this);
@@ -4045,7 +4067,7 @@
4045
4067
  signal
4046
4068
  } = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
4047
4069
  if (!json) {
4048
- return Promise.reject(new Error('fabric.js: `json` is undefined'));
4070
+ return Promise.reject(new FabricError('`json` is undefined'));
4049
4071
  }
4050
4072
 
4051
4073
  // parse json if it wasn't already
@@ -4215,6 +4237,7 @@
4215
4237
  width: this.width,
4216
4238
  height: this.height
4217
4239
  });
4240
+ runningAnimations.cancelByCanvas(this);
4218
4241
  this.disposed = true;
4219
4242
  return new Promise((resolve, reject) => {
4220
4243
  const task = () => {
@@ -4501,10 +4524,10 @@
4501
4524
  const transformPointRelativeToCanvas = (point, canvas, relationBefore, relationAfter) => {
4502
4525
  // is this still needed with TS?
4503
4526
  if (relationBefore !== 'child' && relationBefore !== 'sibling') {
4504
- throw new Error("fabric.js: received bad argument ".concat(relationBefore));
4527
+ throw new FabricError("received bad argument ".concat(relationBefore));
4505
4528
  }
4506
4529
  if (relationAfter !== 'child' && relationAfter !== 'sibling') {
4507
- throw new Error("fabric.js: received bad argument ".concat(relationAfter));
4530
+ throw new FabricError("received bad argument ".concat(relationAfter));
4508
4531
  }
4509
4532
  if (relationBefore === relationAfter) {
4510
4533
  return point;
@@ -5611,6 +5634,31 @@
5611
5634
  }
5612
5635
  }
5613
5636
 
5637
+ /**
5638
+ * Use the ray casting algorithm to determine if {@link point} is in the polygon defined by {@link points}
5639
+ * @see https://en.wikipedia.org/wiki/Point_in_polygon
5640
+ * @param point
5641
+ * @param points polygon points
5642
+ * @returns
5643
+ */
5644
+ static isPointInPolygon(point, points) {
5645
+ const other = new Point(point).setX(Math.min(point.x - 1, ...points.map(p => p.x)));
5646
+ let hits = 0;
5647
+ for (let index = 0; index < points.length; index++) {
5648
+ const inter = this.intersectSegmentSegment(
5649
+ // polygon side
5650
+ points[index], points[(index + 1) % points.length],
5651
+ // ray
5652
+ point, other);
5653
+ if (inter.includes(point)) {
5654
+ // point is on the polygon side
5655
+ return true;
5656
+ }
5657
+ hits += Number(inter.status === 'Intersection');
5658
+ }
5659
+ return hits % 2 === 1;
5660
+ }
5661
+
5614
5662
  /**
5615
5663
  * Checks if a line intersects another
5616
5664
  * @see {@link https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection line intersection}
@@ -6147,21 +6195,15 @@
6147
6195
  * Checks if object is fully contained within area of another object
6148
6196
  * @param {Object} other Object to test
6149
6197
  * @param {Boolean} [absolute] use coordinates without viewportTransform
6150
- * @param {Boolean} [calculate] use coordinates of current position instead of store ones
6198
+ * @param {Boolean} [calculate] use coordinates of current position instead of stored ones
6151
6199
  * @return {Boolean} true if object is fully contained within area of another object
6152
6200
  */
6153
6201
  isContainedWithinObject(other) {
6154
6202
  let absolute = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
6155
6203
  let calculate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
6156
- const points = this.getCoords(absolute, calculate),
6157
- otherCoords = absolute ? other.aCoords : other.lineCoords,
6158
- lines = other._getImageLines(otherCoords);
6159
- for (let i = 0; i < 4; i++) {
6160
- if (!other.containsPoint(points[i], lines)) {
6161
- return false;
6162
- }
6163
- }
6164
- return true;
6204
+ const points = this.getCoords(absolute, calculate);
6205
+ calculate && other.getCoords(absolute, true);
6206
+ return points.every(point => other.containsPoint(point));
6165
6207
  }
6166
6208
 
6167
6209
  /**
@@ -6183,19 +6225,14 @@
6183
6225
  /**
6184
6226
  * Checks if point is inside the object
6185
6227
  * @param {Point} point Point to check against
6186
- * @param {Object} [lines] object returned from @method _getImageLines
6187
6228
  * @param {Boolean} [absolute] use coordinates without viewportTransform
6188
6229
  * @param {Boolean} [calculate] use coordinates of current position instead of stored ones
6189
6230
  * @return {Boolean} true if point is inside the object
6190
6231
  */
6191
- containsPoint(point, lines) {
6192
- let absolute = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
6193
- let calculate = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
6194
- const coords = this._getCoords(absolute, calculate),
6195
- imageLines = lines || this._getImageLines(coords),
6196
- xPoints = this._findCrossPoints(point, imageLines);
6197
- // if xPoints is odd then point is inside the object
6198
- return xPoints !== 0 && xPoints % 2 === 1;
6232
+ containsPoint(point) {
6233
+ let absolute = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
6234
+ let calculate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
6235
+ return Intersection.isPointInPolygon(point, this.getCoords(absolute, calculate));
6199
6236
  }
6200
6237
 
6201
6238
  /**
@@ -6237,7 +6274,7 @@
6237
6274
  _containsCenterOfCanvas(pointTL, pointBR, calculate) {
6238
6275
  // worst case scenario the object is so big that contains the screen
6239
6276
  const centerPoint = pointTL.midPointFrom(pointBR);
6240
- return this.containsPoint(centerPoint, undefined, true, calculate);
6277
+ return this.containsPoint(centerPoint, true, calculate);
6241
6278
  }
6242
6279
 
6243
6280
  /**
@@ -6260,100 +6297,6 @@
6260
6297
  return allPointsAreOutside && this._containsCenterOfCanvas(tl, br, calculate);
6261
6298
  }
6262
6299
 
6263
- /**
6264
- * Method that returns an object with the object edges in it, given the coordinates of the corners
6265
- * @private
6266
- * @param {Object} lineCoords or aCoords Coordinates of the object corners
6267
- */
6268
- _getImageLines(_ref) {
6269
- let {
6270
- tl,
6271
- tr,
6272
- bl,
6273
- br
6274
- } = _ref;
6275
- const lines = {
6276
- topline: {
6277
- o: tl,
6278
- d: tr
6279
- },
6280
- rightline: {
6281
- o: tr,
6282
- d: br
6283
- },
6284
- bottomline: {
6285
- o: br,
6286
- d: bl
6287
- },
6288
- leftline: {
6289
- o: bl,
6290
- d: tl
6291
- }
6292
- };
6293
-
6294
- // // debugging
6295
- // if (this.canvas.contextTop) {
6296
- // this.canvas.contextTop.fillRect(lines.bottomline.d.x, lines.bottomline.d.y, 2, 2);
6297
- // this.canvas.contextTop.fillRect(lines.bottomline.o.x, lines.bottomline.o.y, 2, 2);
6298
- //
6299
- // this.canvas.contextTop.fillRect(lines.leftline.d.x, lines.leftline.d.y, 2, 2);
6300
- // this.canvas.contextTop.fillRect(lines.leftline.o.x, lines.leftline.o.y, 2, 2);
6301
- //
6302
- // this.canvas.contextTop.fillRect(lines.topline.d.x, lines.topline.d.y, 2, 2);
6303
- // this.canvas.contextTop.fillRect(lines.topline.o.x, lines.topline.o.y, 2, 2);
6304
- //
6305
- // this.canvas.contextTop.fillRect(lines.rightline.d.x, lines.rightline.d.y, 2, 2);
6306
- // this.canvas.contextTop.fillRect(lines.rightline.o.x, lines.rightline.o.y, 2, 2);
6307
- // }
6308
-
6309
- return lines;
6310
- }
6311
-
6312
- /**
6313
- * Helper method to determine how many cross points are between the 4 object edges
6314
- * and the horizontal line determined by a point on canvas
6315
- * @private
6316
- * @param {Point} point Point to check
6317
- * @param {Object} lines Coordinates of the object being evaluated
6318
- * @return {number} number of crossPoint
6319
- */
6320
- _findCrossPoints(point, lines) {
6321
- let xcount = 0;
6322
- for (const lineKey in lines) {
6323
- let xi;
6324
- const iLine = lines[lineKey];
6325
- // optimization 1: line below point. no cross
6326
- if (iLine.o.y < point.y && iLine.d.y < point.y) {
6327
- continue;
6328
- }
6329
- // optimization 2: line above point. no cross
6330
- if (iLine.o.y >= point.y && iLine.d.y >= point.y) {
6331
- continue;
6332
- }
6333
- // optimization 3: vertical line case
6334
- if (iLine.o.x === iLine.d.x && iLine.o.x >= point.x) {
6335
- xi = iLine.o.x;
6336
- }
6337
- // calculate the intersection point
6338
- else {
6339
- const b1 = 0;
6340
- const b2 = (iLine.d.y - iLine.o.y) / (iLine.d.x - iLine.o.x);
6341
- const a1 = point.y - b1 * point.x;
6342
- const a2 = iLine.o.y - b2 * iLine.o.x;
6343
- xi = -(a1 - a2) / (b1 - b2);
6344
- }
6345
- // don't count xi < point.x cases
6346
- if (xi >= point.x) {
6347
- xcount += 1;
6348
- }
6349
- // optimization 4: specific for square images
6350
- if (xcount === 2) {
6351
- break;
6352
- }
6353
- }
6354
- return xcount;
6355
- }
6356
-
6357
6300
  /**
6358
6301
  * Returns coordinates of object's bounding rectangle (left, top, width, height)
6359
6302
  * the box is intended as aligned to axis of canvas.
@@ -7119,7 +7062,7 @@
7119
7062
  return name.toLowerCase();
7120
7063
  }
7121
7064
  set type(value) {
7122
- console.warn('Setting type has no effect', value);
7065
+ log('warn', 'Setting type has no effect', value);
7123
7066
  }
7124
7067
 
7125
7068
  /**
@@ -8039,7 +7982,7 @@
8039
7982
  * @param {Boolean} [options.enableRetinaScaling] Enable retina scaling for clone image. Introduce in 1.6.4
8040
7983
  * @param {Boolean} [options.withoutTransform] Remove current object transform ( no scale , no angle, no flip, no skew ). Introduced in 2.3.4
8041
7984
  * @param {Boolean} [options.withoutShadow] Remove current object shadow. Introduced in 2.4.2
8042
- * @return {Image} Object cloned as image.
7985
+ * @return {FabricImage} Object cloned as image.
8043
7986
  */
8044
7987
  cloneAsImage(options) {
8045
7988
  const canvasEl = this.toCanvasElement(options);
@@ -8536,28 +8479,28 @@
8536
8479
  * @type {?Number}
8537
8480
  * @default null
8538
8481
  */
8539
- _defineProperty(this, "sizeX", null);
8482
+ _defineProperty(this, "sizeX", 0);
8540
8483
  /**
8541
8484
  * Sets the height of the control. If null, defaults to object's cornerSize.
8542
8485
  * Expects both sizeX and sizeY to be set when set.
8543
8486
  * @type {?Number}
8544
8487
  * @default null
8545
8488
  */
8546
- _defineProperty(this, "sizeY", null);
8489
+ _defineProperty(this, "sizeY", 0);
8547
8490
  /**
8548
8491
  * Sets the length of the touch area of the control. If null, defaults to object's touchCornerSize.
8549
8492
  * Expects both touchSizeX and touchSizeY to be set when set.
8550
8493
  * @type {?Number}
8551
8494
  * @default null
8552
8495
  */
8553
- _defineProperty(this, "touchSizeX", null);
8496
+ _defineProperty(this, "touchSizeX", 0);
8554
8497
  /**
8555
8498
  * Sets the height of the touch area of the control. If null, defaults to object's touchCornerSize.
8556
8499
  * Expects both touchSizeX and touchSizeY to be set when set.
8557
8500
  * @type {?Number}
8558
8501
  * @default null
8559
8502
  */
8560
- _defineProperty(this, "touchSizeY", null);
8503
+ _defineProperty(this, "touchSizeY", 0);
8561
8504
  /**
8562
8505
  * Css cursor style to display when the control is hovered.
8563
8506
  * if the method `cursorStyleHandler` is provided, this property is ignored.
@@ -8602,10 +8545,16 @@
8602
8545
  * @return {Boolean} true if the action/event modified the object
8603
8546
  */
8604
8547
 
8605
- shouldActivate(controlKey, fabricObject) {
8548
+ shouldActivate(controlKey, fabricObject, pointer, _ref) {
8606
8549
  var _fabricObject$canvas;
8550
+ let {
8551
+ tl,
8552
+ tr,
8553
+ br,
8554
+ bl
8555
+ } = _ref;
8607
8556
  // TODO: locking logic can be handled here instead of in the control handler logic
8608
- return ((_fabricObject$canvas = fabricObject.canvas) === null || _fabricObject$canvas === void 0 ? void 0 : _fabricObject$canvas.getActiveObject()) === fabricObject && fabricObject.isControlVisible(controlKey);
8557
+ return ((_fabricObject$canvas = fabricObject.canvas) === null || _fabricObject$canvas === void 0 ? void 0 : _fabricObject$canvas.getActiveObject()) === fabricObject && fabricObject.isControlVisible(controlKey) && Intersection.isPointInPolygon(pointer, [tl, tr, br, bl]);
8609
8558
  }
8610
8559
 
8611
8560
  /**
@@ -8698,36 +8647,15 @@
8698
8647
  * @param {Number} centerY y coordinate where the control center should be
8699
8648
  * @param {boolean} isTouch true if touch corner, false if normal corner
8700
8649
  */
8701
- calcCornerCoords(objectAngle, objectCornerSize, centerX, centerY, isTouch) {
8702
- let cosHalfOffset, sinHalfOffset, cosHalfOffsetComp, sinHalfOffsetComp;
8703
- const xSize = isTouch ? this.touchSizeX : this.sizeX,
8704
- ySize = isTouch ? this.touchSizeY : this.sizeY;
8705
- if (xSize && ySize && xSize !== ySize) {
8706
- // handle rectangular corners
8707
- const controlTriangleAngle = Math.atan2(ySize, xSize);
8708
- const cornerHypotenuse = Math.sqrt(xSize * xSize + ySize * ySize) / 2;
8709
- const newTheta = controlTriangleAngle - degreesToRadians(objectAngle);
8710
- const newThetaComp = halfPI - controlTriangleAngle - degreesToRadians(objectAngle);
8711
- cosHalfOffset = cornerHypotenuse * cos(newTheta);
8712
- sinHalfOffset = cornerHypotenuse * sin(newTheta);
8713
- // use complementary angle for two corners
8714
- cosHalfOffsetComp = cornerHypotenuse * cos(newThetaComp);
8715
- sinHalfOffsetComp = cornerHypotenuse * sin(newThetaComp);
8716
- } else {
8717
- // handle square corners
8718
- // use default object corner size unless size is defined
8719
- const cornerSize = xSize && ySize ? xSize : objectCornerSize;
8720
- const cornerHypotenuse = cornerSize * Math.SQRT1_2;
8721
- // complementary angles are equal since they're both 45 degrees
8722
- const newTheta = degreesToRadians(45 - objectAngle);
8723
- cosHalfOffset = cosHalfOffsetComp = cornerHypotenuse * cos(newTheta);
8724
- sinHalfOffset = sinHalfOffsetComp = cornerHypotenuse * sin(newTheta);
8725
- }
8650
+ calcCornerCoords(angle, objectCornerSize, centerX, centerY, isTouch, fabricObject) {
8651
+ const t = multiplyTransformMatrixArray([createTranslateMatrix(centerX, centerY), createRotateMatrix({
8652
+ angle
8653
+ }), createScaleMatrix((isTouch ? this.touchSizeX : this.sizeX) || objectCornerSize, (isTouch ? this.touchSizeY : this.sizeY) || objectCornerSize)]);
8726
8654
  return {
8727
- tl: new Point(centerX - sinHalfOffsetComp, centerY - cosHalfOffsetComp),
8728
- tr: new Point(centerX + cosHalfOffset, centerY - sinHalfOffset),
8729
- bl: new Point(centerX - cosHalfOffset, centerY + sinHalfOffset),
8730
- br: new Point(centerX + sinHalfOffsetComp, centerY + cosHalfOffsetComp)
8655
+ tl: new Point(-0.5, -0.5).transform(t),
8656
+ tr: new Point(0.5, -0.5).transform(t),
8657
+ bl: new Point(-0.5, 0.5).transform(t),
8658
+ br: new Point(0.5, 0.5).transform(t)
8731
8659
  };
8732
8660
  }
8733
8661
 
@@ -9369,34 +9297,14 @@
9369
9297
  return '';
9370
9298
  }
9371
9299
  this.__corner = undefined;
9372
- // had to keep the reverse loop because was breaking tests
9373
9300
  const cornerEntries = Object.entries(this.oCoords);
9374
9301
  for (let i = cornerEntries.length - 1; i >= 0; i--) {
9375
9302
  const [key, corner] = cornerEntries[i];
9376
- if (this.controls[key].shouldActivate(key, this)) {
9377
- const lines = this._getImageLines(forTouch ? corner.touchCorner : corner.corner);
9378
- const xPoints = this._findCrossPoints(pointer, lines);
9379
- if (xPoints !== 0 && xPoints % 2 === 1) {
9380
- this.__corner = key;
9381
- return key;
9382
- }
9303
+ if (this.controls[key].shouldActivate(key, this, pointer, forTouch ? corner.touchCorner : corner.corner)) {
9304
+ // this.canvas.contextTop.fillRect(pointer.x - 1, pointer.y - 1, 2, 2);
9305
+ return this.__corner = key;
9383
9306
  }
9384
-
9385
- // // debugging
9386
- //
9387
- // this.canvas.contextTop.fillRect(lines.bottomline.d.x, lines.bottomline.d.y, 2, 2);
9388
- // this.canvas.contextTop.fillRect(lines.bottomline.o.x, lines.bottomline.o.y, 2, 2);
9389
- //
9390
- // this.canvas.contextTop.fillRect(lines.leftline.d.x, lines.leftline.d.y, 2, 2);
9391
- // this.canvas.contextTop.fillRect(lines.leftline.o.x, lines.leftline.o.y, 2, 2);
9392
- //
9393
- // this.canvas.contextTop.fillRect(lines.topline.d.x, lines.topline.d.y, 2, 2);
9394
- // this.canvas.contextTop.fillRect(lines.topline.o.x, lines.topline.o.y, 2, 2);
9395
- //
9396
- // this.canvas.contextTop.fillRect(lines.rightline.d.x, lines.rightline.d.y, 2, 2);
9397
- // this.canvas.contextTop.fillRect(lines.rightline.o.x, lines.rightline.o.y, 2, 2);
9398
9307
  }
9399
-
9400
9308
  return '';
9401
9309
  }
9402
9310
 
@@ -9452,8 +9360,9 @@
9452
9360
  * @private
9453
9361
  */
9454
9362
  _calcCornerCoords(control, position) {
9455
- const corner = control.calcCornerCoords(this.angle, this.cornerSize, position.x, position.y, false);
9456
- const touchCorner = control.calcCornerCoords(this.angle, this.touchCornerSize, position.x, position.y, true);
9363
+ const angle = this.getTotalAngle();
9364
+ const corner = control.calcCornerCoords(angle, this.cornerSize, position.x, position.y, false, this);
9365
+ const touchCorner = control.calcCornerCoords(angle, this.touchCornerSize, position.x, position.y, true, this);
9457
9366
  return {
9458
9367
  corner,
9459
9368
  touchCorner
@@ -9471,7 +9380,7 @@
9471
9380
  setCoords() {
9472
9381
  super.setCoords();
9473
9382
  // set coordinates of the draggable boxes in the corners used to scale/rotate the image
9474
- this.oCoords = this.calcOCoords();
9383
+ this.canvas && (this.oCoords = this.calcOCoords());
9475
9384
  }
9476
9385
 
9477
9386
  /**
@@ -9849,6 +9758,14 @@
9849
9758
  classRegistry.setClass(FabricObject);
9850
9759
  classRegistry.setClass(FabricObject, 'object');
9851
9760
 
9761
+ /**
9762
+ * @deprecated The old fabric.Object class can't be imported as Object because of conflict with the JS api
9763
+ * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object
9764
+ * For this reason it has been renamed to FabricObject.
9765
+ * Please use `import { FabricObject }` in place of `import { Object as FabricObject }`
9766
+ */
9767
+ class _Object extends FabricObject {}
9768
+
9852
9769
  /**
9853
9770
  * Returns true if context has transparent pixel
9854
9771
  * at specified location (taking tolerance into account)
@@ -10553,15 +10470,11 @@
10553
10470
  canEnterGroup(object) {
10554
10471
  if (object === this || this.isDescendantOf(object)) {
10555
10472
  // prevent circular object tree
10556
- /* _DEV_MODE_START_ */
10557
- console.error('fabric.Group: circular object trees are not supported, this call has no effect');
10558
- /* _DEV_MODE_END_ */
10473
+ log('error', 'Group: circular object trees are not supported, this call has no effect');
10559
10474
  return false;
10560
10475
  } else if (this._objects.indexOf(object) !== -1) {
10561
10476
  // is already in the objects array
10562
- /* _DEV_MODE_START_ */
10563
- console.error('fabric.Group: duplicate objects are not supported inside group, this call has no effect');
10564
- /* _DEV_MODE_END_ */
10477
+ log('error', 'Group: duplicate objects are not supported inside group, this call has no effect');
10565
10478
  return false;
10566
10479
  }
10567
10480
  return true;
@@ -11414,7 +11327,9 @@
11414
11327
  // save ref to group for later in order to return to it
11415
11328
  const parent = object.group;
11416
11329
  parent._exitGroup(object);
11417
- object.__owningGroup = parent;
11330
+ // make sure we are setting the correct owning group
11331
+ // in case `object` is transferred between active selections
11332
+ !(parent instanceof ActiveSelection) && (object.__owningGroup = parent);
11418
11333
  }
11419
11334
  this._enterGroup(object, removeParentTransform);
11420
11335
  return true;
@@ -13066,7 +12981,7 @@
13066
12981
  xhr.onerror = xhr.ontimeout = noop;
13067
12982
  };
13068
12983
  if (signal && signal.aborted) {
13069
- throw new Error('`options.signal` is in `aborted` state');
12984
+ throw new SignalAbortedError('request');
13070
12985
  } else if (signal) {
13071
12986
  signal.addEventListener('abort', abort, {
13072
12987
  once: true
@@ -13513,9 +13428,9 @@
13513
13428
  * @type FabricObject[]
13514
13429
  * @private
13515
13430
  */
13516
- _defineProperty(this, "_objectsToRender", []);
13431
+ _defineProperty(this, "_objectsToRender", void 0);
13517
13432
  /**
13518
- * hold a referenfce to a data structure that contains information
13433
+ * hold a reference to a data structure that contains information
13519
13434
  * on the current on going transform
13520
13435
  * @type
13521
13436
  * @private
@@ -13583,6 +13498,10 @@
13583
13498
  }
13584
13499
  super._onObjectRemoved(obj);
13585
13500
  }
13501
+ _onStackOrderChanged() {
13502
+ this._objectsToRender = undefined;
13503
+ super._onStackOrderChanged();
13504
+ }
13586
13505
 
13587
13506
  /**
13588
13507
  * Divides objects in two groups, one to render immediately
@@ -13646,15 +13565,6 @@
13646
13565
  });
13647
13566
  }
13648
13567
 
13649
- /**
13650
- * Given a pointer on the canvas with a viewport applied,
13651
- * find out the pointer in object coordinates
13652
- * @private
13653
- */
13654
- _normalizePointer(object, pointer) {
13655
- return transformPoint(this.restorePointerVpt(pointer), invertTransform(object.calcTransformMatrix()));
13656
- }
13657
-
13658
13568
  /**
13659
13569
  * Set the canvas tolerance value for pixel taret find.
13660
13570
  * Use only integer numbers.
@@ -13675,8 +13585,8 @@
13675
13585
  * @TODO this seems dumb that we treat controls with transparency. we can find controls
13676
13586
  * programmatically without painting them, the cache canvas optimization is always valid
13677
13587
  * @param {FabricObject} target Object to check
13678
- * @param {Number} x Left coordinate
13679
- * @param {Number} y Top coordinate
13588
+ * @param {Number} x Left coordinate in viewport space
13589
+ * @param {Number} y Top coordinate in viewport space
13680
13590
  * @return {Boolean}
13681
13591
  */
13682
13592
  isTargetTransparent(target, x, y) {
@@ -13786,6 +13696,7 @@
13786
13696
  * @param {FaricObject} target
13787
13697
  */
13788
13698
  _setupCurrentTransform(e, target, alreadySelected) {
13699
+ var _control$getActionHan;
13789
13700
  if (!target) {
13790
13701
  return;
13791
13702
  }
@@ -13794,7 +13705,7 @@
13794
13705
  sendPointToPlane(this.getPointer(e), undefined, target.group.calcTransformMatrix()) : this.getPointer(e);
13795
13706
  const corner = target.getActiveControl() || '',
13796
13707
  control = !!corner && target.controls[corner],
13797
- actionHandler = alreadySelected && control ? control.getActionHandler(e, target, control) : dragHandler,
13708
+ actionHandler = alreadySelected && control ? (_control$getActionHan = control.getActionHandler(e, target, control)) === null || _control$getActionHan === void 0 ? void 0 : _control$getActionHan.bind(control) : dragHandler,
13798
13709
  action = getActionFromCorner(alreadySelected, corner, e, target),
13799
13710
  origin = this._getOriginFromCorner(target, corner),
13800
13711
  altKey = e[this.centeredKey],
@@ -13932,19 +13843,15 @@
13932
13843
 
13933
13844
  /**
13934
13845
  * Checks point is inside the object.
13935
- * @param {Object} [pointer] x,y object of point coordinates we want to check.
13936
13846
  * @param {FabricObject} obj Object to test against
13937
- * @param {Object} [globalPointer] x,y object of point coordinates relative to canvas used to search per pixel target.
13847
+ * @param {Object} [pointer] point from viewport.
13938
13848
  * @return {Boolean} true if point is contained within an area of given object
13939
13849
  * @private
13940
13850
  */
13941
- _checkTarget(pointer, obj, globalPointer) {
13942
- if (obj && obj.visible && obj.evented &&
13943
- // http://www.geog.ubc.ca/courses/klink/gis.notes/ncgia/u32.html
13944
- // http://idav.ucdavis.edu/~okreylos/TAship/Spring2000/PointInPolygon.html
13945
- obj.containsPoint(pointer)) {
13851
+ _checkTarget(obj, pointer) {
13852
+ if (obj && obj.visible && obj.evented && obj.containsPoint(this.restorePointerVpt(pointer), true)) {
13946
13853
  if ((this.perPixelTargetFind || obj.perPixelTargetFind) && !obj.isEditing) {
13947
- if (!this.isTargetTransparent(obj, globalPointer.x, globalPointer.y)) {
13854
+ if (!this.isTargetTransparent(obj, pointer.x, pointer.y)) {
13948
13855
  return true;
13949
13856
  }
13950
13857
  } else {
@@ -13963,23 +13870,19 @@
13963
13870
  */
13964
13871
  _searchPossibleTargets(objects, pointer) {
13965
13872
  // Cache all targets where their bounding box contains point.
13966
- let target,
13967
- i = objects.length;
13873
+ let i = objects.length;
13968
13874
  // Do not check for currently grouped objects, since we check the parent group itself.
13969
13875
  // until we call this function specifically to search inside the activeGroup
13970
13876
  while (i--) {
13971
- const objToCheck = objects[i];
13972
- const pointerToUse = objToCheck.group ? this._normalizePointer(objToCheck.group, pointer) : pointer;
13973
- if (this._checkTarget(pointerToUse, objToCheck, pointer)) {
13974
- target = objects[i];
13877
+ const target = objects[i];
13878
+ if (this._checkTarget(target, pointer)) {
13975
13879
  if (isCollection(target) && target.subTargetCheck) {
13976
13880
  const subTarget = this._searchPossibleTargets(target._objects, pointer);
13977
13881
  subTarget && this.targets.push(subTarget);
13978
13882
  }
13979
- break;
13883
+ return target;
13980
13884
  }
13981
13885
  }
13982
- return target;
13983
13886
  }
13984
13887
 
13985
13888
  /**
@@ -13999,6 +13902,7 @@
13999
13902
 
14000
13903
  /**
14001
13904
  * Returns pointer coordinates without the effect of the viewport
13905
+ * Takes a point in html canvas space and gives you back a point of the scene.
14002
13906
  * @param {Object} pointer with "x" and "y" number values in canvas HTML coordinates
14003
13907
  * @return {Object} object with "x" and "y" number values in fabricCanvas coordinates
14004
13908
  */
@@ -14230,6 +14134,11 @@
14230
14134
  return false;
14231
14135
  }
14232
14136
  this._activeObject = object;
14137
+ if (object instanceof ActiveSelection && this._activeSelection !== object) {
14138
+ this._activeSelection = object;
14139
+ object.set('canvas', this);
14140
+ object.setCoords();
14141
+ }
14233
14142
  return true;
14234
14143
  }
14235
14144
 
@@ -15129,7 +15038,7 @@
15129
15038
  const mouseUpHandler = control && control.getMouseUpHandler(e, target, control);
15130
15039
  if (mouseUpHandler) {
15131
15040
  pointer = this.getPointer(e);
15132
- mouseUpHandler(e, transform, pointer.x, pointer.y);
15041
+ mouseUpHandler.call(control, e, transform, pointer.x, pointer.y);
15133
15042
  }
15134
15043
  }
15135
15044
  target.isMoving = false;
@@ -15140,7 +15049,7 @@
15140
15049
  const originalControl = transform.target && transform.target.controls[transform.corner],
15141
15050
  originalMouseUpHandler = originalControl && originalControl.getMouseUpHandler(e, transform.target, originalControl);
15142
15051
  pointer = pointer || this.getPointer(e);
15143
- originalMouseUpHandler && originalMouseUpHandler(e, transform, pointer.x, pointer.y);
15052
+ originalMouseUpHandler && originalMouseUpHandler.call(originalControl, e, transform, pointer.x, pointer.y);
15144
15053
  }
15145
15054
  this._setCursorFromEvent(e, target);
15146
15055
  this._handleEvent(e, 'up', LEFT_CLICK, isClick);
@@ -15162,7 +15071,7 @@
15162
15071
  this.fire(eventType, options);
15163
15072
  target && target.fire(eventType, options);
15164
15073
  for (let i = 0; i < subTargets.length; i++) {
15165
- subTargets[i].fire(eventType, options);
15074
+ subTargets[i] !== target && subTargets[i].fire(eventType, options);
15166
15075
  }
15167
15076
  return options;
15168
15077
  }
@@ -15199,7 +15108,7 @@
15199
15108
  // this may be a little be more complicated of what we want to handle
15200
15109
  target && target.fire("mouse".concat(eventType), options);
15201
15110
  for (let i = 0; i < targets.length; i++) {
15202
- targets[i].fire("mouse".concat(eventType), options);
15111
+ targets[i] !== target && targets[i].fire("mouse".concat(eventType), options);
15203
15112
  }
15204
15113
  }
15205
15114
 
@@ -15371,7 +15280,7 @@
15371
15280
  pointer = this.getPointer(e),
15372
15281
  mouseDownHandler = control && control.getMouseDownHandler(e, target, control);
15373
15282
  if (mouseDownHandler) {
15374
- mouseDownHandler(e, this._currentTransform, pointer.x, pointer.y);
15283
+ mouseDownHandler.call(control, e, this._currentTransform, pointer.x, pointer.y);
15375
15284
  }
15376
15285
  }
15377
15286
  }
@@ -15546,7 +15455,7 @@
15546
15455
  pointer: this.getPointer(e, true),
15547
15456
  absolutePointer: this.getPointer(e)
15548
15457
  });
15549
- fireCanvas && this.fire(canvasIn, outOpt);
15458
+ fireCanvas && this.fire(canvasOut, outOpt);
15550
15459
  oldTarget.fire(targetOut, outOpt);
15551
15460
  }
15552
15461
  if (target && targetChanged) {
@@ -15558,7 +15467,7 @@
15558
15467
  pointer: this.getPointer(e, true),
15559
15468
  absolutePointer: this.getPointer(e)
15560
15469
  });
15561
- fireCanvas && this.fire(canvasOut, inOpt);
15470
+ fireCanvas && this.fire(canvasIn, inOpt);
15562
15471
  target.fire(targetIn, inOpt);
15563
15472
  }
15564
15473
  }
@@ -16214,6 +16123,7 @@
16214
16123
  classRegistry.setClass(Gradient, 'gradient');
16215
16124
 
16216
16125
  const _excluded$b = ["source"];
16126
+
16217
16127
  /**
16218
16128
  * @see {@link http://fabricjs.com/patterns demo}
16219
16129
  * @see {@link http://fabricjs.com/dynamic-patterns demo}
@@ -16231,7 +16141,7 @@
16231
16141
  return 'pattern';
16232
16142
  }
16233
16143
  set type(value) {
16234
- console.warn('Setting type has no effect', value);
16144
+ log('warn', 'Setting type has no effect', value);
16235
16145
  }
16236
16146
 
16237
16147
  /**
@@ -18974,9 +18884,9 @@
18974
18884
  * Text class
18975
18885
  * @tutorial {@link http://fabricjs.com/fabric-intro-part-2#text}
18976
18886
  */
18977
- class Text extends StyledText {
18887
+ class FabricText extends StyledText {
18978
18888
  static getDefaults() {
18979
- return _objectSpread2(_objectSpread2({}, super.getDefaults()), Text.ownDefaults);
18889
+ return _objectSpread2(_objectSpread2({}, super.getDefaults()), FabricText.ownDefaults);
18980
18890
  }
18981
18891
  constructor(text) {
18982
18892
  let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
@@ -20023,7 +19933,7 @@
20023
19933
  fontSize = this.fontSize
20024
19934
  } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
20025
19935
  let forMeasuring = arguments.length > 1 ? arguments[1] : undefined;
20026
- const parsedFontFamily = fontFamily.includes("'") || fontFamily.includes('"') || fontFamily.includes(',') || Text.genericFonts.includes(fontFamily.toLowerCase()) ? fontFamily : "\"".concat(fontFamily, "\"");
19936
+ const parsedFontFamily = fontFamily.includes("'") || fontFamily.includes('"') || fontFamily.includes(',') || FabricText.genericFonts.includes(fontFamily.toLowerCase()) ? fontFamily : "\"".concat(fontFamily, "\"");
20027
19937
  return [fontStyle, fontWeight, "".concat(forMeasuring ? this.CACHE_FONT_SIZE : fontSize, "px"), parsedFontFamily].join(' ');
20028
19938
  }
20029
19939
 
@@ -20129,14 +20039,14 @@
20129
20039
  return 1;
20130
20040
  }
20131
20041
  /**
20132
- * Returns Text instance from an SVG element (<b>not yet implemented</b>)
20042
+ * Returns FabricText instance from an SVG element (<b>not yet implemented</b>)
20133
20043
  * @static
20134
20044
  * @memberOf Text
20135
20045
  * @param {HTMLElement} element Element to parse
20136
20046
  * @param {Object} [options] Options object
20137
20047
  */
20138
20048
  static async fromElement(element, options, cssRules) {
20139
- const parsedAttributes = parseAttributes(element, Text.ATTRIBUTE_NAMES, cssRules);
20049
+ const parsedAttributes = parseAttributes(element, FabricText.ATTRIBUTE_NAMES, cssRules);
20140
20050
  const _options$parsedAttrib = _objectSpread2(_objectSpread2({}, options), parsedAttributes),
20141
20051
  {
20142
20052
  textAnchor = LEFT,
@@ -20191,9 +20101,9 @@
20191
20101
  /* _FROM_SVG_END_ */
20192
20102
 
20193
20103
  /**
20194
- * Returns Text instance from an object representation
20104
+ * Returns FabricText instance from an object representation
20195
20105
  * @param {Object} object plain js Object to create an instance from
20196
- * @returns {Promise<Text>}
20106
+ * @returns {Promise<FabricText>}
20197
20107
  */
20198
20108
  static fromObject(object) {
20199
20109
  return this._fromObject(_objectSpread2(_objectSpread2({}, object), {}, {
@@ -20208,22 +20118,30 @@
20208
20118
  * @type string[]
20209
20119
  * @protected
20210
20120
  */
20211
- _defineProperty(Text, "textLayoutProperties", textLayoutProperties);
20212
- _defineProperty(Text, "cacheProperties", [...cacheProperties, ...additionalProps]);
20213
- _defineProperty(Text, "ownDefaults", textDefaultValues);
20214
- _defineProperty(Text, "type", 'Text');
20215
- _defineProperty(Text, "genericFonts", ['sans-serif', 'serif', 'cursive', 'fantasy', 'monospace']);
20121
+ _defineProperty(FabricText, "textLayoutProperties", textLayoutProperties);
20122
+ _defineProperty(FabricText, "cacheProperties", [...cacheProperties, ...additionalProps]);
20123
+ _defineProperty(FabricText, "ownDefaults", textDefaultValues);
20124
+ _defineProperty(FabricText, "type", 'Text');
20125
+ _defineProperty(FabricText, "genericFonts", ['sans-serif', 'serif', 'cursive', 'fantasy', 'monospace']);
20216
20126
  /* _FROM_SVG_START_ */
20217
20127
  /**
20218
- * List of attribute names to account for when parsing SVG element (used by {@link Text.fromElement})
20128
+ * List of attribute names to account for when parsing SVG element (used by {@link FabricText.fromElement})
20219
20129
  * @static
20220
20130
  * @memberOf Text
20221
20131
  * @see: http://www.w3.org/TR/SVG/text.html#TextElement
20222
20132
  */
20223
- _defineProperty(Text, "ATTRIBUTE_NAMES", SHARED_ATTRIBUTES.concat('x', 'y', 'dx', 'dy', 'font-family', 'font-style', 'font-weight', 'font-size', 'letter-spacing', 'text-decoration', 'text-anchor'));
20224
- applyMixins(Text, [TextSVGExportMixin]);
20225
- classRegistry.setClass(Text);
20226
- classRegistry.setSVGClass(Text);
20133
+ _defineProperty(FabricText, "ATTRIBUTE_NAMES", SHARED_ATTRIBUTES.concat('x', 'y', 'dx', 'dy', 'font-family', 'font-style', 'font-weight', 'font-size', 'letter-spacing', 'text-decoration', 'text-anchor'));
20134
+ applyMixins(FabricText, [TextSVGExportMixin]);
20135
+ classRegistry.setClass(FabricText);
20136
+ classRegistry.setSVGClass(FabricText);
20137
+
20138
+ /**
20139
+ * @deprecated The old fabric.Text class can't be imported as Text because of conflict with Web API.
20140
+ * https://developer.mozilla.org/en-US/docs/Web/API/Text/Text
20141
+ * For this reason it has been renamed to FabricText.
20142
+ * Please use `import { FabricText }` in place of `import { Text as FabricText }`
20143
+ */
20144
+ class Text extends FabricText {}
20227
20145
 
20228
20146
  /**
20229
20147
  * #### Dragging IText/Textbox Lifecycle
@@ -20576,7 +20494,7 @@
20576
20494
  * - `\-` Matches a "-" character (char code 45).
20577
20495
  */ // eslint-disable-next-line no-useless-escape
20578
20496
  const reNonWord = /[ \n\.,;!\?\-]/;
20579
- class ITextBehavior extends Text {
20497
+ class ITextBehavior extends FabricText {
20580
20498
  constructor() {
20581
20499
  super(...arguments);
20582
20500
  /**
@@ -22660,7 +22578,7 @@
22660
22578
  lineIndex = cursorLocation.lineIndex,
22661
22579
  charIndex = cursorLocation.charIndex > 0 ? cursorLocation.charIndex - 1 : 0,
22662
22580
  charHeight = this.getValueOfPropertyAt(lineIndex, charIndex, 'fontSize'),
22663
- multiplier = this.scaleX * this.canvas.getZoom(),
22581
+ multiplier = this.getObjectScaling().x * this.canvas.getZoom(),
22664
22582
  cursorWidth = this.cursorWidth / multiplier,
22665
22583
  dy = this.getValueOfPropertyAt(lineIndex, charIndex, 'deltaY'),
22666
22584
  topOffset = boundaries.topOffset + (1 - this._fontSizeFraction) * this.getHeightOfLine(lineIndex) / this.lineHeight - charHeight * (1 - this._fontSizeFraction);
@@ -23802,9 +23720,9 @@
23802
23720
  /**
23803
23721
  * @tutorial {@link http://fabricjs.com/fabric-intro-part-1#images}
23804
23722
  */
23805
- class Image extends FabricObject {
23723
+ class FabricImage extends FabricObject {
23806
23724
  static getDefaults() {
23807
- return _objectSpread2(_objectSpread2({}, super.getDefaults()), Image.ownDefaults);
23725
+ return _objectSpread2(_objectSpread2({}, super.getDefaults()), FabricImage.ownDefaults);
23808
23726
  }
23809
23727
  /**
23810
23728
  * Constructor
@@ -23822,7 +23740,7 @@
23822
23740
  filters: []
23823
23741
  }, options));
23824
23742
  /**
23825
- * When calling {@link Image.getSrc}, return value from element src with `element.getAttribute('src')`.
23743
+ * When calling {@link FabricImage.getSrc}, return value from element src with `element.getAttribute('src')`.
23826
23744
  * This allows for relative urls as image src.
23827
23745
  * @since 2.7.0
23828
23746
  * @type Boolean
@@ -23879,7 +23797,7 @@
23879
23797
  this._element = element;
23880
23798
  this._originalElement = element;
23881
23799
  this._setWidthHeight(size);
23882
- element.classList.add(Image.CSS_CANVAS);
23800
+ element.classList.add(FabricImage.CSS_CANVAS);
23883
23801
  if (this.filters.length !== 0) {
23884
23802
  this.applyFilters();
23885
23803
  }
@@ -24352,12 +24270,12 @@
24352
24270
  */
24353
24271
 
24354
24272
  /**
24355
- * Creates an instance of Image from its object representation
24273
+ * Creates an instance of FabricImage from its object representation
24356
24274
  * @static
24357
24275
  * @param {Object} object Object to create an instance from
24358
24276
  * @param {object} [options] Options object
24359
24277
  * @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal
24360
- * @returns {Promise<Image>}
24278
+ * @returns {Promise<FabricImage>}
24361
24279
  */
24362
24280
  static fromObject(_ref) {
24363
24281
  let {
@@ -24388,7 +24306,7 @@
24388
24306
  * @static
24389
24307
  * @param {String} url URL to create an image from
24390
24308
  * @param {LoadImageOptions} [options] Options object
24391
- * @returns {Promise<Image>}
24309
+ * @returns {Promise<FabricImage>}
24392
24310
  */
24393
24311
  static fromURL(url) {
24394
24312
  let {
@@ -24403,7 +24321,7 @@
24403
24321
  }
24404
24322
 
24405
24323
  /**
24406
- * Returns {@link Image} instance from an SVG element
24324
+ * Returns {@link FabricImage} instance from an SVG element
24407
24325
  * @static
24408
24326
  * @param {HTMLElement} element Element to parse
24409
24327
  * @param {Object} [options] Options object
@@ -24415,23 +24333,31 @@
24415
24333
  let cssRules = arguments.length > 2 ? arguments[2] : undefined;
24416
24334
  const parsedAttributes = parseAttributes(element, this.ATTRIBUTE_NAMES, cssRules);
24417
24335
  return this.fromURL(parsedAttributes['xlink:href'], options, parsedAttributes).catch(err => {
24418
- console.log(err);
24336
+ log('log', 'Unable to parse Image', err);
24419
24337
  return null;
24420
24338
  });
24421
24339
  }
24422
24340
  }
24423
- _defineProperty(Image, "type", 'Image');
24424
- _defineProperty(Image, "cacheProperties", [...cacheProperties, ...IMAGE_PROPS]);
24425
- _defineProperty(Image, "ownDefaults", imageDefaultValues);
24426
- _defineProperty(Image, "CSS_CANVAS", 'canvas-img');
24341
+ _defineProperty(FabricImage, "type", 'Image');
24342
+ _defineProperty(FabricImage, "cacheProperties", [...cacheProperties, ...IMAGE_PROPS]);
24343
+ _defineProperty(FabricImage, "ownDefaults", imageDefaultValues);
24344
+ _defineProperty(FabricImage, "CSS_CANVAS", 'canvas-img');
24427
24345
  /**
24428
- * List of attribute names to account for when parsing SVG element (used by {@link Image.fromElement})
24346
+ * List of attribute names to account for when parsing SVG element (used by {@link FabricImage.fromElement})
24429
24347
  * @static
24430
24348
  * @see {@link http://www.w3.org/TR/SVG/struct.html#ImageElement}
24431
24349
  */
24432
- _defineProperty(Image, "ATTRIBUTE_NAMES", [...SHARED_ATTRIBUTES, 'x', 'y', 'width', 'height', 'preserveAspectRatio', 'xlink:href', 'crossOrigin', 'image-rendering']);
24433
- classRegistry.setClass(Image);
24434
- classRegistry.setSVGClass(Image);
24350
+ _defineProperty(FabricImage, "ATTRIBUTE_NAMES", [...SHARED_ATTRIBUTES, 'x', 'y', 'width', 'height', 'preserveAspectRatio', 'xlink:href', 'crossOrigin', 'image-rendering']);
24351
+ classRegistry.setClass(FabricImage);
24352
+ classRegistry.setSVGClass(FabricImage);
24353
+
24354
+ /**
24355
+ * @deprecated The old fabric.Image class can't be imported as Image because of conflict with Web API.
24356
+ * https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/Image
24357
+ * For this reason it has been renamed to FabricImage.
24358
+ * Please use `import { FabricImage }` in place of `import { Image as FabricImage }`
24359
+ */
24360
+ class Image extends FabricImage {}
24435
24361
 
24436
24362
  /**
24437
24363
  * Add a <g> element that envelop all child elements and makes the viewbox transformMatrix descend on all elements
@@ -24784,7 +24710,7 @@
24784
24710
  const obj = await klass.fromElement(el, this.options, this.cssRules);
24785
24711
  this.resolveGradient(obj, el, 'fill');
24786
24712
  this.resolveGradient(obj, el, 'stroke');
24787
- if (obj instanceof Image && obj._originalElement) {
24713
+ if (obj instanceof FabricImage && obj._originalElement) {
24788
24714
  removeTransformMatrixForSvgParsing(obj, obj.parsePreserveAspectRatioAttribute());
24789
24715
  } else {
24790
24716
  removeTransformMatrixForSvgParsing(obj);
@@ -24903,7 +24829,7 @@
24903
24829
  signal
24904
24830
  } = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
24905
24831
  if (signal && signal.aborted) {
24906
- console.log('`options.signal` is in `aborted` state');
24832
+ log('log', new SignalAbortedError('parseSVGDocument'));
24907
24833
  // this is an unhappy path, we dont care about speed
24908
24834
  return createEmptyResponse();
24909
24835
  }
@@ -25007,7 +24933,7 @@
25007
24933
  * This function locates the controls.
25008
24934
  * It'll be used both for drawing and for interaction.
25009
24935
  */
25010
- const factoryPolyPositionHandler = pointIndex => {
24936
+ const createPolyPositionHandler = pointIndex => {
25011
24937
  return function (dim, finalMatrix, polyObject) {
25012
24938
  var _polyObject$canvas$vi, _polyObject$canvas;
25013
24939
  const x = polyObject.points[pointIndex].x - polyObject.pathOffset.x,
@@ -25040,7 +24966,7 @@
25040
24966
  /**
25041
24967
  * Keep the polygon in the same position when we change its `width`/`height`/`top`/`left`.
25042
24968
  */
25043
- const anchorWrapper = (pointIndex, fn) => {
24969
+ const factoryPolyActionHandler = (pointIndex, fn) => {
25044
24970
  return function (eventData, transform, x, y) {
25045
24971
  const poly = transform.target,
25046
24972
  anchorPoint = new Point(poly.points[(pointIndex > 0 ? pointIndex : poly.points.length) - 1]),
@@ -25054,14 +24980,15 @@
25054
24980
  return actionPerformed;
25055
24981
  };
25056
24982
  };
24983
+ const createPolyActionHandler = pointIndex => factoryPolyActionHandler(pointIndex, polyActionHandler);
25057
24984
  function createPolyControls(arg0) {
25058
24985
  let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
25059
24986
  const controls = {};
25060
24987
  for (let idx = 0; idx < (typeof arg0 === 'number' ? arg0 : arg0.points.length); idx++) {
25061
24988
  controls["p".concat(idx)] = new Control(_objectSpread2({
25062
24989
  actionName: 'modifyPoly',
25063
- positionHandler: factoryPolyPositionHandler(idx),
25064
- actionHandler: anchorWrapper(idx, polyActionHandler)
24990
+ positionHandler: createPolyPositionHandler(idx),
24991
+ actionHandler: createPolyActionHandler(idx)
25065
24992
  }, options));
25066
24993
  }
25067
24994
  return controls;
@@ -25071,11 +24998,15 @@
25071
24998
  __proto__: null,
25072
24999
  changeWidth: changeWidth,
25073
25000
  createObjectDefaultControls: createObjectDefaultControls,
25001
+ createPolyActionHandler: createPolyActionHandler,
25074
25002
  createPolyControls: createPolyControls,
25003
+ createPolyPositionHandler: createPolyPositionHandler,
25075
25004
  createResizeControls: createResizeControls,
25076
25005
  createTextboxDefaultControls: createTextboxDefaultControls,
25077
25006
  dragHandler: dragHandler,
25007
+ factoryPolyActionHandler: factoryPolyActionHandler,
25078
25008
  getLocalPoint: getLocalPoint,
25009
+ polyActionHandler: polyActionHandler,
25079
25010
  renderCircleControl: renderCircleControl,
25080
25011
  renderSquareControl: renderSquareControl,
25081
25012
  rotationStyleHandler: rotationStyleHandler,
@@ -25170,25 +25101,23 @@
25170
25101
  const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
25171
25102
  const program = gl.createProgram();
25172
25103
  if (!vertexShader || !fragmentShader || !program) {
25173
- throw new Error('Vertex, fragment shader or program creation error');
25104
+ throw new FabricError('Vertex, fragment shader or program creation error');
25174
25105
  }
25175
25106
  gl.shaderSource(vertexShader, vertexSource);
25176
25107
  gl.compileShader(vertexShader);
25177
25108
  if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
25178
- throw new Error("Vertex shader compile error for ".concat(this.type, ": ").concat(gl.getShaderInfoLog(vertexShader)));
25109
+ throw new FabricError("Vertex shader compile error for ".concat(this.type, ": ").concat(gl.getShaderInfoLog(vertexShader)));
25179
25110
  }
25180
25111
  gl.shaderSource(fragmentShader, fragmentSource);
25181
25112
  gl.compileShader(fragmentShader);
25182
25113
  if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
25183
- throw new Error("Fragment shader compile error for ".concat(this.type, ": ").concat(gl.getShaderInfoLog(fragmentShader)));
25114
+ throw new FabricError("Fragment shader compile error for ".concat(this.type, ": ").concat(gl.getShaderInfoLog(fragmentShader)));
25184
25115
  }
25185
25116
  gl.attachShader(program, vertexShader);
25186
25117
  gl.attachShader(program, fragmentShader);
25187
25118
  gl.linkProgram(program);
25188
25119
  if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
25189
- throw new Error(
25190
- // eslint-disable-next-line prefer-template
25191
- 'Shader link error for "${this.type}" ' + gl.getProgramInfoLog(program));
25120
+ throw new FabricError("Shader link error for \"".concat(this.type, "\" ").concat(gl.getProgramInfoLog(program)));
25192
25121
  }
25193
25122
  const uniformLocations = this.getUniformLocations(gl, program) || {};
25194
25123
  uniformLocations.uStepW = gl.getUniformLocation(program, 'uStepW');
@@ -25787,7 +25716,7 @@
25787
25716
  image
25788
25717
  } = _ref2,
25789
25718
  filterOptions = _objectWithoutProperties(_ref2, _excluded$3);
25790
- return Image.fromObject(image, options).then(enlivedImage => new this(_objectSpread2(_objectSpread2({}, filterOptions), {}, {
25719
+ return FabricImage.fromObject(image, options).then(enlivedImage => new this(_objectSpread2(_objectSpread2({}, filterOptions), {}, {
25791
25720
  image: enlivedImage
25792
25721
  })));
25793
25722
  }
@@ -27751,13 +27680,16 @@
27751
27680
  exports.Color = Color;
27752
27681
  exports.Control = Control;
27753
27682
  exports.Ellipse = Ellipse;
27683
+ exports.FabricImage = FabricImage;
27684
+ exports.FabricObject = FabricObject;
27685
+ exports.FabricText = FabricText;
27754
27686
  exports.Gradient = Gradient;
27755
27687
  exports.Group = Group;
27756
27688
  exports.IText = IText;
27757
27689
  exports.Image = Image;
27758
27690
  exports.Intersection = Intersection;
27759
27691
  exports.Line = Line;
27760
- exports.Object = FabricObject;
27692
+ exports.Object = _Object;
27761
27693
  exports.Observable = Observable;
27762
27694
  exports.Path = Path;
27763
27695
  exports.Pattern = Pattern;