diff --git a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs index 4ae306ff16..02aae6d7bc 100644 --- a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs +++ b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs @@ -10,16 +10,14 @@ namespace Avalonia.Skia { internal class DrawingContextImpl : IDrawingContextImpl { - private Stack surfaceStack = new Stack(); - private Stack maskStack = new Stack(); - private SKCanvas initialCanvas; - - public SKCanvas CurrentCanvas => surfaceStack.Count == 0 ? initialCanvas : surfaceStack.Peek().Canvas; + private Stack maskStack = new Stack(); + + public SKCanvas CurrentCanvas { get; private set; } public DrawingContextImpl(SKCanvas canvas) { - initialCanvas = canvas; - initialCanvas.Clear(); + CurrentCanvas = canvas; + CurrentCanvas.Clear(); } public void DrawImage(IBitmap source, double opacity, Rect sourceRect, Rect destRect) @@ -57,18 +55,6 @@ namespace Avalonia.Skia } } - struct MaskWrapper : IDisposable - { - public PaintWrapper Mask { get; set; } - public Rect Bounds { get; set; } - - public void Dispose() - { - Mask.Dispose(); - } - } - - struct PaintWrapper : IDisposable { //We are saving memory allocations there @@ -317,37 +303,19 @@ namespace Avalonia.Skia public void PushOpacityMask(IBrush mask, Rect bounds) { - surfaceStack.Push(SKSurface.Create((int)bounds.Width, (int)bounds.Height, SKColorType.N_32, SKAlphaType.Premul)); - surfaceStack.Peek().Canvas.Clear(); - var paint = new MaskWrapper { Mask = CreatePaint(mask, bounds.Size), Bounds = bounds }; - maskStack.Push(paint); + CurrentCanvas.SaveLayer(new SKPaint()); + maskStack.Push(CreatePaint(mask, bounds.Size)); } public void PopOpacityMask() { - using (var surface = surfaceStack.Pop()) - using (var mask = maskStack.Pop()) - using (var combindingPaint = new SKPaint()) - using (var surfaceImage = surface.Snapshot()) + CurrentCanvas.SaveLayer(new SKPaint { XferMode = SKXferMode.DstIn }); + using (var paintWrapper = maskStack.Pop()) { - using (var maskSurface = SKSurface.Create((int)mask.Bounds.Width, (int)mask.Bounds.Height, SKColorType.N_32, SKAlphaType.Premul)) - { - maskSurface.Canvas.Clear(SKColors.Transparent); - maskSurface.Canvas.DrawRect(SKRect.Create((float)mask.Bounds.Width, (float)mask.Bounds.Height), mask.Mask.Paint); - using (var maskImage = maskSurface.Snapshot()) - using (var combindingSurface = SKSurface.Create((int)mask.Bounds.Width, (int)mask.Bounds.Height, SKColorType.N_32, SKAlphaType.Premul)) - { - combindingSurface.Canvas.Clear(SKColors.Transparent); - combindingSurface.Canvas.DrawImage(surfaceImage, 0, 0, combindingPaint); - combindingPaint.XferMode = SKXferMode.DstIn; - combindingSurface.Canvas.DrawImage(maskImage, 0, 0, combindingPaint); - using (var maskedImage = combindingSurface.Snapshot()) - { - CurrentCanvas.DrawImage(maskedImage, mask.Bounds.ToSKRect()); - } - } - } + CurrentCanvas.DrawPaint(paintWrapper.Paint); } + CurrentCanvas.Restore(); + CurrentCanvas.Restore(); } private Matrix _currentTransform = Matrix.Identity; diff --git a/tests/Avalonia.RenderTests/OpacityMaskTests.cs b/tests/Avalonia.RenderTests/OpacityMaskTests.cs index 903181c763..b23f231f2e 100644 --- a/tests/Avalonia.RenderTests/OpacityMaskTests.cs +++ b/tests/Avalonia.RenderTests/OpacityMaskTests.cs @@ -21,11 +21,7 @@ namespace Avalonia.Direct2D1.RenderTests { } -#if AVALONIA_SKIA - [Fact(Skip = "Opacity Masks on Skia are currently bugged.")] -#else [Fact] -#endif public void Opacity_Mask_Masks_Element() { var target = new Canvas diff --git a/tests/TestFiles/Skia/OpacityMask/Opacity_Mask_Masks_Element.expected.png b/tests/TestFiles/Skia/OpacityMask/Opacity_Mask_Masks_Element.expected.png index f57c675b7a..935ba57aff 100644 Binary files a/tests/TestFiles/Skia/OpacityMask/Opacity_Mask_Masks_Element.expected.png and b/tests/TestFiles/Skia/OpacityMask/Opacity_Mask_Masks_Element.expected.png differ