fabric 6.0.0-beta13 → 6.0.0-beta15

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 (108) hide show
  1. package/.eslintrc.js +9 -0
  2. package/CHANGELOG.md +35 -1
  3. package/CONTRIBUTING.md +9 -9
  4. package/dist/fabric.d.ts +36 -3
  5. package/dist/index.js +218 -324
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.min.js +1 -1
  8. package/dist/index.mjs +214 -323
  9. package/dist/index.mjs.map +1 -1
  10. package/dist/index.node.cjs +218 -324
  11. package/dist/index.node.cjs.map +1 -1
  12. package/dist/index.node.mjs +214 -323
  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 +11 -11
  28. package/dist/src/shapes/Object/InteractiveObject.d.ts +2 -3
  29. package/dist/src/shapes/Object/Object.d.ts +4 -4
  30. package/dist/src/shapes/Object/ObjectGeometry.d.ts +3 -29
  31. package/dist/src/shapes/Object/types/FabricObjectProps.d.ts +1 -1
  32. package/dist/src/shapes/Path.d.ts +1 -1
  33. package/dist/src/shapes/Text/StyledText.d.ts +2 -2
  34. package/dist/src/shapes/Text/Text.d.ts +7 -7
  35. package/dist/src/shapes/Text/TextSVGExportMixin.d.ts +7 -7
  36. package/dist/src/shapes/Text/constants.d.ts +2 -2
  37. package/dist/src/util/animation/AnimationRegistry.d.ts +4 -4
  38. package/dist/src/util/internals/console.d.ts +8 -0
  39. package/dist/src/util/misc/dom.d.ts +1 -1
  40. package/dist/src/util/misc/svgParsing.d.ts +2 -1
  41. package/dist/src/util/typeAssertions.d.ts +2 -2
  42. package/fabric.ts +45 -3
  43. package/jest.extend.ts +3 -1
  44. package/package.json +5 -6
  45. package/playwright.setup.ts +82 -14
  46. package/src/ClassRegistry.ts +3 -1
  47. package/src/Collection.ts +2 -3
  48. package/src/Intersection.spec.ts +74 -0
  49. package/src/Intersection.ts +30 -0
  50. package/src/Pattern/Pattern.ts +2 -1
  51. package/src/benchmarks/README.md +7 -0
  52. package/src/benchmarks/calcCornerCoords.mjs +117 -0
  53. package/src/benchmarks/raycasting.mjs +154 -0
  54. package/src/canvas/Canvas.ts +23 -11
  55. package/src/canvas/CanvasOptions.ts +1 -1
  56. package/src/canvas/DOMManagers/CanvasDOMManager.ts +1 -1
  57. package/src/canvas/DOMManagers/StaticCanvasDOMManager.ts +7 -7
  58. package/src/canvas/SelectableCanvas.ts +30 -43
  59. package/src/canvas/StaticCanvas.ts +9 -7
  60. package/src/canvas/__tests__/SelectableCanvas.spec.ts +60 -0
  61. package/src/canvas/__tests__/__snapshots__/eventData.test.ts.snap +193 -2
  62. package/src/canvas/__tests__/eventData.test.ts +40 -1
  63. package/src/controls/Control.spec.ts +41 -0
  64. package/src/controls/Control.ts +36 -44
  65. package/src/controls/index.ts +1 -1
  66. package/src/controls/polyControl.ts +8 -5
  67. package/src/filters/BaseFilter.ts +8 -6
  68. package/src/filters/BlendImage.ts +4 -4
  69. package/src/filters/GLProbes/WebGLProbe.ts +2 -1
  70. package/src/parser/elements_parser.ts +2 -2
  71. package/src/parser/loadSVGFromString.test.ts +36 -0
  72. package/src/parser/parseSVGDocument.ts +2 -1
  73. package/src/parser/parseUseDirectives.ts +6 -2
  74. package/src/parser/recursivelyParseGradientsXlink.ts +1 -3
  75. package/src/shapes/ActiveSelection.spec.ts +35 -1
  76. package/src/shapes/ActiveSelection.ts +3 -1
  77. package/src/shapes/Group.ts +7 -8
  78. package/src/shapes/IText/IText.test.ts +43 -0
  79. package/src/shapes/IText/IText.ts +1 -1
  80. package/src/shapes/IText/ITextBehavior.ts +2 -2
  81. package/src/shapes/IText/__snapshots__/IText.test.ts.snap +50 -0
  82. package/src/shapes/Image.ts +15 -14
  83. package/src/shapes/Object/FabricObject.spec.ts +16 -0
  84. package/src/shapes/Object/InteractiveObject.spec.ts +43 -0
  85. package/src/shapes/Object/InteractiveObject.ts +20 -30
  86. package/src/shapes/Object/Object.ts +6 -5
  87. package/src/shapes/Object/ObjectGeometry.ts +11 -126
  88. package/src/shapes/Object/types/FabricObjectProps.ts +1 -1
  89. package/src/shapes/Text/StyledText.ts +5 -2
  90. package/src/shapes/Text/Text.spec.ts +9 -9
  91. package/src/shapes/Text/Text.ts +16 -15
  92. package/src/shapes/Text/TextSVGExportMixin.spec.ts +29 -0
  93. package/src/shapes/Text/TextSVGExportMixin.ts +16 -13
  94. package/src/shapes/Text/__snapshots__/Text.spec.ts.snap +6 -6
  95. package/src/shapes/Text/constants.ts +2 -2
  96. package/src/util/animation/AnimationRegistry.ts +7 -6
  97. package/src/util/internals/console.ts +18 -0
  98. package/src/util/internals/dom_request.ts +2 -1
  99. package/src/util/misc/dom.ts +3 -2
  100. package/src/util/misc/objectEnlive.ts +3 -2
  101. package/src/util/misc/planeChange.ts +3 -2
  102. package/src/util/misc/svgParsing.ts +22 -9
  103. package/src/util/transform_matrix_removal.ts +3 -3
  104. package/src/util/typeAssertions.ts +2 -2
  105. package/typedoc.config.json +6 -0
  106. package/typedoc.json +3 -2
  107. package/dist/src/parser/elementById.d.ts +0 -7
  108. package/src/parser/elementById.ts +0 -18
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-beta15";
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
  /**
@@ -10553,15 +10462,11 @@
10553
10462
  canEnterGroup(object) {
10554
10463
  if (object === this || this.isDescendantOf(object)) {
10555
10464
  // 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_ */
