From e0cbfc3a2df49d572714fd5f05c63ecddd975661 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Sat, 11 Apr 2015 14:57:34 +0100 Subject: [PATCH] Added support for dashed pens. --- Perspex.Controls/Shapes/Shape.cs | 22 ++++++++++++++++++- Perspex.SceneGraph/Media/Pen.cs | 19 ++++++++++++---- .../Perspex.Direct2D1/Media/DrawingContext.cs | 15 ++++++++++--- .../Perspex.Direct2D1/PrimitiveExtensions.cs | 18 +++++++++++++++ 4 files changed, 66 insertions(+), 8 deletions(-) diff --git a/Perspex.Controls/Shapes/Shape.cs b/Perspex.Controls/Shapes/Shape.cs index 8125473cc2..3f296c6b00 100644 --- a/Perspex.Controls/Shapes/Shape.cs +++ b/Perspex.Controls/Shapes/Shape.cs @@ -7,6 +7,7 @@ namespace Perspex.Controls.Shapes { using System; + using Perspex.Collections; using Perspex.Controls; using Perspex.Media; @@ -21,6 +22,9 @@ namespace Perspex.Controls.Shapes public static readonly PerspexProperty StrokeProperty = PerspexProperty.Register("Stroke"); + public static readonly PerspexProperty> StrokeDashArrayProperty = + PerspexProperty.Register>("StrokeDashArray"); + public static readonly PerspexProperty StrokeThicknessProperty = PerspexProperty.Register("StrokeThickness"); @@ -28,6 +32,15 @@ namespace Perspex.Controls.Shapes private Geometry renderedGeometry; + static Shape() + { + Control.AffectsRender(FillProperty); + Control.AffectsMeasure(StretchProperty); + Control.AffectsRender(StrokeProperty); + Control.AffectsRender(StrokeDashArrayProperty); + Control.AffectsMeasure(StrokeThicknessProperty); + } + public abstract Geometry DefiningGeometry { get; @@ -68,6 +81,12 @@ namespace Perspex.Controls.Shapes set { this.SetValue(StrokeProperty, value); } } + public PerspexList StrokeDashArray + { + get { return this.GetValue(StrokeDashArrayProperty); } + set { this.SetValue(StrokeDashArrayProperty, value); } + } + public double StrokeThickness { get { return this.GetValue(StrokeThicknessProperty); } @@ -80,7 +99,8 @@ namespace Perspex.Controls.Shapes if (geometry != null) { - context.DrawGeometry(this.Fill, new Pen(this.Stroke, this.StrokeThickness), geometry); + var pen = new Pen(this.Stroke, this.StrokeThickness, this.StrokeDashArray); + context.DrawGeometry(this.Fill, pen, geometry); } } diff --git a/Perspex.SceneGraph/Media/Pen.cs b/Perspex.SceneGraph/Media/Pen.cs index 5e73c40334..46b46185d2 100644 --- a/Perspex.SceneGraph/Media/Pen.cs +++ b/Perspex.SceneGraph/Media/Pen.cs @@ -6,6 +6,8 @@ namespace Perspex.Media { + using System.Collections.Generic; + /// /// Describes how a stroke is drawn. /// @@ -16,10 +18,12 @@ namespace Perspex.Media /// /// The brush used to draw. /// The stroke thickness. - public Pen(Brush brush, double thickness) + /// The length of alternating dashes and gaps. + public Pen(Brush brush, double thickness, IReadOnlyList dashArray = null) { this.Brush = brush; this.Thickness = thickness; + this.DashArray = dashArray; } /// @@ -27,20 +31,27 @@ namespace Perspex.Media /// /// The stroke color. /// The stroke thickness. - public Pen(uint color, double thickness) + /// The length of alternating dashes and gaps. + public Pen(uint color, double thickness, IReadOnlyList dashArray = null) { this.Brush = new SolidColorBrush(color); this.Thickness = thickness; + this.DashArray = dashArray; } /// /// Gets the brush used to draw the stroke. /// - public Brush Brush { get; private set; } + public Brush Brush { get; } + + /// + /// Gets the length of alternating dashes and gaps. + /// + public IReadOnlyList DashArray { get; } /// /// Gets the stroke thickness. /// - public double Thickness { get; private set; } + public double Thickness { get; } } } diff --git a/Windows/Perspex.Direct2D1/Media/DrawingContext.cs b/Windows/Perspex.Direct2D1/Media/DrawingContext.cs index 2279dc6cd2..bbbc81266c 100644 --- a/Windows/Perspex.Direct2D1/Media/DrawingContext.cs +++ b/Windows/Perspex.Direct2D1/Media/DrawingContext.cs @@ -80,8 +80,14 @@ namespace Perspex.Direct2D1.Media if (pen != null) { using (var d2dBrush = pen.Brush.ToDirect2D(this.renderTarget)) + using (var d2dStroke = pen.ToDirect2DStrokeStyle(this.renderTarget)) { - this.renderTarget.DrawLine(p1.ToSharpDX(), p2.ToSharpDX(), d2dBrush); + this.renderTarget.DrawLine( + p1.ToSharpDX(), + p2.ToSharpDX(), + d2dBrush, + (float)pen.Thickness, + d2dStroke); } } } @@ -106,9 +112,10 @@ namespace Perspex.Direct2D1.Media if (pen != null) { using (var d2dBrush = pen.Brush.ToDirect2D(this.renderTarget)) + using (var d2dStroke = pen.ToDirect2DStrokeStyle(this.renderTarget)) { GeometryImpl impl = (GeometryImpl)geometry.PlatformImpl; - this.renderTarget.DrawGeometry(impl.Geometry, d2dBrush, (float)pen.Thickness); + this.renderTarget.DrawGeometry(impl.Geometry, d2dBrush, (float)pen.Thickness, d2dStroke); } } } @@ -121,11 +128,13 @@ namespace Perspex.Direct2D1.Media public void DrawRectange(Pen pen, Rect rect) { using (var brush = pen.Brush.ToDirect2D(this.renderTarget)) + using (var d2dStroke = pen.ToDirect2DStrokeStyle(this.renderTarget)) { this.renderTarget.DrawRectangle( rect.ToDirect2D(), brush, - (float)pen.Thickness); + (float)pen.Thickness, + d2dStroke); } } diff --git a/Windows/Perspex.Direct2D1/PrimitiveExtensions.cs b/Windows/Perspex.Direct2D1/PrimitiveExtensions.cs index 997cd51f0a..b7e43b6fe0 100644 --- a/Windows/Perspex.Direct2D1/PrimitiveExtensions.cs +++ b/Windows/Perspex.Direct2D1/PrimitiveExtensions.cs @@ -6,6 +6,7 @@ namespace Perspex.Direct2D1 { + using System.Linq; using SharpDX; using SharpDX.Direct2D1; @@ -51,6 +52,23 @@ namespace Perspex.Direct2D1 } } + public static StrokeStyle ToDirect2DStrokeStyle(this Perspex.Media.Pen pen, RenderTarget target) + { + if (pen.DashArray != null && pen.DashArray.Count > 0) + { + var properties = new StrokeStyleProperties + { + DashStyle = DashStyle.Custom, + }; + + return new StrokeStyle(target.Factory, properties, pen.DashArray.Select(x => (float)x).ToArray()); + } + else + { + return null; + } + } + /// /// Converts a Perspex to Direct2D. ///