Browse Source

Fix TileBrush Source/DestinationRect handling (#15289)

* Fix TileBrush Source/DestinationRect handling

* Add unit test

* Add cross render tests

* Add missing test image
pull/15318/head
Benedikt Stebner 2 years ago
committed by GitHub
parent
commit
544d5372e3
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 39
      src/Skia/Avalonia.Skia/DrawingContextImpl.cs
  2. 61
      tests/Avalonia.RenderTests/CrossTests/Brushes/CrossTileBrushTests.cs
  3. 4
      tests/Avalonia.RenderTests/Media/ImageDrawingTests.cs
  4. 30
      tests/Avalonia.RenderTests/Media/TileBrushTests.cs
  5. BIN
      tests/TestFiles/CrossTests/Media/TileBrushes/Should_Render_Scaled_TileBrush.wpf.png
  6. BIN
      tests/TestFiles/CrossTests/Media/TileBrushes/Should_Render_With_Transform.wpf.png
  7. BIN
      tests/TestFiles/Direct2D1/Media/DrawingBrush/DrawingBrushIsProperlyScaled.expected.png
  8. BIN
      tests/TestFiles/Skia/Media/DrawingBrush/DrawingBrushIsProperlyScaled.expected.png

39
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)

61
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<CrossDrawing>()
{
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
});
}
}

4
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()
{

30
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]

BIN
tests/TestFiles/CrossTests/Media/TileBrushes/Should_Render_Scaled_TileBrush.wpf.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 962 B

BIN
tests/TestFiles/CrossTests/Media/TileBrushes/Should_Render_With_Transform.wpf.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 B

BIN
tests/TestFiles/Direct2D1/Media/DrawingBrush/DrawingBrushIsProperlyScaled.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
tests/TestFiles/Skia/Media/DrawingBrush/DrawingBrushIsProperlyScaled.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Loading…
Cancel
Save