10465
+ log('error', 'Group: circular object trees are not supported, this call has no effect');
10559
10466
  return false;
10560
10467
  } else if (this._objects.indexOf(object) !== -1) {
10561
10468
  // 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_ */
10469
+ log('error', 'Group: duplicate objects are not supported inside group, this call has no effect');
10565
10470
  return false;
10566
10471
  }
10567
10472
  return true;
@@ -11414,7 +11319,9 @@
11414
11319
  // save ref to group for later in order to return to it
11415
11320
  const parent = object.group;
11416
11321
  parent._exitGroup(object);
11417
- object.__owningGroup = parent;
11322
+ // make sure we are setting the correct owning group
11323
+ // in case `object` is transferred between active selections
11324
+ !(parent instanceof ActiveSelection) && (object.__owningGroup = parent);
11418
11325
  }
11419
11326
  this._enterGroup(object, removeParentTransform);
11420
11327
  return true;
@@ -13066,7 +12973,7 @@
13066
12973
  xhr.onerror = xhr.ontimeout = noop;
13067
12974
  };
13068
12975
  if (signal && signal.aborted) {
13069
- throw new Error('`options.signal` is in `aborted` state');
12976
+ throw new SignalAbortedError('request');
13070
12977
  } else if (signal) {
13071
12978
  signal.addEventListener('abort', abort, {
13072
12979
  once: true
@@ -13513,9 +13420,9 @@
13513
13420
  * @type FabricObject[]
13514
13421
  * @private
13515
13422
  */
13516
- _defineProperty(this, "_objectsToRender", []);
13423
+ _defineProperty(this, "_objectsToRender", void 0);
13517
13424
  /**
13518
- * hold a referenfce to a data structure that contains information
13425
+ * hold a reference to a data structure that contains information
13519
13426
  * on the current on going transform
13520
13427
  * @type
13521
13428
  * @private
@@ -13583,6 +13490,10 @@
13583
13490
  }
13584
13491
  super._onObjectRemoved(obj);
13585
13492
  }
13493
+ _onStackOrderChanged() {
13494
+ this._objectsToRender = undefined;
13495
+ super._onStackOrderChanged();
13496
+ }
13586
13497
 
13587
13498
  /**
13588
13499
  * Divides objects in two groups, one to render immediately
@@ -13646,15 +13557,6 @@
13646
13557
  });
13647
13558
  }
13648
13559
 
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
13560
  /**
13659
13561
  * Set the canvas tolerance value for pixel taret find.
13660
13562
  * Use only integer numbers.
@@ -13675,8 +13577,8 @@
13675
13577
  * @TODO this seems dumb that we treat controls with transparency. we can find controls
13676
13578
  * programmatically without painting them, the cache canvas optimization is always valid
13677
13579
  * @param {FabricObject} target Object to check
13678
- * @param {Number} x Left coordinate
13679
- * @param {Number} y Top coordinate
13580
+ * @param {Number} x Left coordinate in viewport space
13581
+ * @param {Number} y Top coordinate in viewport space
13680
13582
  * @return {Boolean}
13681
13583
  */
13682
13584
  isTargetTransparent(target, x, y) {
@@ -13786,6 +13688,7 @@
13786
13688
  * @param {FaricObject} target
13787
13689
  */
13788
13690
  _setupCurrentTransform(e, target, alreadySelected) {
13691
+ var _control$getActionHan;
13789
13692
  if (!target) {
13790
13693
  return;
13791
13694
  }
@@ -13794,7 +13697,7 @@
13794
13697
  sendPointToPlane(this.getPointer(e), undefined, target.group.calcTransformMatrix()) : this.getPointer(e);
13795
13698
  const corner = target.getActiveControl() || '',
13796
13699
  control = !!corner && target.controls[corner],
13797
- actionHandler = alreadySelected && control ? control.getActionHandler(e, target, control) : dragHandler,
13700
+ actionHandler = alreadySelected && control ? (_control$getActionHan = control.getActionHandler(e, target, control)) === null || _control$getActionHan === void 0 ? void 0 : _control$getActionHan.bind(control) : dragHandler,
13798
13701
  action = getActionFromCorner(alreadySelected, corner, e, target),
13799
13702
  origin = this._getOriginFromCorner(target, corner),
13800
13703
  altKey = e[this.centeredKey],
@@ -13932,19 +13835,15 @@
13932
13835
 
13933
13836
  /**
13934
13837
  * Checks point is inside the object.
13935
- * @param {Object} [pointer] x,y object of point coordinates we want to check.
13936
13838
  * @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.
13839
+ * @param {Object} [pointer] point from viewport.
13938
13840
  * @return {Boolean} true if point is contained within an area of given object
13939
13841
  * @private
13940
13842
  */
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)) {
13843
+ _checkTarget(obj, pointer) {
13844
+ if (obj && obj.visible && obj.evented && obj.containsPoint(this.restorePointerVpt(pointer), true)) {
13946
13845
  if ((this.perPixelTargetFind || obj.perPixelTargetFind) && !obj.isEditing) {
13947
- if (!this.isTargetTransparent(obj, globalPointer.x, globalPointer.y)) {
13846
+ if (!this.isTargetTransparent(obj, pointer.x, pointer.y)) {
13948
13847
  return true;
13949
13848
  }
13950
13849
  } else {
@@ -13963,23 +13862,19 @@
13963
13862
  */
13964
13863
  _searchPossibleTargets(objects, pointer) {
13965
13864
  // Cache all targets where their bounding box contains point.
13966
- let target,
13967
- i = objects.length;
13865
+ let i = objects.length;
13968
13866
  // Do not check for currently grouped objects, since we check the parent group itself.
13969
13867
  // until we call this function specifically to search inside the activeGroup
13970
13868
  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];
13869
+ const target = objects[i];
13870
+ if (this._checkTarget(target, pointer)) {
13975
13871
  if (isCollection(target) && target.subTargetCheck) {
13976
13872
  const subTarget = this._searchPossibleTargets(target._objects, pointer);
13977
13873
  subTarget && this.targets.push(subTarget);
13978
13874
  }
13979
- break;
13875
+ return target;
13980
13876
  }
13981
13877
  }
13982
- return target;
13983
13878
  }
13984
13879
 
13985
13880
  /**
@@ -13999,6 +13894,7 @@
13999
13894
 
14000
13895
  /**
14001
13896
  * Returns pointer coordinates without the effect of the viewport
13897
+ * Takes a point in html canvas space and gives you back a point of the scene.
14002
13898
  * @param {Object} pointer with "x" and "y" number values in canvas HTML coordinates
14003
13899
  * @return {Object} object with "x" and "y" number values in fabricCanvas coordinates
14004
13900
  */
@@ -14230,6 +14126,11 @@
14230
14126
  return false;
14231
14127
  }
14232
14128
  this._activeObject = object;
14129
+ if (object instanceof ActiveSelection && this._activeSelection !== object) {
14130
+ this._activeSelection = object;
14131
+ object.set('canvas', this);
14132
+ object.setCoords();
14133
+ }
14233
14134
  return true;
14234
14135
  }
14235
14136
 
@@ -15129,7 +15030,7 @@
15129
15030
  const mouseUpHandler = control && control.getMouseUpHandler(e, target, control);
15130
15031
  if (mouseUpHandler) {
15131
15032
  pointer = this.getPointer(e);
15132
- mouseUpHandler(e, transform, pointer.x, pointer.y);
15033
+ mouseUpHandler.call(control, e, transform, pointer.x, pointer.y);
15133
15034
  }
15134
15035
  }
15135
15036
  target.isMoving = false;
@@ -15140,7 +15041,7 @@
15140
15041
  const originalControl = transform.target && transform.target.controls[transform.corner],
15141
15042
  originalMouseUpHandler = originalControl && originalControl.getMouseUpHandler(e, transform.target, originalControl);
15142
15043
  pointer = pointer || this.getPointer(e);
15143
- originalMouseUpHandler && originalMouseUpHandler(e, transform, pointer.x, pointer.y);
15044
+ originalMouseUpHandler && originalMouseUpHandler.call(originalControl, e, transform, pointer.x, pointer.y);
15144
15045
  }
15145
15046
  this._setCursorFromEvent(e, target);
15146
15047
  this._handleEvent(e, 'up', LEFT_CLICK, isClick);
@@ -15162,7 +15063,7 @@
15162
15063
  this.fire(eventType, options);
15163
15064
  target && target.fire(eventType, options);
15164
15065
  for (let i = 0; i < subTargets.length; i++) {
15165
- subTargets[i].fire(eventType, options);
15066
+ subTargets[i] !== target && subTargets[i].fire(eventType, options);
15166
15067
  }
15167
15068
  return options;
15168
15069
  }
@@ -15199,7 +15100,7 @@
15199
15100
  // this may be a little be more complicated of what we want to handle
15200
15101
  target && target.fire("mouse".concat(eventType), options);
15201
15102
  for (let i = 0; i < targets.length; i++) {
15202
- targets[i].fire("mouse".concat(eventType), options);
15103
+ targets[i] !== target && targets[i].fire("mouse".concat(eventType), options);
15203
15104
  }
15204
15105
  }
