diff --git a/src/Perspex.Controls/Shapes/Line.cs b/src/Perspex.Controls/Shapes/Line.cs index 785ea7bbd1..f71cb216e4 100644 --- a/src/Perspex.Controls/Shapes/Line.cs +++ b/src/Perspex.Controls/Shapes/Line.cs @@ -9,19 +9,31 @@ namespace Perspex.Controls.Shapes { public class Line : Shape { - private Geometry _geometry; + public static readonly PerspexProperty PointPairProperty = + PerspexProperty.Register("PointPair"); - private Size _geometrySize; + private LineGeometry _geometry; + private PointPair _pointPair; + + public Line() + { + StrokeThickness = 1; + } + + public PointPair PointPair + { + get { return GetValue(PointPairProperty); } + set { SetValue(PointPairProperty, value); } + } public override Geometry DefiningGeometry { get { - if (_geometry == null || _geometrySize != Bounds.Size) + if (_geometry == null || _pointPair == null || PointPair.P1 != _pointPair.P1 || PointPair.P2 != _pointPair.P2) { - var rect = new Rect(Bounds.Size).Deflate(StrokeThickness); - _geometry = new LineGeometry(rect.TopLeft, rect.BottomRight); - _geometrySize = Bounds.Size; + _pointPair = PointPair; + _geometry = new LineGeometry(_pointPair); } return _geometry; diff --git a/src/Perspex.SceneGraph/Media/LineGeometry.cs b/src/Perspex.SceneGraph/Media/LineGeometry.cs index 196fdc40eb..6efc5c9ead 100644 --- a/src/Perspex.SceneGraph/Media/LineGeometry.cs +++ b/src/Perspex.SceneGraph/Media/LineGeometry.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using Perspex.Platform; +using System; namespace Perspex.Media { @@ -10,25 +11,22 @@ namespace Perspex.Media /// public class LineGeometry : Geometry { - private Point _startPoint; - private Point _endPoint; + private PointPair _pointPair; /// /// Initializes a new instance of the class. /// - /// The start point. - /// The end point. - public LineGeometry(Point startPoint, Point endPoint) + /// The pointPair. + public LineGeometry(PointPair pointPair) { - _startPoint = startPoint; - _endPoint = endPoint; + _pointPair = pointPair; IPlatformRenderInterface factory = PerspexLocator.Current.GetService(); IStreamGeometryImpl impl = factory.CreateStreamGeometry(); using (IStreamGeometryContextImpl context = impl.Open()) { - context.BeginFigure(startPoint, false); - context.LineTo(endPoint); + context.BeginFigure(_pointPair.P1, false); + context.LineTo(_pointPair.P2); context.EndFigure(false); } @@ -36,12 +34,40 @@ namespace Perspex.Media } /// - public override Rect Bounds => new Rect(_startPoint, _endPoint); + public override Rect Bounds + { + get + { + double xMin, yMin, xMax, yMax; + if (_pointPair.P1.X <= _pointPair.P2.X) + { + xMin = _pointPair.P1.X; + xMax = _pointPair.P2.X; + } + else + { + xMin = _pointPair.P2.X; + xMax = _pointPair.P1.X; + } + if (_pointPair.P1.Y <= _pointPair.P2.Y) + { + yMin = _pointPair.P1.Y; + yMax = _pointPair.P2.Y; + } + else + { + yMin = _pointPair.P2.Y; + yMax = _pointPair.P1.Y; + } + + return new Rect(xMin, yMin, xMax - xMin, yMax - yMin); + } + } /// public override Geometry Clone() { - return new LineGeometry(Bounds.TopLeft, Bounds.BottomRight); + return new LineGeometry(new PointPair(_pointPair.P1, _pointPair.P2)); } } } diff --git a/src/Perspex.SceneGraph/PointPair.cs b/src/Perspex.SceneGraph/PointPair.cs new file mode 100644 index 0000000000..cc036f13f8 --- /dev/null +++ b/src/Perspex.SceneGraph/PointPair.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Perspex +{ + /// + /// Defines a PointPair. + /// + public class PointPair + { + /// + /// The first point. + /// + public Point P1 { get; set; } + + /// + /// The second point. + /// + public Point P2 { get; set; } + + /// + /// Initializes a new instance of the structure. + /// + /// The first point. + /// The second point. + public PointPair(Point p1, Point p2) + { + P1 = p1; + P2 = p2; + } + + /// + /// Initializes a new instance of the structure. + /// + /// The x position of first point. + /// The y position of first point. + /// The x position of second point. + /// The y position of second point. + public PointPair(double x1, double y1, double x2, double y2) + { + P1 = new Point(x1, y1); + P2 = new Point(x2, y2); + } + } +} diff --git a/tests/Perspex.RenderTests/Shapes/LineTests.cs b/tests/Perspex.RenderTests/Shapes/LineTests.cs index 80eb7c75ca..2e836a898d 100644 --- a/tests/Perspex.RenderTests/Shapes/LineTests.cs +++ b/tests/Perspex.RenderTests/Shapes/LineTests.cs @@ -26,13 +26,51 @@ namespace Perspex.Direct2D1.RenderTests.Shapes { Decorator target = new Decorator { - Padding = new Thickness(8), Width = 200, Height = 200, Child = new Line { Stroke = Brushes.Black, StrokeThickness = 1, + PointPair = new PointPair(0, 0, 200, 200) + } + }; + + RenderToFile(target); + CompareImages(); + } + + [Fact] + public void Line_1px_Stroke_Reversed() + { + Decorator target = new Decorator + { + Width = 200, + Height = 200, + Child = new Line + { + Stroke = Brushes.Black, + StrokeThickness = 1, + PointPair = new PointPair(200, 0, 0, 200) + } + }; + + RenderToFile(target); + CompareImages(); + } + + [Fact] + public void Line_1px_Stroke_Vertical() + { + Decorator target = new Decorator + { + Width = 200, + Height = 200, + Child = new Line + { + Stroke = Brushes.Black, + StrokeThickness = 1, + PointPair = new PointPair(100, 200, 100, 0) } }; diff --git a/tests/TestFiles/Cairo/Shapes/Line/Line_1px_Stroke.expected.png b/tests/TestFiles/Cairo/Shapes/Line/Line_1px_Stroke.expected.png index 18ade2da0f..f0a6a9b109 100644 Binary files a/tests/TestFiles/Cairo/Shapes/Line/Line_1px_Stroke.expected.png and b/tests/TestFiles/Cairo/Shapes/Line/Line_1px_Stroke.expected.png differ diff --git a/tests/TestFiles/Cairo/Shapes/Line/Line_1px_Stroke_Reversed.expected.png b/tests/TestFiles/Cairo/Shapes/Line/Line_1px_Stroke_Reversed.expected.png new file mode 100644 index 0000000000..9ed7e713a9 Binary files /dev/null and b/tests/TestFiles/Cairo/Shapes/Line/Line_1px_Stroke_Reversed.expected.png differ diff --git a/tests/TestFiles/Cairo/Shapes/Line/Line_1px_Stroke_Vertical.expected.png b/tests/TestFiles/Cairo/Shapes/Line/Line_1px_Stroke_Vertical.expected.png new file mode 100644 index 0000000000..845961351c Binary files /dev/null and b/tests/TestFiles/Cairo/Shapes/Line/Line_1px_Stroke_Vertical.expected.png differ diff --git a/tests/TestFiles/Direct2D1/Shapes/Line/Line_1px_Stroke.expected.png b/tests/TestFiles/Direct2D1/Shapes/Line/Line_1px_Stroke.expected.png index 18ade2da0f..f0a6a9b109 100644 Binary files a/tests/TestFiles/Direct2D1/Shapes/Line/Line_1px_Stroke.expected.png and b/tests/TestFiles/Direct2D1/Shapes/Line/Line_1px_Stroke.expected.png differ diff --git a/tests/TestFiles/Direct2D1/Shapes/Line/Line_1px_Stroke_Reversed.expected.png b/tests/TestFiles/Direct2D1/Shapes/Line/Line_1px_Stroke_Reversed.expected.png new file mode 100644 index 0000000000..9ed7e713a9 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Shapes/Line/Line_1px_Stroke_Reversed.expected.png differ diff --git a/tests/TestFiles/Direct2D1/Shapes/Line/Line_1px_Stroke_Vertical.expected.png b/tests/TestFiles/Direct2D1/Shapes/Line/Line_1px_Stroke_Vertical.expected.png new file mode 100644 index 0000000000..845961351c Binary files /dev/null and b/tests/TestFiles/Direct2D1/Shapes/Line/Line_1px_Stroke_Vertical.expected.png differ diff --git a/tests/TestFiles/Skia/Shapes/Line/Line_1px_Stroke.expected.png b/tests/TestFiles/Skia/Shapes/Line/Line_1px_Stroke.expected.png index 18ade2da0f..f0a6a9b109 100644 Binary files a/tests/TestFiles/Skia/Shapes/Line/Line_1px_Stroke.expected.png and b/tests/TestFiles/Skia/Shapes/Line/Line_1px_Stroke.expected.png differ diff --git a/tests/TestFiles/Skia/Shapes/Line/Line_1px_Stroke_Reversed.expected.png b/tests/TestFiles/Skia/Shapes/Line/Line_1px_Stroke_Reversed.expected.png new file mode 100644 index 0000000000..9ed7e713a9 Binary files /dev/null and b/tests/TestFiles/Skia/Shapes/Line/Line_1px_Stroke_Reversed.expected.png differ diff --git a/tests/TestFiles/Skia/Shapes/Line/Line_1px_Stroke_Vertical.expected.png b/tests/TestFiles/Skia/Shapes/Line/Line_1px_Stroke_Vertical.expected.png new file mode 100644 index 0000000000..845961351c Binary files /dev/null and b/tests/TestFiles/Skia/Shapes/Line/Line_1px_Stroke_Vertical.expected.png differ