@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
@@ -412,7 +412,7 @@ class Cache {
412
412
  }
413
413
  const cache = new Cache();
414
414
 
415
- var version = "7.0.1-beta2";
415
+ var version = "7.0.1-beta5";
416
416
 
417
417
  // use this syntax so babel plugin see this import here
418
418
  const VERSION = version;
@@ -17629,33 +17629,29 @@ class PatternBrush extends PencilBrush {
17629
17629
  }
17630
17630
  }
17631
17631
 
17632
- // @TODO this code is terrible and Line should be a special case of polyline.
17633
-
17634
17632
  const coordProps = ['x1', 'x2', 'y1', 'y2'];
17635
- /**
17636
- * A Class to draw a line
17637
- * A bunch of methods will be added to Polyline to handle the line case
17638
- * The line class is very strange to work with, is all special, it hardly aligns
17639
- * to what a developer want everytime there is an angle
17640
- * @deprecated
17641
- */
17642
17633
  class Line extends FabricObject {
17643
- /**
17644
- * Constructor
17645
- * @param {Array} [points] Array of points
17646
- * @param {Object} [options] Options object
17647
- * @return {Line} thisArg
17648
- */
17649
17634
  constructor() {
17650
- let [x1, y1, x2, y2] = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [0, 0, 0, 0];
17635
+ let [x1, y1, x2, y2] = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [0, 0, 100, 0];
17651
17636
  let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
17652
17637
  super();
17653
- Object.assign(this, Line.ownDefaults);
17638
+ _defineProperty(this, "hitStrokeWidth", 'auto');
17639
+ _defineProperty(this, "_updatingEndpoints", false);
17640
+ _defineProperty(this, "_useEndpointCoords", true);
17654
17641
  this.setOptions(options);
17655
17642
  this.x1 = x1;
17656
17643
  this.x2 = x2;
17657
17644
  this.y1 = y1;
17658
17645
  this.y2 = y2;
17646
+ if (options.hitStrokeWidth !== undefined) {
17647
+ this.hitStrokeWidth = options.hitStrokeWidth;
17648
+ }
17649
+ this.hasBorders = false;
17650
+ this.hasControls = true;
17651
+ this.selectable = true;
17652
+ this.hoverCursor = 'move';
17653
+ this.perPixelTargetFind = false;
17654
+ this.strokeLineCap = 'butt';
17659
17655
  this._setWidthHeight();
17660
17656
  const {
17661
17657
  left,
@@ -17663,96 +17659,323 @@ class Line extends FabricObject {
17663
17659
  } = options;
17664
17660
  typeof left === 'number' && this.set(LEFT, left);
17665
17661
  typeof top === 'number' && this.set(TOP, top);
17662
+ this._setupLineControls();
17663
+ }
17664
+ _setupLineControls() {
17665
+ this.controls = {
17666
+ p1: new Control({
17667
+ x: 0,
17668
+ y: 0,
17669
+ cursorStyle: 'move',
17670
+ actionHandler: this._endpointActionHandler.bind(this),
17671
+ positionHandler: this._p1PositionHandler.bind(this),
17672
+ render: this._renderEndpointControl.bind(this),
17673
+ sizeX: 12,
17674
+ sizeY: 12
17675
+ }),
17676
+ p2: new Control({
17677
+ x: 0,
17678
+ y: 0,
17679
+ cursorStyle: 'move',
17680
+ actionHandler: this._endpointActionHandler.bind(this),
17681
+ positionHandler: this._p2PositionHandler.bind(this),
17682
+ render: this._renderEndpointControl.bind(this),
17683
+ sizeX: 12,
17684
+ sizeY: 12
17685
+ })
17686
+ };
17687
+ }
17688
+ _p1PositionHandler() {
17689
+ var _this$canvas;
17690
+ const vpt = ((_this$canvas = this.canvas) === null || _this$canvas === void 0 ? void 0 : _this$canvas.viewportTransform) || [1, 0, 0, 1, 0, 0];
17691
+ return new Point(this.x1, this.y1).transform(vpt);
17692
+ }
17693
+ _p2PositionHandler() {
17694
+ var _this$canvas2;
17695
+ const vpt = ((_this$canvas2 = this.canvas) === null || _this$canvas2 === void 0 ? void 0 : _this$canvas2.viewportTransform) || [1, 0, 0, 1, 0, 0];
17696
+ return new Point(this.x2, this.y2).transform(vpt);
17697
+ }
17698
+ _renderEndpointControl(ctx, left, top) {
17699
+ const size = 12;
17700
+ ctx.save();
17701
+ ctx.fillStyle = '#007bff';
17702
+ ctx.strokeStyle = '#ffffff';
17703
+ ctx.lineWidth = 2;
17704
+ ctx.beginPath();
17705
+ ctx.arc(left, top, size / 2, 0, 2 * Math.PI);
17706
+ ctx.fill();
17707
+ ctx.stroke();
17708
+ ctx.restore();
17709
+ }
17710
+ drawBorders(ctx) {
17711
+ let styleOverride = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
17712
+ if (this._useEndpointCoords) {
17713
+ this._drawLineBorders(ctx, styleOverride);
17714
+ return this;
17715
+ }
17716
+ return super.drawBorders(ctx, styleOverride, {});
17717
+ }
17718
+ _drawLineBorders(ctx) {
17719
+ var _this$canvas3;
17720
+ let styleOverride = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
17721
+ const vpt = ((_this$canvas3 = this.canvas) === null || _this$canvas3 === void 0 ? void 0 : _this$canvas3.viewportTransform) || [1, 0, 0, 1, 0, 0];
17722
+ ctx.save();
17723
+ ctx.setTransform(vpt[0], vpt[1], vpt[2], vpt[3], vpt[4], vpt[5]);
17724
+ ctx.strokeStyle = styleOverride.borderColor || this.borderColor || 'rgba(100, 200, 200, 0.5)';
17725
+ ctx.lineWidth = (this.strokeWidth || 1) + 5;
17726
+ ctx.lineCap = this.strokeLineCap || 'butt';
17727
+ ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;
17728
+ ctx.beginPath();
17729
+ ctx.moveTo(this.x1, this.y1);
17730
+ ctx.lineTo(this.x2, this.y2);
17731
+ ctx.stroke();
17732
+ ctx.restore();
17733
+ }
17734
+ _renderControls(ctx) {
17735
+ let styleOverride = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
17736
+ ctx.save();
17737
+ ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;
17738
+ this.drawControls(ctx, styleOverride);
17739
+ ctx.restore();
17740
+ }
17741
+ getBoundingRect() {
17742
+ if (this._useEndpointCoords) {
17743
+ const {
17744
+ x1,
17745
+ y1,
17746
+ x2,
17747
+ y2
17748
+ } = this;
17749
+ const effectiveStrokeWidth = this.hitStrokeWidth === 'auto' ? this.strokeWidth : this.hitStrokeWidth;
17750
+ const padding = Math.max(effectiveStrokeWidth / 2 + 5, 10);
17751
+ return {
17752
+ left: Math.min(x1, x2) - padding,
17753
+ top: Math.min(y1, y2) - padding,
17754
+ width: Math.abs(x2 - x1) + padding * 2 || padding * 2,
17755
+ height: Math.abs(y2 - y1) + padding * 2 || padding * 2
17756
+ };
17757
+ }
17758
+ return super.getBoundingRect();
17666
17759
  }
17760
+ setCoords() {
17761
+ if (this._useEndpointCoords) {
17762
+ // Set the object's center to the geometric center of the line
17763
+ const center = this._findCenterFromElement();
17764
+ this.left = center.x;
17765
+ this.top = center.y;
17766
+
17767
+ // Set width and height for hit detection and bounding box
17768
+ const effectiveStrokeWidth = this.hitStrokeWidth === 'auto' ? this.strokeWidth : this.hitStrokeWidth;
17769
+ const hitPadding = Math.max(effectiveStrokeWidth / 2 + 5, 10);
17770
+ this.width = Math.abs(this.x2 - this.x1) + hitPadding * 2;
17771
+ this.height = Math.abs(this.y2 - this.y1) + hitPadding * 2;
17772
+ }
17773
+ super.setCoords();
17774
+ }
17775
+ getCoords() {
17776
+ if (this._useEndpointCoords) {
17777
+ const deltaX = this.x2 - this.x1;
17778
+ const deltaY = this.y2 - this.y1;
17779
+ const length = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
17780
+ if (length === 0) {
17781
+ return super.getCoords();
17782
+ }
17783
+ const effectiveStrokeWidth = this.hitStrokeWidth === 'auto' ? this.strokeWidth : this.hitStrokeWidth;
17784
+ const halfWidth = Math.max(effectiveStrokeWidth / 2 + 2, 5);
17667
17785
 
17668
- /**
17669
- * @private
17670
- * @param {Object} [options] Options
17671
- */
17672
- _setWidthHeight() {
17673
- const {
17674
- x1,
17675
- y1,
17676
- x2,
17677
- y2
17678
- } = this;
17679
- this.width = Math.abs(x2 - x1);
17680
- this.height = Math.abs(y2 - y1);
17681
- const {
17682
- left,
17683
- top,
17684
- width,
17685
- height
17686
- } = makeBoundingBoxFromPoints([{
17687
- x: x1,
17688
- y: y1
17689
- }, {
17690
- x: x2,
17691
- y: y2
17692
- }]);
17693
- const position = new Point(left + width / 2, top + height / 2);
17694
- this.setPositionByOrigin(position, CENTER, CENTER);
17786
+ // Unit vector perpendicular to line
17787
+ const perpX = -deltaY / length;
17788
+ const perpY = deltaX / length;
17789
+
17790
+ // Four corners of oriented rectangle
17791
+ 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)];
17792
+ }
17793
+ return super.getCoords();
17695
17794
  }
17795
+ containsPoint(point) {
17796
+ if (this._useEndpointCoords) {
17797
+ var _this$canvas4;
17798
+ if (((_this$canvas4 = this.canvas) === null || _this$canvas4 === void 0 ? void 0 : _this$canvas4.getActiveObject()) === this) {
17799
+ return super.containsPoint(point);
17800
+ }
17801
+ const distance = this._distanceToLineSegment(point.x, point.y);
17802
+ const effectiveStrokeWidth = this.hitStrokeWidth === 'auto' ? this.strokeWidth : this.hitStrokeWidth || 1;
17803
+ const tolerance = Math.max(effectiveStrokeWidth / 2 + 2, 5);
17804
+ return distance <= tolerance;
17805
+ }
17806
+ return super.containsPoint(point);
17807
+ }
17808
+ _distanceToLineSegment(px, py) {
17809
+ const x1 = this.x1,
17810
+ y1 = this.y1,
17811
+ x2 = this.x2,
17812
+ y2 = this.y2;
17813
+ const pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
17814
+ if (pd2 === 0) {
17815
+ return Math.sqrt((px - x1) * (px - x1) + (py - y1) * (py - y1));
17816
+ }
17817
+ const u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / pd2;
17818
+ let closestX, closestY;
17819
+ if (u < 0) {
17820
+ closestX = x1;
17821
+ closestY = y1;
17822
+ } else if (u > 1) {
17823
+ closestX = x2;
17824
+ closestY = y2;
17825
+ } else {
17826
+ closestX = x1 + u * (x2 - x1);
17827
+ closestY = y1 + u * (y2 - y1);
17828
+ }
17829
+ return Math.sqrt((px - closestX) * (px - closestX) + (py - closestY) * (py - closestY));
17830
+ }
17831
+ _endpointActionHandler(eventData, transformData, x, y) {
17832
+ var _this$canvas6;
17833
+ const controlKey = transformData.corner;
17834
+ const pointer = new Point(x, y);
17835
+ let newX = pointer.x;
17836
+ let newY = pointer.y;
17837
+ if (eventData.shiftKey) {
17838
+ const otherControl = controlKey === 'p1' ? 'p2' : 'p1';
17839
+ const otherX = this[otherControl === 'p1' ? 'x1' : 'x2'];
17840
+ const otherY = this[otherControl === 'p1' ? 'y1' : 'y2'];
17841
+ const snapped = this._snapToAngle(otherX, otherY, newX, newY);
17842
+ newX = snapped.x;
17843
+ newY = snapped.y;
17844
+ }
17845
+ if (this._useEndpointCoords) {
17846
+ var _this$canvas5;
17847
+ if (controlKey === 'p1') {
17848
+ this.x1 = newX;
17849
+ this.y1 = newY;
17850
+ } else if (controlKey === 'p2') {
17851
+ this.x2 = newX;
17852
+ this.y2 = newY;
17853
+ }
17854
+ this.dirty = true;
17855
+ this.setCoords();
17856
+ (_this$canvas5 = this.canvas) === null || _this$canvas5 === void 0 || _this$canvas5.requestRenderAll();
17857
+ return true;
17858
+ }
17696
17859
 
17697
- /**
17698
- * @private
17699
- * @param {String} key
17700
- * @param {*} value
17701
- */
17860
+ // Fallback for old system
17861
+ this._updatingEndpoints = true;
17862
+ if (controlKey === 'p1') {
17863
+ this.x1 = newX;
17864
+ this.y1 = newY;
17865
+ } else if (controlKey === 'p2') {
17866
+ this.x2 = newX;
17867
+ this.y2 = newY;
17868
+ }
17869
+ this._setWidthHeight();
17870
+ this.dirty = true;
17871
+ this._updatingEndpoints = false;
17872
+ (_this$canvas6 = this.canvas) === null || _this$canvas6 === void 0 || _this$canvas6.requestRenderAll();
17873
+ this.fire('modified', {
17874
+ transform: transformData,
17875
+ target: this,
17876
+ e: eventData
17877
+ });
17878
+ return true;
17879
+ }
17880
+ _snapToAngle(fromX, fromY, toX, toY) {
17881
+ const deltaX = toX - fromX;
17882
+ const deltaY = toY - fromY;
17883
+ const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
17884
+ if (distance === 0) return {
17885
+ x: toX,
17886
+ y: toY
17887
+ };
17888
+ let angle = Math.atan2(deltaY, deltaX) * (180 / Math.PI);
17889
+ const snapIncrement = 15;
17890
+ const snappedAngle = Math.round(angle / snapIncrement) * snapIncrement;
17891
+ const snappedRadians = snappedAngle * (Math.PI / 180);
17892
+ return {
17893
+ x: fromX + Math.cos(snappedRadians) * distance,
17894
+ y: fromY + Math.sin(snappedRadians) * distance
17895
+ };
17896
+ }
17897
+ _setWidthHeight() {
17898
+ let skipReposition = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
17899
+ this.width = Math.abs(this.x2 - this.x1) || 1;
17900
+ this.height = Math.abs(this.y2 - this.y1) || 1;
17901
+ if (!skipReposition && !this._updatingEndpoints) {
17902
+ const {
17903
+ left,
17904
+ top,
17905
+ width,
17906
+ height
17907
+ } = makeBoundingBoxFromPoints([{
17908
+ x: this.x1,
17909
+ y: this.y1
17910
+ }, {
17911
+ x: this.x2,
17912
+ y: this.y2
17913
+ }]);
17914
+ this.setPositionByOrigin(new Point(left + width / 2, top + height / 2), CENTER, CENTER);
17915
+ }
17916
+ }
17702
17917
  _set(key, value) {
17918
+ const oldLeft = this.left;
17919
+ const oldTop = this.top;
17703
17920
  super._set(key, value);
17704
17921
  if (coordProps.includes(key)) {
17705
- // this doesn't make sense very much, since setting x1 when top or left
17706
- // are already set, is just going to show a strange result since the
17707
- // line will move way more than the developer expect.
17708
- // in fabric5 it worked only when the line didn't have extra transformations,
17709
- // in fabric6 too. With extra transform they behave bad in different ways.
17710
- // This needs probably a good rework or a tutorial if you have to create a dynamic line
17711
17922
  this._setWidthHeight();
17923
+ this.dirty = true;
17924
+ }
17925
+ if ((key === 'left' || key === 'top') && this.canvas && !this._updatingEndpoints) {
17926
+ const deltaX = this.left - oldLeft;
17927
+ const deltaY = this.top - oldTop;
17928
+ if (deltaX !== 0 || deltaY !== 0) {
17929
+ this._updatingEndpoints = true;
17930
+ this.x1 += deltaX;
17931
+ this.y1 += deltaY;
17932
+ this.x2 += deltaX;
17933
+ this.y2 += deltaY;
17934
+ this._updatingEndpoints = false;
17935
+ }
17712
17936
  }
17713
17937
  return this;
17714
17938
  }
17715
-
17716
- /**
17717
- * @private
17718
- * @param {CanvasRenderingContext2D} ctx Context to render on
17719
- */
17939
+ render(ctx) {
17940
+ if (this._useEndpointCoords) {
17941
+ this._renderDirectly(ctx);
17942
+ return;
17943
+ }
17944
+ super.render(ctx);
17945
+ }
17946
+ _renderDirectly(ctx) {
17947
+ var _this$canvas7, _this$stroke;
17948
+ if (!this.visible) return;
17949
+ ctx.save();
17950
+ const vpt = ((_this$canvas7 = this.canvas) === null || _this$canvas7 === void 0 ? void 0 : _this$canvas7.viewportTransform) || [1, 0, 0, 1, 0, 0];
17951
+ ctx.transform(vpt[0], vpt[1], vpt[2], vpt[3], vpt[4], vpt[5]);
17952
+ ctx.globalAlpha = this.opacity;
17953
+ ctx.strokeStyle = ((_this$stroke = this.stroke) === null || _this$stroke === void 0 ? void 0 : _this$stroke.toString()) || '#000';
17954
+ ctx.lineWidth = this.strokeWidth;
17955
+ ctx.lineCap = this.strokeLineCap || 'butt';
17956
+ ctx.beginPath();
17957
+ ctx.moveTo(this.x1, this.y1);
17958
+ ctx.lineTo(this.x2, this.y2);
17959
+ ctx.stroke();
17960
+ ctx.restore();
17961
+ }
17720
17962
  _render(ctx) {
17963
+ if (this._useEndpointCoords) return;
17721
17964
  ctx.beginPath();
17722
17965
  const p = this.calcLinePoints();
17723
17966
  ctx.moveTo(p.x1, p.y1);
17724
17967
  ctx.lineTo(p.x2, p.y2);
17725
17968
  ctx.lineWidth = this.strokeWidth;
17726
-
17727
- // TODO: test this
17728
- // make sure setting "fill" changes color of a line
17729
- // (by copying fillStyle to strokeStyle, since line is stroked, not filled)
17730
17969
  const origStrokeStyle = ctx.strokeStyle;
17731
17970
  if (isFiller(this.stroke)) {
17732
17971
  ctx.strokeStyle = this.stroke.toLive(ctx);
17733
- } else {
17734
- var _this$stroke;
17735
- ctx.strokeStyle = (_this$stroke = this.stroke) !== null && _this$stroke !== void 0 ? _this$stroke : ctx.fillStyle;
17736
17972
  }
17737
17973
  this.stroke && this._renderStroke(ctx);
17738
17974
  ctx.strokeStyle = origStrokeStyle;
17739
17975
  }
17740
-
17741
- /**
17742
- * This function is an helper for svg import. it returns the center of the object in the svg
17743
- * untransformed coordinates
17744
- * @private
17745
- * @return {Point} center point from element coordinates
17746
- */
17747
17976
  _findCenterFromElement() {
17748
17977
  return new Point((this.x1 + this.x2) / 2, (this.y1 + this.y2) / 2);
17749
17978
  }
17750
-
17751
- /**
17752
- * Returns object representation of an instance
17753
- * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
17754
- * @return {Object} object representation of an instance
17755
- */
17756
17979
  toObject() {
17757
17980
  let propertiesToInclude = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
17758
17981
  return {
@@ -17760,32 +17983,25 @@ class Line extends FabricObject {
17760
17983
  ...this.calcLinePoints()
17761
17984
  };
17762
17985
  }
17763
-
17764
- /*
17765
- * Calculate object dimensions from its properties
17766
- * @private
17767
- */
17768
17986
  _getNonTransformedDimensions() {
17769
17987
  const dim = super._getNonTransformedDimensions();
17770
- if (this.strokeLineCap === 'butt') {
17771
- if (this.width === 0) {
17772
- dim.y -= this.strokeWidth;
17773
- }
17774
- if (this.height === 0) {
17775
- dim.x -= this.strokeWidth;
17776
- }
17988
+ if (this.strokeLineCap === 'round') {
17989
+ dim.x += this.strokeWidth;
17990
+ dim.y += this.strokeWidth;
17777
17991
  }
17778
17992
  return dim;
17779
17993
  }
17780
-
17781
- /**
17782
- * Recalculates line points given width and height
17783
- * Those points are simply placed around the center,
17784
- * This is not useful outside internal render functions and svg output
17785
- * Is not meant to be for the developer.
17786
- * @private
17787
- */
17788
17994
  calcLinePoints() {
17995
+ if (this._updatingEndpoints) {
17996
+ const centerX = (this.x1 + this.x2) / 2;
17997
+ const centerY = (this.y1 + this.y2) / 2;
17998
+ return {
17999
+ x1: this.x1 - centerX,
18000
+ y1: this.y1 - centerY,
18001
+ x2: this.x2 - centerX,
18002
+ y2: this.y2 - centerY
18003
+ };
18004
+ }
17789
18005
  const {
17790
18006
  x1: _x1,
17791
18007
  x2: _x2,
@@ -17794,48 +18010,39 @@ class Line extends FabricObject {
17794
18010
  width,
17795
18011
  height
17796
18012
  } = this;
17797
- const xMult = _x1 <= _x2 ? -1 : 1,
17798
- yMult = _y1 <= _y2 ? -1 : 1,
17799
- x1 = xMult * width / 2,
17800
- y1 = yMult * height / 2,
17801
- x2 = xMult * -width / 2,
17802
- y2 = yMult * -height / 2;
18013
+ const xMult = _x1 <= _x2 ? -1 : 1;
18014
+ const yMult = _y1 <= _y2 ? -1 : 1;
17803
18015
  return {
17804
- x1,
17805
- x2,
17806
- y1,
17807
- y2
18016
+ x1: xMult * width / 2,
18017
+ y1: yMult * height / 2,
18018
+ x2: xMult * -width / 2,
18019
+ y2: yMult * -height / 2
17808
18020
  };
17809
18021
  }
17810
-
17811
- /* _FROM_SVG_START_ */
17812
-
17813
- /**
17814
- * Returns svg representation of an instance
17815
- * @return {Array} an array of strings with the specific svg representation
17816
- * of the instance
17817
- */
17818
18022
  _toSVG() {
17819
- const {
17820
- x1,
17821
- x2,
17822
- y1,
17823
- y2
17824
- } = this.calcLinePoints();
17825
- return ['<line ', 'COMMON_PARTS', `x1="${x1}" y1="${y1}" x2="${x2}" y2="${y2}" />\n`];
18023
+ if (this._useEndpointCoords) {
18024
+ // Use absolute coordinates to bypass all Fabric.js transforms
18025
+ 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`];
18026
+ } else {
18027
+ // Use standard calcLinePoints for legacy mode
18028
+ const {
18029
+ x1,
18030
+ x2,
18031
+ y1,
18032
+ y2
18033
+ } = this.calcLinePoints();
18034
+ return ['<line ', 'COMMON_PARTS', `x1="${x1}" y1="${y1}" x2="${x2}" y2="${y2}" />\n`];
18035
+ }
18036
+ }
18037
+ toSVG(reviver) {
18038
+ if (this._useEndpointCoords) {
18039
+ // Override toSVG to prevent Fabric.js from adding transform wrapper
18040
+ const markup = this._toSVG().join('');
18041
+ return reviver ? reviver(markup) : markup;
18042
+ }
18043
+ // Use default behavior for legacy mode
18044
+ return super.toSVG(reviver);
17826
18045
  }
17827
-
17828
- /**
17829
- * List of attribute names to account for when parsing SVG element (used by {@link Line.fromElement})
17830
- * @see http://www.w3.org/TR/SVG/shapes.html#LineElement
17831
- */
17832
-
17833
- /**
17834
- * Returns Line instance from an SVG element
17835
- * @param {HTMLElement} element Element to parse
17836
- * @param {Object} [options] Options object
17837
- * @param {Function} [callback] callback function invoked after parsing
17838
- */
17839
18046
  static async fromElement(element, options, cssRules) {
17840
18047
  const {
17841
18048
  x1 = 0,
@@ -17846,14 +18053,6 @@ class Line extends FabricObject {
17846
18053
  } = parseAttributes(element, this.ATTRIBUTE_NAMES, cssRules);
17847
18054
  return new this([x1, y1, x2, y2], parsedAttributes);
17848
18055
  }
17849
-
17850
- /* _FROM_SVG_END_ */
17851
-
17852
- /**
17853
- * Returns Line instance from an object representation
17854
- * @param {Object} object Object to create an instance from
17855
- * @returns {Promise<Line>}
17856
- */
17857
18056
  static fromObject(_ref) {
17858
18057
  let {
17859
18058
  x1,
@@ -17870,22 +18069,6 @@ class Line extends FabricObject {
17870
18069
  });
17871
18070
  }
17872
18071
  }
17873
- /**
17874
- * x value or first line edge
17875
- * @type number
17876
- */
17877
- /**
17878
- * y value or first line edge
17879
- * @type number
17880
- */
17881
- /**
17882
- * x value or second line edge
17883
- * @type number
17884
- */
17885
- /**
17886
- * y value or second line edge
17887
- * @type number
17888
- */
17889
18072
  _defineProperty(Line, "type", 'Line');
17890
18073
  _defineProperty(Line, "cacheProperties", [...cacheProperties, ...coordProps]);
17891
18074
  _defineProperty(Line, "ATTRIBUTE_NAMES", SHARED_ATTRIBUTES.concat(coordProps));