Browse Source

Fixed Line rendering (PointPair instead of Rect) and added unit-tests.

Ivan Kochurkin 10 years ago
parent
commit
e07d085ef5

+ 18 - 6
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<PointPair> PointPairProperty =
+            PerspexProperty.Register<Line, PointPair>("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;

+ 37 - 11
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
     /// </summary>
     public class LineGeometry : Geometry
     {
-        private Point _startPoint;
-        private Point _endPoint;
+        private PointPair _pointPair;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="LineGeometry"/> class.
         /// </summary>
-        /// <param name="startPoint">The start point.</param>
-        /// <param name="endPoint">The end point.</param>
-        public LineGeometry(Point startPoint, Point endPoint)
+        /// <param name="pointPair">The pointPair.</param>
+        public LineGeometry(PointPair pointPair)
         {
-            _startPoint = startPoint;
-            _endPoint = endPoint;
+            _pointPair = pointPair;
             IPlatformRenderInterface factory = PerspexLocator.Current.GetService<IPlatformRenderInterface>();
             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
         }
 
         /// <inheritdoc/>
-        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);
+            }
+        }
 
         /// <inheritdoc/>
         public override Geometry Clone()
         {
-            return new LineGeometry(Bounds.TopLeft, Bounds.BottomRight);
+            return new LineGeometry(new PointPair(_pointPair.P1, _pointPair.P2));
         }
     }
 }

+ 48 - 0
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
+{
+    /// <summary>
+    /// Defines a PointPair.
+    /// </summary>
+    public class PointPair
+    {
+        /// <summary>
+        /// The first point.
+        /// </summary>
+        public Point P1 { get; set; }
+
+        /// <summary>
+        /// The second point.
+        /// </summary>
+        public Point P2 { get; set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="PointPair"/> structure.
+        /// </summary>
+        /// <param name="p1">The first point.</param>
+        /// <param name="p2">The second point.</param>
+        public PointPair(Point p1, Point p2)
+        {
+            P1 = p1;
+            P2 = p2;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="PointPair"/> structure.
+        /// </summary>
+        /// <param name="x1">The x position of first point.</param>
+        /// <param name="y1">The y position of first point.</param>
+        /// <param name="x2">The x position of second point.</param>
+        /// <param name="y2">The y position of second point.</param>
+        public PointPair(double x1, double y1, double x2, double y2)
+        {
+            P1 = new Point(x1, y1);
+            P2 = new Point(x2, y2);
+        }
+    }
+}

+ 39 - 1
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)
                 }
             };
 

BIN
tests/TestFiles/Cairo/Shapes/Line/Line_1px_Stroke.expected.png


BIN
tests/TestFiles/Cairo/Shapes/Line/Line_1px_Stroke_Reversed.expected.png


BIN
tests/TestFiles/Cairo/Shapes/Line/Line_1px_Stroke_Vertical.expected.png


BIN
tests/TestFiles/Direct2D1/Shapes/Line/Line_1px_Stroke.expected.png


BIN
tests/TestFiles/Direct2D1/Shapes/Line/Line_1px_Stroke_Reversed.expected.png


BIN
tests/TestFiles/Direct2D1/Shapes/Line/Line_1px_Stroke_Vertical.expected.png


BIN
tests/TestFiles/Skia/Shapes/Line/Line_1px_Stroke.expected.png


BIN
tests/TestFiles/Skia/Shapes/Line/Line_1px_Stroke_Reversed.expected.png


BIN
tests/TestFiles/Skia/Shapes/Line/Line_1px_Stroke_Vertical.expected.png