From e07d085ef51505e7d7d6d7fc6feccbfd9047dd30 Mon Sep 17 00:00:00 2001 From: Ivan Kochurkin Date: Mon, 25 Jan 2016 01:02:27 +0300 Subject: [PATCH] Fixed Line rendering (PointPair instead of Rect) and added unit-tests. --- src/Perspex.Controls/Shapes/Line.cs | 24 ++++++--- src/Perspex.SceneGraph/Media/LineGeometry.cs | 48 ++++++++++++++---- src/Perspex.SceneGraph/PointPair.cs | 48 ++++++++++++++++++ tests/Perspex.RenderTests/Shapes/LineTests.cs | 40 ++++++++++++++- .../Shapes/Line/Line_1px_Stroke.expected.png | Bin 618 -> 624 bytes .../Line_1px_Stroke_Reversed.expected.png | Bin 0 -> 629 bytes .../Line_1px_Stroke_Vertical.expected.png | Bin 0 -> 621 bytes .../Shapes/Line/Line_1px_Stroke.expected.png | Bin 618 -> 624 bytes .../Line_1px_Stroke_Reversed.expected.png | Bin 0 -> 629 bytes .../Line_1px_Stroke_Vertical.expected.png | Bin 0 -> 621 bytes .../Shapes/Line/Line_1px_Stroke.expected.png | Bin 618 -> 624 bytes .../Line_1px_Stroke_Reversed.expected.png | Bin 0 -> 629 bytes .../Line_1px_Stroke_Vertical.expected.png | Bin 0 -> 621 bytes 13 files changed, 142 insertions(+), 18 deletions(-) create mode 100644 src/Perspex.SceneGraph/PointPair.cs create mode 100644 tests/TestFiles/Cairo/Shapes/Line/Line_1px_Stroke_Reversed.expected.png create mode 100644 tests/TestFiles/Cairo/Shapes/Line/Line_1px_Stroke_Vertical.expected.png create mode 100644 tests/TestFiles/Direct2D1/Shapes/Line/Line_1px_Stroke_Reversed.expected.png create mode 100644 tests/TestFiles/Direct2D1/Shapes/Line/Line_1px_Stroke_Vertical.expected.png create mode 100644 tests/TestFiles/Skia/Shapes/Line/Line_1px_Stroke_Reversed.expected.png create mode 100644 tests/TestFiles/Skia/Shapes/Line/Line_1px_Stroke_Vertical.expected.png 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 18ade2da0f3d2f0e70679fdbcc139ddfc43265a6..f0a6a9b10984cd1276deb34e741a0a9ba815a51b 100644 GIT binary patch literal 624 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yF%}28J29*~C-V}>VM%xNb!1@J z*w6hZk(GggNy^j3F{C2y?PW(!215asgB;!U+8YaJmp{1WAj;Fz829+hH`@cRk0}cM oP!!@&YE&2{Mno70AGeZsk`ufzBV)xvV5(v8boFyt=akR{0E2FQp#T5? literal 618 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yF%}28J29*~C-V}>VM%xNb!1@J z*w6hZk(GggNyO8|F{C2y?d6TUha5y$4^EyFFok;&PnPOJ-gCz|CmnrO;a2slob?S* zD-iq$K3!P9^Zeas^M3RH*mQ1hANL#qPL_!dqr{L7gBIPsVM%xNb!1@J z*w6hZk(GggN#4`NF{C2y?d6M{4Gui42Sw8Uuf5UM#qqr`o7Gt0lhh5yZGFGbl{2l@ u?|aV7UFaad&N51jgfKY3UwGi!8CEAb!3zP#lN^9ahr!d;&t;ucLK6V^2zq(| literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..845961351cca646869f1d7ba644262407a61ac98 GIT binary patch literal 621 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yF%}28J29*~C-V}>VM%xNb!1@J z*w6hZk(GggN!-)LF{C2y?d6TU42lBG2Zg8Bzf@`YbBx7!(o?Roic{ssl&@7ja8eLp jVR9TLMo1X!Pcw@yXX;<`K5s2B$uM}j`njxgN@xNAErwO? literal 0 HcmV?d00001 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 18ade2da0f3d2f0e70679fdbcc139ddfc43265a6..f0a6a9b10984cd1276deb34e741a0a9ba815a51b 100644 GIT binary patch literal 624 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yF%}28J29*~C-V}>VM%xNb!1@J z*w6hZk(GggNy^j3F{C2y?PW(!215asgB;!U+8YaJmp{1WAj;Fz829+hH`@cRk0}cM oP!!@&YE&2{Mno70AGeZsk`ufzBV)xvV5(v8boFyt=akR{0E2FQp#T5? literal 618 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yF%}28J29*~C-V}>VM%xNb!1@J z*w6hZk(GggNyO8|F{C2y?d6TUha5y$4^EyFFok;&PnPOJ-gCz|CmnrO;a2slob?S* zD-iq$K3!P9^Zeas^M3RH*mQ1hANL#qPL_!dqr{L7gBIPsVM%xNb!1@J z*w6hZk(GggN#4`NF{C2y?d6M{4Gui42Sw8Uuf5UM#qqr`o7Gt0lhh5yZGFGbl{2l@ u?|aV7UFaad&N51jgfKY3UwGi!8CEAb!3zP#lN^9ahr!d;&t;ucLK6V^2zq(| literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..845961351cca646869f1d7ba644262407a61ac98 GIT binary patch literal 621 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yF%}28J29*~C-V}>VM%xNb!1@J z*w6hZk(GggN!-)LF{C2y?d6TU42lBG2Zg8Bzf@`YbBx7!(o?Roic{ssl&@7ja8eLp jVR9TLMo1X!Pcw@yXX;<`K5s2B$uM}j`njxgN@xNAErwO? literal 0 HcmV?d00001 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 18ade2da0f3d2f0e70679fdbcc139ddfc43265a6..f0a6a9b10984cd1276deb34e741a0a9ba815a51b 100644 GIT binary patch literal 624 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yF%}28J29*~C-V}>VM%xNb!1@J z*w6hZk(GggNy^j3F{C2y?PW(!215asgB;!U+8YaJmp{1WAj;Fz829+hH`@cRk0}cM oP!!@&YE&2{Mno70AGeZsk`ufzBV)xvV5(v8boFyt=akR{0E2FQp#T5? literal 618 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yF%}28J29*~C-V}>VM%xNb!1@J z*w6hZk(GggNyO8|F{C2y?d6TUha5y$4^EyFFok;&PnPOJ-gCz|CmnrO;a2slob?S* zD-iq$K3!P9^Zeas^M3RH*mQ1hANL#qPL_!dqr{L7gBIPsVM%xNb!1@J z*w6hZk(GggN#4`NF{C2y?d6M{4Gui42Sw8Uuf5UM#qqr`o7Gt0lhh5yZGFGbl{2l@ u?|aV7UFaad&N51jgfKY3UwGi!8CEAb!3zP#lN^9ahr!d;&t;ucLK6V^2zq(| literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..845961351cca646869f1d7ba644262407a61ac98 GIT binary patch literal 621 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yF%}28J29*~C-V}>VM%xNb!1@J z*w6hZk(GggN!-)LF{C2y?d6TU42lBG2Zg8Bzf@`YbBx7!(o?Roic{ssl&@7ja8eLp jVR9TLMo1X!Pcw@yXX;<`K5s2B$uM}j`njxgN@xNAErwO? literal 0 HcmV?d00001