Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix transform desync #16363

Merged
merged 11 commits into from
Sep 12, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -148,5 +148,10 @@ public void Flush()
ExecCommand(ref commands[index]);

_commands.Clear();

if (Transform != _impl.Transform)
{
_impl.Transform = Transform;
}
}
}
}
17 changes: 16 additions & 1 deletion tests/Avalonia.RenderTests.WpfCompare/CrossUI.Wpf.cs
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,22 @@ private static ImageSource ConvertImage(CrossImage image)
return new DrawingImage(ConvertDrawing(di.Drawing));
throw new NotSupportedException();
}


public void PushTransform(Matrix matrix)
{
_ctx.PushTransform(new MatrixTransform(matrix.ToWpf()));
}

public void Pop()
{
_ctx.Pop();
}

public void DrawLine(CrossPen pen, Point p1, Point p2)
{
_ctx.DrawLine(ConvertPen(pen), p1.ToWpf(), p2.ToWpf());
}

public void DrawRectangle(CrossBrush? brush, CrossPen? pen, Rect rc) => _ctx.DrawRectangle(ConvertBrush(brush), ConvertPen(pen), rc.ToWpf());
public void DrawGeometry(CrossBrush? brush, CrossPen? pen, CrossGeometry geo) =>
_ctx.DrawGeometry(ConvertBrush(brush), ConvertPen(pen), ConvertGeometry(geo));
Expand Down
51 changes: 51 additions & 0 deletions tests/Avalonia.RenderTests/CrossTests/Media/DrawingContextTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using Avalonia.Media;
using CrossUI;

#if AVALONIA_SKIA
namespace Avalonia.Skia.RenderTests.CrossTests;
#elif AVALONIA_D2D
namespace Avalonia.Direct2D1.RenderTests.CrossTests;
#else
namespace Avalonia.RenderTests.WpfCompare.CrossTests;
#endif


public class DrawingContextTests : CrossTestBase
{
public DrawingContextTests() : base("Media/DrawingContext")
{
}

[CrossFact]
public void Transform_Should_Work_As_Expected()
{
RenderAndCompare(

new CrossFuncControl(ctx =>
{
ctx.PushTransform(Matrix.CreateTranslation(100, 100));
ctx.DrawLine(new CrossPen { Brush = new CrossSolidColorBrush(Colors.Red), Thickness = 1 },
new Point(0, 0), new Point(100, 0));
ctx.Pop();

ctx.PushTransform(Matrix.CreateTranslation(200, 100));
ctx.DrawLine(new CrossPen { Brush = new CrossSolidColorBrush(Colors.Orange), Thickness = 1 },
new Point(0, 0), new Point(0, 100));
ctx.Pop();

ctx.PushTransform(Matrix.CreateTranslation(200, 200));
ctx.DrawLine(
new CrossPen { Brush = new CrossSolidColorBrush(Colors.Yellow), Thickness = 1 },
new Point(0, 0), new Point(-100, 0));
ctx.Pop();

ctx.PushTransform(Matrix.CreateTranslation(100, 200));
ctx.DrawLine(new CrossPen { Brush = new CrossSolidColorBrush(Colors.Green), Thickness = 1 },
new Point(0, 0), new Point(0, -100));
ctx.Pop();
}) { Width = 300, Height = 300 }

);

}
}
27 changes: 26 additions & 1 deletion tests/Avalonia.RenderTests/CrossUI/CrossUI.Avalonia.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ public override void Render(DrawingContext context)
class AvaloniaCrossDrawingContext : ICrossDrawingContext
{
private readonly DrawingContext _ctx;
private readonly Stack<DrawingContext.PushedState> _stack = new();

public AvaloniaCrossDrawingContext(DrawingContext ctx)
{
Expand Down Expand Up @@ -303,7 +304,31 @@ static IImage ConvertImage(CrossImage image)
return new DrawingImage(ConvertDrawing(di.Drawing));
throw new NotSupportedException();
}


public void PushTransform(Matrix matrix)
{
_stack.Push(_ctx.PushTransform(matrix));
}

public void Pop()
{
var state = _stack.Pop();

state.Dispose();
}

public void DrawLine(CrossPen pen, Point p1, Point p2)
{
var avPen = ConvertPen(pen);

if (avPen == null)
{
return;
}

_ctx.DrawLine(avPen, p1, p2);
}

public void DrawRectangle(CrossBrush? brush, CrossPen? pen, Rect rc) => _ctx.DrawRectangle(ConvertBrush(brush), ConvertPen(pen), rc);
public void DrawGeometry(CrossBrush? brush, CrossPen? pen, CrossGeometry geometry) =>
_ctx.DrawGeometry(ConvertBrush(brush), ConvertPen(pen), ConvertGeometry(geometry));
Expand Down
3 changes: 3 additions & 0 deletions tests/Avalonia.RenderTests/CrossUI/CrossUI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,9 @@ public interface ICrossStreamGeometryContextImplProvider

public interface ICrossDrawingContext
{
void PushTransform(Matrix matrix);
void Pop();
void DrawLine(CrossPen pen, Point p1, Point p2);
void DrawRectangle(CrossBrush? brush, CrossPen? pen, Rect rc);
void DrawGeometry(CrossBrush? brush, CrossPen? pen, CrossGeometry geometry);
void DrawImage(CrossImage image, Rect rc);
Expand Down
69 changes: 69 additions & 0 deletions tests/Avalonia.RenderTests/Media/DrawingContextTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using System.Globalization;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Media;
using Xunit;
#pragma warning disable CS0649

#if AVALONIA_SKIA
namespace Avalonia.Skia.RenderTests;

public class DrawingContextTests : TestBase
{
public DrawingContextTests() : base(@"Media\DrawingContext")
{
}

[Fact]
public async Task Should_Render_LinesAndText()
{
var target = new Border
{
Width = 300,
Height = 300,
Background = Brushes.White,
Child = new RenderControl()
};

await RenderToFile(target);
CompareImages(skipImmediate: true);
}

internal class RenderControl : Control
{
private static readonly Typeface s_typeface = new Typeface(TestFontFamily);

public override void Render(DrawingContext context)
{
var pen = new Pen(Brushes.LightGray, 10);
RenderLine1(context, pen);
RenderLine2(context, pen);
RenderLine3(context, pen);
RenderLine4(context, pen);

RenderLine1(context, new Pen(Brushes.Red));
RenderAText(context, new Point(50, 20));
RenderLine2(context, new Pen(Brushes.Orange));
RenderAText(context, new Point(50, -50));
RenderLine3(context, new Pen(Brushes.Yellow));
RenderAText(context, new Point(0, 0));
RenderLine4(context, new Pen(Brushes.Green));
}

private static void RenderLine1(DrawingContext context, IPen pen) => context.DrawLine(pen, new Point(100, 100), new Point(200, 100));
private static void RenderLine2(DrawingContext context, IPen pen) => context.DrawLine(pen, new Point(200, 100), new Point(200, 200));
private static void RenderLine3(DrawingContext context, IPen pen) => context.DrawLine(pen, new Point(200, 200), new Point(100, 200));
private static void RenderLine4(DrawingContext context, IPen pen) => context.DrawLine(pen, new Point(100, 200), new Point(100, 100));

private static void RenderAText(DrawingContext context, Point point)
{
using (context.PushOpacity(0.7))
{
context.DrawText(
new FormattedText("any text to render", CultureInfo.CurrentCulture, FlowDirection.LeftToRight,
s_typeface, 12, Brushes.Black), point);
}
}
}
}
#endif
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.
Loading