diff --git a/src/Avalonia.Visuals/Media/PixelSize.cs b/src/Avalonia.Visuals/Media/PixelSize.cs
index 3d0ae0b351..6785b51716 100644
--- a/src/Avalonia.Visuals/Media/PixelSize.cs
+++ b/src/Avalonia.Visuals/Media/PixelSize.cs
@@ -159,8 +159,8 @@ namespace Avalonia
/// The dots per inch.
/// The device-independent size.
public static PixelSize FromSize(Size size, Vector dpi) => new PixelSize(
- (int)(size.Width * (dpi.X / 96)),
- (int)(size.Height * (dpi.Y / 96)));
+ (int)Math.Ceiling(size.Width * (dpi.X / 96)),
+ (int)Math.Ceiling(size.Height * (dpi.Y / 96)));
///
/// Returns the string representation of the size.
diff --git a/src/Avalonia.Visuals/Rendering/Utilities/TileBrushCalculator.cs b/src/Avalonia.Visuals/Rendering/Utilities/TileBrushCalculator.cs
index 52a8fb5ab7..27949fcf55 100644
--- a/src/Avalonia.Visuals/Rendering/Utilities/TileBrushCalculator.cs
+++ b/src/Avalonia.Visuals/Rendering/Utilities/TileBrushCalculator.cs
@@ -116,8 +116,8 @@ namespace Avalonia.Rendering.Utilities
return true;
if (SourceRect.Size.AspectRatio == _imageSize.AspectRatio)
return false;
- if ((int)SourceRect.Width != _imageSize.Width ||
- (int)SourceRect.Height != _imageSize.Height)
+ if (SourceRect.Width != _imageSize.Width ||
+ SourceRect.Height != _imageSize.Height)
return true;
return false;
}
diff --git a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs
index 1bfd7fd90d..076d69ae4a 100644
--- a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs
+++ b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs
@@ -225,10 +225,7 @@ namespace Avalonia.Skia
///
public IRenderTargetBitmapImpl CreateLayer(Size size)
{
- var normalizedDpi = new Vector(_dpi.X / SkiaPlatform.DefaultDpi.X, _dpi.Y / SkiaPlatform.DefaultDpi.Y);
- var pixelSize = size * normalizedDpi;
-
- return CreateRenderTarget((int) pixelSize.Width, (int) pixelSize.Height, _dpi);
+ return CreateRenderTarget(size);
}
///
@@ -387,26 +384,27 @@ namespace Avalonia.Skia
/// Target size.
/// Tile brush to use.
/// Tile brush image.
- /// The bitmap interpolation mode.
private void ConfigureTileBrush(ref PaintWrapper paintWrapper, Size targetSize, ITileBrush tileBrush, IDrawableBitmapImpl tileBrushImage)
{
- var calc = new TileBrushCalculator(tileBrush,
- new Size(tileBrushImage.PixelSize.Width, tileBrushImage.PixelSize.Height), targetSize);
-
- var intermediate = CreateRenderTarget(
- (int)calc.IntermediateSize.Width,
- (int)calc.IntermediateSize.Height, _dpi);
+ var calc = new TileBrushCalculator(tileBrush, tileBrushImage.PixelSize.ToSize(_dpi), targetSize);
+ var intermediate = CreateRenderTarget(calc.IntermediateSize);
paintWrapper.AddDisposable(intermediate);
using (var context = intermediate.CreateDrawingContext(null))
{
- var rect = new Rect(0, 0, tileBrushImage.PixelSize.Width, tileBrushImage.PixelSize.Height);
+ var sourceRect = new Rect(tileBrushImage.PixelSize.ToSize(96));
+ var targetRect = new Rect(tileBrushImage.PixelSize.ToSize(_dpi));
context.Clear(Colors.Transparent);
context.PushClip(calc.IntermediateClip);
context.Transform = calc.IntermediateTransform;
- context.DrawImage(RefCountable.CreateUnownedNotClonable(tileBrushImage), 1, rect, rect, tileBrush.BitmapInterpolationMode);
+ context.DrawImage(
+ RefCountable.CreateUnownedNotClonable(tileBrushImage),
+ 1,
+ sourceRect,
+ targetRect,
+ tileBrush.BitmapInterpolationMode);
context.PopClip();
}
@@ -433,7 +431,14 @@ namespace Avalonia.Skia
var image = intermediate.SnapshotImage();
paintWrapper.AddDisposable(image);
- using (var shader = image.ToShader(tileX, tileY, tileTransform))
+ var paintTransform = default(SKMatrix);
+
+ SKMatrix.Concat(
+ ref paintTransform,
+ tileTransform,
+ SKMatrix.MakeScale((float)(96.0 / _dpi.X), (float)(96.0 / _dpi.Y)));
+
+ using (var shader = image.ToShader(tileX, tileY, paintTransform))
{
paintWrapper.Paint.Shader = shader;
}
@@ -457,7 +462,7 @@ namespace Avalonia.Skia
if (intermediateSize.Width >= 1 && intermediateSize.Height >= 1)
{
- var intermediate = CreateRenderTarget((int)intermediateSize.Width, (int)intermediateSize.Height, _dpi);
+ var intermediate = CreateRenderTarget(intermediateSize);
using (var ctx = intermediate.CreateDrawingContext(visualBrushRenderer))
{
@@ -609,18 +614,17 @@ namespace Avalonia.Skia
///
/// Create new render target compatible with this drawing context.
///
- /// Width.
- /// Height.
- /// Drawing dpi.
+ /// The size of the render target in DIPs.
/// Pixel format.
///
- private SurfaceRenderTarget CreateRenderTarget(int width, int height, Vector dpi, PixelFormat? format = null)
+ private SurfaceRenderTarget CreateRenderTarget(Size size, PixelFormat? format = null)
{
+ var pixelSize = PixelSize.FromSize(size, _dpi);
var createInfo = new SurfaceRenderTarget.CreateInfo
{
- Width = width,
- Height = height,
- Dpi = dpi,
+ Width = pixelSize.Width,
+ Height = pixelSize.Height,
+ Dpi = _dpi,
Format = format,
DisableTextLcdRendering = !_canTextUseLcdRendering,
GrContext = _grContext
diff --git a/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs
index efe26ba01a..aaca1a3b00 100644
--- a/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs
+++ b/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs
@@ -434,10 +434,16 @@ namespace Avalonia.Direct2D1.Media
if (intermediateSize.Width >= 1 && intermediateSize.Height >= 1)
{
+ // We need to ensure the size we're requesting is an integer pixel size, otherwise
+ // D2D alters the DPI of the render target, which messes stuff up. PixelSize.FromSize
+ // will do the rounding for us.
+ var dpi = new Vector(_deviceContext.DotsPerInch.Width, _deviceContext.DotsPerInch.Height);
+ var pixelSize = PixelSize.FromSize(intermediateSize, dpi);
+
using (var intermediate = new BitmapRenderTarget(
_deviceContext,
CompatibleRenderTargetOptions.None,
- intermediateSize.ToSharpDX()))
+ pixelSize.ToSize(dpi).ToSharpDX()))
{
using (var ctx = new RenderTarget(intermediate).CreateDrawingContext(_visualBrushRenderer))
{
diff --git a/src/Windows/Avalonia.Direct2D1/Media/ImageBrushImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/ImageBrushImpl.cs
index 55877cefcb..19d320b783 100644
--- a/src/Windows/Avalonia.Direct2D1/Media/ImageBrushImpl.cs
+++ b/src/Windows/Avalonia.Direct2D1/Media/ImageBrushImpl.cs
@@ -20,7 +20,8 @@ namespace Avalonia.Direct2D1.Media
BitmapImpl bitmap,
Size targetSize)
{
- var calc = new TileBrushCalculator(brush, bitmap.PixelSize.ToSize(96), targetSize);
+ var dpi = new Vector(target.DotsPerInch.Width, target.DotsPerInch.Height);
+ var calc = new TileBrushCalculator(brush, bitmap.PixelSize.ToSize(dpi), targetSize);
if (!calc.NeedsIntermediate)
{
@@ -99,7 +100,8 @@ namespace Avalonia.Direct2D1.Media
using (var context = new RenderTarget(result).CreateDrawingContext(null))
{
- var rect = new Rect(0, 0, bitmap.PixelSize.Width, bitmap.PixelSize.Height);
+ var dpi = new Vector(target.DotsPerInch.Width, target.DotsPerInch.Height);
+ var rect = new Rect(bitmap.PixelSize.ToSize(dpi));
context.Clear(Colors.Transparent);
context.PushClip(calc.IntermediateClip);
diff --git a/src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DRenderTargetBitmapImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DRenderTargetBitmapImpl.cs
index 72367ac50f..fbe7f840d7 100644
--- a/src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DRenderTargetBitmapImpl.cs
+++ b/src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DRenderTargetBitmapImpl.cs
@@ -1,8 +1,10 @@
// 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 System.IO;
using Avalonia.Platform;
using Avalonia.Rendering;
+using Avalonia.Utilities;
using SharpDX;
using SharpDX.Direct2D1;
using D2DBitmap = SharpDX.Direct2D1.Bitmap;
@@ -49,5 +51,22 @@ namespace Avalonia.Direct2D1.Media.Imaging
{
return new OptionalDispose(_renderTarget.Bitmap, false);
}
+
+ public override void Save(Stream stream)
+ {
+ using (var wic = new WicRenderTargetBitmapImpl(PixelSize, Dpi))
+ {
+ using (var dc = wic.CreateDrawingContext(null))
+ {
+ dc.DrawImage(
+ RefCountable.CreateUnownedNotClonable(this),
+ 1,
+ new Rect(PixelSize.ToSize(Dpi.X)),
+ new Rect(PixelSize.ToSize(Dpi.X)));
+ }
+
+ wic.Save(stream);
+ }
+ }
}
}
diff --git a/src/Windows/Avalonia.Direct2D1/Utils/DebugUtils.cs b/src/Windows/Avalonia.Direct2D1/Utils/DebugUtils.cs
new file mode 100644
index 0000000000..9ce8f15cf4
--- /dev/null
+++ b/src/Windows/Avalonia.Direct2D1/Utils/DebugUtils.cs
@@ -0,0 +1,13 @@
+using Avalonia.Direct2D1.Media.Imaging;
+
+namespace Avalonia.Direct2D1.Utils
+{
+ internal static class DebugUtils
+ {
+ public static void Save(SharpDX.Direct2D1.BitmapRenderTarget bitmap, string filename)
+ {
+ var rtb = new D2DRenderTargetBitmapImpl(bitmap);
+ rtb.Save(filename);
+ }
+ }
+}
diff --git a/tests/Avalonia.RenderTests/Media/VisualBrushTests.cs b/tests/Avalonia.RenderTests/Media/VisualBrushTests.cs
index 6f90dfd19e..7c53f4516a 100644
--- a/tests/Avalonia.RenderTests/Media/VisualBrushTests.cs
+++ b/tests/Avalonia.RenderTests/Media/VisualBrushTests.cs
@@ -449,5 +449,281 @@ namespace Avalonia.Direct2D1.RenderTests.Media
await RenderToFile(target);
CompareImages();
}
+
+ [Fact]
+ public async Task VisualBrush_Grip_96_Dpi()
+ {
+ var target = new Border
+ {
+ Width = 100,
+ Height = 10,
+ Background = new VisualBrush
+ {
+ SourceRect = new RelativeRect(0, 0, 4, 5, RelativeUnit.Absolute),
+ DestinationRect = new RelativeRect(0, 0, 4, 5, RelativeUnit.Absolute),
+ TileMode = TileMode.Tile,
+ Stretch = Stretch.UniformToFill,
+ Visual = new Canvas
+ {
+ Width = 4,
+ Height = 5,
+ Background = Brushes.WhiteSmoke,
+ Children =
+ {
+ new Rectangle
+ {
+ Width = 1,
+ Height = 1,
+ Fill = Brushes.Red,
+ [Canvas.LeftProperty] = 2,
+ },
+ new Rectangle
+ {
+ Width = 1,
+ Height = 1,
+ Fill = Brushes.Red,
+ [Canvas.TopProperty] = 2,
+ },
+ new Rectangle
+ {
+ Width = 1,
+ Height = 1,
+ Fill = Brushes.Red,
+ [Canvas.LeftProperty] = 2,
+ [Canvas.TopProperty] = 4,
+ }
+ }
+ }
+ }
+ };
+
+ await RenderToFile(target);
+ CompareImages();
+ }
+
+ [Fact]
+ public async Task VisualBrush_Grip_144_Dpi()
+ {
+ var target = new Border
+ {
+ Width = 100,
+ Height = 7.5,
+ Background = new VisualBrush
+ {
+ SourceRect = new RelativeRect(0, 0, 4, 5, RelativeUnit.Absolute),
+ DestinationRect = new RelativeRect(0, 0, 4, 5, RelativeUnit.Absolute),
+ TileMode = TileMode.Tile,
+ Stretch = Stretch.UniformToFill,
+ Visual = new Canvas
+ {
+ Width = 4,
+ Height = 5,
+ Background = Brushes.WhiteSmoke,
+ Children =
+ {
+ new Rectangle
+ {
+ Width = 1,
+ Height = 1,
+ Fill = Brushes.Red,
+ [Canvas.LeftProperty] = 2,
+ },
+ new Rectangle
+ {
+ Width = 1,
+ Height = 1,
+ Fill = Brushes.Red,
+ [Canvas.TopProperty] = 2,
+ },
+ new Rectangle
+ {
+ Width = 1,
+ Height = 1,
+ Fill = Brushes.Red,
+ [Canvas.LeftProperty] = 2,
+ [Canvas.TopProperty] = 4,
+ }
+ }
+ }
+ }
+ };
+
+ await RenderToFile(target, dpi: 144);
+ CompareImages();
+ }
+
+ [Fact]
+ public async Task VisualBrush_Grip_192_Dpi()
+ {
+ var target = new Border
+ {
+ Width = 100,
+ Height = 10,
+ Background = new VisualBrush
+ {
+ SourceRect = new RelativeRect(0, 0, 4, 5, RelativeUnit.Absolute),
+ DestinationRect = new RelativeRect(0, 0, 4, 5, RelativeUnit.Absolute),
+ TileMode = TileMode.Tile,
+ Stretch = Stretch.UniformToFill,
+ Visual = new Canvas
+ {
+ Width = 4,
+ Height = 5,
+ Background = Brushes.WhiteSmoke,
+ Children =
+ {
+ new Rectangle
+ {
+ Width = 1,
+ Height = 1,
+ Fill = Brushes.Red,
+ [Canvas.LeftProperty] = 2,
+ },
+ new Rectangle
+ {
+ Width = 1,
+ Height = 1,
+ Fill = Brushes.Red,
+ [Canvas.TopProperty] = 2,
+ },
+ new Rectangle
+ {
+ Width = 1,
+ Height = 1,
+ Fill = Brushes.Red,
+ [Canvas.LeftProperty] = 2,
+ [Canvas.TopProperty] = 4,
+ }
+ }
+ }
+ }
+ };
+
+ await RenderToFile(target, dpi: 192);
+ CompareImages();
+ }
+
+ [Fact]
+ public async Task VisualBrush_Checkerboard_96_Dpi()
+ {
+ var target = new Border
+ {
+ Width = 200,
+ Height = 200,
+ Background = new VisualBrush
+ {
+ DestinationRect = new RelativeRect(0, 0, 16, 16, RelativeUnit.Absolute),
+ TileMode = TileMode.Tile,
+ Visual = new Canvas
+ {
+ Width = 16,
+ Height= 16,
+ Background = Brushes.Red,
+ Children =
+ {
+ new Rectangle
+ {
+ Width = 8,
+ Height = 8,
+ Fill = Brushes.Green,
+ },
+ new Rectangle
+ {
+ Width = 8,
+ Height = 8,
+ Fill = Brushes.Green,
+ [Canvas.LeftProperty] = 8,
+ [Canvas.TopProperty] = 8,
+ },
+ }
+ }
+ }
+ };
+
+ await RenderToFile(target);
+ CompareImages();
+ }
+
+ [Fact]
+ public async Task VisualBrush_Checkerboard_144_Dpi()
+ {
+ var target = new Border
+ {
+ Width = 200,
+ Height = 200,
+ Background = new VisualBrush
+ {
+ DestinationRect = new RelativeRect(0, 0, 16, 16, RelativeUnit.Absolute),
+ TileMode = TileMode.Tile,
+ Visual = new Canvas
+ {
+ Width = 16,
+ Height = 16,
+ Background = Brushes.Red,
+ Children =
+ {
+ new Rectangle
+ {
+ Width = 8,
+ Height = 8,
+ Fill = Brushes.Green,
+ },
+ new Rectangle
+ {
+ Width = 8,
+ Height = 8,
+ Fill = Brushes.Green,
+ [Canvas.LeftProperty] = 8,
+ [Canvas.TopProperty] = 8,
+ },
+ }
+ }
+ }
+ };
+
+ await RenderToFile(target, dpi: 144);
+ CompareImages();
+ }
+
+ [Fact]
+ public async Task VisualBrush_Checkerboard_192_Dpi()
+ {
+ var target = new Border
+ {
+ Width = 200,
+ Height = 200,
+ Background = new VisualBrush
+ {
+ DestinationRect = new RelativeRect(0, 0, 16, 16, RelativeUnit.Absolute),
+ TileMode = TileMode.Tile,
+ Visual = new Canvas
+ {
+ Width = 16,
+ Height = 16,
+ Background = Brushes.Red,
+ Children =
+ {
+ new Rectangle
+ {
+ Width = 8,
+ Height = 8,
+ Fill = Brushes.Green,
+ },
+ new Rectangle
+ {
+ Width = 8,
+ Height = 8,
+ Fill = Brushes.Green,
+ [Canvas.LeftProperty] = 8,
+ [Canvas.TopProperty] = 8,
+ },
+ }
+ }
+ }
+ };
+
+ await RenderToFile(target, dpi: 192);
+ CompareImages();
+ }
}
}
diff --git a/tests/Avalonia.RenderTests/TestBase.cs b/tests/Avalonia.RenderTests/TestBase.cs
index 2892615e48..4c8abd85f7 100644
--- a/tests/Avalonia.RenderTests/TestBase.cs
+++ b/tests/Avalonia.RenderTests/TestBase.cs
@@ -63,7 +63,7 @@ namespace Avalonia.Direct2D1.RenderTests
get;
}
- protected async Task RenderToFile(Control target, [CallerMemberName] string testName = "")
+ protected async Task RenderToFile(Control target, [CallerMemberName] string testName = "", double dpi = 96)
{
if (!Directory.Exists(OutputPath))
{
@@ -75,9 +75,9 @@ namespace Avalonia.Direct2D1.RenderTests
var factory = AvaloniaLocator.Current.GetService();
var pixelSize = new PixelSize((int)target.Width, (int)target.Height);
var size = new Size(target.Width, target.Height);
- var dpi = new Vector(96, 96);
+ var dpiVector = new Vector(dpi, dpi);
- using (RenderTargetBitmap bitmap = new RenderTargetBitmap(pixelSize, dpi))
+ using (RenderTargetBitmap bitmap = new RenderTargetBitmap(pixelSize, dpiVector))
{
target.Measure(size);
target.Arrange(new Rect(size));
@@ -85,7 +85,7 @@ namespace Avalonia.Direct2D1.RenderTests
bitmap.Save(immediatePath);
}
- using (var rtb = factory.CreateRenderTargetBitmap(pixelSize, dpi))
+ using (var rtb = factory.CreateRenderTargetBitmap(pixelSize, dpiVector))
using (var renderer = new DeferredRenderer(target, rtb))
{
target.Measure(size);
diff --git a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Checkerboard_144_Dpi.expected.png b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Checkerboard_144_Dpi.expected.png
new file mode 100644
index 0000000000..7e674b849a
Binary files /dev/null and b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Checkerboard_144_Dpi.expected.png differ
diff --git a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Checkerboard_192_Dpi.expected.png b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Checkerboard_192_Dpi.expected.png
new file mode 100644
index 0000000000..f80ac7f90d
Binary files /dev/null and b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Checkerboard_192_Dpi.expected.png differ
diff --git a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Checkerboard_96_Dpi.expected.png b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Checkerboard_96_Dpi.expected.png
new file mode 100644
index 0000000000..0f88a0d468
Binary files /dev/null and b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Checkerboard_96_Dpi.expected.png differ
diff --git a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Grip_144_Dpi.expected.png b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Grip_144_Dpi.expected.png
new file mode 100644
index 0000000000..1900ade5e2
Binary files /dev/null and b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Grip_144_Dpi.expected.png differ
diff --git a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Grip_192_Dpi.expected.png b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Grip_192_Dpi.expected.png
new file mode 100644
index 0000000000..a209dc94cc
Binary files /dev/null and b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Grip_192_Dpi.expected.png differ
diff --git a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Grip_96_Dpi.expected.png b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Grip_96_Dpi.expected.png
new file mode 100644
index 0000000000..6ac1bdb088
Binary files /dev/null and b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Grip_96_Dpi.expected.png differ
diff --git a/tests/TestFiles/Skia/Media/VisualBrush/VisualBrush_Checkerboard_144_Dpi.expected.png b/tests/TestFiles/Skia/Media/VisualBrush/VisualBrush_Checkerboard_144_Dpi.expected.png
new file mode 100644
index 0000000000..7e674b849a
Binary files /dev/null and b/tests/TestFiles/Skia/Media/VisualBrush/VisualBrush_Checkerboard_144_Dpi.expected.png differ
diff --git a/tests/TestFiles/Skia/Media/VisualBrush/VisualBrush_Checkerboard_192_Dpi.expected.png b/tests/TestFiles/Skia/Media/VisualBrush/VisualBrush_Checkerboard_192_Dpi.expected.png
new file mode 100644
index 0000000000..f80ac7f90d
Binary files /dev/null and b/tests/TestFiles/Skia/Media/VisualBrush/VisualBrush_Checkerboard_192_Dpi.expected.png differ
diff --git a/tests/TestFiles/Skia/Media/VisualBrush/VisualBrush_Checkerboard_96_Dpi.expected.png b/tests/TestFiles/Skia/Media/VisualBrush/VisualBrush_Checkerboard_96_Dpi.expected.png
new file mode 100644
index 0000000000..0f88a0d468
Binary files /dev/null and b/tests/TestFiles/Skia/Media/VisualBrush/VisualBrush_Checkerboard_96_Dpi.expected.png differ
diff --git a/tests/TestFiles/Skia/Media/VisualBrush/VisualBrush_Grip_144_Dpi.expected.png b/tests/TestFiles/Skia/Media/VisualBrush/VisualBrush_Grip_144_Dpi.expected.png
new file mode 100644
index 0000000000..d530c72519
Binary files /dev/null and b/tests/TestFiles/Skia/Media/VisualBrush/VisualBrush_Grip_144_Dpi.expected.png differ
diff --git a/tests/TestFiles/Skia/Media/VisualBrush/VisualBrush_Grip_192_Dpi.expected.png b/tests/TestFiles/Skia/Media/VisualBrush/VisualBrush_Grip_192_Dpi.expected.png
new file mode 100644
index 0000000000..a209dc94cc
Binary files /dev/null and b/tests/TestFiles/Skia/Media/VisualBrush/VisualBrush_Grip_192_Dpi.expected.png differ
diff --git a/tests/TestFiles/Skia/Media/VisualBrush/VisualBrush_Grip_96_Dpi.expected.png b/tests/TestFiles/Skia/Media/VisualBrush/VisualBrush_Grip_96_Dpi.expected.png
new file mode 100644
index 0000000000..6ac1bdb088
Binary files /dev/null and b/tests/TestFiles/Skia/Media/VisualBrush/VisualBrush_Grip_96_Dpi.expected.png differ