diff --git a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs index 493d87988b..4f75a63321 100644 --- a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs +++ b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs @@ -1160,35 +1160,21 @@ namespace Avalonia.Skia return; } - var brushTransform = Matrix.CreateTranslation(-contentBounds.Position); - - contentBounds = contentBounds.TransformToAABB(brushTransform); + var brushTransform = Matrix.Identity; var destinationRect = content.Brush.DestinationRect.ToPixels(targetRect.Size); - if (tileBrush.Stretch != Stretch.None) - { - //scale content to destination size - var scale = tileBrush.Stretch.CalculateScaling(destinationRect.Size, contentBounds.Size); - - var scaleTransform = Matrix.CreateScale(scale); - - contentBounds = contentBounds.TransformToAABB(scaleTransform); - - brushTransform *= scaleTransform; - } - var sourceRect = tileBrush.SourceRect.ToPixels(contentBounds); - //scale content to source size - if (contentBounds.Size != sourceRect.Size) + brushTransform *= Matrix.CreateTranslation(-sourceRect.Position); + + if (sourceRect.Size != destinationRect.Size) { - var scale = tileBrush.Stretch.CalculateScaling(sourceRect.Size, contentBounds.Size); + //scale source to destination size + var scale = tileBrush.Stretch.CalculateScaling(destinationRect.Size, sourceRect.Size); var scaleTransform = Matrix.CreateScale(scale); - contentBounds = contentBounds.TransformToAABB(scaleTransform); - brushTransform *= scaleTransform; } @@ -1199,11 +1185,16 @@ namespace Avalonia.Skia var transformOrigin = content.TransformOrigin.ToPixels(targetRect); var offset = Matrix.CreateTranslation(transformOrigin); transform = -offset * content.Transform.Value * offset; - } - if (content.Brush.TileMode == TileMode.None) - { - brushTransform *= transform; + if (tileBrush.TileMode == TileMode.None) + { + brushTransform *= transform; + + destinationRect = destinationRect.TransformToAABB(transform); + + destinationRect = new Rect(0, 0, destinationRect.Left + destinationRect.Width, + destinationRect.Top + destinationRect.Height); + } } if (tileBrush.Stretch == Stretch.None && transform == Matrix.Identity) diff --git a/tests/Avalonia.RenderTests/CrossTests/Brushes/CrossTileBrushTests.cs b/tests/Avalonia.RenderTests/CrossTests/Brushes/CrossTileBrushTests.cs index d7283cf9d9..160aa25942 100644 --- a/tests/Avalonia.RenderTests/CrossTests/Brushes/CrossTileBrushTests.cs +++ b/tests/Avalonia.RenderTests/CrossTests/Brushes/CrossTileBrushTests.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using Avalonia.Media; using CrossUI; using Xunit; @@ -51,4 +52,64 @@ public class CrossTileBrushTests : CrossTestBase }); } + + [CrossFact] + public void Should_Render_Scaled_TileBrush() + { + var brush = new CrossDrawingBrush + { + TileMode = TileMode.Tile, + Viewbox = new Rect(0, 0, 20, 20), + ViewboxUnits = BrushMappingMode.Absolute, + Viewport = new Rect(0, 0, 20, 20), + ViewportUnits = BrushMappingMode.Absolute, + Drawing = new CrossGeometryDrawing(new CrossSvgGeometry("M 0 0 l 50 50")) + { + Pen = new CrossPen { Brush = new CrossSolidColorBrush(Colors.Red), Thickness = 5 } + } + }; + + RenderAndCompare(new CrossControl() + { + Width = 100, + Height = 100, + Background = brush + }); + + } + + [CrossFact] + public void Should_Render_With_Transform() + { + var brush = new CrossDrawingBrush() + { + TileMode = TileMode.None, + Viewbox = new Rect(0, 0, 1, 1), + ViewboxUnits = BrushMappingMode.RelativeToBoundingBox, + Viewport = new Rect(0, 0, 50, 50), + ViewportUnits = BrushMappingMode.Absolute, + Transform = Matrix.CreateTranslation(150, 150), + Drawing = new CrossDrawingGroup() + { + Children = new List() + { + new CrossGeometryDrawing(new CrossRectangleGeometry(new(0, 0, 100, 100))) + { + Brush = new CrossSolidColorBrush(Colors.Crimson) + }, + new CrossGeometryDrawing(new CrossRectangleGeometry(new(20, 20, 60, 60))) + { + Brush = new CrossSolidColorBrush(Colors.Blue) + } + } + } + }; + + RenderAndCompare(new CrossControl() + { + Width = 200, + Height = 200, + Background = brush + }); + } } diff --git a/tests/Avalonia.RenderTests/Media/ImageDrawingTests.cs b/tests/Avalonia.RenderTests/Media/ImageDrawingTests.cs index 3d593cd677..8a571c4d19 100644 --- a/tests/Avalonia.RenderTests/Media/ImageDrawingTests.cs +++ b/tests/Avalonia.RenderTests/Media/ImageDrawingTests.cs @@ -107,8 +107,8 @@ namespace Avalonia.Direct2D1.RenderTests.Media _brush = new DrawingBrush() { TileMode = TileMode.None, - SourceRect = new RelativeRect(0, 0, 50, 50, RelativeUnit.Absolute), - DestinationRect = new RelativeRect(0, 0, 1, 1, RelativeUnit.Relative), + SourceRect = new RelativeRect(0, 0, 1, 1, RelativeUnit.Relative), + DestinationRect = new RelativeRect(0, 0, 50, 50, RelativeUnit.Absolute), Transform = new TranslateTransform(150, 150), Drawing = new DrawingGroup() { diff --git a/tests/Avalonia.RenderTests/Media/TileBrushTests.cs b/tests/Avalonia.RenderTests/Media/TileBrushTests.cs index c8ec8483ac..c3249422ea 100644 --- a/tests/Avalonia.RenderTests/Media/TileBrushTests.cs +++ b/tests/Avalonia.RenderTests/Media/TileBrushTests.cs @@ -40,7 +40,35 @@ public class DrawingBrushTests: TestBase await RenderToFile(target); CompareImages(); } - + + + [Fact] + public async Task DrawingBrushIsProperlyScaled() + { + Decorator target = new Decorator + { + Padding = new Thickness(10), + Width = 220, + Height = 220, + Child = new Rectangle + { + Fill = new DrawingBrush + { + TileMode = TileMode.Tile, + SourceRect = new RelativeRect(0, 0, 20, 20, RelativeUnit.Absolute), + DestinationRect = new RelativeRect(0, 0, 20, 20, RelativeUnit.Absolute), + Drawing = new GeometryDrawing() + { + Pen = new Pen(Brushes.Red, 5), + Geometry = Geometry.Parse("M 0 0 l 50 50") + } + } + } + }; + + await RenderToFile(target); + CompareImages(); + } #if AVALONIA_SKIA [Fact] diff --git a/tests/TestFiles/CrossTests/Media/TileBrushes/Should_Render_Scaled_TileBrush.wpf.png b/tests/TestFiles/CrossTests/Media/TileBrushes/Should_Render_Scaled_TileBrush.wpf.png new file mode 100644 index 0000000000..733e6200d8 Binary files /dev/null and b/tests/TestFiles/CrossTests/Media/TileBrushes/Should_Render_Scaled_TileBrush.wpf.png differ diff --git a/tests/TestFiles/CrossTests/Media/TileBrushes/Should_Render_With_Transform.wpf.png b/tests/TestFiles/CrossTests/Media/TileBrushes/Should_Render_With_Transform.wpf.png new file mode 100644 index 0000000000..4276ba62c8 Binary files /dev/null and b/tests/TestFiles/CrossTests/Media/TileBrushes/Should_Render_With_Transform.wpf.png differ diff --git a/tests/TestFiles/Direct2D1/Media/DrawingBrush/DrawingBrushIsProperlyScaled.expected.png b/tests/TestFiles/Direct2D1/Media/DrawingBrush/DrawingBrushIsProperlyScaled.expected.png new file mode 100644 index 0000000000..16f4d712f4 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Media/DrawingBrush/DrawingBrushIsProperlyScaled.expected.png differ diff --git a/tests/TestFiles/Skia/Media/DrawingBrush/DrawingBrushIsProperlyScaled.expected.png b/tests/TestFiles/Skia/Media/DrawingBrush/DrawingBrushIsProperlyScaled.expected.png new file mode 100644 index 0000000000..63873b65fd Binary files /dev/null and b/tests/TestFiles/Skia/Media/DrawingBrush/DrawingBrushIsProperlyScaled.expected.png differ