diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/EllipseGeometry.cs b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/EllipseGeometry.cs index b67934e4b30..0329104e024 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/EllipseGeometry.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/EllipseGeometry.cs @@ -2,25 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; using MS.Internal; -using System.ComponentModel; -using System.ComponentModel.Design.Serialization; -using System.Reflection; -using System.Collections; -using System.Text; -using System.Globalization; -using System.Windows.Media; using System.Windows.Media.Composition; -using System.Windows; -using System.Text.RegularExpressions; -using System.Windows.Media.Animation; -using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Security; -using SR=MS.Internal.PresentationCore.SR; + +using SR = MS.Internal.PresentationCore.SR; namespace System.Windows.Media { @@ -34,9 +19,7 @@ public sealed partial class EllipseGeometry : Geometry /// /// /// - public EllipseGeometry() - { - } + public EllipseGeometry() { } /// /// Constructor - sets the ellipse to the paramters with the given transformation @@ -45,7 +28,7 @@ public EllipseGeometry(Rect rect) { if (rect.IsEmpty) { - throw new System.ArgumentException(SR.Format(SR.Rect_Empty, "rect")); + throw new ArgumentException(SR.Format(SR.Rect_Empty, nameof(rect))); } RadiusX = (rect.Right - rect.X) * (1.0 / 2.0); @@ -56,10 +39,7 @@ public EllipseGeometry(Rect rect) /// /// Constructor - sets the ellipse to the parameters /// - public EllipseGeometry( - Point center, - double radiusX, - double radiusY) + public EllipseGeometry(Point center, double radiusX, double radiusY) { Center = center; RadiusX = radiusX; @@ -69,11 +49,7 @@ public EllipseGeometry( /// /// Constructor - sets the ellipse to the parameters /// - public EllipseGeometry( - Point center, - double radiusX, - double radiusY, - Transform transform) : this(center, radiusX, radiusY) + public EllipseGeometry(Point center, double radiusX, double radiusY, Transform transform) : this(center, radiusX, radiusY) { Transform = transform; } @@ -96,14 +72,13 @@ public override Rect Bounds if (transform == null || transform.IsIdentity) { Point currentCenter = Center; - Double currentRadiusX = RadiusX; - Double currentRadiusY = RadiusY; - - boundsRect = new Rect( - currentCenter.X - Math.Abs(currentRadiusX), - currentCenter.Y - Math.Abs(currentRadiusY), - 2.0 * Math.Abs(currentRadiusX), - 2.0 * Math.Abs(currentRadiusY)); + double currentRadiusX = RadiusX; + double currentRadiusY = RadiusY; + + boundsRect = new Rect(currentCenter.X - Math.Abs(currentRadiusX), + currentCenter.Y - Math.Abs(currentRadiusY), + 2.0 * Math.Abs(currentRadiusX), + 2.0 * Math.Abs(currentRadiusY)); } else { @@ -114,9 +89,7 @@ public override Rect Bounds // it's easier to let unmanaged code do the work for us. // - Matrix geometryMatrix; - - Transform.GetTransformValue(transform, out geometryMatrix); + Transform.GetTransformValue(transform, out Matrix geometryMatrix); boundsRect = EllipseGeometry.GetBoundsHelper( null /* no pen */, @@ -139,87 +112,46 @@ public override Rect Bounds /// internal override Rect GetBoundsInternal(Pen pen, Matrix matrix, double tolerance, ToleranceType type) { - Matrix geometryMatrix; - - Transform.GetTransformValue(Transform, out geometryMatrix); - - return EllipseGeometry.GetBoundsHelper( - pen, - matrix, - Center, - RadiusX, - RadiusY, - geometryMatrix, - tolerance, - type); + Transform.GetTransformValue(Transform, out Matrix geometryMatrix); + + return EllipseGeometry.GetBoundsHelper(pen, matrix, Center, RadiusX, RadiusY, geometryMatrix, tolerance, type); } - internal static Rect GetBoundsHelper(Pen pen, Matrix worldMatrix, Point center, double radiusX, double radiusY, - Matrix geometryMatrix, double tolerance, ToleranceType type) + internal static unsafe Rect GetBoundsHelper(Pen pen, Matrix worldMatrix, Point center, double radiusX, double radiusY, + Matrix geometryMatrix, double tolerance, ToleranceType type) { - Rect rect; - - if ( (pen == null || pen.DoesNotContainGaps) && - worldMatrix.IsIdentity && geometryMatrix.IsIdentity) + if ((pen is null || pen.DoesNotContainGaps) && worldMatrix.IsIdentity && geometryMatrix.IsIdentity) { - double strokeThickness = 0.0; - - if (Pen.ContributesToBounds(pen)) - { - strokeThickness = Math.Abs(pen.Thickness); - } + double strokeThickness = Pen.ContributesToBounds(pen) ? Math.Abs(pen.Thickness) : 0.0; - rect = new Rect( - center.X - Math.Abs(radiusX)-0.5*strokeThickness, - center.Y - Math.Abs(radiusY)-0.5*strokeThickness, - 2.0 * Math.Abs(radiusX)+strokeThickness, - 2.0 * Math.Abs(radiusY)+strokeThickness); + return new Rect(center.X - Math.Abs(radiusX) - 0.5 * strokeThickness, + center.Y - Math.Abs(radiusY) - 0.5 * strokeThickness, + 2.0 * Math.Abs(radiusX) + strokeThickness, + 2.0 * Math.Abs(radiusY) + strokeThickness); } else { - unsafe + Point* ptrPoints = stackalloc Point[(int)PointCount]; + EllipseGeometry.InitializePointList(ptrPoints, (int)PointCount, center, radiusX, radiusY); + + fixed (byte* ptrTypes = RoundedPathTypes) // Merely retrieves the pointer to static PE data, no actual pinning occurs { - Point* pPoints = stackalloc Point[(int)c_pointCount]; - EllipseGeometry.GetPointList(pPoints, c_pointCount, center, radiusX, radiusY); - - fixed (byte* pTypes = RoundedPathTypes) //Merely retrieves the pointer to static PE data, no actual pinning occurs - { - rect = Geometry.GetBoundsHelper( - pen, - &worldMatrix, - pPoints, - pTypes, - c_pointCount, - c_segmentCount, - &geometryMatrix, - tolerance, - type, - false); // skip hollows - meaningless here, this is never a hollow - } + return Geometry.GetBoundsHelper(pen, &worldMatrix, ptrPoints, ptrTypes, PointCount, SegmentCount, &geometryMatrix, + tolerance, type, false); // skip hollows - meaningless here, this is never a hollow } } - - return rect; } internal override bool ContainsInternal(Pen pen, Point hitPoint, double tolerance, ToleranceType type) { unsafe { - Point* pPoints = stackalloc Point[(int)GetPointCount()]; - EllipseGeometry.GetPointList(pPoints, GetPointCount(), Center, RadiusX, RadiusY); + Point* ptrPoints = stackalloc Point[(int)PointCount]; + EllipseGeometry.InitializePointList(ptrPoints, (int)PointCount, Center, RadiusX, RadiusY); - fixed (byte* pTypes = RoundedPathTypes) //Merely retrieves the pointer to static PE data, no actual pinning occurs + fixed (byte* ptrTypes = RoundedPathTypes) // Merely retrieves the pointer to static PE data, no actual pinning occurs { - return ContainsInternal( - pen, - hitPoint, - tolerance, - type, - pPoints, - GetPointCount(), - pTypes, - GetSegmentCount()); + return ContainsInternal(pen, hitPoint, tolerance, type, ptrPoints, PointCount, ptrTypes, SegmentCount); } } } @@ -267,32 +199,25 @@ public override double GetArea(double tolerance, ToleranceType type) internal override PathFigureCollection GetTransformedFigureCollection(Transform transform) { - Point [] points = GetPointList(); + // Initialize the point list + Span points = stackalloc Point[(int)PointCount]; + InitializePointList(points); // Get the combined transform argument with the internal transform Matrix matrix = GetCombinedMatrix(transform); if (!matrix.IsIdentity) { - for (int i=0; i @@ -300,7 +225,7 @@ internal override PathFigureCollection GetTransformedFigureCollection(Transform /// internal override PathGeometry GetAsPathGeometry() { - PathStreamGeometryContext ctx = new PathStreamGeometryContext(FillRule.EvenOdd, Transform); + PathStreamGeometryContext ctx = new(FillRule.EvenOdd, Transform); PathGeometry.ParsePathGeometryData(GetPathGeometryData(), ctx); return ctx.GetPathGeometry(); @@ -317,14 +242,13 @@ internal override PathGeometryData GetPathGeometryData() return Geometry.GetEmptyPathGeometryData(); } - PathGeometryData data = new PathGeometryData(); - data.FillRule = FillRule.EvenOdd; - data.Matrix = CompositionResourceManager.TransformToMilMatrix3x2D(Transform); - - Point[] points = GetPointList(); + PathGeometryData data = new() { FillRule = FillRule.EvenOdd, Matrix = CompositionResourceManager.TransformToMilMatrix3x2D(Transform) }; - ByteStreamGeometryContext ctx = new ByteStreamGeometryContext(); + // Initialize the point list + Span points = stackalloc Point[(int)PointCount]; + InitializePointList(points); + ByteStreamGeometryContext ctx = new(); ctx.BeginFigure(points[0], true /* is filled */, true /* is closed */); // i == 0, 3, 6, 9 @@ -340,32 +264,28 @@ internal override PathGeometryData GetPathGeometryData() } /// + /// Initializes the point list into . Optionally pins the source if not stack-allocated. /// - /// - private Point[] GetPointList() + private unsafe void InitializePointList(Span destination) { - Point[] points = new Point[GetPointCount()]; - - unsafe + fixed (Point* ptrPoints = destination) // In case this is stackallocated, it's a no-op { - fixed(Point *pPoints = points) - { - EllipseGeometry.GetPointList(pPoints, GetPointCount(), Center, RadiusX, RadiusY); - } + EllipseGeometry.InitializePointList(ptrPoints, destination.Length, Center, RadiusX, RadiusY); } - - return points; } - private unsafe static void GetPointList(Point * points, uint pointsCount, Point center, double radiusX, double radiusY) + /// + /// Initializes the point list specified by . The pointer must be pinned. + /// + private unsafe static void InitializePointList(Point* points, int pointsCount, Point center, double radiusX, double radiusY) { - Invariant.Assert(pointsCount >= c_pointCount); + Invariant.Assert((uint)pointsCount >= PointCount); radiusX = Math.Abs(radiusX); radiusY = Math.Abs(radiusY); // Set the X coordinates - double mid = radiusX * c_arcAsBezier; + double mid = radiusX * ArcAsBezier; points[0].X = points[1].X = points[11].X = points[12].X = center.X + radiusX; points[2].X = points[10].X = center.X + mid; @@ -374,7 +294,7 @@ private unsafe static void GetPointList(Point * points, uint pointsCount, Point points[5].X = points[6].X = points[7].X = center.X - radiusX; // Set the Y coordinates - mid = radiusY * c_arcAsBezier; + mid = radiusY * ArcAsBezier; points[2].Y = points[3].Y = points[4].Y = center.Y + radiusY; points[1].Y = points[5].Y = center.Y + mid; @@ -382,29 +302,26 @@ private unsafe static void GetPointList(Point * points, uint pointsCount, Point points[7].Y = points[11].Y = center.Y - mid; points[8].Y = points[9].Y = points[10].Y = center.Y - radiusY; } - - private static uint GetPointCount() { return c_pointCount; } - private static uint GetSegmentCount() { return c_segmentCount; } #region Static Data // Approximating a 1/4 circle with a Bezier curve _ - internal const double c_arcAsBezier = 0.5522847498307933984; // =( \/2 - 1)*4/3 + internal const double ArcAsBezier = 0.5522847498307933984; // =( \/2 - 1)*4/3 - private const UInt32 c_segmentCount = 4; - private const UInt32 c_pointCount = 13; + private const uint SegmentCount = 4; + private const uint PointCount = 13; - private const byte c_smoothBezier = (byte)MILCoreSegFlags.SegTypeBezier | - (byte)MILCoreSegFlags.SegIsCurved | - (byte)MILCoreSegFlags.SegSmoothJoin; + private const byte SmoothBezier = (byte)MILCoreSegFlags.SegTypeBezier | + (byte)MILCoreSegFlags.SegIsCurved | + (byte)MILCoreSegFlags.SegSmoothJoin; private static ReadOnlySpan RoundedPathTypes => [(byte)MILCoreSegFlags.SegTypeBezier | (byte)MILCoreSegFlags.SegIsCurved | (byte)MILCoreSegFlags.SegSmoothJoin | (byte)MILCoreSegFlags.SegClosed, - c_smoothBezier, - c_smoothBezier, - c_smoothBezier]; + SmoothBezier, + SmoothBezier, + SmoothBezier]; #endregion } diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/LineGeometry.cs b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/LineGeometry.cs index 93e1d68afe4..502511cfc6d 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/LineGeometry.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/LineGeometry.cs @@ -1,27 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -// - -using System; -using MS.Internal; -using System.ComponentModel; -using System.ComponentModel.Design.Serialization; -using System.Reflection; -using System.Collections; -using System.Text; -using System.Globalization; -using System.Windows.Media; -using System.Windows; -using System.Text.RegularExpressions; -using System.Windows.Media.Animation; -using System.Windows.Media.Composition; -using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Security; +// See the LICENSE file in the project root for more information. -using SR=MS.Internal.PresentationCore.SR; +using System.Windows.Media.Composition; namespace System.Windows.Media { @@ -35,9 +16,7 @@ public sealed partial class LineGeometry : Geometry /// /// /// - public LineGeometry() - { - } + public LineGeometry() { } /// /// @@ -51,10 +30,7 @@ public LineGeometry(Point startPoint, Point endPoint) /// /// /// - public LineGeometry( - Point startPoint, - Point endPoint, - Transform transform) : this(startPoint, endPoint) + public LineGeometry(Point startPoint, Point endPoint, Transform transform) : this(startPoint, endPoint) { Transform = transform; } @@ -89,50 +65,25 @@ public override Rect Bounds /// internal override Rect GetBoundsInternal(Pen pen, Matrix worldMatrix, double tolerance, ToleranceType type) { - Matrix geometryMatrix; - - Transform.GetTransformValue(Transform, out geometryMatrix); - - return LineGeometry.GetBoundsHelper( - pen, - worldMatrix, - StartPoint, - EndPoint, - geometryMatrix, - tolerance, - type); + Transform.GetTransformValue(Transform, out Matrix geometryMatrix); + + return LineGeometry.GetBoundsHelper(pen, worldMatrix, StartPoint, EndPoint, geometryMatrix, tolerance, type); } - internal static Rect GetBoundsHelper(Pen pen, Matrix worldMatrix, Point pt1, Point pt2, - Matrix geometryMatrix, double tolerance, ToleranceType type) + internal static unsafe Rect GetBoundsHelper(Pen pen, Matrix worldMatrix, Point pt1, Point pt2, + Matrix geometryMatrix, double tolerance, ToleranceType type) { - if (pen == null && worldMatrix.IsIdentity && geometryMatrix.IsIdentity) - { + if (pen is null && worldMatrix.IsIdentity && geometryMatrix.IsIdentity) return new Rect(pt1, pt2); - } - else + + Point* ptrPoints = stackalloc Point[(int)PointCount]; + ptrPoints[0] = pt1; + ptrPoints[1] = pt2; + + fixed (byte* ptrTypes = LineTypes) // Merely retrieves the pointer to static PE data, no actual pinning occurs { - unsafe - { - Point* pPoints = stackalloc Point[2]; - pPoints[0] = pt1; - pPoints[1] = pt2; - - fixed (byte* pTypes = LineTypes) //Merely retrieves the pointer to static PE data, no actual pinning occurs - { - return Geometry.GetBoundsHelper( - pen, - &worldMatrix, - pPoints, - pTypes, - c_pointCount, - c_segmentCount, - &geometryMatrix, - tolerance, - type, - false); // skip hollows - meaningless here, this is never a hollow - } - } + return Geometry.GetBoundsHelper(pen, &worldMatrix, ptrPoints, ptrTypes, PointCount, SegmentCount, + &geometryMatrix, tolerance, type, false); // skip hollows - meaningless here, this is never a hollow } } @@ -140,21 +91,13 @@ internal override bool ContainsInternal(Pen pen, Point hitPoint, double toleranc { unsafe { - Point* pPoints = stackalloc Point[2]; - pPoints[0] = StartPoint; - pPoints[1] = EndPoint; + Point* ptrPoints = stackalloc Point[(int)PointCount]; + ptrPoints[0] = StartPoint; + ptrPoints[1] = EndPoint; - fixed (byte* pTypes = LineTypes) //Merely retrieves the pointer to static PE data, no actual pinning occurs + fixed (byte* ptrTypes = LineTypes) // Merely retrieves the pointer to static PE data, no actual pinning occurs { - return ContainsInternal( - pen, - hitPoint, - tolerance, - type, - pPoints, - GetPointCount(), - pTypes, - GetSegmentCount()); + return ContainsInternal(pen, hitPoint, tolerance, type, ptrPoints, PointCount, ptrTypes, SegmentCount); } } } @@ -185,18 +128,12 @@ public override double GetArea(double tolerance, ToleranceType type) return 0.0; } - private static ReadOnlySpan LineTypes => [(byte)MILCoreSegFlags.SegTypeLine]; - - private static uint GetPointCount() { return c_pointCount; } - - private static uint GetSegmentCount() { return c_segmentCount; } - /// /// GetAsPathGeometry - return a PathGeometry version of this Geometry /// internal override PathGeometry GetAsPathGeometry() { - PathStreamGeometryContext ctx = new PathStreamGeometryContext(FillRule.EvenOdd, Transform); + PathStreamGeometryContext ctx = new(FillRule.EvenOdd, Transform); PathGeometry.ParsePathGeometryData(GetPathGeometryData(), ctx); return ctx.GetPathGeometry(); @@ -230,16 +167,7 @@ internal override PathFigureCollection GetTransformedFigureCollection(Transform endPoint *= matrix; } - PathFigureCollection collection = new PathFigureCollection(); - collection.Add( - new PathFigure( - startPoint, - new PathSegment[]{new LineSegment(endPoint, true)}, - false // ==> not closed - ) - ); - - return collection; + return new PathFigureCollection(1) { new PathFigure(startPoint, [new LineSegment(endPoint, true)], false) }; // ==> not closed; } /// @@ -253,12 +181,9 @@ internal override PathGeometryData GetPathGeometryData() return Geometry.GetEmptyPathGeometryData(); } - PathGeometryData data = new PathGeometryData(); - data.FillRule = FillRule.EvenOdd; - data.Matrix = CompositionResourceManager.TransformToMilMatrix3x2D(Transform); - - ByteStreamGeometryContext ctx = new ByteStreamGeometryContext(); + PathGeometryData data = new() { FillRule = FillRule.EvenOdd, Matrix = CompositionResourceManager.TransformToMilMatrix3x2D(Transform) }; + ByteStreamGeometryContext ctx = new(); ctx.BeginFigure(StartPoint, true /* is filled */, false /* is closed */); ctx.LineTo(EndPoint, true /* is stroked */, false /* is smooth join */); @@ -270,8 +195,10 @@ internal override PathGeometryData GetPathGeometryData() #region Static Data - private const UInt32 c_segmentCount = 1; - private const UInt32 c_pointCount = 2; + private const uint SegmentCount = 1; + private const uint PointCount = 2; + + private static ReadOnlySpan LineTypes => [(byte)MILCoreSegFlags.SegTypeLine]; #endregion } diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/PathFigure.cs b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/PathFigure.cs index 06b2596be8a..da7024829d9 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/PathFigure.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/PathFigure.cs @@ -50,15 +50,24 @@ public PathFigure() /// Indicates whether the figure is closed public PathFigure(Point start, IEnumerable segments, bool closed) { + ArgumentNullException.ThrowIfNull(segments); + StartPoint = start; PathSegmentCollection mySegments = Segments; - ArgumentNullException.ThrowIfNull(segments); + foreach (PathSegment item in segments) + mySegments.Add(item); + + IsClosed = closed; + } + + internal PathFigure(Point start, ReadOnlySpan segments, bool closed) + { + StartPoint = start; + PathSegmentCollection mySegments = Segments; foreach (PathSegment item in segments) - { mySegments.Add(item); - } IsClosed = closed; } diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/PathGeometry.cs b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/PathGeometry.cs index 12a800b80bf..f9f6891a0ce 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/PathGeometry.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/PathGeometry.cs @@ -76,6 +76,14 @@ public PathGeometry(IEnumerable figures) SetDirty(); } + internal PathGeometry(params ReadOnlySpan figures) + { + foreach (PathFigure item in figures) + Figures.Add(item); + + SetDirty(); + } + /// /// Constructor /// diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/RectangleGeometry.cs b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/RectangleGeometry.cs index 5c6316dc425..ab9c5a2d456 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/RectangleGeometry.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/RectangleGeometry.cs @@ -2,25 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; using MS.Internal; -using System.ComponentModel.Design.Serialization; -using System.Reflection; -using System.Collections; -using System.Text; -using System.Globalization; -using System.Windows.Media; using System.Windows.Media.Composition; -using System.Windows; -using System.Text.RegularExpressions; -using System.Windows.Media.Animation; -using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Security; - -using SR=MS.Internal.PresentationCore.SR; namespace System.Windows.Media { @@ -34,9 +17,7 @@ public sealed partial class RectangleGeometry : Geometry /// /// /// - public RectangleGeometry() - { - } + public RectangleGeometry() { } /// /// Constructor - sets the rounded rectangle to equal the passed in parameters @@ -49,9 +30,7 @@ public RectangleGeometry(Rect rect) /// /// Constructor - sets the rounded rectangle to equal the passed in parameters /// - public RectangleGeometry(Rect rect, - double radiusX, - double radiusY) : this(rect) + public RectangleGeometry(Rect rect, double radiusX, double radiusY) : this(rect) { RadiusX = radiusX; RadiusY = radiusY; @@ -64,11 +43,7 @@ public RectangleGeometry(Rect rect, /// /// /// - public RectangleGeometry( - Rect rect, - double radiusX, - double radiusY, - Transform transform) : this(rect, radiusX, radiusY) + public RectangleGeometry(Rect rect, double radiusX, double radiusY, Transform transform) : this(rect, radiusX, radiusY) { Transform = transform; } @@ -118,9 +93,7 @@ public override Rect Bounds // it's easier to let unmanaged code do the work for us. // - Matrix geometryMatrix; - - Transform.GetTransformValue(transform, out geometryMatrix); + Transform.GetTransformValue(transform, out Matrix geometryMatrix); boundsRect = RectangleGeometry.GetBoundsHelper( null /* no pen */, @@ -140,24 +113,20 @@ public override Rect Bounds internal override bool AreClose(Geometry geometry) { - RectangleGeometry rectGeometry2 = geometry as RectangleGeometry; - - if (rectGeometry2 != null) + if (geometry is RectangleGeometry rectGeometry2) { RectangleGeometry rectGeometry1 = this; Rect rect1 = rectGeometry1.Rect; Rect rect2 = rectGeometry2.Rect; - - return ( - DoubleUtil.AreClose(rect1.X, rect2.X) && - DoubleUtil.AreClose(rect1.Y, rect2.Y) && - DoubleUtil.AreClose(rect1.Width, rect2.Width) && - DoubleUtil.AreClose(rect1.Height, rect2.Height) && - DoubleUtil.AreClose(rectGeometry1.RadiusX, rectGeometry2.RadiusX) && - DoubleUtil.AreClose(rectGeometry1.RadiusY, rectGeometry2.RadiusY) && - (rectGeometry1.Transform == rectGeometry2.Transform) && - (rectGeometry1.IsFrozen == rectGeometry2.IsFrozen) - ); + + return DoubleUtil.AreClose(rect1.X, rect2.X) && + DoubleUtil.AreClose(rect1.Y, rect2.Y) && + DoubleUtil.AreClose(rect1.Width, rect2.Width) && + DoubleUtil.AreClose(rect1.Height, rect2.Height) && + DoubleUtil.AreClose(rectGeometry1.RadiusX, rectGeometry2.RadiusX) && + DoubleUtil.AreClose(rectGeometry1.RadiusY, rectGeometry2.RadiusY) && + (rectGeometry1.Transform == rectGeometry2.Transform) && + (rectGeometry1.IsFrozen == rectGeometry2.IsFrozen); } return base.AreClose(geometry); @@ -169,78 +138,51 @@ internal override bool AreClose(Geometry geometry) /// internal override Rect GetBoundsInternal(Pen pen, Matrix worldMatrix, double tolerance, ToleranceType type) { - Matrix geometryMatrix; - - Transform.GetTransformValue(Transform, out geometryMatrix); - - return RectangleGeometry.GetBoundsHelper( - pen, - worldMatrix, - Rect, - RadiusX, - RadiusY, - geometryMatrix, - tolerance, - type); + Transform.GetTransformValue(Transform, out Matrix geometryMatrix); + + return RectangleGeometry.GetBoundsHelper(pen, worldMatrix, Rect, RadiusX, RadiusY, geometryMatrix, tolerance, type); } - internal static Rect GetBoundsHelper(Pen pen, Matrix worldMatrix, Rect rect, double radiusX, double radiusY, + internal static unsafe Rect GetBoundsHelper(Pen pen, Matrix worldMatrix, Rect rect, double radiusX, double radiusY, Matrix geometryMatrix, double tolerance, ToleranceType type) { - Rect boundingRect; - if (rect.IsEmpty) - { - boundingRect = Rect.Empty; - } - else if ( (pen == null || pen.DoesNotContainGaps) && - geometryMatrix.IsIdentity && worldMatrix.IsIdentity) + return Rect.Empty; + + if ((pen is null || pen.DoesNotContainGaps) && geometryMatrix.IsIdentity && worldMatrix.IsIdentity) { double strokeThickness = 0.0; - boundingRect = rect; + Rect boundingRect = rect; if (Pen.ContributesToBounds(pen)) { strokeThickness = Math.Abs(pen.Thickness); - boundingRect.X -= 0.5*strokeThickness; - boundingRect.Y -= 0.5*strokeThickness; + boundingRect.X -= 0.5 * strokeThickness; + boundingRect.Y -= 0.5 * strokeThickness; boundingRect.Width += strokeThickness; boundingRect.Height += strokeThickness; } + + return boundingRect; } else { - unsafe - { - uint pointCount, segmentCount; - GetCounts(rect, radiusX, radiusY, out pointCount, out segmentCount); + GetCounts(rect, radiusX, radiusY, out uint pointCount, out uint segmentCount); - // We've checked that rect isn't empty above - Invariant.Assert(pointCount != 0); + // We've checked that rect isn't empty above + Invariant.Assert(pointCount != 0); - Point* pPoints = stackalloc Point[(int)pointCount]; - RectangleGeometry.GetPointList(pPoints, pointCount, rect, radiusX, radiusY); + Point* ptrPoints = stackalloc Point[(int)pointCount]; + RectangleGeometry.InitializePointList(ptrPoints, (int)pointCount, rect, radiusX, radiusY); - fixed (byte* pTypes = GetTypeList(rect, radiusX, radiusY)) //Merely retrieves the pointer to static PE data, no actual pinning occurs - { - boundingRect = Geometry.GetBoundsHelper( - pen, - &worldMatrix, - pPoints, - pTypes, - pointCount, - segmentCount, - &geometryMatrix, - tolerance, - type, - false); // skip hollows - meaningless here, this is never a hollow - } + fixed (byte* ptrTypes = GetTypeList(rect, radiusX, radiusY)) // Merely retrieves the pointer to static PE data, no actual pinning occurs + { + return Geometry.GetBoundsHelper(pen, &worldMatrix, ptrPoints, ptrTypes, pointCount, segmentCount, + &geometryMatrix, tolerance, type, false); // skip hollows - meaningless here, this is never a hollow } } - - return boundingRect; } internal override bool ContainsInternal(Pen pen, Point hitPoint, double tolerance, ToleranceType type) @@ -259,20 +201,12 @@ internal override bool ContainsInternal(Pen pen, Point hitPoint, double toleranc unsafe { - Point* pPoints = stackalloc Point[(int)pointCount]; - RectangleGeometry.GetPointList(pPoints, pointCount, rect, radiusX, radiusY); + Point* ptrPoints = stackalloc Point[(int)pointCount]; + RectangleGeometry.InitializePointList(ptrPoints, (int)pointCount, rect, radiusX, radiusY); - fixed (byte* pTypes = GetTypeList(rect, radiusX, radiusY)) //Merely retrieves the pointer to static PE data, no actual pinning occurs + fixed (byte* ptrTypes = GetTypeList(rect, radiusX, radiusY)) // Merely retrieves the pointer to static PE data, no actual pinning occurs { - return ContainsInternal( - pen, - hitPoint, - tolerance, - type, - pPoints, - pointCount, - pTypes, - segmentCount); + return ContainsInternal(pen, hitPoint, tolerance, type, ptrPoints, pointCount, ptrTypes, segmentCount); } } } @@ -327,55 +261,33 @@ internal override PathFigureCollection GetTransformedFigureCollection(Transform if (IsRounded(radiusX, radiusY)) { - Point[] points = GetPointList(rect, radiusX, radiusY); + // Initialize the point list + Span points = stackalloc Point[(int)GetPointCount(rect, radiusX, radiusY)]; + InitializePointList(points, rect, radiusX, radiusY); // Transform if applicable. if (!matrix.IsIdentity) { - for (int i=0; i @@ -395,7 +306,7 @@ internal bool IsRounded() /// internal override PathGeometry GetAsPathGeometry() { - PathStreamGeometryContext ctx = new PathStreamGeometryContext(FillRule.EvenOdd, Transform); + PathStreamGeometryContext ctx = new(FillRule.EvenOdd, Transform); PathGeometry.ParsePathGeometryData(GetPathGeometryData(), ctx); return ctx.GetPathGeometry(); @@ -412,19 +323,19 @@ internal override PathGeometryData GetPathGeometryData() return Geometry.GetEmptyPathGeometryData(); } - PathGeometryData data = new PathGeometryData(); - data.FillRule = FillRule.EvenOdd; - data.Matrix = CompositionResourceManager.TransformToMilMatrix3x2D(Transform); + PathGeometryData data = new() { FillRule = FillRule.EvenOdd, Matrix = CompositionResourceManager.TransformToMilMatrix3x2D(Transform) }; double radiusX = RadiusX; double radiusY = RadiusY; Rect rect = Rect; - ByteStreamGeometryContext ctx = new ByteStreamGeometryContext(); + ByteStreamGeometryContext ctx = new(); if (IsRounded(radiusX, radiusY)) { - Point[] points = GetPointList(rect, radiusX, radiusY); + // Initialize the point list + Span points = stackalloc Point[(int)GetPointCount(rect, radiusX, radiusY)]; + InitializePointList(points, rect, radiusX, radiusY); ctx.BeginFigure(points[0], true /* is filled */, true /* is closed */); ctx.BezierTo(points[1], points[2], points[3], true /* is stroked */, false /* is smooth join */); @@ -450,36 +361,31 @@ internal override PathGeometryData GetPathGeometryData() } /// + /// Initializes the point list into . Optionally pins the source if not stack-allocated. /// - /// - private Point[] GetPointList(Rect rect, double radiusX, double radiusY) + private unsafe void InitializePointList(Span destination, Rect rect, double radiusX, double radiusY) { - uint pointCount = GetPointCount(rect, radiusX, radiusY); - Point[] points = new Point[pointCount]; - - unsafe + fixed (Point* ptrPoints = destination) // In case this is stackallocated, it's a no-op { - fixed(Point *pPoints = points) - { - RectangleGeometry.GetPointList(pPoints, pointCount, rect, radiusX, radiusY); - } + RectangleGeometry.InitializePointList(ptrPoints, destination.Length, rect, radiusX, radiusY); } - - return points; } - private unsafe static void GetPointList(Point * points, uint pointsCount, Rect rect, double radiusX, double radiusY) + /// + /// Initializes the point list specified by . The pointer must be pinned. + /// + private unsafe static void InitializePointList(Point* points, int pointsCount, Rect rect, double radiusX, double radiusY) { if (IsRounded(radiusX, radiusY)) { // It is a rounded rectangle - Invariant.Assert(pointsCount >= c_roundedPointCount); + Invariant.Assert((uint)pointsCount >= RoundedPointCount); radiusX = Math.Min(rect.Width * (1.0 / 2.0), Math.Abs(radiusX)); radiusY = Math.Min(rect.Height * (1.0 / 2.0), Math.Abs(radiusY)); - double bezierX = ((1.0 - EllipseGeometry.c_arcAsBezier) * radiusX); - double bezierY = ((1.0 - EllipseGeometry.c_arcAsBezier) * radiusY); + double bezierX = ((1.0 - EllipseGeometry.ArcAsBezier) * radiusX); + double bezierY = ((1.0 - EllipseGeometry.ArcAsBezier) * radiusY); points[1].X = points[0].X = points[15].X = points[14].X = rect.X; points[2].X = points[13].X = rect.X + bezierX; @@ -500,7 +406,7 @@ private unsafe static void GetPointList(Point * points, uint pointsCount, Rect r else { // The rectangle is not rounded - Invariant.Assert(pointsCount >= c_squaredPointCount); + Invariant.Assert((uint)pointsCount >= SquaredPointCount); points[0].X = points[3].X = points[4].X = rect.X; points[1].X = points[2].X = rect.Right; @@ -526,7 +432,7 @@ private static ReadOnlySpan GetTypeList(Rect rect, double radiusX, double } } - private uint GetPointCount(Rect rect, double radiusX, double radiusY) + private static uint GetPointCount(Rect rect, double radiusX, double radiusY) { if (rect.IsEmpty) { @@ -534,15 +440,15 @@ private uint GetPointCount(Rect rect, double radiusX, double radiusY) } else if (IsRounded(radiusX, radiusY)) { - return c_roundedPointCount; + return RoundedPointCount; } else { - return c_squaredPointCount; + return SquaredPointCount; } } - private uint GetSegmentCount(Rect rect, double radiusX, double radiusY) + private static uint GetSegmentCount(Rect rect, double radiusX, double radiusY) { if (rect.IsEmpty) { @@ -550,11 +456,11 @@ private uint GetSegmentCount(Rect rect, double radiusX, double radiusY) } else if (IsRounded(radiusX, radiusY)) { - return c_roundedSegmentCount; + return RoundedSegmentCount; } else { - return c_squaredSegmentCount; + return SquaredSegmentCount; } } @@ -568,13 +474,13 @@ private static void GetCounts(Rect rect, double radiusX, double radiusY, out uin else if (IsRounded(radiusX, radiusY)) { // The rectangle is rounded - pointCount = c_roundedPointCount; - segmentCount = c_roundedSegmentCount; + pointCount = RoundedPointCount; + segmentCount = RoundedSegmentCount; } else { - pointCount = c_squaredPointCount; - segmentCount = c_squaredSegmentCount; + pointCount = SquaredPointCount; + segmentCount = SquaredSegmentCount; } } @@ -601,32 +507,30 @@ public override bool MayHaveCurves() #region InstanceData // Rouneded - static private UInt32 c_roundedSegmentCount = 8; - static private UInt32 c_roundedPointCount = 17; - - static private byte smoothBezier = (byte)MILCoreSegFlags.SegTypeBezier | - (byte)MILCoreSegFlags.SegIsCurved | - (byte)MILCoreSegFlags.SegSmoothJoin; - - static private byte smoothLine = (byte)MILCoreSegFlags.SegTypeLine | (byte)MILCoreSegFlags.SegSmoothJoin; - - private static ReadOnlySpan RoundedPathTypes => new byte[] { - (byte)MILCoreSegFlags.SegTypeBezier | - (byte)MILCoreSegFlags.SegIsCurved | - (byte)MILCoreSegFlags.SegSmoothJoin | - (byte)MILCoreSegFlags.SegClosed, - smoothLine, - smoothBezier, - smoothLine, - smoothBezier, - smoothLine, - smoothBezier, - smoothLine - }; + private const uint RoundedSegmentCount = 8; + private const uint RoundedPointCount = 17; + + private const byte SmoothBezier = (byte)MILCoreSegFlags.SegTypeBezier | + (byte)MILCoreSegFlags.SegIsCurved | + (byte)MILCoreSegFlags.SegSmoothJoin; + + private const byte SmoothLine = (byte)MILCoreSegFlags.SegTypeLine | (byte)MILCoreSegFlags.SegSmoothJoin; + + private static ReadOnlySpan RoundedPathTypes => [(byte)MILCoreSegFlags.SegTypeBezier | + (byte)MILCoreSegFlags.SegIsCurved | + (byte)MILCoreSegFlags.SegSmoothJoin | + (byte)MILCoreSegFlags.SegClosed, + SmoothLine, + SmoothBezier, + SmoothLine, + SmoothBezier, + SmoothLine, + SmoothBezier, + SmoothLine]; // Squared - private const UInt32 c_squaredSegmentCount = 4; - private const UInt32 c_squaredPointCount = 5; + private const uint SquaredSegmentCount = 4; + private const uint SquaredPointCount = 5; private static ReadOnlySpan SquaredPathTypes => [(byte)MILCoreSegFlags.SegTypeLine | (byte)MILCoreSegFlags.SegClosed, (byte)MILCoreSegFlags.SegTypeLine, diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/Primitives/TickBar.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/Primitives/TickBar.cs index aafca780871..739172c8b60 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/Primitives/TickBar.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/Primitives/TickBar.cs @@ -478,9 +478,7 @@ protected override void OnRender(DrawingContext dc) // This property is rarely set so let's try to avoid the GetValue // caching of the mutable default value DoubleCollection ticks = null; - bool hasModifiers; - if (GetValueSource(TicksProperty, null, out hasModifiers) - != BaseValueSourceInternal.Default || hasModifiers) + if ((GetValueSource(TicksProperty, null, out bool hasModifiers) != BaseValueSourceInternal.Default) || hasModifiers) { ticks = Ticks; } @@ -534,11 +532,7 @@ protected override void OnRender(DrawingContext dc) Point pt1 = new Point(startPoint.X + tickLen2, y0); Point pt2 = new Point(startPoint.X + tickLen2, y0 + Math.Abs(tickLen2) * progression); - PathSegment[] segments = new PathSegment[] { - new LineSegment(pt2, true), - new LineSegment(pt0, true), - }; - PathGeometry geo = new PathGeometry(new PathFigure[] { new PathFigure(pt1, segments, true) }); + PathGeometry geo = new PathGeometry(new PathFigure(pt1, [new LineSegment(pt2, true), new LineSegment(pt0, true)], true)); dc.DrawGeometry(Fill, pen, geo); @@ -547,11 +541,7 @@ protected override void OnRender(DrawingContext dc) pt1 = new Point(startPoint.X + tickLen2, y0); pt2 = new Point(startPoint.X + tickLen2, y0 - Math.Abs(tickLen2) * progression); - segments = new PathSegment[] { - new LineSegment(pt2, true), - new LineSegment(pt0, true), - }; - geo = new PathGeometry(new PathFigure[] { new PathFigure(pt1, segments, true) }); + geo = new PathGeometry(new PathFigure(pt1, [new LineSegment(pt2, true), new LineSegment(pt0, true)], true)); dc.DrawGeometry(Fill, pen, geo); } } @@ -585,9 +575,7 @@ protected override void OnRender(DrawingContext dc) // This property is rarely set so let's try to avoid the GetValue // caching of the mutable default value DoubleCollection ticks = null; - bool hasModifiers; - if (GetValueSource(TicksProperty, null, out hasModifiers) - != BaseValueSourceInternal.Default || hasModifiers) + if ((GetValueSource(TicksProperty, null, out bool hasModifiers) != BaseValueSourceInternal.Default) || hasModifiers) { ticks = Ticks; } @@ -639,11 +627,7 @@ protected override void OnRender(DrawingContext dc) Point pt1 = new Point(x0, startPoint.Y + tickLen2); Point pt2 = new Point(x0 + Math.Abs(tickLen2) * progression, startPoint.Y + tickLen2); - PathSegment[] segments = new PathSegment[] { - new LineSegment(pt2, true), - new LineSegment(pt0, true), - }; - PathGeometry geo = new PathGeometry(new PathFigure[] { new PathFigure(pt1, segments, true) }); + PathGeometry geo = new PathGeometry(new PathFigure(pt1, [new LineSegment(pt2, true), new LineSegment(pt0, true)], true)); dc.DrawGeometry(Fill, pen, geo); @@ -652,11 +636,7 @@ protected override void OnRender(DrawingContext dc) pt1 = new Point(x0, startPoint.Y + tickLen2); pt2 = new Point(x0 - Math.Abs(tickLen2) * progression, startPoint.Y + tickLen2); - segments = new PathSegment[] { - new LineSegment(pt2, true), - new LineSegment(pt0, true), - }; - geo = new PathGeometry(new PathFigure[] { new PathFigure(pt1, segments, true) }); + geo = new PathGeometry(new PathFigure(pt1, [new LineSegment(pt2, true), new LineSegment(pt0, true)], true)); dc.DrawGeometry(Fill, pen, geo); } }