|
|
|
@ -10,16 +10,14 @@ namespace Avalonia.Skia |
|
|
|
{ |
|
|
|
internal class DrawingContextImpl : IDrawingContextImpl |
|
|
|
{ |
|
|
|
private Stack<SKSurface> surfaceStack = new Stack<SKSurface>(); |
|
|
|
private Stack<MaskWrapper> maskStack = new Stack<MaskWrapper>(); |
|
|
|
private SKCanvas initialCanvas; |
|
|
|
|
|
|
|
public SKCanvas CurrentCanvas => surfaceStack.Count == 0 ? initialCanvas : surfaceStack.Peek().Canvas; |
|
|
|
private Stack<PaintWrapper> maskStack = new Stack<PaintWrapper>(); |
|
|
|
|
|
|
|
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; |
|
|
|
|