diff --git a/src/Avalonia.Controls/Image.cs b/src/Avalonia.Controls/Image.cs
index 43c8fbcbb4..f6f11aa9ad 100644
--- a/src/Avalonia.Controls/Image.cs
+++ b/src/Avalonia.Controls/Image.cs
@@ -63,10 +63,10 @@ namespace Avalonia.Controls
Vector scale = Stretch.CalculateScaling(Bounds.Size, sourceSize);
Size scaledSize = sourceSize * scale;
Rect destRect = viewPort
- .CenterIn(new Rect(scaledSize))
+ .CenterRect(new Rect(scaledSize))
.Intersect(viewPort);
Rect sourceRect = new Rect(sourceSize)
- .CenterIn(new Rect(destRect.Size / scale));
+ .CenterRect(new Rect(destRect.Size / scale));
context.DrawImage(source, 1, sourceRect, destRect);
}
diff --git a/src/Avalonia.Visuals/Rect.cs b/src/Avalonia.Visuals/Rect.cs
index 0d6aadbcaa..0132c5e8a3 100644
--- a/src/Avalonia.Visuals/Rect.cs
+++ b/src/Avalonia.Visuals/Rect.cs
@@ -238,7 +238,7 @@ namespace Avalonia
///
/// The rectangle to center.
/// The centered rectangle.
- public Rect CenterIn(Rect rect)
+ public Rect CenterRect(Rect rect)
{
return new Rect(
_x + ((_width - rect._width) / 2),
@@ -401,6 +401,32 @@ namespace Avalonia
return new Rect(Position + offset, Size);
}
+ ///
+ /// Gets the union of two rectangles.
+ ///
+ /// The other rectangle.
+ /// The union.
+ public Rect Union(Rect rect)
+ {
+ if (IsEmpty)
+ {
+ return rect;
+ }
+ else if (rect.IsEmpty)
+ {
+ return this;
+ }
+ else
+ {
+ var x1 = Math.Min(this.X, rect.X);
+ var x2 = Math.Max(this.Right, rect.Right);
+ var y1 = Math.Min(this.Y, rect.Y);
+ var y2 = Math.Max(this.Bottom, rect.Bottom);
+
+ return new Rect(new Point(x1, y1), new Point(x2, y2));
+ }
+ }
+
///
/// Returns a new with the specified X position.
///
diff --git a/tests/Avalonia.Visuals.UnitTests/Avalonia.Visuals.UnitTests.csproj b/tests/Avalonia.Visuals.UnitTests/Avalonia.Visuals.UnitTests.csproj
index 9e7f739a1c..b5b6dbd404 100644
--- a/tests/Avalonia.Visuals.UnitTests/Avalonia.Visuals.UnitTests.csproj
+++ b/tests/Avalonia.Visuals.UnitTests/Avalonia.Visuals.UnitTests.csproj
@@ -80,6 +80,7 @@
+
diff --git a/tests/Avalonia.Visuals.UnitTests/RectTests.cs b/tests/Avalonia.Visuals.UnitTests/RectTests.cs
new file mode 100644
index 0000000000..6e3f654bfb
--- /dev/null
+++ b/tests/Avalonia.Visuals.UnitTests/RectTests.cs
@@ -0,0 +1,42 @@
+// Copyright (c) The Avalonia Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using Xunit;
+
+namespace Avalonia.Visuals.UnitTests
+{
+ public class RectTests
+ {
+ [Fact]
+ public void Union_Should_Return_Correct_Value_For_Intersecting_Rects()
+ {
+ var result = new Rect(0, 0, 100, 100).Union(new Rect(50, 50, 100, 100));
+
+ Assert.Equal(new Rect(0, 0, 150, 150), result);
+ }
+
+ [Fact]
+ public void Union_Should_Return_Correct_Value_For_NonIntersecting_Rects()
+ {
+ var result = new Rect(0, 0, 100, 100).Union(new Rect(150, 150, 100, 100));
+
+ Assert.Equal(new Rect(0, 0, 250, 250), result);
+ }
+
+ [Fact]
+ public void Union_Should_Ignore_Empty_This_rect()
+ {
+ var result = new Rect(0, 0, 0, 0).Union(new Rect(150, 150, 100, 100));
+
+ Assert.Equal(new Rect(150, 150, 100, 100), result);
+ }
+
+ [Fact]
+ public void Union_Should_Ignore_Empty_Other_rect()
+ {
+ var result = new Rect(0, 0, 100, 100).Union(new Rect(150, 150, 0, 0));
+
+ Assert.Equal(new Rect(0, 0, 100, 100), result);
+ }
+ }
+}