@nasser-sw/fabric 7.0.1-beta3 → 7.0.1-beta5

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/0 +0 -0
  2. package/dist/index.js +345 -162
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.min.js +1 -1
  5. package/dist/index.min.js.map +1 -1
  6. package/dist/index.min.mjs +1 -1
  7. package/dist/index.min.mjs.map +1 -1
  8. package/dist/index.mjs +345 -162
  9. package/dist/index.mjs.map +1 -1
  10. package/dist/index.node.cjs +345 -162
  11. package/dist/index.node.cjs.map +1 -1
  12. package/dist/index.node.mjs +345 -162
  13. package/dist/index.node.mjs.map +1 -1
  14. package/dist/package.json.min.mjs +1 -1
  15. package/dist/package.json.mjs +1 -1
  16. package/dist/src/shapes/Line.d.ts +32 -86
  17. package/dist/src/shapes/Line.d.ts.map +1 -1
  18. package/dist/src/shapes/Line.min.mjs +1 -1
  19. package/dist/src/shapes/Line.min.mjs.map +1 -1
  20. package/dist/src/shapes/Line.mjs +345 -161
  21. package/dist/src/shapes/Line.mjs.map +1 -1
  22. package/dist-extensions/src/shapes/CustomLine.d.ts +10 -0
  23. package/dist-extensions/src/shapes/CustomLine.d.ts.map +1 -0
  24. package/dist-extensions/src/shapes/Line.d.ts +32 -86
  25. package/dist-extensions/src/shapes/Line.d.ts.map +1 -1
  26. package/fabric-test-editor.html +157 -8
  27. package/fabric-test2.html +513 -0
  28. package/fabric.ts +182 -182
  29. package/package.json +1 -1
  30. package/src/shapes/Line.ts +397 -164
  31. package/debug/konva/CHANGELOG.md +0 -1474
  32. package/debug/konva/LICENSE +0 -22
  33. package/debug/konva/README.md +0 -205
  34. package/debug/konva/gulpfile.mjs +0 -110
  35. package/debug/konva/package.json +0 -139
  36. package/debug/konva/release.sh +0 -65
  37. package/debug/konva/resources/doc-includes/ContainerParams.txt +0 -6
  38. package/debug/konva/resources/doc-includes/NodeParams.txt +0 -20
  39. package/debug/konva/resources/doc-includes/ShapeParams.txt +0 -53
  40. package/debug/konva/resources/jsdoc.conf.json +0 -28
  41. package/debug/konva/rollup.config.mjs +0 -32
  42. package/debug/konva/src/Animation.ts +0 -237
  43. package/debug/konva/src/BezierFunctions.ts +0 -826
  44. package/debug/konva/src/Canvas.ts +0 -193
  45. package/debug/konva/src/Container.ts +0 -649
  46. package/debug/konva/src/Context.ts +0 -1017
  47. package/debug/konva/src/Core.ts +0 -5
  48. package/debug/konva/src/DragAndDrop.ts +0 -173
  49. package/debug/konva/src/Factory.ts +0 -246
  50. package/debug/konva/src/FastLayer.ts +0 -29
  51. package/debug/konva/src/Global.ts +0 -210
  52. package/debug/konva/src/Group.ts +0 -31
  53. package/debug/konva/src/Layer.ts +0 -546
  54. package/debug/konva/src/Node.ts +0 -3477
  55. package/debug/konva/src/PointerEvents.ts +0 -67
  56. package/debug/konva/src/Shape.ts +0 -2081
  57. package/debug/konva/src/Stage.ts +0 -1000
  58. package/debug/konva/src/Tween.ts +0 -811
  59. package/debug/konva/src/Util.ts +0 -1123
  60. package/debug/konva/src/Validators.ts +0 -210
  61. package/debug/konva/src/_CoreInternals.ts +0 -85
  62. package/debug/konva/src/_FullInternals.ts +0 -171
  63. package/debug/konva/src/canvas-backend.ts +0 -36
  64. package/debug/konva/src/filters/Blur.ts +0 -388
  65. package/debug/konva/src/filters/Brighten.ts +0 -48
  66. package/debug/konva/src/filters/Brightness.ts +0 -30
  67. package/debug/konva/src/filters/Contrast.ts +0 -75
  68. package/debug/konva/src/filters/Emboss.ts +0 -207
  69. package/debug/konva/src/filters/Enhance.ts +0 -154
  70. package/debug/konva/src/filters/Grayscale.ts +0 -25
  71. package/debug/konva/src/filters/HSL.ts +0 -108
  72. package/debug/konva/src/filters/HSV.ts +0 -106
  73. package/debug/konva/src/filters/Invert.ts +0 -23
  74. package/debug/konva/src/filters/Kaleidoscope.ts +0 -274
  75. package/debug/konva/src/filters/Mask.ts +0 -220
  76. package/debug/konva/src/filters/Noise.ts +0 -44
  77. package/debug/konva/src/filters/Pixelate.ts +0 -107
  78. package/debug/konva/src/filters/Posterize.ts +0 -46
  79. package/debug/konva/src/filters/RGB.ts +0 -82
  80. package/debug/konva/src/filters/RGBA.ts +0 -103
  81. package/debug/konva/src/filters/Sepia.ts +0 -27
  82. package/debug/konva/src/filters/Solarize.ts +0 -29
  83. package/debug/konva/src/filters/Threshold.ts +0 -44
  84. package/debug/konva/src/index.ts +0 -3
  85. package/debug/konva/src/shapes/Arc.ts +0 -176
  86. package/debug/konva/src/shapes/Arrow.ts +0 -231
  87. package/debug/konva/src/shapes/Circle.ts +0 -76
  88. package/debug/konva/src/shapes/Ellipse.ts +0 -121
  89. package/debug/konva/src/shapes/Image.ts +0 -319
  90. package/debug/konva/src/shapes/Label.ts +0 -386
  91. package/debug/konva/src/shapes/Line.ts +0 -364
  92. package/debug/konva/src/shapes/Path.ts +0 -1013
  93. package/debug/konva/src/shapes/Rect.ts +0 -79
  94. package/debug/konva/src/shapes/RegularPolygon.ts +0 -167
  95. package/debug/konva/src/shapes/Ring.ts +0 -94
  96. package/debug/konva/src/shapes/Sprite.ts +0 -370
  97. package/debug/konva/src/shapes/Star.ts +0 -125
  98. package/debug/konva/src/shapes/Text.ts +0 -1065
  99. package/debug/konva/src/shapes/TextPath.ts +0 -583
  100. package/debug/konva/src/shapes/Transformer.ts +0 -1889
  101. package/debug/konva/src/shapes/Wedge.ts +0 -129
  102. package/debug/konva/src/skia-backend.ts +0 -35
  103. package/debug/konva/src/types.ts +0 -84
  104. package/debug/konva/tsconfig.json +0 -31
  105. package/debug/konva/tsconfig.test.json +0 -7