15205
15106
 
@@ -15371,7 +15272,7 @@
15371
15272
  pointer = this.getPointer(e),
15372
15273
  mouseDownHandler = control && control.getMouseDownHandler(e, target, control);
15373
15274
  if (mouseDownHandler) {
15374
- mouseDownHandler(e, this._currentTransform, pointer.x, pointer.y);
15275
+ mouseDownHandler.call(control, e, this._currentTransform, pointer.x, pointer.y);
15375
15276
  }
15376
15277
  }
15377
15278
  }
@@ -15546,7 +15447,7 @@
15546
15447
  pointer: this.getPointer(e, true),
15547
15448
  absolutePointer: this.getPointer(e)
15548
15449
  });
15549
- fireCanvas && this.fire(canvasIn, outOpt);
15450
+ fireCanvas && this.fire(canvasOut, outOpt);
15550
15451
  oldTarget.fire(targetOut, outOpt);
15551
15452
  }
15552
15453
  if (target && targetChanged) {
@@ -15558,7 +15459,7 @@
15558
15459
  pointer: this.getPointer(e, true),
15559
15460
  absolutePointer: this.getPointer(e)
15560
15461
  });
15561
- fireCanvas && this.fire(canvasOut, inOpt);
15462
+ fireCanvas && this.fire(canvasIn, inOpt);
15562
15463
  target.fire(targetIn, inOpt);
