diff --git a/samples/TestApplicationShared/MainWindow.cs b/samples/TestApplicationShared/MainWindow.cs index 6a412a95b5..02edd23634 100644 --- a/samples/TestApplicationShared/MainWindow.cs +++ b/samples/TestApplicationShared/MainWindow.cs @@ -688,6 +688,15 @@ namespace TestApplication [Canvas.LeftProperty] = 130, [Canvas.TopProperty] = 79, }, + new Line + { + Width = 90, + Height = 70, + Stroke = Brushes.Red, + StrokeThickness = 2, + [Canvas.LeftProperty] = 30, + [Canvas.TopProperty] = 120 + } } }, } diff --git a/src/Perspex.Controls/Perspex.Controls.csproj b/src/Perspex.Controls/Perspex.Controls.csproj index a99b3fbbfd..394fdccd2d 100644 --- a/src/Perspex.Controls/Perspex.Controls.csproj +++ b/src/Perspex.Controls/Perspex.Controls.csproj @@ -47,6 +47,7 @@ + diff --git a/src/Perspex.Controls/Shapes/Line.cs b/src/Perspex.Controls/Shapes/Line.cs new file mode 100644 index 0000000000..785ea7bbd1 --- /dev/null +++ b/src/Perspex.Controls/Shapes/Line.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Perspex.Media; + +namespace Perspex.Controls.Shapes +{ + public class Line : Shape + { + private Geometry _geometry; + + private Size _geometrySize; + + public override Geometry DefiningGeometry + { + get + { + if (_geometry == null || _geometrySize != Bounds.Size) + { + var rect = new Rect(Bounds.Size).Deflate(StrokeThickness); + _geometry = new LineGeometry(rect.TopLeft, rect.BottomRight); + _geometrySize = Bounds.Size; + } + + return _geometry; + } + } + + protected override Size MeasureOverride(Size availableSize) + { + return new Size(StrokeThickness, StrokeThickness); + } + } +} diff --git a/src/Perspex.SceneGraph/Media/LineGeometry.cs b/src/Perspex.SceneGraph/Media/LineGeometry.cs new file mode 100644 index 0000000000..fb5219e82e --- /dev/null +++ b/src/Perspex.SceneGraph/Media/LineGeometry.cs @@ -0,0 +1,42 @@ +// Copyright (c) The Perspex Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using Perspex.Platform; + +namespace Perspex.Media +{ + /// + /// Represents the geometry of a line. + /// + public class LineGeometry : Geometry + { + /// + /// Initializes a new instance of the class. + /// + /// The start point. + /// The end point. + public LineGeometry(Point startPoint, Point endPoint) + { + IPlatformRenderInterface factory = PerspexLocator.Current.GetService(); + IStreamGeometryImpl impl = factory.CreateStreamGeometry(); + + using (IStreamGeometryContextImpl context = impl.Open()) + { + context.BeginFigure(startPoint, true); + context.LineTo(endPoint); + context.EndFigure(true); + } + + PlatformImpl = impl; + } + + /// + public override Rect Bounds => PlatformImpl.Bounds; + + /// + public override Geometry Clone() + { + return new LineGeometry(Bounds.TopLeft, Bounds.BottomRight); + } + } +} diff --git a/src/Perspex.SceneGraph/Perspex.SceneGraph.csproj b/src/Perspex.SceneGraph/Perspex.SceneGraph.csproj index 2121be7bfc..ac08406268 100644 --- a/src/Perspex.SceneGraph/Perspex.SceneGraph.csproj +++ b/src/Perspex.SceneGraph/Perspex.SceneGraph.csproj @@ -70,6 +70,7 @@ + diff --git a/tests/Perspex.RenderTests/Perspex.Direct2D1.RenderTests.csproj b/tests/Perspex.RenderTests/Perspex.Direct2D1.RenderTests.csproj index eb948aec81..2abf92fdb5 100644 --- a/tests/Perspex.RenderTests/Perspex.Direct2D1.RenderTests.csproj +++ b/tests/Perspex.RenderTests/Perspex.Direct2D1.RenderTests.csproj @@ -76,6 +76,7 @@ + diff --git a/tests/Perspex.RenderTests/Shapes/LineTests.cs b/tests/Perspex.RenderTests/Shapes/LineTests.cs new file mode 100644 index 0000000000..bc5eb36dbf --- /dev/null +++ b/tests/Perspex.RenderTests/Shapes/LineTests.cs @@ -0,0 +1,43 @@ +// Copyright (c) The Perspex Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using Perspex.Controls; +using Perspex.Controls.Shapes; +using Perspex.Media; +using Xunit; + +#if PERSPEX_CAIRO +namespace Perspex.Cairo.RenderTests.Shapes +#elif PERSPEX_SKIA +namespace Perspex.Skia.RenderTests +#else +namespace Perspex.Direct2D1.RenderTests.Shapes +#endif +{ + public class LineTests : TestBase + { + public LineTests() + : base(@"Shapes\Line") + { + } + + [Fact] + public void Circle_1px_Stroke() + { + Decorator target = new Decorator + { + Padding = new Thickness(8), + Width = 200, + Height = 200, + Child = new Line + { + Stroke = Brushes.Black, + StrokeThickness = 1, + } + }; + + RenderToFile(target); + CompareImages(); + } + } +} diff --git a/tests/TestFiles/Direct2D1/Shapes/Line/Circle_1px_Stroke.expected.png b/tests/TestFiles/Direct2D1/Shapes/Line/Circle_1px_Stroke.expected.png new file mode 100644 index 0000000000..539d27fdd3 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Shapes/Line/Circle_1px_Stroke.expected.png differ