package/dist/index.mjs CHANGED
@@ -354,7 +354,7 @@ class Cache {
354
354
  }
355
355
  const cache = new Cache();
356
356
 
357
- var version = "7.0.1-beta2";
357
+ var version = "7.0.1-beta5";
358
358
 
359
359
  // use this syntax so babel plugin see this import here
360
360
  const VERSION = version;
@@ -17571,33 +17571,29 @@ class PatternBrush extends PencilBrush {
17571
17571
  }
17572
17572
  }
17573
17573
 
17574
- // @TODO this code is terrible and Line should be a special case of polyline.
17575
-
17576
17574
  const coordProps = ['x1', 'x2', 'y1', 'y2'];
17577
- /**
17578
- * A Class to draw a line
17579
- * A bunch of methods will be added to Polyline to handle the line case
17580
- * The line class is very strange to work with, is all special, it hardly aligns
17581
- * to what a developer want everytime there is an angle
17582
- * @deprecated
17583
- */
17584
17575
  class Line extends FabricObject {
17585
- /**
17586
- * Constructor
17587
- * @param {Array} [points] Array of points
17588
- * @param {Object} [options] Options object
17589
- * @return {Line} thisArg
17590
- */
17591
17576
  constructor() {
17592
- let [x1, y1, x2, y2] = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [0, 0, 0, 0];
17577
+ let [x1, y1, x2, y2] = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [0, 0, 100, 0];
17593
17578
  let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
17594
17579
  super();
17595
- Object.assign(this, Line.ownDefaults);
17580
+ _defineProperty(this, "hitStrokeWidth", 'auto');
17581
+ _defineProperty(this, "_updatingEndpoints", false);
17582
+ _defineProperty(this, "_useEndpointCoords", true);
17596
17583
  this.setOptions(options);
17597
17584
  this.x1 = x1;
17598
17585
  this.x2 = x2;
17599
17586
  this.y1 = y1;
17600
17587
  this.y2 = y2;
17588
+ if (options.hitStrokeWidth !== undefined) {
17589
+ this.hitStrokeWidth = options.hitStrokeWidth;
17590
+ }
17591
+ this.hasBorders = false;
17592
+ this.hasControls = true;
17593
+ this.selectable = true;
17594
+ this.hoverCursor = 'move';
17595
+ this.perPixelTargetFind = false;
17596
+ this.strokeLineCap = 'butt';
17601
17597
  this._setWidthHeight();
17602
17598
  const {
17603
17599
  left,
@@ -17605,96 +17601,323 @@ class Line extends FabricObject {
17605
17601
  } = options;
17606
17602
  typeof left === 'number' && this.set(LEFT, left);
17607
17603
  typeof top === 'number' && this.set(TOP, top);
17604
+ this._setupLineControls();
17605
+ }
17606
+ _setupLineControls() {
17607
+ this.controls = {
17608
+ p1: new Control({
17609
+ x: 0,
17610
+ y: 0,
17611
+ cursorStyle: 'move',
17612
+ actionHandler: this._endpointActionHandler.bind(this),
17613
+ positionHandler: this._p1PositionHandler.bind(this),
17614
+ render: this._renderEndpointControl.bind(this),
17615
+ sizeX: 12,
17616
+ sizeY: 12
17617
+ }),
17618
+ p2: new Control({
17619
+ x: 0,
17620
+ y: 0,
17621
+ cursorStyle: 'move',
17622
+ actionHandler: this._endpointActionHandler.bind(this),
17623
+ positionHandler: this._p2PositionHandler.bind(this),
17624
+ render: this._renderEndpointControl.bind(this),
17625
+ sizeX: 12,
17626
+ sizeY: 12
17627
+ })
17628
+ };
17629
+ }
17630
+ _p1PositionHandler() {
17631
+ var _this$canvas;
17632
+ const vpt = ((_this$canvas = this.canvas) === null || _this$canvas === void 0 ? void 0 : _this$canvas.viewportTransform) || [1, 0, 0, 1, 0, 0];
17633
+ return new Point(this.x1, this.y1).transform(vpt);
17634
+ }
17635
+ _p2PositionHandler() {
17636
+ var _this$canvas2;
17637
+ const vpt = ((_this$canvas2 = this.canvas) === null || _this$canvas2 === void 0 ? void 0 : _this$canvas2.viewportTransform) || [1, 0, 0, 1, 0, 0];
17638
+ return new Point(this.x2, this.y2).transform(vpt);
17639
+ }
17640
+ _renderEndpointControl(ctx, left, top) {
17641
+ const size = 12;
17642
+ ctx.save();
17643
+ ctx.fillStyle = '#007bff';
17644
+ ctx.strokeStyle = '#ffffff';
17645
+ ctx.lineWidth = 2;
17646
+ ctx.beginPath();
17647
+ ctx.arc(left, top, size / 2, 0, 2 * Math.PI);
17648
+ ctx.fill();
17649
+ ctx.stroke();
17650
+ ctx.restore();
17651
+ }
17652
+ drawBorders(ctx) {
17653
+ let styleOverride = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
17654
+ if (this._useEndpointCoords) {
17655
+ this._drawLineBorders(ctx, styleOverride);
17656
+ return this;
17657
+ }
17658
+ return super.drawBorders(ctx, styleOverride, {});
17659
+ }
17660
+ _drawLineBorders(ctx) {
17661
+ var _this$canvas3;
17662
+ let styleOverride = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
17663
+ const vpt = ((_this$canvas3 = this.canvas) === null || _this$canvas3 === void 0 ? void 0 : _this$canvas3.viewportTransform) || [1, 0, 0, 1, 0, 0];
17664
+ ctx.save();
17665
+ ctx.setTransform(vpt[0], vpt[1], vpt[2], vpt[3], vpt[4], vpt[5]);
17666
+ ctx.strokeStyle = styleOverride.borderColor || this.borderColor || 'rgba(100, 200, 200, 0.5)';
17667
+ ctx.lineWidth = (this.strokeWidth || 1) + 5;
17668
+ ctx.lineCap = this.strokeLineCap || 'butt';
17669
+ ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;
17670
+ ctx.beginPath();
17671
+ ctx.moveTo(this.x1, this.y1);
17672
+ ctx.lineTo(this.x2, this.y2);
17673
+ ctx.stroke();
17674
+ ctx.restore();
17675
+ }
17676
+ _renderControls(ctx) {
17677
+ let styleOverride = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
17678
+ ctx.save();
17679
+ ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;
17680
+ this.drawControls(ctx, styleOverride);
17681
+ ctx.restore();
17682
+ }
17683
+ getBoundingRect() {
17684
+ if (this._useEndpointCoords) {
17685
+ const {
17686
+ x1,
17687
+ y1,
17688
+ x2,
17689
+ y2
17690
+ } = this;
17691
+ const effectiveStrokeWidth = this.hitStrokeWidth === 'auto' ? this.strokeWidth : this.hitStrokeWidth;
17692
+ const padding = Math.max(effectiveStrokeWidth / 2 + 5, 10);
17693
+ return {
17694
+ left: Math.min(x1, x2) - padding,
17695
+ top: Math.min(y1, y2) - padding,
17696
+ width: Math.abs(x2 - x1) + padding * 2 || padding * 2,
17697
+ height: Math.abs(y2 - y1) + padding * 2 || padding * 2
17698
+ };
17699
+ }
17700
+ return super.getBoundingRect();
17608
17701
  }
17702
+ setCoords() {
17703
+ if (this._useEndpointCoords) {
17704
+ // Set the object's center to the geometric center of the line
17705
+ const center = this._findCenterFromElement();
17706
+ this.left = center.x;
17707
+ this.top = center.y;
17708
+
17709
+ // Set width and height for hit detection and bounding box
17710
+ const effectiveStrokeWidth = this.hitStrokeWidth === 'auto' ? this.strokeWidth : this.hitStrokeWidth;
17711
+ const hitPadding = Math.max(effectiveStrokeWidth / 2 + 5, 10);
17712
+ this.width = Math.abs(this.x2 - this.x1) + hitPadding * 2;
17713
+ this.height = Math.abs(this.y2 - this.y1) + hitPadding * 2;
17714
+ }
17715
+ super.setCoords();
17716
+ }
17717
+ getCoords() {
17718
+ if (this._useEndpointCoords) {
17719
+ const deltaX = this.x2 - this.x1;
17720
+ const deltaY = this.y2 - this.y1;
17721
+ const length = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
17722
+ if (length === 0) {
17723
+ return super.getCoords();
17724
+ }
17725
+ const effectiveStrokeWidth = this.hitStrokeWidth === 'auto' ? this.strokeWidth : this.hitStrokeWidth;
17726
+ const halfWidth = Math.max(effectiveStrokeWidth / 2 + 2, 5);
17609
17727
 
17610
- /**
17611
- * @private
17612
- * @param {Object} [options] Options
17613
- */
17614
- _setWidthHeight() {
17615
- const {
17616
- x1,
17617
- y1,
17618
- x2,
17619
- y2
17620
- } = this;
17621
- this.width = Math.abs(x2 - x1);
17622
- this.height = Math.abs(y2 - y1);
17623
- const {
17624
- left,
17625
- top,
17626
- width,
17627
- height
17628
- } = makeBoundingBoxFromPoints([{
17629
- x: x1,
17630
- y: y1
17631
- }, {
17632
- x: x2,
17633
- y: y2
17634
- }]);
17635
- const position = new Point(left + width / 2, top + height / 2);
17636
- this.setPositionByOrigin(position, CENTER, CENTER);
17728
+ // Unit vector perpendicular to line
17729
+ const perpX = -deltaY / length;
17730
+ const perpY = deltaX / length;
17731
+
17732
+ // Four corners of oriented rectangle
17733
+ return [new Point(this.x1 + perpX * halfWidth, this.y1 + perpY * halfWidth), new Point(this.x2 + perpX * halfWidth, this.y2 + perpY * halfWidth), new Point(this.x2 - perpX * halfWidth, this.y2 - perpY * halfWidth), new Point(this.x1 - perpX * halfWidth, this.y1 - perpY * halfWidth)];
17734
+ }
17735
+ return super.getCoords();
17637
17736
  }
17737
+ containsPoint(point) {
17738
+ if (this._useEndpointCoords) {
17739
+ var _this$canvas4;
17740
+ if (((_this$canvas4 = this.canvas) === null || _this$canvas4 === void 0 ? void 0 : _this$canvas4.getActiveObject()) === this) {
17741
+ return super.containsPoint(point);
17742
+ }
17743
+ const distance = this._distanceToLineSegment(point.x, point.y);
17744
+ const effectiveStrokeWidth = this.hitStrokeWidth === 'auto' ? this.strokeWidth : this.hitStrokeWidth || 1;
17745
+ const tolerance = Math.max(effectiveStrokeWidth / 2 + 2, 5);
17746
+ return distance <= tolerance;
17747
+ }
17748
+ return super.containsPoint(point);
17749
+ }
17750
+ _distanceToLineSegment(px, py) {
17751
+ const x1 = this.x1,
17752
+ y1 = this.y1,
17753
+ x2 = this.x2,
17754
+ y2 = this.y2;
17755
+ const pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
17756
+ if (pd2 === 0) {
17757
+ return Math.sqrt((px - x1) * (px - x1) + (py - y1) * (py - y1));
17758
+ }
17759
+ const u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / pd2;
17760
+ let closestX, closestY;
17761
+ if (u < 0) {
17762
+ closestX = x1;
17763
+ closestY = y1;
17764
+ } else if (u > 1) {
17765
+ closestX = x2;
17766
+ closestY = y2;
17767
+ } else {
17768
+ closestX = x1 + u * (x2 - x1);
17769
+ closestY = y1 + u * (y2 - y1);
17770
+ }
17771
+ return Math.sqrt((px - closestX) * (px - closestX) + (py - closestY) * (py - closestY));
17772
+ }
17773
+ _endpointActionHandler(eventData, transformData, x, y) {
17774
+ var _this$canvas6;
17775
+ const controlKey = transformData.corner;
17776
+ const pointer = new Point(x, y);
17777
+ let newX = pointer.x;
17778
+ let newY = pointer.y;
17779
+ if (eventData.shiftKey) {
17780
+ const otherControl = controlKey === 'p1' ? 'p2' : 'p1';
17781
+ const otherX = this[otherControl === 'p1' ? 'x1' : 'x2'];
17782
+ const otherY = this[otherControl === 'p1' ? 'y1' : 'y2'];
17783
+ const snapped = this._snapToAngle(otherX, otherY, newX, newY);
17784
+ newX = snapped.x;
17785
+ newY = snapped.y;
17786
+ }
17787
+ if (this._useEndpointCoords) {
17788
+ var _this$canvas5;
17789
+ if (controlKey === 'p1') {
17790
+ this.x1 = newX;
17791
+ this.y1 = newY;
17792
+ } else if (controlKey === 'p2') {
17793
+ this.x2 = newX;
17794
+ this.y2 = newY;
17795
+ }
17796
+ this.dirty = true;
17797
+ this.setCoords();
17798
+ (_this$canvas5 = this.canvas) === null || _this$canvas5 === void 0 || _this$canvas5.requestRenderAll();
17799
+ return true;
17800
+ }
17638
17801
 
17639
- /**
17640
- * @private
17641
- * @param {String} key
17642
- * @param {*} value
17643
- */
17802
+ // Fallback for old system
17803
+ this._updatingEndpoints = true;
17804
+ if (controlKey === 'p1') {
17805
+ this.x1 = newX;
17806
+ this.y1 = newY;
17807
+ } else if (controlKey === 'p2') {
17808
+ this.x2 = newX;
17809
+ this.y2 = newY;
17810
+ }
17811
+ this._setWidthHeight();
17812
+ this.dirty = true;
17813
+ this._updatingEndpoints = false;
17814
+ (_this$canvas6 = this.canvas) === null || _this$canvas6 === void 0 || _this$canvas6.requestRenderAll();
17815
+ this.fire('modified', {
17816
+ transform: transformData,
17817
+ target: this,
17818
+ e: eventData
17819
+ });
17820
+ return true;
17821
+ }
17822
+ _snapToAngle(fromX, fromY, toX, toY) {
17823
+ const deltaX = toX - fromX;
17824
+ const deltaY = toY - fromY;
17825
+ const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
17826
+ if (distance === 0) return {
17827
+ x: toX,
17828
+ y: toY
17829
+ };
17830
+ let angle = Math.atan2(deltaY, deltaX) * (180 / Math.PI);
17831
+ const snapIncrement = 15;
17832
+ const snappedAngle = Math.round(angle / snapIncrement) * snapIncrement;
17833
+ const snappedRadians = snappedAngle * (Math.PI / 180);
17834
+ return {
17835
+ x: fromX + Math.cos(snappedRadians) * distance,
17836
+ y: fromY + Math.sin(snappedRadians) * distance
17837
+ };
17838
+ }
17839
+ _setWidthHeight() {
17840
+ let skipReposition = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
17841
+ this.width = Math.abs(this.x2 - this.x1) || 1;
17842
+ this.height = Math.abs(this.y2 - this.y1) || 1;
17843
+ if (!skipReposition && !this._updatingEndpoints) {
17844
+ const {
17845
+ left,
17846
+ top,
17847
+ width,
17848
+ height
17849
+ } = makeBoundingBoxFromPoints([{
17850
+ x: this.x1,
17851
+ y: this.y1
17852
+ }, {
17853
+ x: this.x2,
17854
+ y: this.y2
17855
+ }]);
17856
+ this.setPositionByOrigin(new Point(left + width / 2, top + height / 2), CENTER, CENTER);
17857
+ }
17858
+ }
17644
17859
  _set(key, value) {
17860
+ const oldLeft = this.left;
17861
+ const oldTop = this.top;
17645
17862
  super._set(key, value);
17646
17863
  if (coordProps.includes(key)) {
17647
- // this doesn't make sense very much, since setting x1 when top or left
17648
- // are already set, is just going to show a strange result since the
17649
- // line will move way more than the developer expect.
17650
- // in fabric5 it worked only when the line didn't have extra transformations,
17651
- // in fabric6 too. With extra transform they behave bad in different ways.
17652
- // This needs probably a good rework or a tutorial if you have to create a dynamic line
17653
17864
  this._setWidthHeight();
17865
+ this.dirty = true;
17866
+ }
17867
+ if ((key === 'left' || key === 'top') && this.canvas && !this._updatingEndpoints) {
17868
+ const deltaX = this.left - oldLeft;
17869
+ const deltaY = this.top - oldTop;
17870
+ if (deltaX !== 0 || deltaY !== 0) {
17871
+ this._updatingEndpoints = true;
17872
+ this.x1 += deltaX;
17873
+ this.y1 += deltaY;
17874
+ this.x2 += deltaX;
17875
+ this.y2 += deltaY;
17876
+ this._updatingEndpoints = false;
17877
+ }
17654
17878
  }
17655
17879
  return this;
17656
17880
  }
17657
-
17658
- /**
17659
- * @private
17660
- * @param {CanvasRenderingContext2D} ctx Context to render on
17661
- */
17881
+ render(ctx) {
17882
+ if (this._useEndpointCoords) {
17883
+ this._renderDirectly(ctx);
17884
+ return;
17885
+ }
17886
+ super.render(ctx);
17887
+ }
17888
+ _renderDirectly(ctx) {
17889
+ var _this$canvas7, _this$stroke;
17890
+ if (!this.visible) return;
17891
+ ctx.save();
17892
+ const vpt = ((_this$canvas7 = this.canvas) === null || _this$canvas7 === void 0 ? void 0 : _this$canvas7.viewportTransform) || [1, 0, 0, 1, 0, 0];
17893
+ ctx.transform(vpt[0], vpt[1], vpt[2], vpt[3], vpt[4], vpt[5]);
17894
+ ctx.globalAlpha = this.opacity;
17895
+ ctx.strokeStyle = ((_this$stroke = this.stroke) === null || _this$stroke === void 0 ? void 0 : _this$stroke.toString()) || '#000';
17896
+ ctx.lineWidth = this.strokeWidth;
17897
+ ctx.lineCap = this.strokeLineCap || 'butt';
17898
+ ctx.beginPath();
17899
+ ctx.moveTo(this.x1, this.y1);
17900
+ ctx.lineTo(this.x2, this.y2);
17901
+ ctx.stroke();
17902
+ ctx.restore();
17903
+ }
17662
17904
  _render(ctx) {
17905
+ if (this._useEndpointCoords) return;
17663
17906
  ctx.beginPath();
17664
17907
  const p = this.calcLinePoints();
17665
17908
  ctx.moveTo(p.x1, p.y1);
17666
17909
  ctx.lineTo(p.x2, p.y2);
17667
17910
  ctx.lineWidth = this.strokeWidth;
17668
-
17669
- // TODO: test this
17670
- // make sure setting "fill" changes color of a line
17671
- // (by copying fillStyle to strokeStyle, since line is stroked, not filled)
17672
17911
  const origStrokeStyle = ctx.strokeStyle;
17673
17912
  if (isFiller(this.stroke)) {
17674
17913
  ctx.strokeStyle = this.stroke.toLive(ctx);
17675
- } else {
17676
- var _this$stroke;
17677
- ctx.strokeStyle = (_this$stroke = this.stroke) !== null && _this$stroke !== void 0 ? _this$stroke : ctx.fillStyle;
17678
17914
  }
17679
17915
  this.stroke && this._renderStroke(ctx);
17680
17916
  ctx.strokeStyle = origStrokeStyle;
17681
17917
  }
17682
-
17683
- /**
17684
- * This function is an helper for svg import. it returns the center of the object in the svg
17685
- * untransformed coordinates
17686
- * @private
17687
- * @return {Point} center point from element coordinates
17688
- */
17689
17918
  _findCenterFromElement() {
17690
17919
  return new Point((this.x1 + this.x2) / 2, (this.y1 + this.y2) / 2);
17691
17920
  }
17692
-
17693
- /**
17694
- * Returns object representation of an instance
17695
- * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
17696
- * @return {Object} object representation of an instance
17697
- */
17698
17921
  toObject() {
17699
17922
  let propertiesToInclude = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
17700
17923
  return {
@@ -17702,32 +17925,25 @@ class Line extends FabricObject {
17702
17925
  ...this.calcLinePoints()
17703
17926
  };
17704
17927
  }
17705
-
17706
- /*
17707
- * Calculate object dimensions from its properties
17708
- * @private
17709
- */
17710
17928
  _getNonTransformedDimensions() {
17711
17929
  const dim = super._getNonTransformedDimensions();
17712
- if (this.strokeLineCap === 'butt') {
17713
- if (this.width === 0) {
17714
- dim.y -= this.strokeWidth;
17715
- }
17716
- if (this.height === 0) {
17717
- dim.x -= this.strokeWidth;
17718
- }
17930
+ if (this.strokeLineCap === 'round') {
17931
+ dim.x += this.strokeWidth;
17932
+ dim.y += this.strokeWidth;
17719
17933
  }
17720
17934
  return dim;
17721
17935
  }
17722
-
17723
- /**
17724
- * Recalculates line points given width and height
17725
- * Those points are simply placed around the center,
17726
- * This is not useful outside internal render functions and svg output
17727
- * Is not meant to be for the developer.
17728
- * @private
17729
- */
17730
17936
  calcLinePoints() {
17937
+ if (this._updatingEndpoints) {
17938
+ const centerX = (this.x1 + this.x2) / 2;
17939
+ const centerY = (this.y1 + this.y2) / 2;
17940
+ return {
17941
+ x1: this.x1 - centerX,
17942
+ y1: this.y1 - centerY,
17943
+ x2: this.x2 - centerX,
17944
+ y2: this.y2 - centerY
17945
+ };
17946
+ }
17731
17947
  const {
17732
17948
  x1: _x1,
17733
17949
  x2: _x2,
@@ -17736,48 +17952,39 @@ class Line extends FabricObject {
17736
17952
  width,
17737
17953
  height
17738
17954
  } = this;
17739
- const xMult = _x1 <= _x2 ? -1 : 1,
17740
- yMult = _y1 <= _y2 ? -1 : 1,
17741
- x1 = xMult * width / 2,
17742
- y1 = yMult * height / 2,
17743
- x2 = xMult * -width / 2,
17744
- y2 = yMult * -height / 2;
17955
+ const xMult = _x1 <= _x2 ? -1 : 1;
17956
+ const yMult = _y1 <= _y2 ? -1 : 1;
17745
17957
  return {
17746
- x1,
17747
- x2,
17748
- y1,
17749
- y2
17958
+ x1: xMult * width / 2,
17959
+ y1: yMult * height / 2,
17960
+ x2: xMult * -width / 2,
17961
+ y2: yMult * -height / 2
17750
17962
  };
17751
17963
  }
17752
-
17753
- /* _FROM_SVG_START_ */
17754
-
17755
- /**
17756
- * Returns svg representation of an instance
17757
- * @return {Array} an array of strings with the specific svg representation
17758
- * of the instance
17759
- */
17760
17964
  _toSVG() {
17761
- const {
17762
- x1,
17763
- x2,
17764
- y1,
17765
- y2
17766
- } = this.calcLinePoints();
17767
- return ['<line ', 'COMMON_PARTS', `x1="${x1}" y1="${y1}" x2="${x2}" y2="${y2}" />\n`];
17965
+ if (this._useEndpointCoords) {
17966
+ // Use absolute coordinates to bypass all Fabric.js transforms
17967
+ return [`<line stroke="${this.stroke}" stroke-width="${this.strokeWidth}" stroke-linecap="${this.strokeLineCap}" `, `x1="${this.x1}" y1="${this.y1}" x2="${this.x2}" y2="${this.y2}" />\n`];
17968
+ } else {
17969
+ // Use standard calcLinePoints for legacy mode
17970
+ const {
17971
+ x1,
17972
+ x2,
17973
+ y1,
17974
+ y2
17975
+ } = this.calcLinePoints();
17976
+ return ['<line ', 'COMMON_PARTS', `x1="${x1}" y1="${y1}" x2="${x2}" y2="${y2}" />\n`];
17977
+ }
17978
+ }
17979
+ toSVG(reviver) {
17980
+ if (this._useEndpointCoords) {
17981
+ // Override toSVG to prevent Fabric.js from adding transform wrapper
17982
+ const markup = this._toSVG().join('');
17983
+ return reviver ? reviver(markup) : markup;
17984
+ }
17985
+ // Use default behavior for legacy mode
17986
+ return super.toSVG(reviver);
17768
17987
  }
17769
-
17770
- /**
17771
- * List of attribute names to account for when parsing SVG element (used by {@link Line.fromElement})
17772
- * @see http://www.w3.org/TR/SVG/shapes.html#LineElement
17773
- */
17774
-
17775
- /**
17776
- * Returns Line instance from an SVG element
17777
- * @param {HTMLElement} element Element to parse
17778
- * @param {Object} [options] Options object
17779
- * @param {Function} [callback] callback function invoked after parsing
17780
- */
17781
17988
  static async fromElement(element, options, cssRules) {
17782
17989
  const {
17783
17990
  x1 = 0,
@@ -17788,14 +17995,6 @@ class Line extends FabricObject {
17788
17995
  } = parseAttributes(element, this.ATTRIBUTE_NAMES, cssRules);
17789
17996
  return new this([x1, y1, x2, y2], parsedAttributes);
17790
17997
  }
17791
-
17792
- /* _FROM_SVG_END_ */
17793
-
17794
- /**
17795
- * Returns Line instance from an object representation
17796
- * @param {Object} object Object to create an instance from
17797
- * @returns {Promise<Line>}
17798
- */
17799
17998
  static fromObject(_ref) {
17800
17999
  let {
17801
18000
  x1,
@@ -17812,22 +18011,6 @@ class Line extends FabricObject {
17812
18011
  });
17813
18012
  }
17814
18013
  }
17815
- /**
17816
- * x value or first line edge
17817
- * @type number
17818
- */
17819
- /**
17820
- * y value or first line edge
17821
- * @type number
17822
- */
17823
- /**
17824
- * x value or second line edge
17825
- * @type number
17826
- */
17827
- /**
17828
- * y value or second line edge
17829
- * @type number
17830
- */
17831
18014
  _defineProperty(Line, "type", 'Line');
17832
18015
  _defineProperty(Line, "cacheProperties", [...cacheProperties, ...coordProps]);
17833
18016
  _defineProperty(Line, "ATTRIBUTE_NAMES", SHARED_ATTRIBUTES.concat(coordProps));