15563
15464
  }
15564
15465
  }
@@ -16214,6 +16115,7 @@
16214
16115
  classRegistry.setClass(Gradient, 'gradient');
16215
16116
 
16216
16117
  const _excluded$b = ["source"];
16118
+
16217
16119
  /**
16218
16120
  * @see {@link http://fabricjs.com/patterns demo}
16219
16121
  * @see {@link http://fabricjs.com/dynamic-patterns demo}
@@ -16231,7 +16133,7 @@
16231
16133
  return 'pattern';
16232
16134
  }
16233
16135
  set type(value) {
16234
- console.warn('Setting type has no effect', value);
16136
+ log('warn', 'Setting type has no effect', value);
16235
16137
  }
16236
16138
 
16237
16139
  /**
@@ -18974,9 +18876,9 @@
18974
18876
  * Text class
18975
18877
  * @tutorial {@link http://fabricjs.com/fabric-intro-part-2#text}
18976
18878
  */
18977
- class Text extends StyledText {
18879
+ class FabricText extends StyledText {
18978
18880
  static getDefaults() {
18979
- return _objectSpread2(_objectSpread2({}, super.getDefaults()), Text.ownDefaults);
18881
+ return _objectSpread2(_objectSpread2({}, super.getDefaults()), FabricText.ownDefaults);
18980
18882
  }
18981
18883
  constructor(text) {
18982
18884
  let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
@@ -20023,7 +19925,7 @@
20023
19925
  fontSize = this.fontSize
20024
19926
  } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
20025
19927
  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, "\"");
19928
+ const parsedFontFamily = fontFamily.includes("'") || fontFamily.includes('"') || fontFamily.includes(',') || FabricText.genericFonts.includes(fontFamily.toLowerCase()) ? fontFamily : "\"".concat(fontFamily, "\"");
20027
19929
  return [fontStyle, fontWeight, "".concat(forMeasuring ? this.CACHE_FONT_SIZE : fontSize, "px"), parsedFontFamily].join(' ');
20028
19930
  }
20029
19931
 
@@ -20129,14 +20031,14 @@
20129
20031
  return 1;
20130
20032
  }
