diff --git a/src/Avalonia.Visuals/Rect.cs b/src/Avalonia.Visuals/Rect.cs index b0c4cb62eb..d1110e0613 100644 --- a/src/Avalonia.Visuals/Rect.cs +++ b/src/Avalonia.Visuals/Rect.cs @@ -421,11 +421,50 @@ namespace Avalonia } /// - /// Gets the union of two rectangles. - /// - /// The other rectangle. - /// The union. - public Rect Union(Rect rect) + /// Normalizes the rectangle so both the and are positive, without changing the location of the rectangle + /// + /// Normalized Rect + /// + /// Empty rect will be return when Rect contains invalid values. Like NaN. + /// + public Rect Normalize() + { + Rect rect = this; + + if(double.IsNaN(rect.Right) || double.IsNaN(rect.Bottom) || + double.IsNaN(rect.X) || double.IsNaN(rect.Y) || + double.IsNaN(Height) || double.IsNaN(Width)) + { + return Rect.Empty; + } + + if (rect.Width < 0) + { + var x = X + Width; + var width = X - x; + + rect = rect.WithX(x).WithWidth(width); + } + + if (rect.Height < 0) + { + var y = Y + Height; + var height = Y - y; + + rect = rect.WithY(y).WithHeight(height); + } + + return rect; + } + + + /// + /// Gets the union of two rectangles. + /// + /// The other rectangle. + /// The union. + public Rect Union(Rect rect) { if (IsEmpty) { diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/DrawOperation.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/DrawOperation.cs index 0b04b97ff2..c49e7705e0 100644 --- a/src/Avalonia.Visuals/Rendering/SceneGraph/DrawOperation.cs +++ b/src/Avalonia.Visuals/Rendering/SceneGraph/DrawOperation.cs @@ -11,7 +11,8 @@ namespace Avalonia.Rendering.SceneGraph { public DrawOperation(Rect bounds, Matrix transform) { - bounds = bounds.TransformToAABB(transform); + bounds = bounds.Normalize().TransformToAABB(transform); + Bounds = new Rect( new Point(Math.Floor(bounds.X), Math.Floor(bounds.Y)), new Point(Math.Ceiling(bounds.Right), Math.Ceiling(bounds.Bottom))); diff --git a/tests/Avalonia.Visuals.UnitTests/RectTests.cs b/tests/Avalonia.Visuals.UnitTests/RectTests.cs index 34953e5fd7..a2b0569949 100644 --- a/tests/Avalonia.Visuals.UnitTests/RectTests.cs +++ b/tests/Avalonia.Visuals.UnitTests/RectTests.cs @@ -35,5 +35,24 @@ namespace Avalonia.Visuals.UnitTests Assert.Equal(new Rect(0, 0, 100, 100), result); } + + [Fact] + public void Normalize_Should_Reverse_Negative_Size() + { + var result = new Rect(new Point(100, 100), new Point(0, 0)).Normalize(); + + Assert.Equal(new Rect(0, 0, 100, 100), result); + } + + [Fact] + public void Normalize_Should_Make_Invalid_Rects_Empty() + { + var result = new Rect( + double.NegativeInfinity, double.PositiveInfinity, + double.PositiveInfinity, double.PositiveInfinity) + .Normalize(); + + Assert.Equal(Rect.Empty, result); + } } }