From 071d1e2ab0232c4e4a64c03baa4fd1e45f97af76 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Mon, 18 Mar 2024 23:26:16 +0600 Subject: [PATCH] [SKIA] Don't skip setting SKCanvas.TotalMatrix when we aren't sure what the current transform is due to Save/Restore calls (#15027) --- src/Skia/Avalonia.Skia/DrawingContextImpl.cs | 26 ++++++++++++------- src/Skia/Avalonia.Skia/SkiaSharpExtensions.cs | 5 ++++ 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs index 2b058d8fb7..ead84a82e2 100644 --- a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs +++ b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs @@ -30,7 +30,7 @@ namespace Avalonia.Skia private readonly Matrix? _postTransform; private double _currentOpacity = 1.0f; private readonly bool _disableSubpixelTextRendering; - private Matrix _currentTransform; + private Matrix? _currentTransform; private bool _disposed; private GRContext? _grContext; public GRContext? GrContext => _grContext; @@ -466,7 +466,7 @@ namespace Avalonia.Skia Transform = oldTransform; } - Canvas.Restore(); + RestoreCanvas(); } } } @@ -509,7 +509,7 @@ namespace Avalonia.Skia using (var outerRRect = new SKRoundRect(outerRect)) Canvas.DrawRoundRectDifference(outerRRect, shadowRect, shadow.Paint); Transform = oldTransform; - Canvas.Restore(); + RestoreCanvas(); SKRoundRectCache.Shared.Return(shadowRect); } } @@ -672,11 +672,17 @@ namespace Avalonia.Skia Canvas.ClipRegion(r); } + private void RestoreCanvas() + { + _currentTransform = null; + Canvas.Restore(); + } + /// public void PopClip() { CheckLease(); - Canvas.Restore(); + RestoreCanvas(); } public void PushLayer(Rect bounds) @@ -688,7 +694,7 @@ namespace Avalonia.Skia public void PopLayer() { CheckLease(); - Canvas.Restore(); + RestoreCanvas(); } /// @@ -731,7 +737,7 @@ namespace Avalonia.Skia if (useOpacitySaveLayer) { - Canvas.Restore(); + RestoreCanvas(); } _currentOpacity = _opacityStack.Pop(); @@ -796,7 +802,7 @@ namespace Avalonia.Skia public void PopGeometryClip() { CheckLease(); - Canvas.Restore(); + RestoreCanvas(); } /// @@ -829,15 +835,15 @@ namespace Avalonia.Skia // Return the paint wrapper's paint less the reset since the paint is already reset in the Dispose method above. SKPaintCache.Shared.Return(paintWrapper.Paint); - Canvas.Restore(); + RestoreCanvas(); - Canvas.Restore(); + RestoreCanvas(); } /// public Matrix Transform { - get { return _currentTransform; } + get { return _currentTransform ??= Canvas.TotalMatrix.ToAvaloniaMatrix(); } set { CheckLease(); diff --git a/src/Skia/Avalonia.Skia/SkiaSharpExtensions.cs b/src/Skia/Avalonia.Skia/SkiaSharpExtensions.cs index 32a89a58a5..273308cb57 100644 --- a/src/Skia/Avalonia.Skia/SkiaSharpExtensions.cs +++ b/src/Skia/Avalonia.Skia/SkiaSharpExtensions.cs @@ -124,6 +124,11 @@ namespace Avalonia.Skia return sm; } + internal static Matrix ToAvaloniaMatrix(this SKMatrix m) => new( + m.ScaleX, m.SkewY, m.Persp0, + m.SkewX, m.ScaleY, m.Persp1, + m.TransX, m.TransY, m.Persp2); + public static SKColor ToSKColor(this Color c) { return new SKColor(c.R, c.G, c.B, c.A);