diff --git a/Tests/Perspex.RenderTests/Media/ImageBrushTests.cs b/Tests/Perspex.RenderTests/Media/ImageBrushTests.cs
new file mode 100644
index 0000000000..21a3047529
--- /dev/null
+++ b/Tests/Perspex.RenderTests/Media/ImageBrushTests.cs
@@ -0,0 +1,395 @@
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using Perspex.Controls;
+using Perspex.Controls.Shapes;
+using Perspex.Layout;
+using Perspex.Media;
+using Perspex.Media.Imaging;
+using Xunit;
+
+#if PERSPEX_CAIRO
+namespace Perspex.Cairo.RenderTests.Media
+#else
+namespace Perspex.Direct2D1.RenderTests.Media
+#endif
+{
+ public class ImageBrushTests : TestBase
+ {
+ public ImageBrushTests()
+ : base(@"Media\ImageBrush")
+ {
+ }
+
+ private string BitmapPath
+ {
+ get { return System.IO.Path.Combine(OutputPath, "github_icon.png"); }
+ }
+
+#if PERSPEX_CAIRO
+ [Fact(Skip = "ImageBrush not yet implemented on Cairo")]
+#else
+ [Fact]
+#endif
+ public void ImageBrush_NoStretch_NoTile_Alignment_TopLeft()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Rectangle
+ {
+ Fill = new ImageBrush
+ {
+ Stretch = Stretch.None,
+ TileMode = TileMode.None,
+ AlignmentX = AlignmentX.Left,
+ AlignmentY = AlignmentY.Top,
+ Source = new Bitmap(BitmapPath),
+ }
+ }
+ };
+
+ RenderToFile(target);
+ CompareImages();
+ }
+
+#if PERSPEX_CAIRO
+ [Fact(Skip = "ImageBrush not yet implemented on Cairo")]
+#else
+ [Fact]
+#endif
+ public void ImageBrush_NoStretch_NoTile_Alignment_Center()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Rectangle
+ {
+ Fill = new ImageBrush
+ {
+ Stretch = Stretch.None,
+ TileMode = TileMode.None,
+ AlignmentX = AlignmentX.Center,
+ AlignmentY = AlignmentY.Center,
+ Source = new Bitmap(BitmapPath),
+ }
+ }
+ };
+
+ RenderToFile(target);
+ CompareImages();
+ }
+
+#if PERSPEX_CAIRO
+ [Fact(Skip = "ImageBrush not yet implemented on Cairo")]
+#else
+ [Fact]
+#endif
+ public void ImageBrush_NoStretch_NoTile_Alignment_BottomRight()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Rectangle
+ {
+ Fill = new ImageBrush
+ {
+ Stretch = Stretch.None,
+ TileMode = TileMode.None,
+ AlignmentX = AlignmentX.Right,
+ AlignmentY = AlignmentY.Bottom,
+ Source = new Bitmap(BitmapPath),
+ }
+ }
+ };
+
+ RenderToFile(target);
+ CompareImages();
+ }
+
+#if PERSPEX_CAIRO
+ [Fact(Skip = "ImageBrush not yet implemented on Cairo")]
+#else
+ [Fact]
+#endif
+ public void ImageBrush_Fill_NoTile()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 920,
+ Height = 920,
+ Child = new Rectangle
+ {
+ Fill = new ImageBrush
+ {
+ Stretch = Stretch.Fill,
+ TileMode = TileMode.None,
+ Source = new Bitmap(BitmapPath),
+ }
+ }
+ };
+
+ RenderToFile(target);
+ CompareImages();
+ }
+
+#if PERSPEX_CAIRO
+ [Fact(Skip = "ImageBrush not yet implemented on Cairo")]
+#else
+ [Fact]
+#endif
+ public void ImageBrush_Uniform_NoTile()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 300,
+ Height = 200,
+ Child = new Rectangle
+ {
+ Fill = new ImageBrush
+ {
+ Stretch = Stretch.Uniform,
+ TileMode = TileMode.None,
+ Source = new Bitmap(BitmapPath),
+ }
+ }
+ };
+
+ RenderToFile(target);
+ CompareImages();
+ }
+
+#if PERSPEX_CAIRO
+ [Fact(Skip = "ImageBrush not yet implemented on Cairo")]
+#else
+ [Fact]
+#endif
+ public void ImageBrush_UniformToFill_NoTile()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 300,
+ Height = 200,
+ Child = new Rectangle
+ {
+ Fill = new ImageBrush
+ {
+ Stretch = Stretch.UniformToFill,
+ TileMode = TileMode.None,
+ Source = new Bitmap(BitmapPath),
+ }
+ }
+ };
+
+ RenderToFile(target);
+ CompareImages();
+ }
+
+#if PERSPEX_CAIRO
+ [Fact(Skip = "ImageBrush not yet implemented on Cairo")]
+#else
+ [Fact]
+#endif
+ public void ImageBrush_NoStretch_NoTile_BottomRightQuarterSource()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Rectangle
+ {
+ Fill = new ImageBrush
+ {
+ Stretch = Stretch.None,
+ TileMode = TileMode.None,
+ SourceRect = new RelativeRect(250, 250, 250, 250, RelativeUnit.Absolute),
+ Source = new Bitmap(BitmapPath),
+ }
+ }
+ };
+
+ RenderToFile(target);
+ CompareImages();
+ }
+
+#if PERSPEX_CAIRO
+ [Fact(Skip = "ImageBrush not yet implemented on Cairo")]
+#else
+ [Fact]
+#endif
+ public void ImageBrush_NoStretch_NoTile_BottomRightQuarterDest()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Rectangle
+ {
+ Fill = new ImageBrush
+ {
+ Stretch = Stretch.None,
+ TileMode = TileMode.None,
+ DestinationRect = new RelativeRect(92, 92, 92, 92, RelativeUnit.Absolute),
+ Source = new Bitmap(BitmapPath),
+ }
+ }
+ };
+
+ RenderToFile(target);
+ CompareImages();
+ }
+
+#if PERSPEX_CAIRO
+ [Fact(Skip = "ImageBrush not yet implemented on Cairo")]
+#else
+ [Fact]
+#endif
+ public void ImageBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Rectangle
+ {
+ Fill = new ImageBrush
+ {
+ Stretch = Stretch.None,
+ TileMode = TileMode.None,
+ SourceRect = new RelativeRect(0.5, 0.5, 0.5, 0.5, RelativeUnit.Relative),
+ DestinationRect = new RelativeRect(0.5, 0.5, 0.5, 0.5, RelativeUnit.Relative),
+ Source = new Bitmap(BitmapPath),
+ }
+ }
+ };
+
+ RenderToFile(target);
+ CompareImages();
+ }
+
+#if PERSPEX_CAIRO
+ [Fact(Skip = "ImageBrush not yet implemented on Cairo")]
+#else
+ [Fact]
+#endif
+ public void ImageBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Rectangle
+ {
+ Fill = new ImageBrush
+ {
+ Stretch = Stretch.None,
+ TileMode = TileMode.Tile,
+ SourceRect = new RelativeRect(0.5, 0.5, 0.5, 0.5, RelativeUnit.Relative),
+ DestinationRect = new RelativeRect(0.25, 0.25, 0.5, 0.5, RelativeUnit.Relative),
+ Source = new Bitmap(BitmapPath),
+ }
+ }
+ };
+
+ RenderToFile(target);
+ CompareImages();
+ }
+
+#if PERSPEX_CAIRO
+ [Fact(Skip = "ImageBrush not yet implemented on Cairo")]
+#else
+ [Fact]
+#endif
+ public void ImageBrush_NoStretch_FlipX_TopLeftDest()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Rectangle
+ {
+ Fill = new ImageBrush
+ {
+ Stretch = Stretch.None,
+ TileMode = TileMode.FlipX,
+ DestinationRect = new RelativeRect(0, 0, 0.5, 0.5, RelativeUnit.Relative),
+ Source = new Bitmap(BitmapPath),
+ }
+ }
+ };
+
+ RenderToFile(target);
+ CompareImages();
+ }
+
+#if PERSPEX_CAIRO
+ [Fact(Skip = "ImageBrush not yet implemented on Cairo")]
+#else
+ [Fact]
+#endif
+ public void ImageBrush_NoStretch_FlipY_TopLeftDest()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Rectangle
+ {
+ Fill = new ImageBrush
+ {
+ Stretch = Stretch.None,
+ TileMode = TileMode.FlipY,
+ DestinationRect = new RelativeRect(0, 0, 0.5, 0.5, RelativeUnit.Relative),
+ Source = new Bitmap(BitmapPath),
+ }
+ }
+ };
+
+ RenderToFile(target);
+ CompareImages();
+ }
+
+#if PERSPEX_CAIRO
+ [Fact(Skip = "ImageBrush not yet implemented on Cairo")]
+#else
+ [Fact]
+#endif
+ public void ImageBrush_NoStretch_FlipXY_TopLeftDest()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Rectangle
+ {
+ Fill = new ImageBrush
+ {
+ Stretch = Stretch.None,
+ TileMode = TileMode.FlipXY,
+ DestinationRect = new RelativeRect(0, 0, 0.5, 0.5, RelativeUnit.Relative),
+ Source = new Bitmap(BitmapPath),
+ }
+ }
+ };
+
+ RenderToFile(target);
+ CompareImages();
+ }
+ }
+}
diff --git a/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_Fill_NoTile.expected.png b/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_Fill_NoTile.expected.png
new file mode 100644
index 0000000000..73d147bf77
Binary files /dev/null and b/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_Fill_NoTile.expected.png differ
diff --git a/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_FlipXY_TopLeftDest.expected.png b/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_FlipXY_TopLeftDest.expected.png
new file mode 100644
index 0000000000..f99f56ec14
Binary files /dev/null and b/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_FlipXY_TopLeftDest.expected.png differ
diff --git a/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_FlipX_TopLeftDest.expected.png b/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_FlipX_TopLeftDest.expected.png
new file mode 100644
index 0000000000..4d89f995c4
Binary files /dev/null and b/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_FlipX_TopLeftDest.expected.png differ
diff --git a/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_FlipY_TopLeftDest.expected.png b/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_FlipY_TopLeftDest.expected.png
new file mode 100644
index 0000000000..75c53f0c28
Binary files /dev/null and b/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_FlipY_TopLeftDest.expected.png differ
diff --git a/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_BottomRight.expected.png b/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_BottomRight.expected.png
new file mode 100644
index 0000000000..a13b34ba2d
Binary files /dev/null and b/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_BottomRight.expected.png differ
diff --git a/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_Center.expected.png b/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_Center.expected.png
new file mode 100644
index 0000000000..14704f751c
Binary files /dev/null and b/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_Center.expected.png differ
diff --git a/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_TopLeft.expected.png b/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_TopLeft.expected.png
new file mode 100644
index 0000000000..7ebac13d30
Binary files /dev/null and b/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_TopLeft.expected.png differ
diff --git a/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterDest.expected.png b/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterDest.expected.png
new file mode 100644
index 0000000000..dd41cb98c3
Binary files /dev/null and b/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterDest.expected.png differ
diff --git a/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterSource.expected.png b/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterSource.expected.png
new file mode 100644
index 0000000000..ab9f2b76e3
Binary files /dev/null and b/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterSource.expected.png differ
diff --git a/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest.expected.png b/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest.expected.png
new file mode 100644
index 0000000000..fea4a2a8e9
Binary files /dev/null and b/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest.expected.png differ
diff --git a/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest.expected.png b/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest.expected.png
new file mode 100644
index 0000000000..afd39c2360
Binary files /dev/null and b/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest.expected.png differ
diff --git a/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_UniformToFill_NoTile.expected.png b/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_UniformToFill_NoTile.expected.png
new file mode 100644
index 0000000000..e173fa6cee
Binary files /dev/null and b/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_UniformToFill_NoTile.expected.png differ
diff --git a/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_Uniform_NoTile.expected.png b/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_Uniform_NoTile.expected.png
new file mode 100644
index 0000000000..de73af8170
Binary files /dev/null and b/Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_Uniform_NoTile.expected.png differ
diff --git a/Tests/TestFiles/Direct2D1/Media/ImageBrush/github_icon.png b/Tests/TestFiles/Direct2D1/Media/ImageBrush/github_icon.png
new file mode 100644
index 0000000000..cd053c5fe1
Binary files /dev/null and b/Tests/TestFiles/Direct2D1/Media/ImageBrush/github_icon.png differ
diff --git a/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Fill_NoTile.expected.png b/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Fill_NoTile.expected.png
new file mode 100644
index 0000000000..6638456643
Binary files /dev/null and b/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Fill_NoTile.expected.png differ
diff --git a/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_FlipXY_TopLeftDest.expected.png b/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_FlipXY_TopLeftDest.expected.png
new file mode 100644
index 0000000000..e6b0098c25
Binary files /dev/null and b/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_FlipXY_TopLeftDest.expected.png differ
diff --git a/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_FlipX_TopLeftDest.expected.png b/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_FlipX_TopLeftDest.expected.png
new file mode 100644
index 0000000000..c64b88dc68
Binary files /dev/null and b/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_FlipX_TopLeftDest.expected.png differ
diff --git a/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_FlipY_TopLeftDest.expected.png b/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_FlipY_TopLeftDest.expected.png
new file mode 100644
index 0000000000..a6e8b0688c
Binary files /dev/null and b/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_FlipY_TopLeftDest.expected.png differ
diff --git a/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_BottomRight.expected.png b/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_BottomRight.expected.png
new file mode 100644
index 0000000000..a13b34ba2d
Binary files /dev/null and b/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_BottomRight.expected.png differ
diff --git a/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_Center.expected.png b/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_Center.expected.png
new file mode 100644
index 0000000000..5d75c9cc6c
Binary files /dev/null and b/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_Center.expected.png differ
diff --git a/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_TopLeft.expected.png b/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_TopLeft.expected.png
new file mode 100644
index 0000000000..7ebac13d30
Binary files /dev/null and b/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_TopLeft.expected.png differ
diff --git a/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterDest.expected.png b/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterDest.expected.png
new file mode 100644
index 0000000000..8664cafbdf
Binary files /dev/null and b/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterDest.expected.png differ
diff --git a/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterSource.expected.png b/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterSource.expected.png
new file mode 100644
index 0000000000..ab9f2b76e3
Binary files /dev/null and b/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterSource.expected.png differ
diff --git a/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest.expected.png b/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest.expected.png
new file mode 100644
index 0000000000..fea4a2a8e9
Binary files /dev/null and b/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest.expected.png differ
diff --git a/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest.expected.png b/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest.expected.png
new file mode 100644
index 0000000000..afd39c2360
Binary files /dev/null and b/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest.expected.png differ
diff --git a/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_No_Visual.expected.png b/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_No_Visual.expected.png
deleted file mode 100644
index 31d16498cc..0000000000
Binary files a/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_No_Visual.expected.png and /dev/null differ
diff --git a/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_UniformToFill_NoTile.expected.png b/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_UniformToFill_NoTile.expected.png
new file mode 100644
index 0000000000..fefd9c0d30
Binary files /dev/null and b/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_UniformToFill_NoTile.expected.png differ
diff --git a/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Uniform_NoTile.expected.png b/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Uniform_NoTile.expected.png
new file mode 100644
index 0000000000..ca7d498ba4
Binary files /dev/null and b/Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Uniform_NoTile.expected.png differ
diff --git a/Tests/TestFiles/Direct2D1/Media/VisualBrush/github_icon.png b/Tests/TestFiles/Direct2D1/Media/VisualBrush/github_icon.png
new file mode 100644
index 0000000000..cd053c5fe1
Binary files /dev/null and b/Tests/TestFiles/Direct2D1/Media/VisualBrush/github_icon.png differ
diff --git a/src/Perspex.Controls/Image.cs b/src/Perspex.Controls/Image.cs
index 0782b51f2a..79b79c6141 100644
--- a/src/Perspex.Controls/Image.cs
+++ b/src/Perspex.Controls/Image.cs
@@ -73,29 +73,14 @@ namespace Perspex.Controls
/// The desired size of the control.
protected override Size MeasureOverride(Size availableSize)
{
- double width = 0;
- double height = 0;
- Vector scale = new Vector();
-
if (Source != null)
{
- width = Source.PixelWidth;
- height = Source.PixelHeight;
-
- if (Width > 0)
- {
- availableSize = new Size(Width, availableSize.Height);
- }
-
- if (Height > 0)
- {
- availableSize = new Size(availableSize.Width, Height);
- }
-
- scale = Stretch.CalculateScaling(availableSize, new Size(width, height));
+ return new Size(Source.PixelWidth, Source.PixelHeight);
+ }
+ else
+ {
+ return new Size();
}
-
- return new Size(width * scale.X, height * scale.Y);
}
}
}
\ No newline at end of file
diff --git a/src/Perspex.SceneGraph/Media/ImageBush.cs b/src/Perspex.SceneGraph/Media/ImageBush.cs
new file mode 100644
index 0000000000..1b3fd07d28
--- /dev/null
+++ b/src/Perspex.SceneGraph/Media/ImageBush.cs
@@ -0,0 +1,44 @@
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using Perspex.Media.Imaging;
+
+namespace Perspex.Media
+{
+ ///
+ /// Paints an area with an .
+ ///
+ public class ImageBrush : TileBrush
+ {
+ ///
+ /// Defines the property.
+ ///
+ public static readonly PerspexProperty SourceProperty =
+ PerspexProperty.Register("Source");
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public ImageBrush()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The image to draw.
+ public ImageBrush(IBitmap source)
+ {
+ Source = source;
+ }
+
+ ///
+ /// Gets or sets the image to draw.
+ ///
+ public IBitmap Source
+ {
+ get { return GetValue(SourceProperty); }
+ set { SetValue(SourceProperty, value); }
+ }
+ }
+}
diff --git a/src/Perspex.SceneGraph/Perspex.SceneGraph.csproj b/src/Perspex.SceneGraph/Perspex.SceneGraph.csproj
index 660cbe38d7..fac8cf2924 100644
--- a/src/Perspex.SceneGraph/Perspex.SceneGraph.csproj
+++ b/src/Perspex.SceneGraph/Perspex.SceneGraph.csproj
@@ -64,11 +64,11 @@
-
+
@@ -97,6 +97,7 @@
+
diff --git a/src/Windows/Perspex.Direct2D1/Media/DrawingContext.cs b/src/Windows/Perspex.Direct2D1/Media/DrawingContext.cs
index 53f5ff3d5c..d0c2e4c254 100644
--- a/src/Windows/Perspex.Direct2D1/Media/DrawingContext.cs
+++ b/src/Windows/Perspex.Direct2D1/Media/DrawingContext.cs
@@ -303,6 +303,7 @@ namespace Perspex.Direct2D1.Media
{
var solidColorBrush = brush as Perspex.Media.SolidColorBrush;
var linearGradientBrush = brush as Perspex.Media.LinearGradientBrush;
+ var imageBrush = brush as ImageBrush;
var visualBrush = brush as VisualBrush;
if (solidColorBrush != null)
@@ -313,6 +314,10 @@ namespace Perspex.Direct2D1.Media
{
return new LinearGradientBrushImpl(linearGradientBrush, _renderTarget, destinationSize);
}
+ else if (imageBrush != null)
+ {
+ return new ImageBrushImpl(imageBrush, _renderTarget, destinationSize);
+ }
else if (visualBrush != null)
{
return new VisualBrushImpl(visualBrush, _renderTarget, destinationSize);
diff --git a/src/Windows/Perspex.Direct2D1/Media/ImageBrushImpl.cs b/src/Windows/Perspex.Direct2D1/Media/ImageBrushImpl.cs
new file mode 100644
index 0000000000..590f7d1f33
--- /dev/null
+++ b/src/Windows/Perspex.Direct2D1/Media/ImageBrushImpl.cs
@@ -0,0 +1,95 @@
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+using Perspex.Media;
+using SharpDX.Direct2D1;
+
+namespace Perspex.Direct2D1.Media
+{
+ public class ImageBrushImpl : TileBrushImpl
+ {
+ public ImageBrushImpl(
+ ImageBrush brush,
+ RenderTarget target,
+ Size targetSize)
+ {
+ if (brush.Source == null)
+ {
+ return;
+ }
+
+ var image = ((BitmapImpl)brush.Source.PlatformImpl).GetDirect2DBitmap(target);
+ var imageSize = new Size(brush.Source.PixelWidth, brush.Source.PixelHeight);
+ var tileMode = brush.TileMode;
+ var sourceRect = brush.SourceRect.ToPixels(imageSize);
+ var destinationRect = brush.DestinationRect.ToPixels(targetSize);
+ var scale = brush.Stretch.CalculateScaling(destinationRect.Size, sourceRect.Size);
+ var translate = CalculateTranslate(brush, sourceRect, destinationRect, scale);
+ var intermediateSize = CalculateIntermediateSize(tileMode, targetSize, destinationRect.Size);
+ var brtOpts = CompatibleRenderTargetOptions.None;
+
+ // TODO: There are times where we don't need to draw an intermediate bitmap. Identify
+ // them and directly use 'image' in those cases.
+ using (var intermediate = new BitmapRenderTarget(target, brtOpts, intermediateSize))
+ {
+ Rect drawRect;
+ var transform = CalculateIntermediateTransform(
+ tileMode,
+ sourceRect,
+ destinationRect,
+ scale,
+ translate,
+ out drawRect);
+
+ intermediate.BeginDraw();
+ intermediate.Transform = transform.ToDirect2D();
+ drawRect *= -transform;
+ intermediate.PushAxisAlignedClip(drawRect.ToDirect2D(), AntialiasMode.Aliased);
+ intermediate.DrawBitmap(image, 1, BitmapInterpolationMode.Linear);
+ intermediate.PopAxisAlignedClip();
+ intermediate.EndDraw();
+
+ this.PlatformBrush = new BitmapBrush(
+ target,
+ intermediate.Bitmap,
+ GetBitmapBrushProperties(brush),
+ GetBrushProperties(brush, destinationRect));
+ }
+ }
+
+ private BitmapBrush CreateDirectBrush(
+ ImageBrush brush,
+ RenderTarget target,
+ Bitmap image,
+ Rect sourceRect,
+ Rect destinationRect)
+ {
+ var tileMode = brush.TileMode;
+ var scale = brush.Stretch.CalculateScaling(destinationRect.Size, sourceRect.Size);
+ var translate = CalculateTranslate(brush, sourceRect, destinationRect, scale);
+ var transform = Matrix.CreateTranslation(-sourceRect.Position) *
+ Matrix.CreateScale(scale) *
+ Matrix.CreateTranslation(translate);
+
+ var opts = new BrushProperties
+ {
+ Transform = transform.ToDirect2D(),
+ Opacity = (float)brush.Opacity,
+ };
+
+ var bitmapOpts = new BitmapBrushProperties
+ {
+ ExtendModeX = GetExtendModeX(tileMode),
+ ExtendModeY = GetExtendModeY(tileMode),
+ };
+
+ return new BitmapBrush(target, image, bitmapOpts, opts);
+ }
+
+ private BitmapBrush CreateIndirectBrush()
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/Windows/Perspex.Direct2D1/Media/TileBrushImpl.cs b/src/Windows/Perspex.Direct2D1/Media/TileBrushImpl.cs
new file mode 100644
index 0000000000..fd9b938b2d
--- /dev/null
+++ b/src/Windows/Perspex.Direct2D1/Media/TileBrushImpl.cs
@@ -0,0 +1,135 @@
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+using Perspex.Layout;
+using Perspex.Media;
+using SharpDX;
+using SharpDX.Direct2D1;
+
+namespace Perspex.Direct2D1.Media
+{
+ public class TileBrushImpl : BrushImpl
+ {
+ ///
+ /// Calculates a translate based on a , a source and destination
+ /// rectangle and a scale.
+ ///
+ /// The brush.
+ /// The source rectangle.
+ /// The destination rectangle.
+ /// The scale factor.
+ /// A vector with the X and Y translate.
+ protected static Vector CalculateTranslate(
+ TileBrush brush,
+ Rect sourceRect,
+ Rect destinationRect,
+ Vector scale)
+ {
+ var x = 0.0;
+ var y = 0.0;
+ var size = sourceRect.Size * scale;
+
+ switch (brush.AlignmentX)
+ {
+ case AlignmentX.Center:
+ x += (destinationRect.Width - size.Width) / 2;
+ break;
+ case AlignmentX.Right:
+ x += destinationRect.Width - size.Width;
+ break;
+ }
+
+ switch (brush.AlignmentY)
+ {
+ case AlignmentY.Center:
+ y += (destinationRect.Height - size.Height) / 2;
+ break;
+ case AlignmentY.Bottom:
+ y += destinationRect.Height - size.Height;
+ break;
+ }
+
+ return new Vector(x, y);
+ }
+
+ protected static Size2F CalculateIntermediateSize(
+ TileMode tileMode,
+ Size targetSize,
+ Size destinationSize)
+ {
+ var result = tileMode == TileMode.None ? targetSize : destinationSize;
+ return result.ToSharpDX();
+ }
+
+ protected static Matrix CalculateIntermediateTransform(
+ TileMode tileMode,
+ Rect sourceRect,
+ Rect destinationRect,
+ Vector scale,
+ Vector translate,
+ out Rect drawRect)
+ {
+ var transform = Matrix.CreateTranslation(-sourceRect.Position) *
+ Matrix.CreateScale(scale) *
+ Matrix.CreateTranslation(translate);
+ Rect dr;
+
+ if (tileMode == TileMode.None)
+ {
+ dr = destinationRect;
+ transform *= Matrix.CreateTranslation(destinationRect.Position);
+ }
+ else
+ {
+ dr = new Rect(destinationRect.Size);
+ }
+
+ drawRect = dr;
+
+ return transform;
+ }
+
+ protected static BrushProperties GetBrushProperties(TileBrush brush, Rect destinationRect)
+ {
+ var tileMode = brush.TileMode;
+
+ return new BrushProperties
+ {
+ Opacity = (float)brush.Opacity,
+ Transform = brush.TileMode != TileMode.None ?
+ SharpDX.Matrix3x2.Translation(
+ (float)destinationRect.X,
+ (float)destinationRect.Y) :
+ SharpDX.Matrix3x2.Identity,
+ };
+ }
+
+ protected static BitmapBrushProperties GetBitmapBrushProperties(TileBrush brush)
+ {
+ var tileMode = brush.TileMode;
+
+ return new BitmapBrushProperties
+ {
+ ExtendModeX = GetExtendModeX(tileMode),
+ ExtendModeY = GetExtendModeY(tileMode),
+ };
+ }
+
+ protected static ExtendMode GetExtendModeX(TileMode tileMode)
+ {
+ return (tileMode & TileMode.FlipX) != 0 ? ExtendMode.Mirror : ExtendMode.Wrap;
+ }
+
+ protected static ExtendMode GetExtendModeY(TileMode tileMode)
+ {
+ return (tileMode & TileMode.FlipY) != 0 ? ExtendMode.Mirror : ExtendMode.Wrap;
+ }
+
+ public override void Dispose()
+ {
+ ((BitmapBrush)PlatformBrush)?.Bitmap.Dispose();
+ base.Dispose();
+ }
+ }
+}
diff --git a/src/Windows/Perspex.Direct2D1/Media/VisualBrushImpl.cs b/src/Windows/Perspex.Direct2D1/Media/VisualBrushImpl.cs
index f7e12187f6..bc049e7ca3 100644
--- a/src/Windows/Perspex.Direct2D1/Media/VisualBrushImpl.cs
+++ b/src/Windows/Perspex.Direct2D1/Media/VisualBrushImpl.cs
@@ -8,7 +8,7 @@ using SharpDX.Direct2D1;
namespace Perspex.Direct2D1.Media
{
- public class VisualBrushImpl : BrushImpl
+ public class VisualBrushImpl : TileBrushImpl
{
public VisualBrushImpl(
VisualBrush brush,
@@ -30,86 +30,78 @@ namespace Perspex.Direct2D1.Media
layoutable.Arrange(new Rect(layoutable.DesiredSize));
}
+ var tileMode = brush.TileMode;
var sourceRect = brush.SourceRect.ToPixels(layoutable.Bounds.Size);
var destinationRect = brush.DestinationRect.ToPixels(targetSize);
- var bitmapSize = brush.TileMode == TileMode.None ? targetSize : destinationRect.Size;
var scale = brush.Stretch.CalculateScaling(destinationRect.Size, sourceRect.Size);
var translate = CalculateTranslate(brush, sourceRect, destinationRect, scale);
- var options = CompatibleRenderTargetOptions.None;
+ var intermediateSize = CalculateIntermediateSize(tileMode, targetSize, destinationRect.Size);
+ var brtOpts = CompatibleRenderTargetOptions.None;
- using (var brt = new BitmapRenderTarget(target, options, bitmapSize.ToSharpDX()))
+ // TODO: There are times where we don't need to draw an intermediate bitmap. Identify
+ // them and directly use 'image' in those cases.
+ using (var intermediate = new BitmapRenderTarget(target, brtOpts, intermediateSize))
{
- var renderer = new Renderer(brt);
- var transform = Matrix.CreateTranslation(-sourceRect.Position) *
- Matrix.CreateScale(scale) *
- Matrix.CreateTranslation(translate);
-
Rect drawRect;
-
- if (brush.TileMode == TileMode.None)
- {
- drawRect = destinationRect;
- transform *= Matrix.CreateTranslation(destinationRect.Position);
- }
- else
- {
- drawRect = new Rect(0, 0, destinationRect.Width, destinationRect.Height);
- }
+ var transform = CalculateIntermediateTransform(
+ tileMode,
+ sourceRect,
+ destinationRect,
+ scale,
+ translate,
+ out drawRect);
+ var renderer = new Renderer(intermediate);
renderer.Render(visual, null, transform, drawRect);
- var result = new BitmapBrush(brt, brt.Bitmap);
- result.ExtendModeX = (brush.TileMode & TileMode.FlipX) != 0 ? ExtendMode.Mirror : ExtendMode.Wrap;
- result.ExtendModeY = (brush.TileMode & TileMode.FlipY) != 0 ? ExtendMode.Mirror : ExtendMode.Wrap;
-
- if (brush.TileMode != TileMode.None)
- {
- result.Transform = SharpDX.Matrix3x2.Translation(
- (float)destinationRect.X,
- (float)destinationRect.Y);
- }
-
- PlatformBrush = result;
+ this.PlatformBrush = new BitmapBrush(
+ target,
+ intermediate.Bitmap,
+ GetBitmapBrushProperties(brush),
+ GetBrushProperties(brush, destinationRect));
}
- }
- private static Vector CalculateTranslate(
- VisualBrush brush,
- Rect sourceRect,
- Rect destinationRect,
- Vector scale)
- {
- var x = 0.0;
- var y = 0.0;
- var size = sourceRect.Size * scale;
-
- switch (brush.AlignmentX)
- {
- case AlignmentX.Center:
- x += (destinationRect.Width - size.Width) / 2;
- break;
- case AlignmentX.Right:
- x += destinationRect.Width - size.Width;
- break;
- }
-
- switch (brush.AlignmentY)
- {
- case AlignmentY.Center:
- y += (destinationRect.Height - size.Height) / 2;
- break;
- case AlignmentY.Bottom:
- y += destinationRect.Height - size.Height;
- break;
- }
-
- return new Vector(x, y);
- }
-
- public override void Dispose()
- {
- ((BitmapBrush)PlatformBrush)?.Bitmap.Dispose();
- base.Dispose();
+ //var sourceRect = brush.SourceRect.ToPixels(layoutable.Bounds.Size);
+ //var destinationRect = brush.DestinationRect.ToPixels(targetSize);
+ //var bitmapSize = brush.TileMode == TileMode.None ? targetSize : destinationRect.Size;
+ //var scale = brush.Stretch.CalculateScaling(destinationRect.Size, sourceRect.Size);
+ //var translate = CalculateTranslate(brush, sourceRect, destinationRect, scale);
+ //var options = CompatibleRenderTargetOptions.None;
+
+ //using (var brt = new BitmapRenderTarget(target, options, bitmapSize.ToSharpDX()))
+ //{
+ // var renderer = new Renderer(brt);
+ // var transform = Matrix.CreateTranslation(-sourceRect.Position) *
+ // Matrix.CreateScale(scale) *
+ // Matrix.CreateTranslation(translate);
+
+ // Rect drawRect;
+
+ // if (brush.TileMode == TileMode.None)
+ // {
+ // drawRect = destinationRect;
+ // transform *= Matrix.CreateTranslation(destinationRect.Position);
+ // }
+ // else
+ // {
+ // drawRect = new Rect(0, 0, destinationRect.Width, destinationRect.Height);
+ // }
+
+ // renderer.Render(visual, null, transform, drawRect);
+
+ // var result = new BitmapBrush(brt, brt.Bitmap);
+ // result.ExtendModeX = GetExtendModeX(brush.TileMode);
+ // result.ExtendModeY = GetExtendModeY(brush.TileMode);
+
+ // if (brush.TileMode != TileMode.None)
+ // {
+ // result.Transform = SharpDX.Matrix3x2.Translation(
+ // (float)destinationRect.X,
+ // (float)destinationRect.Y);
+ // }
+
+ // PlatformBrush = result;
+ //}
}
}
}
diff --git a/src/Windows/Perspex.Direct2D1/Perspex.Direct2D1.csproj b/src/Windows/Perspex.Direct2D1/Perspex.Direct2D1.csproj
index 922f67391b..0fa382e99d 100644
--- a/src/Windows/Perspex.Direct2D1/Perspex.Direct2D1.csproj
+++ b/src/Windows/Perspex.Direct2D1/Perspex.Direct2D1.csproj
@@ -82,6 +82,8 @@
+
+
diff --git a/tests/Perspex.RenderTests/Media/VisualBrushTests.cs b/tests/Perspex.RenderTests/Media/VisualBrushTests.cs
index 499f8207c3..7003adca0b 100644
--- a/tests/Perspex.RenderTests/Media/VisualBrushTests.cs
+++ b/tests/Perspex.RenderTests/Media/VisualBrushTests.cs
@@ -5,6 +5,7 @@ using Perspex.Controls;
using Perspex.Controls.Shapes;
using Perspex.Layout;
using Perspex.Media;
+using Perspex.Media.Imaging;
using Xunit;
#if PERSPEX_CAIRO
@@ -20,47 +21,41 @@ namespace Perspex.Direct2D1.RenderTests.Media
{
}
-#if PERSPEX_CAIRO
- [Fact(Skip = "VisualBrush not yet implemented on Cairo")]
-#else
- [Fact]
-#endif
- public void VisualBrush_Align_TopLeft()
+ private string BitmapPath
{
- Decorator target = new Decorator
+ get { return System.IO.Path.Combine(OutputPath, "github_icon.png"); }
+ }
+
+ private Control Visual
+ {
+ get
{
- Padding = new Thickness(8),
- Width = 200,
- Height = 200,
- Child = new Rectangle
+ return new Panel
{
- Fill = new VisualBrush
+ Children = new Perspex.Controls.Controls
{
- AlignmentX = AlignmentX.Left,
- AlignmentY = AlignmentY.Top,
- Stretch = Stretch.None,
- Visual = new Border
+ new Image
+ {
+ Source = new Bitmap(BitmapPath),
+ },
+ new Border
{
- Width = 92,
- Height = 92,
- Background = Brushes.Red,
- BorderBrush = Brushes.Black,
+ BorderBrush = Brushes.Blue,
BorderThickness = 2,
+ HorizontalAlignment = HorizontalAlignment.Center,
+ VerticalAlignment = VerticalAlignment.Center,
Child = new TextBlock
{
- Text = "Perspex",
- FontSize = 12,
+ FontSize = 24,
FontFamily = "Arial",
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
+ Background = Brushes.Green,
+ Foreground = Brushes.Yellow,
+ Text = "VisualBrush",
}
}
}
- }
- };
-
- RenderToFile(target);
- CompareImages();
+ };
+ }
}
#if PERSPEX_CAIRO
@@ -68,7 +63,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
#else
[Fact]
#endif
- public void VisualBrush_Align_Center()
+ public void VisualBrush_NoStretch_NoTile_Alignment_TopLeft()
{
Decorator target = new Decorator
{
@@ -79,25 +74,11 @@ namespace Perspex.Direct2D1.RenderTests.Media
{
Fill = new VisualBrush
{
- AlignmentX = AlignmentX.Center,
- AlignmentY = AlignmentY.Center,
Stretch = Stretch.None,
- Visual = new Border
- {
- Width = 92,
- Height = 92,
- Background = Brushes.Red,
- BorderBrush = Brushes.Black,
- BorderThickness = 2,
- Child = new TextBlock
- {
- Text = "Perspex",
- FontSize = 12,
- FontFamily = "Arial",
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
- }
- }
+ TileMode = TileMode.None,
+ AlignmentX = AlignmentX.Left,
+ AlignmentY = AlignmentY.Top,
+ Visual = Visual,
}
}
};
@@ -111,7 +92,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
#else
[Fact]
#endif
- public void VisualBrush_Align_BottomRight()
+ public void VisualBrush_NoStretch_NoTile_Alignment_Center()
{
Decorator target = new Decorator
{
@@ -122,25 +103,11 @@ namespace Perspex.Direct2D1.RenderTests.Media
{
Fill = new VisualBrush
{
- AlignmentX = AlignmentX.Right,
- AlignmentY = AlignmentY.Bottom,
Stretch = Stretch.None,
- Visual = new Border
- {
- Width = 92,
- Height = 92,
- Background = Brushes.Red,
- BorderBrush = Brushes.Black,
- BorderThickness = 2,
- Child = new TextBlock
- {
- Text = "Perspex",
- FontSize = 12,
- FontFamily = "Arial",
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
- }
- }
+ TileMode = TileMode.None,
+ AlignmentX = AlignmentX.Center,
+ AlignmentY = AlignmentY.Center,
+ Visual = Visual,
}
}
};
@@ -154,34 +121,22 @@ namespace Perspex.Direct2D1.RenderTests.Media
#else
[Fact]
#endif
- public void VisualBrush_Stretch_Fill_Large()
+ public void VisualBrush_NoStretch_NoTile_Alignment_BottomRight()
{
Decorator target = new Decorator
{
Padding = new Thickness(8),
- Width = 920,
- Height = 920,
+ Width = 200,
+ Height = 200,
Child = new Rectangle
{
Fill = new VisualBrush
{
- Stretch = Stretch.Fill,
- Visual = new Border
- {
- Width = 92,
- Height = 92,
- Background = Brushes.Red,
- BorderBrush = Brushes.Black,
- BorderThickness = 2,
- Child = new TextBlock
- {
- Text = "Perspex",
- FontSize = 12,
- FontFamily = "Arial",
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
- }
- }
+ Stretch = Stretch.None,
+ TileMode = TileMode.None,
+ AlignmentX = AlignmentX.Right,
+ AlignmentY = AlignmentY.Bottom,
+ Visual = Visual,
}
}
};
@@ -195,34 +150,20 @@ namespace Perspex.Direct2D1.RenderTests.Media
#else
[Fact]
#endif
- public void VisualBrush_Stretch_Uniform()
+ public void VisualBrush_Fill_NoTile()
{
Decorator target = new Decorator
{
Padding = new Thickness(8),
Width = 920,
- Height = 820,
+ Height = 920,
Child = new Rectangle
{
Fill = new VisualBrush
{
- Stretch = Stretch.Uniform,
- Visual = new Border
- {
- Width = 92,
- Height = 92,
- Background = Brushes.Red,
- BorderBrush = Brushes.Black,
- BorderThickness = 2,
- Child = new TextBlock
- {
- Text = "Perspex",
- FontSize = 12,
- FontFamily = "Arial",
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
- }
- }
+ Stretch = Stretch.Fill,
+ TileMode = TileMode.None,
+ Visual = Visual,
}
}
};
@@ -236,34 +177,20 @@ namespace Perspex.Direct2D1.RenderTests.Media
#else
[Fact]
#endif
- public void VisualBrush_Stretch_UniformToFill()
+ public void VisualBrush_Uniform_NoTile()
{
Decorator target = new Decorator
{
Padding = new Thickness(8),
- Width = 920,
- Height = 820,
+ Width = 300,
+ Height = 200,
Child = new Rectangle
{
Fill = new VisualBrush
{
- Stretch = Stretch.UniformToFill,
- Visual = new Border
- {
- Width = 92,
- Height = 92,
- Background = Brushes.Red,
- BorderBrush = Brushes.Black,
- BorderThickness = 2,
- Child = new TextBlock
- {
- Text = "Perspex",
- FontSize = 12,
- FontFamily = "Arial",
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
- }
- }
+ Stretch = Stretch.Uniform,
+ TileMode = TileMode.None,
+ Visual = Visual,
}
}
};
@@ -277,34 +204,20 @@ namespace Perspex.Direct2D1.RenderTests.Media
#else
[Fact]
#endif
- public void VisualBrush_SourceRect_Absolute()
+ public void VisualBrush_UniformToFill_NoTile()
{
Decorator target = new Decorator
{
Padding = new Thickness(8),
- Width = 200,
+ Width = 300,
Height = 200,
Child = new Rectangle
{
Fill = new VisualBrush
{
- SourceRect = new RelativeRect(40, 40, 100, 100, RelativeUnit.Absolute),
- Visual = new Border
- {
- Width = 180,
- Height = 180,
- Background = Brushes.Red,
- BorderBrush = Brushes.Black,
- BorderThickness = 2,
- Child = new Ellipse
- {
- Width = 100,
- Height = 100,
- Fill = Brushes.Yellow,
- VerticalAlignment = VerticalAlignment.Center,
- HorizontalAlignment = HorizontalAlignment.Center,
- }
- }
+ Stretch = Stretch.UniformToFill,
+ TileMode = TileMode.None,
+ Visual = Visual,
}
}
};
@@ -318,7 +231,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
#else
[Fact]
#endif
- public void VisualBrush_DestinationRect_Absolute()
+ public void VisualBrush_NoStretch_NoTile_BottomRightQuarterSource()
{
Decorator target = new Decorator
{
@@ -329,23 +242,10 @@ namespace Perspex.Direct2D1.RenderTests.Media
{
Fill = new VisualBrush
{
- DestinationRect = new RelativeRect(92, 92, 92, 92, RelativeUnit.Absolute),
- Visual = new Border
- {
- Width = 180,
- Height = 180,
- Background = Brushes.Red,
- BorderBrush = Brushes.Black,
- BorderThickness = 2,
- Child = new Ellipse
- {
- Width = 100,
- Height = 100,
- Fill = Brushes.Yellow,
- VerticalAlignment = VerticalAlignment.Center,
- HorizontalAlignment = HorizontalAlignment.Center,
- }
- }
+ Stretch = Stretch.None,
+ TileMode = TileMode.None,
+ SourceRect = new RelativeRect(250, 250, 250, 250, RelativeUnit.Absolute),
+ Visual = Visual,
}
}
};
@@ -359,7 +259,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
#else
[Fact]
#endif
- public void VisualBrush_SourceRect_DestinationRect_Absolute()
+ public void VisualBrush_NoStretch_NoTile_BottomRightQuarterDest()
{
Decorator target = new Decorator
{
@@ -370,24 +270,10 @@ namespace Perspex.Direct2D1.RenderTests.Media
{
Fill = new VisualBrush
{
- SourceRect = new RelativeRect(40, 40, 100, 100, RelativeUnit.Absolute),
+ Stretch = Stretch.None,
+ TileMode = TileMode.None,
DestinationRect = new RelativeRect(92, 92, 92, 92, RelativeUnit.Absolute),
- Visual = new Border
- {
- Width = 180,
- Height = 180,
- Background = Brushes.Red,
- BorderBrush = Brushes.Black,
- BorderThickness = 2,
- Child = new Ellipse
- {
- Width = 100,
- Height = 100,
- Fill = Brushes.Yellow,
- VerticalAlignment = VerticalAlignment.Center,
- HorizontalAlignment = HorizontalAlignment.Center,
- }
- }
+ Visual = Visual,
}
}
};
@@ -401,7 +287,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
#else
[Fact]
#endif
- public void VisualBrush_SourceRect_DestinationRect_Percent()
+ public void VisualBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest()
{
Decorator target = new Decorator
{
@@ -412,24 +298,11 @@ namespace Perspex.Direct2D1.RenderTests.Media
{
Fill = new VisualBrush
{
- SourceRect = new RelativeRect(0.22, 0.22, 0.56, 0.56, RelativeUnit.Relative),
+ Stretch = Stretch.None,
+ TileMode = TileMode.None,
+ SourceRect = new RelativeRect(0.5, 0.5, 0.5, 0.5, RelativeUnit.Relative),
DestinationRect = new RelativeRect(0.5, 0.5, 0.5, 0.5, RelativeUnit.Relative),
- Visual = new Border
- {
- Width = 180,
- Height = 180,
- Background = Brushes.Red,
- BorderBrush = Brushes.Black,
- BorderThickness = 2,
- Child = new Ellipse
- {
- Width = 100,
- Height = 100,
- Fill = Brushes.Yellow,
- VerticalAlignment = VerticalAlignment.Center,
- HorizontalAlignment = HorizontalAlignment.Center,
- }
- }
+ Visual = Visual,
}
}
};
@@ -443,7 +316,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
#else
[Fact]
#endif
- public void VisualBrush_Tile()
+ public void VisualBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest()
{
Decorator target = new Decorator
{
@@ -456,67 +329,9 @@ namespace Perspex.Direct2D1.RenderTests.Media
{
Stretch = Stretch.None,
TileMode = TileMode.Tile,
+ SourceRect = new RelativeRect(0.5, 0.5, 0.5, 0.5, RelativeUnit.Relative),
DestinationRect = new RelativeRect(0.25, 0.25, 0.5, 0.5, RelativeUnit.Relative),
- Visual = new Border
- {
- Width = 92,
- Height = 92,
- Background = Brushes.Red,
- BorderBrush = Brushes.Black,
- BorderThickness = 2,
- Child = new TextBlock
- {
- Text = "Perspex",
- FontSize = 12,
- FontFamily = "Arial",
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
- }
- }
- }
- }
- };
-
- RenderToFile(target);
- CompareImages();
- }
-
-#if PERSPEX_CAIRO
- [Fact(Skip = "VisualBrush not yet implemented on Cairo")]
-#else
- [Fact]
-#endif
- public void VisualBrush_Tile_Alignment_BottomRight()
- {
- Decorator target = new Decorator
- {
- Padding = new Thickness(8),
- Width = 200,
- Height = 200,
- Child = new Rectangle
- {
- Fill = new VisualBrush
- {
- Stretch = Stretch.None,
- TileMode = TileMode.Tile,
- AlignmentX = AlignmentX.Right,
- AlignmentY = AlignmentY.Bottom,
- Visual = new Border
- {
- Width = 92,
- Height = 92,
- Background = Brushes.Red,
- BorderBrush = Brushes.Black,
- BorderThickness = 2,
- Child = new TextBlock
- {
- Text = "Perspex",
- FontSize = 12,
- FontFamily = "Arial",
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
- }
- }
+ Visual = Visual,
}
}
};
@@ -530,7 +345,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
#else
[Fact]
#endif
- public void VisualBrush_FlipX()
+ public void VisualBrush_NoStretch_FlipX_TopLeftDest()
{
Decorator target = new Decorator
{
@@ -544,22 +359,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
Stretch = Stretch.None,
TileMode = TileMode.FlipX,
DestinationRect = new RelativeRect(0, 0, 0.5, 0.5, RelativeUnit.Relative),
- Visual = new Border
- {
- Width = 92,
- Height = 92,
- Background = Brushes.Red,
- BorderBrush = Brushes.Black,
- BorderThickness = 2,
- Child = new TextBlock
- {
- Text = "Perspex",
- FontSize = 12,
- FontFamily = "Arial",
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
- }
- }
+ Visual = Visual,
}
}
};
@@ -573,7 +373,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
#else
[Fact]
#endif
- public void VisualBrush_FlipY()
+ public void VisualBrush_NoStretch_FlipY_TopLeftDest()
{
Decorator target = new Decorator
{
@@ -587,22 +387,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
Stretch = Stretch.None,
TileMode = TileMode.FlipY,
DestinationRect = new RelativeRect(0, 0, 0.5, 0.5, RelativeUnit.Relative),
- Visual = new Border
- {
- Width = 92,
- Height = 92,
- Background = Brushes.Red,
- BorderBrush = Brushes.Black,
- BorderThickness = 2,
- Child = new TextBlock
- {
- Text = "Perspex",
- FontSize = 12,
- FontFamily = "Arial",
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
- }
- }
+ Visual = Visual,
}
}
};
@@ -616,7 +401,7 @@ namespace Perspex.Direct2D1.RenderTests.Media
#else
[Fact]
#endif
- public void VisualBrush_FlipXY()
+ public void VisualBrush_NoStretch_FlipXY_TopLeftDest()
{
Decorator target = new Decorator
{
@@ -630,48 +415,11 @@ namespace Perspex.Direct2D1.RenderTests.Media
Stretch = Stretch.None,
TileMode = TileMode.FlipXY,
DestinationRect = new RelativeRect(0, 0, 0.5, 0.5, RelativeUnit.Relative),
- Visual = new Border
- {
- Width = 92,
- Height = 92,
- Background = Brushes.Red,
- BorderBrush = Brushes.Black,
- BorderThickness = 2,
- Child = new TextBlock
- {
- Text = "Perspex",
- FontSize = 12,
- FontFamily = "Arial",
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
- }
- }
+ Visual = Visual,
}
}
};
- RenderToFile(target);
- CompareImages();
- }
-
-#if PERSPEX_CAIRO
- [Fact(Skip = "VisualBrush not yet implemented on Cairo")]
-#else
- [Fact]
-#endif
- public void VisualBrush_No_Visual()
- {
- Decorator target = new Decorator
- {
- Padding = new Thickness(8),
- Width = 200,
- Height = 200,
- Child = new Rectangle
- {
- Fill = new VisualBrush(),
- }
- };
-
RenderToFile(target);
CompareImages();
}
diff --git a/tests/Perspex.RenderTests/Perspex.Direct2D1.RenderTests.csproj b/tests/Perspex.RenderTests/Perspex.Direct2D1.RenderTests.csproj
index 6a8b105dc5..7956643dca 100644
--- a/tests/Perspex.RenderTests/Perspex.Direct2D1.RenderTests.csproj
+++ b/tests/Perspex.RenderTests/Perspex.Direct2D1.RenderTests.csproj
@@ -75,6 +75,7 @@
+
diff --git a/tests/Perspex.RenderTests/TestBase.cs b/tests/Perspex.RenderTests/TestBase.cs
index 36a34610a2..18e406fedd 100644
Binary files a/tests/Perspex.RenderTests/TestBase.cs and b/tests/Perspex.RenderTests/TestBase.cs differ
diff --git a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Align_BottomRight.expected.png b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Align_BottomRight.expected.png
deleted file mode 100644
index 0918b7fd51..0000000000
Binary files a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Align_BottomRight.expected.png and /dev/null differ
diff --git a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Align_Center.expected.png b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Align_Center.expected.png
deleted file mode 100644
index dc6050fec4..0000000000
Binary files a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Align_Center.expected.png and /dev/null differ
diff --git a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Align_TopLeft.expected.png b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Align_TopLeft.expected.png
deleted file mode 100644
index 905ec5386a..0000000000
Binary files a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Align_TopLeft.expected.png and /dev/null differ
diff --git a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_DestinationRect_Absolute.expected.png b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_DestinationRect_Absolute.expected.png
deleted file mode 100644
index 9253eee164..0000000000
Binary files a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_DestinationRect_Absolute.expected.png and /dev/null differ
diff --git a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_FlipX.expected.png b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_FlipX.expected.png
deleted file mode 100644
index da7003b419..0000000000
Binary files a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_FlipX.expected.png and /dev/null differ
diff --git a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_FlipXY.expected.png b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_FlipXY.expected.png
deleted file mode 100644
index 4bfcdb2dd3..0000000000
Binary files a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_FlipXY.expected.png and /dev/null differ
diff --git a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_FlipY.expected.png b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_FlipY.expected.png
deleted file mode 100644
index 74a01bb78c..0000000000
Binary files a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_FlipY.expected.png and /dev/null differ
diff --git a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_SourceRect_Absolute.expected.png b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_SourceRect_Absolute.expected.png
deleted file mode 100644
index e1fcdbc1a6..0000000000
Binary files a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_SourceRect_Absolute.expected.png and /dev/null differ
diff --git a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_SourceRect_DestinationRect_Absolute.expected.png b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_SourceRect_DestinationRect_Absolute.expected.png
deleted file mode 100644
index b2abed4041..0000000000
Binary files a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_SourceRect_DestinationRect_Absolute.expected.png and /dev/null differ
diff --git a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_SourceRect_DestinationRect_Percent.expected.png b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_SourceRect_DestinationRect_Percent.expected.png
deleted file mode 100644
index 1aedd35831..0000000000
Binary files a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_SourceRect_DestinationRect_Percent.expected.png and /dev/null differ
diff --git a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Stretch_Fill_Large.expected.png b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Stretch_Fill_Large.expected.png
deleted file mode 100644
index f1914a404f..0000000000
Binary files a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Stretch_Fill_Large.expected.png and /dev/null differ
diff --git a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Stretch_Uniform.expected.png b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Stretch_Uniform.expected.png
deleted file mode 100644
index fb2ae9f8cc..0000000000
Binary files a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Stretch_Uniform.expected.png and /dev/null differ
diff --git a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Stretch_UniformToFill.expected.png b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Stretch_UniformToFill.expected.png
deleted file mode 100644
index d0009b6abb..0000000000
Binary files a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Stretch_UniformToFill.expected.png and /dev/null differ
diff --git a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Tile.expected.png b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Tile.expected.png
deleted file mode 100644
index 64695d4bb1..0000000000
Binary files a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Tile.expected.png and /dev/null differ
diff --git a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Tile_Alignment_BottomRight.expected.png b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Tile_Alignment_BottomRight.expected.png
deleted file mode 100644
index 0918b7fd51..0000000000
Binary files a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Tile_Alignment_BottomRight.expected.png and /dev/null differ