20131
20033
  /**
20132
- * Returns Text instance from an SVG element (<b>not yet implemented</b>)
20034
+ * Returns FabricText instance from an SVG element (<b>not yet implemented</b>)
20133
20035
  * @static
20134
20036
  * @memberOf Text
20135
20037
  * @param {HTMLElement} element Element to parse
20136
20038
  * @param {Object} [options] Options object
20137
20039
  */
20138
20040
  static async fromElement(element, options, cssRules) {
20139
- const parsedAttributes = parseAttributes(element, Text.ATTRIBUTE_NAMES, cssRules);
20041
+ const parsedAttributes = parseAttributes(element, FabricText.ATTRIBUTE_NAMES, cssRules);
20140
20042
  const _options$parsedAttrib = _objectSpread2(_objectSpread2({}, options), parsedAttributes),
20141
20043
  {
20142
20044
  textAnchor = LEFT,
@@ -20191,9 +20093,9 @@
20191
20093
  /* _FROM_SVG_END_ */
20192
20094
 
20193
20095
  /**
20194
- * Returns Text instance from an object representation
20096
+ * Returns FabricText instance from an object representation
20195
20097
  * @param {Object} object plain js Object to create an instance from
20196
- * @returns {Promise<Text>}
20098
+ * @returns {Promise<FabricText>}
20197
20099
  */
20198
20100
  static fromObject(object) {
20199
20101
  return this._fromObject(_objectSpread2(_objectSpread2({}, object), {}, {
@@ -20208,22 +20110,22 @@
20208
20110
  * @type string[]
20209
20111
  * @protected
20210
20112
  */
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']);
20113
+ _defineProperty(FabricText, "textLayoutProperties", textLayoutProperties);
20114
+ _defineProperty(FabricText, "cacheProperties", [...cacheProperties, ...additionalProps]);
20115
+ _defineProperty(FabricText, "ownDefaults", textDefaultValues);
20116
+ _defineProperty(FabricText, "type", 'Text');
20117
+ _defineProperty(FabricText, "genericFonts", ['sans-serif', 'serif', 'cursive', 'fantasy', 'monospace']);
20216
20118
  /* _FROM_SVG_START_ */
20217
20119
  /**
20218
- * List of attribute names to account for when parsing SVG element (used by {@link Text.fromElement})
20120
+ * List of attribute names to account for when parsing SVG element (used by {@link FabricText.fromElement})
20219
20121
  * @static
20220
20122
  * @memberOf Text
20221
20123
  * @see: http://www.w3.org/TR/SVG/text.html#TextElement
20222
20124
  */
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);
20125
+ _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'));
20126
+ applyMixins(FabricText, [TextSVGExportMixin]);
20127
+ classRegistry.setClass(FabricText);
20128
+ classRegistry.setSVGClass(FabricText);
20227
20129
 
20228
20130
  /**
20229
20131
  * #### Dragging IText/Textbox Lifecycle
@@ -20576,7 +20478,7 @@
20576
20478
  * - `\-` Matches a "-" character (char code 45).
20577
20479
  */ // eslint-disable-next-line no-useless-escape
20578
20480
  const reNonWord = /[ \n\.,;!\?\-]/;
20579
- class ITextBehavior extends Text {
20481
+ class ITextBehavior extends FabricText {
20580
20482
  constructor() {
20581
20483
  super(...arguments);
20582
20484
  /**
@@ -22660,7 +22562,7 @@
22660
22562
  lineIndex = cursorLocation.lineIndex,
22661
22563
  charIndex = cursorLocation.charIndex > 0 ? cursorLocation.charIndex - 1 : 0,
22662
22564
  charHeight = this.getValueOfPropertyAt(lineIndex, charIndex, 'fontSize'),
22663
- multiplier = this.scaleX * this.canvas.getZoom(),
22565
+ multiplier = this.getObjectScaling().x * this.canvas.getZoom(),
22664
22566
  cursorWidth = this.cursorWidth / multiplier,
22665
22567
  dy = this.getValueOfPropertyAt(lineIndex, charIndex, 'deltaY'),
22666
22568
  topOffset = boundaries.topOffset + (1 - this._fontSizeFraction) * this.getHeightOfLine(lineIndex) / this.lineHeight - charHeight * (1 - this._fontSizeFraction);
@@ -23802,9 +23704,9 @@
23802
23704
  /**
23803
23705
  * @tutorial {@link http://fabricjs.com/fabric-intro-part-1#images}
23804
23706
  */
23805
- class Image extends FabricObject {
23707
+ class FabricImage extends FabricObject {
23806
23708
  static getDefaults() {
23807
- return _objectSpread2(_objectSpread2({}, super.getDefaults()), Image.ownDefaults);
23709
+ return _objectSpread2(_objectSpread2({}, super.getDefaults()), FabricImage.ownDefaults);
23808
23710
  }
23809
23711
  /**
23810
23712
  * Constructor
@@ -23822,7 +23724,7 @@
23822
23724
  filters: []
23823
23725
  }, options));
23824
23726
  /**
23825
- * When calling {@link Image.getSrc}, return value from element src with `element.getAttribute('src')`.
23727
+ * When calling {@link FabricImage.getSrc}, return value from element src with `element.getAttribute('src')`.
23826
23728
  * This allows for relative urls as image src.
23827
23729
  * @since 2.7.0
23828
23730
  * @type Boolean
@@ -23879,7 +23781,7 @@
23879
23781
  this._element = element;
23880
23782
  this._originalElement = element;
23881
23783
  this._setWidthHeight(size);
23882
- element.classList.add(Image.CSS_CANVAS);
23784
+ element.classList.add(FabricImage.CSS_CANVAS);
23883
23785
  if (this.filters.length !== 0) {
23884
23786
  this.applyFilters();
23885
23787
  }
@@ -24352,12 +24254,12 @@
24352
24254
  */
24353
24255
 
24354
24256
  /**
24355
- * Creates an instance of Image from its object representation
24257
+ * Creates an instance of FabricImage from its object representation
24356
24258
  * @static
24357
24259
  * @param {Object} object Object to create an instance from
24358
24260
  * @param {object} [options] Options object
24359
24261
  * @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal
24360
- * @returns {Promise<Image>}
24262
+ * @returns {Promise<FabricImage>}
24361
24263
  */
24362
24264
  static fromObject(_ref) {
24363
24265
  let {
@@ -24388,7 +24290,7 @@
24388
24290
  * @static
24389
24291
  * @param {String} url URL to create an image from
24390
24292
  * @param {LoadImageOptions} [options] Options object
24391
- * @returns {Promise<Image>}
24293
+ * @returns {Promise<FabricImage>}
24392
24294
  */
24393
24295
  static fromURL(url) {
24394
24296
  let {
@@ -24403,7 +24305,7 @@
24403
24305
  }
24404
24306
 
24405
24307
  /**
24406
- * Returns {@link Image} instance from an SVG element
24308
+ * Returns {@link FabricImage} instance from an SVG element
24407
24309
  * @static
24408
24310
  * @param {HTMLElement} element Element to parse
24409
24311
  * @param {Object} [options] Options object
@@ -24415,23 +24317,23 @@
24415
24317
  let cssRules = arguments.length > 2 ? arguments[2] : undefined;
24416
24318
  const parsedAttributes = parseAttributes(element, this.ATTRIBUTE_NAMES, cssRules);
24417
24319
  return this.fromURL(parsedAttributes['xlink:href'], options, parsedAttributes).catch(err => {
24418
- console.log(err);
24320
+ log('log', 'Unable to parse Image', err);
24419
24321
  return null;
24420
24322
  });
24421
24323
  }
24422
24324
  }
24423
- _defineProperty(Image, "type", 'Image');
24424
- _defineProperty(Image, "cacheProperties", [...cacheProperties, ...IMAGE_PROPS]);
24425
- _defineProperty(Image, "ownDefaults", imageDefaultValues);
24426
- _defineProperty(Image, "CSS_CANVAS", 'canvas-img');
24325
+ _defineProperty(FabricImage, "type", 'Image');
24326
+ _defineProperty(FabricImage, "cacheProperties", [...cacheProperties, ...IMAGE_PROPS]);
24327
+ _defineProperty(FabricImage, "ownDefaults", imageDefaultValues);
24328
+ _defineProperty(FabricImage, "CSS_CANVAS", 'canvas-img');
24427
24329
  /**
24428
- * List of attribute names to account for when parsing SVG element (used by {@link Image.fromElement})
24330
+ * List of attribute names to account for when parsing SVG element (used by {@link FabricImage.fromElement})
24429
24331
  * @static
24430
24332
  * @see {@link http://www.w3.org/TR/SVG/struct.html#ImageElement}
24431
24333
  */
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);
24334
+ _defineProperty(FabricImage, "ATTRIBUTE_NAMES", [...SHARED_ATTRIBUTES, 'x', 'y', 'width', 'height', 'preserveAspectRatio', 'xlink:href', 'crossOrigin', 'image-rendering']);
24335
+ classRegistry.setClass(FabricImage);
24336
+ classRegistry.setSVGClass(FabricImage);
24435
24337
 
24436
24338
  /**
24437
24339
  * Add a <g> element that envelop all child elements and makes the viewbox transformMatrix descend on all elements
@@ -24567,25 +24469,6 @@
24567
24469
  return false;
24568
24470
  }
24569
24471
 
24570
- /**
24571
- * @private
24572
- * TODO: verify if this is still needed
24573
- * to support IE8 missing getElementById on SVGdocument and on node xmlDOM
24574
- */
24575
- function elementById(doc, id) {
24576
- if (doc.getElementById) {
24577
- return doc.getElementById(id);
24578
- }
24579
- const nodelist = doc.getElementsByTagName('*');
24580
- for (let i = 0, len = nodelist.length; i < len; i++) {
24581
- const node = nodelist[i];
24582
- if (id === node.getAttribute('id')) {
24583
- return node;
24584
- }
24585
- }
24586
- return null;
24587
- }
24588
-
24589
24472
  function getMultipleNodes(doc, nodeNames) {
24590
24473
  let nodeName,
24591
24474
  nodeArray = [],
@@ -24612,7 +24495,12 @@
24612
24495
  const xlink = xlinkAttribute.slice(1);
24613
24496
  const x = el.getAttribute('x') || 0;
24614
24497
  const y = el.getAttribute('y') || 0;
24615
- let el2 = elementById(doc, xlink).cloneNode(true);
24498
+ const el2Orig = doc.getElementById(xlink);
24499
+ if (el2Orig === null) {
24500
+ // if we can't find the target of the xlink, consider this use tag bad, similar to no xlink
24501
+ return;
24502
+ }
24503
+ let el2 = el2Orig.cloneNode(true);
24616
24504
  let currentTrans = (el2.getAttribute('transform') || '') + ' translate(' + x + ', ' + y + ')';
24617
24505
  const oldLength = nodelist.length;
24618
24506
  const namespace = svgNS;
@@ -24664,7 +24552,7 @@
24664
24552
  function recursivelyParseGradientsXlink(doc, gradient) {
24665
24553
  var _gradient$getAttribut;
24666
24554
  const xLink = ((_gradient$getAttribut = gradient.getAttribute(xlinkAttr)) === null || _gradient$getAttribut === void 0 ? void 0 : _gradient$getAttribut.slice(1)) || '',
24667
- referencedGradient = elementById(doc, xLink);
24555
+ referencedGradient = doc.getElementById(xLink);
24668
24556
  if (referencedGradient && referencedGradient.getAttribute(xlinkAttr)) {
24669
24557
  recursivelyParseGradientsXlink(doc, referencedGradient);
24670
24558
  }
@@ -24784,7 +24672,7 @@
24784
24672
  const obj = await klass.fromElement(el, this.options, this.cssRules);
24785
24673
  this.resolveGradient(obj, el, 'fill');
24786
24674
  this.resolveGradient(obj, el, 'stroke');
24787
- if (obj instanceof Image && obj._originalElement) {
24675
+ if (obj instanceof FabricImage && obj._originalElement) {
24788
24676
  removeTransformMatrixForSvgParsing(obj, obj.parsePreserveAspectRatioAttribute());
24789
24677
  } else {
24790
24678
  removeTransformMatrixForSvgParsing(obj);
@@ -24903,7 +24791,7 @@
24903
24791
  signal
24904
24792
  } = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
24905
24793
  if (signal && signal.aborted) {
24906
- console.log('`options.signal` is in `aborted` state');
24794
+ log('log', new SignalAbortedError('parseSVGDocument'));
24907
24795
  // this is an unhappy path, we dont care about speed
24908
24796
  return createEmptyResponse();
24909
24797
  }
@@ -25007,7 +24895,7 @@
25007
24895
  * This function locates the controls.
25008
24896
  * It'll be used both for drawing and for interaction.
25009
24897
  */
25010
- const factoryPolyPositionHandler = pointIndex => {
24898
+ const createPolyPositionHandler = pointIndex => {
25011
24899
  return function (dim, finalMatrix, polyObject) {
25012
24900
  var _polyObject$canvas$vi, _polyObject$canvas;
25013
24901
  const x = polyObject.points[pointIndex].x - polyObject.pathOffset.x,
@@ -25040,7 +24928,7 @@
25040
24928
  /**
25041
24929
  * Keep the polygon in the same position when we change its `width`/`height`/`top`/`left`.
25042
24930
  */
25043
- const anchorWrapper = (pointIndex, fn) => {
24931
+ const factoryPolyActionHandler = (pointIndex, fn) => {
25044
24932
  return function (eventData, transform, x, y) {
25045
24933
  const poly = transform.target,
25046
24934
  anchorPoint = new Point(poly.points[(pointIndex > 0 ? pointIndex : poly.points.length) - 1]),
@@ -25054,14 +24942,15 @@
25054
24942
  return actionPerformed;
25055
24943
  };
25056
24944
  };
24945
+ const createPolyActionHandler = pointIndex => factoryPolyActionHandler(pointIndex, polyActionHandler);
25057
24946
  function createPolyControls(arg0) {
25058
24947
  let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
25059
24948
  const controls = {};
25060
24949
  for (let idx = 0; idx < (typeof arg0 === 'number' ? arg0 : arg0.points.length); idx++) {
25061
24950
  controls["p".concat(idx)] = new Control(_objectSpread2({
25062
24951
  actionName: 'modifyPoly',
25063
- positionHandler: factoryPolyPositionHandler(idx),
25064
- actionHandler: anchorWrapper(idx, polyActionHandler)
24952
+ positionHandler: createPolyPositionHandler(idx),
24953
+ actionHandler: createPolyActionHandler(idx)
25065
24954
  }, options));
25066
24955
  }
25067
24956
  return controls;
@@ -25071,11 +24960,15 @@
25071
24960
  __proto__: null,
25072
24961
  changeWidth: changeWidth,
25073
24962
  createObjectDefaultControls: createObjectDefaultControls,
24963
+ createPolyActionHandler: createPolyActionHandler,
25074
24964
  createPolyControls: createPolyControls,
24965
+ createPolyPositionHandler: createPolyPositionHandler,
25075
24966
  createResizeControls: createResizeControls,
25076
24967
  createTextboxDefaultControls: createTextboxDefaultControls,
25077
24968
  dragHandler: dragHandler,
24969
+ factoryPolyActionHandler: factoryPolyActionHandler,
25078
24970
  getLocalPoint: getLocalPoint,
24971
+ polyActionHandler: polyActionHandler,
25079
24972
  renderCircleControl: renderCircleControl,
25080
24973
  renderSquareControl: renderSquareControl,
25081
24974
  rotationStyleHandler: rotationStyleHandler,
@@ -25170,25 +25063,23 @@
25170
25063
  const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
25171
25064
  const program = gl.createProgram();
25172
25065
  if (!vertexShader || !fragmentShader || !program) {
25173
- throw new Error('Vertex, fragment shader or program creation error');
25066
+ throw new FabricError('Vertex, fragment shader or program creation error');
25174
25067
  }
25175
25068
  gl.shaderSource(vertexShader, vertexSource);
25176
25069
  gl.compileShader(vertexShader);
25177
25070
  if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
25178
- throw new Error("Vertex shader compile error for ".concat(this.type, ": ").concat(gl.getShaderInfoLog(vertexShader)));
25071
+ throw new FabricError("Vertex shader compile error for ".concat(this.type, ": ").concat(gl.getShaderInfoLog(vertexShader)));
25179
25072
  }
25180
25073
  gl.shaderSource(fragmentShader, fragmentSource);
25181
25074
  gl.compileShader(fragmentShader);
25182
25075
  if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
25183
- throw new Error("Fragment shader compile error for ".concat(this.type, ": ").concat(gl.getShaderInfoLog(fragmentShader)));
25076
+ throw new FabricError("Fragment shader compile error for ".concat(this.type, ": ").concat(gl.getShaderInfoLog(fragmentShader)));
25184
25077
  }
25185
25078
  gl.attachShader(program, vertexShader);
25186
25079
  gl.attachShader(program, fragmentShader);
25187
25080
  gl.linkProgram(program);
25188
25081
  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));
25082
+ throw new FabricError("Shader link error for \"".concat(this.type, "\" ").concat(gl.getProgramInfoLog(program)));
25192
25083
  }
25193
25084
  const uniformLocations = this.getUniformLocations(gl, program) || {};
25194
25085
  uniformLocations.uStepW = gl.getUniformLocation(program, 'uStepW');
@@ -25787,7 +25678,7 @@
25787
25678
  image
25788
25679
  } = _ref2,
25789
25680
  filterOptions = _objectWithoutProperties(_ref2, _excluded$3);
25790
- return Image.fromObject(image, options).then(enlivedImage => new this(_objectSpread2(_objectSpread2({}, filterOptions), {}, {
25681
+ return FabricImage.fromObject(image, options).then(enlivedImage => new this(_objectSpread2(_objectSpread2({}, filterOptions), {}, {
25791
25682
  image: enlivedImage
25792
25683
  })));
25793
25684
  }
@@ -27751,10 +27642,13 @@
27751
27642
  exports.Color = Color;
27752
27643
  exports.Control = Control;
27753
27644
  exports.Ellipse = Ellipse;
27645
+ exports.FabricImage = FabricImage;
27646
+ exports.FabricObject = FabricObject;
27647
+ exports.FabricText = FabricText;
27754
27648
  exports.Gradient = Gradient;
27755
27649
  exports.Group = Group;
27756
27650
  exports.IText = IText;
27757
- exports.Image = Image;
27651
+ exports.Image = FabricImage;
27758
27652
  exports.Intersection = Intersection;
27759
27653
  exports.Line = Line;
27760
27654
  exports.Object = FabricObject;
@@ -27771,7 +27665,7 @@
27771
27665
  exports.SprayBrush = SprayBrush;
27772
27666
  exports.StaticCanvas = StaticCanvas;
27773
27667
  exports.StaticCanvasDOMManager = StaticCanvasDOMManager;
27774
- exports.Text = Text;
27668
+ exports.Text = FabricText;
27775
27669
  exports.Textbox = Textbox;
27776
27670
  exports.Triangle = Triangle;
27777
27671
  exports.WebGLFilterBackend = WebGLFilterBackend;