Skip to content
14 changes: 10 additions & 4 deletions src/Controls/src/Core/Shapes/Shape.cs
Original file line number Diff line number Diff line change
Expand Up @@ -280,10 +280,16 @@ internal void TransformPathForBounds(PathF path, Graphics.Rect viewBounds)
// since default GetBoundsByFlattening(0.001) returns incorrect results for curves
RectF pathBounds = path.GetBoundsByFlattening(1);

viewBounds.X += StrokeThickness / 2;
viewBounds.Y += StrokeThickness / 2;
viewBounds.Width -= StrokeThickness;
viewBounds.Height -= StrokeThickness;
// For Line shapes with Stretch.None, don't adjust viewBounds for stroke thickness
// as this causes incorrect positioning. Lines should use exact coordinates.
bool isLineWithNoStretch = this is Shapes.Line && Aspect == Stretch.None;
if (!isLineWithNoStretch)
{
viewBounds.X += StrokeThickness / 2;
viewBounds.Y += StrokeThickness / 2;
viewBounds.Width -= StrokeThickness;
viewBounds.Height -= StrokeThickness;
}

Matrix3x2 transform;

Expand Down
56 changes: 56 additions & 0 deletions src/Controls/tests/Core.UnitTests/LineTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.Maui.Controls.Shapes;
using Microsoft.Maui.Graphics;
using Xunit;

namespace Microsoft.Maui.Controls.Core.UnitTests
Expand Down Expand Up @@ -32,5 +33,60 @@ public void YPointCanBeSetFromStyle()
line.SetValue(Line.Y2Property, 10.0, new SetterSpecificity(SetterSpecificity.StyleImplicit, 0, 0, 0));
Assert.Equal(10.0, line.Y2);
}

[Fact]
public void LinePathCoordinatesRemainExactWithThickStroke()
{
// Test for the issue where thick strokes cause incorrect coordinate positioning
var line = new Line()
{
X1 = 0,
Y1 = 0,
X2 = 100,
Y2 = 100,
StrokeThickness = 10
};

var path = line.GetPath();

// The path should maintain exact coordinates regardless of stroke thickness
Assert.Equal(0f, path.GetPointAtIndex(0).X);
Assert.Equal(0f, path.GetPointAtIndex(0).Y);
Assert.Equal(100f, path.GetPointAtIndex(1).X);
Assert.Equal(100f, path.GetPointAtIndex(1).Y);
}

[Fact]
public void LinePathForBoundsWithThickStrokePreservesCoordinates()
{
// Test that PathForBounds doesn't shift line coordinates incorrectly with thick strokes
var line = new Line()
{
X1 = 200,
Y1 = 0,
X2 = 100,
Y2 = 100,
StrokeThickness = 10
};

var bounds = new RectF(0, 0, 200, 200);
var path = line.PathForBounds(bounds);

// For lines with Stretch.None (default), coordinates should be preserved
// The issue manifests as the line being shifted due to stroke thickness adjustment
var points = new System.Collections.Generic.List<PointF>();
for (int i = 0; i < path.GetSubPathPointCount(0); i++)
{
points.Add(path.GetPointAtIndex(i));
}

// The line should go from the specified coordinates
// These coordinates should not be affected by stroke thickness bounds adjustment
Assert.Equal(2, points.Count); // MoveTo and LineTo
Assert.Equal(200f, points[0].X, precision: 1);
Assert.Equal(0f, points[0].Y, precision: 1);
Assert.Equal(100f, points[1].X, precision: 1);
Assert.Equal(100f, points[1].Y, precision: 1);
}
}
}