Skip to content

Commit

Permalink
Fixes/drawing brush transform (AvaloniaUI#14978)
Browse files Browse the repository at this point in the history
* Apply brush transform to SKPicture instead to the local matrix of the resulting SKShader

* Add unit test
Implement Direct2D1
  • Loading branch information
Gillibald authored Mar 15, 2024
1 parent 1911955 commit 6eb9d7a
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 9 deletions.
14 changes: 5 additions & 9 deletions src/Skia/Avalonia.Skia/DrawingContextImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1150,6 +1150,11 @@ private void ConfigureSceneBrushContentWithPicture(ref PaintWrapper paintWrapper
var tileBrush = content.Brush;
var transform = rect.TopLeft == default ? Matrix.Identity : Matrix.CreateTranslation(-rect.X, -rect.Y);

if (content.Transform is not null)
{
transform = content.Transform.Value * transform;
}

var calc = new TileBrushCalculator(tileBrush, contentSize, targetRect.Size);
transform *= calc.IntermediateTransform;

Expand Down Expand Up @@ -1186,15 +1191,6 @@ private void ConfigureSceneBrushContentWithPicture(ref PaintWrapper paintWrapper
paintTransform = SKMatrix.Concat(paintTransform,
SKMatrix.CreateScale((float)(96.0 / _intermediateSurfaceDpi.X), (float)(96.0 / _intermediateSurfaceDpi.Y)));

if (tileBrush.Transform is { })
{
var origin = tileBrush.TransformOrigin.ToPixels(targetRect);
var offset = Matrix.CreateTranslation(origin);
var brushTransform = (-offset) * tileBrush.Transform.Value * (offset);

paintTransform = paintTransform.PreConcat(brushTransform.ToSKMatrix());
}

if (tileBrush.DestinationRect.Unit == RelativeUnit.Relative)
paintTransform =
paintTransform.PreConcat(SKMatrix.CreateTranslation((float)targetRect.X, (float)targetRect.Y));
Expand Down
6 changes: 6 additions & 0 deletions src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,12 @@ public BrushImpl CreateBrush(IBrush brush, Rect destinationRect)
using (var ctx = new RenderTarget(intermediate).CreateDrawingContext(true))
{
intermediate.Clear(null);

if (sceneBrush?.Transform is not null)
{
ctx.Transform *= sceneBrush.Transform.Value;
}

sceneBrushContent.Render(ctx,
rect.TopLeft == default ? null : Matrix.CreateTranslation(-rect.X, -rect.Y));
}
Expand Down
30 changes: 30 additions & 0 deletions tests/Avalonia.RenderTests/Media/ImageBrushTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -460,5 +460,35 @@ public async Task ImageBrush_Is_Properly_Mapped(bool relative)
await RenderToFile(new RelativePointTestPrimitivesHelper(brush), testName);
CompareImages(testName);
}

[Fact]
public async Task ImageBrush_Should_Render_With_Transform()
{
var image = new Image
{
Width = 200,
Height = 200,
Source = new DrawingImage
{
Drawing = new GeometryDrawing
{
Brush = new DrawingBrush
{
Transform = new TranslateTransform { X = 10, Y = 10 },
Drawing = new GeometryDrawing
{
Brush = Brushes.MediumBlue,
Geometry = new RectangleGeometry { Rect = new Rect(0, 0, 48, 48) }
}
},
Geometry = new RectangleGeometry { Rect = new Rect(0, 0, 48, 48) }
}
}
};

await RenderToFile(image);

CompareImages();
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 6eb9d7a

Please sign in to comment.