Skip to content

Commit 6ac896b

Browse files
committed
Refactored Matrix/Rect extensions
1 parent fedef9b commit 6ac896b

File tree

4 files changed

+81
-112
lines changed

4 files changed

+81
-112
lines changed

Microsoft.Toolkit.Uwp.UI.Controls.Layout/LayoutTransformControl/LayoutTransformControl.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ private static bool IsSizeSmaller(Size a, Size b)
126126
private void ProcessTransform()
127127
{
128128
// Get the transform matrix and apply it
129-
_transformation = MatrixHelperEx.Round(GetTransformMatrix(Transform), DecimalsAfterRound);
129+
_transformation = GetTransformMatrix(Transform).Round(DecimalsAfterRound);
130130

131131
if (_matrixTransform != null)
132132
{
@@ -241,7 +241,8 @@ protected override Size MeasureOverride(Size availableSize)
241241
_layoutRoot.Measure(measureSize);
242242

243243
// Transform DesiredSize to find its width/height
244-
Rect transformedDesiredRect = MatrixHelperEx.RectTransform(new Rect(0, 0, _layoutRoot.DesiredSize.Width, _layoutRoot.DesiredSize.Height), _transformation);
244+
Rect startingRect = new Rect(0, 0, _layoutRoot.DesiredSize.Width, _layoutRoot.DesiredSize.Height);
245+
Rect transformedDesiredRect = startingRect.Transform(_transformation);
245246
Size transformedDesiredSize = new Size(transformedDesiredRect.Width, transformedDesiredRect.Height);
246247

247248
// Return result to allocate enough space for the transformation
@@ -273,7 +274,8 @@ protected override Size ArrangeOverride(Size finalSize)
273274
}
274275

275276
// Transform the working size to find its width/height
276-
Rect transformedRect = MatrixHelperEx.RectTransform(new Rect(0, 0, finalSizeTransformed.Width, finalSizeTransformed.Height), _transformation);
277+
Rect startingRect = new Rect(0, 0, finalSizeTransformed.Width, finalSizeTransformed.Height);
278+
Rect transformedRect = startingRect.Transform(_transformation);
277279

278280
// Create the Arrange rect to center the transformed content
279281
Rect finalRect = new Rect(

Microsoft.Toolkit.Uwp.UI/Extensions/Media/MatrixExtensions.cs

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,12 @@ namespace Microsoft.Toolkit.Uwp.UI
1313
public static class MatrixExtensions
1414
{
1515
/// <summary>
16-
/// Implements WPF's Matrix.HasInverse.
16+
/// Implements WPF's <c>Matrix.HasInverse</c> logic.
1717
/// </summary>
1818
/// <param name="matrix">The matrix.</param>
1919
/// <returns>True if matrix has an inverse.</returns>
2020
public static bool HasInverse(this Matrix matrix)
2121
{
22-
// TODO: Check if we can make this an extension property in C#8.
23-
24-
// WPF equivalent of following code:
25-
// return matrix.HasInverse;
2622
return ((matrix.M11 * matrix.M22) - (matrix.M12 * matrix.M21)) != 0;
2723
}
2824

@@ -34,7 +30,30 @@ public static bool HasInverse(this Matrix matrix)
3430
/// <returns>Multiplied Matrix</returns>
3531
public static Matrix Multiply(this Matrix matrix1, Matrix matrix2)
3632
{
37-
return MatrixHelperEx.Multiply(matrix1, matrix2);
33+
return new(
34+
(matrix1.M11 * matrix2.M11) + (matrix1.M12 * matrix2.M21),
35+
(matrix1.M11 * matrix2.M12) + (matrix1.M12 * matrix2.M22),
36+
(matrix1.M21 * matrix2.M11) + (matrix1.M22 * matrix2.M21),
37+
(matrix1.M21 * matrix2.M12) + (matrix1.M22 * matrix2.M22),
38+
(matrix1.OffsetX * matrix2.M11) + (matrix1.OffsetY * matrix2.M21) + matrix2.OffsetX,
39+
(matrix1.OffsetX * matrix2.M12) + (matrix1.OffsetY * matrix2.M22) + matrix2.OffsetY);
40+
}
41+
42+
/// <summary>
43+
/// Rounds the non-offset elements of a matrix to avoid issues due to floating point imprecision and returns the result.
44+
/// </summary>
45+
/// <param name="matrix">The matrix to round.</param>
46+
/// <param name="decimalsAfterRound">The number of decimals after the round.</param>
47+
/// <returns>The rounded matrix.</returns>
48+
public static Matrix Round(this Matrix matrix, int decimalsAfterRound)
49+
{
50+
return new(
51+
Math.Round(matrix.M11, decimalsAfterRound),
52+
Math.Round(matrix.M12, decimalsAfterRound),
53+
Math.Round(matrix.M21, decimalsAfterRound),
54+
Math.Round(matrix.M22, decimalsAfterRound),
55+
matrix.OffsetX,
56+
matrix.OffsetY);
3857
}
3958

4059
/// <summary>
@@ -108,53 +127,37 @@ public static Matrix Skew(this Matrix matrix, double skewX, double skewY)
108127
/// <returns>Translated Matrix.</returns>
109128
public static Matrix Translate(this Matrix matrix, double offsetX, double offsetY)
110129
{
111-
return new Matrix(matrix.M11, matrix.M12, matrix.M21, matrix.M22, matrix.OffsetX + offsetX, matrix.OffsetY + offsetY);
130+
return new(matrix.M11, matrix.M12, matrix.M21, matrix.M22, matrix.OffsetX + offsetX, matrix.OffsetY + offsetY);
112131
}
113132

114-
internal static Matrix CreateRotationRadians(double angle)
133+
private static Matrix CreateRotationRadians(double angle)
115134
{
116135
return CreateRotationRadians(angle, 0, 0);
117136
}
118137

119-
internal static Matrix CreateRotationRadians(double angle, double centerX, double centerY)
138+
private static Matrix CreateRotationRadians(double angle, double centerX, double centerY)
120139
{
121140
var sin = Math.Sin(angle);
122141
var cos = Math.Cos(angle);
123142
var dx = (centerX * (1.0 - cos)) + (centerY * sin);
124143
var dy = (centerY * (1.0 - cos)) - (centerX * sin);
125144

126-
#pragma warning disable SA1117 // Parameters must be on same line or separate lines
127-
return new Matrix(cos, sin,
128-
-sin, cos,
129-
dx, dy);
130-
#pragma warning restore SA1117 // Parameters must be on same line or separate lines
145+
return new(cos, sin, -sin, cos, dx, dy);
131146
}
132147

133-
internal static Matrix CreateScaling(double scaleX, double scaleY)
148+
private static Matrix CreateScaling(double scaleX, double scaleY)
134149
{
135-
#pragma warning disable SA1117 // Parameters must be on same line or separate lines
136-
return new Matrix(scaleX, 0,
137-
0, scaleY,
138-
0, 0);
139-
#pragma warning restore SA1117 // Parameters must be on same line or separate lines
150+
return new(scaleX, 0, 0, scaleY, 0, 0);
140151
}
141152

142-
internal static Matrix CreateScaling(double scaleX, double scaleY, double centerX, double centerY)
153+
private static Matrix CreateScaling(double scaleX, double scaleY, double centerX, double centerY)
143154
{
144-
#pragma warning disable SA1117 // Parameters must be on same line or separate lines
145-
return new Matrix(scaleX, 0,
146-
0, scaleY,
147-
centerX - (scaleX * centerX), centerY - (scaleY * centerY));
148-
#pragma warning restore SA1117 // Parameters must be on same line or separate lines
155+
return new(scaleX, 0, 0, scaleY, centerX - (scaleX * centerX), centerY - (scaleY * centerY));
149156
}
150157

151-
internal static Matrix CreateSkewRadians(double skewX, double skewY)
158+
private static Matrix CreateSkewRadians(double skewX, double skewY)
152159
{
153-
#pragma warning disable SA1117 // Parameters must be on same line or separate lines
154-
return new Matrix(1.0, Math.Tan(skewY),
155-
Math.Tan(skewX), 1.0,
156-
0.0, 0.0);
157-
#pragma warning restore SA1117 // Parameters must be on same line or separate lines
160+
return new(1.0, Math.Tan(skewY), Math.Tan(skewX), 1.0, 0.0, 0.0);
158161
}
159162
}
160163
}

Microsoft.Toolkit.Uwp.UI/Extensions/Media/MatrixHelperEx.cs

Lines changed: 0 additions & 77 deletions
This file was deleted.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.Diagnostics.Contracts;
7+
using Windows.Foundation;
8+
using Windows.UI.Xaml.Media;
9+
using Rect = Windows.Foundation.Rect;
10+
11+
namespace Microsoft.Toolkit.Uwp.UI
12+
{
13+
/// <summary>
14+
/// Provides a set of extensions to the <see cref="Rect"/> struct.
15+
/// </summary>
16+
public static class RectExtensions
17+
{
18+
/// <summary>
19+
/// Implement WPF's <c>Rect.Transform(Matrix)</c> logic.
20+
/// </summary>
21+
/// <param name="rectangle">The rectangle to transform.</param>
22+
/// <param name="matrix">The matrix to use to transform the rectangle.
23+
/// </param>
24+
/// <returns>The transformed rectangle.</returns>
25+
[Pure]
26+
public static Rect Transform(this Rect rectangle, Matrix matrix)
27+
{
28+
Point leftTop = matrix.Transform(new Point(rectangle.Left, rectangle.Top));
29+
Point rightTop = matrix.Transform(new Point(rectangle.Right, rectangle.Top));
30+
Point leftBottom = matrix.Transform(new Point(rectangle.Left, rectangle.Bottom));
31+
Point rightBottom = matrix.Transform(new Point(rectangle.Right, rectangle.Bottom));
32+
33+
double left = Math.Min(Math.Min(leftTop.X, rightTop.X), Math.Min(leftBottom.X, rightBottom.X));
34+
double top = Math.Min(Math.Min(leftTop.Y, rightTop.Y), Math.Min(leftBottom.Y, rightBottom.Y));
35+
double right = Math.Max(Math.Max(leftTop.X, rightTop.X), Math.Max(leftBottom.X, rightBottom.X));
36+
double bottom = Math.Max(Math.Max(leftTop.Y, rightTop.Y), Math.Max(leftBottom.Y, rightBottom.Y));
37+
38+
return new(left, top, right - left, bottom - top);
39+
}
40+
}
41+
}

0 commit comments

Comments
 (0)