From 180e3bf21d0ce6b3cba68a119e63ded839479ed3 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Sat, 28 May 2016 17:02:44 -0400 Subject: [PATCH] Added support for opacity masks into Cairo. --- .../Avalonia.Cairo/Media/DrawingContext.cs | 80 ++++++++++++------- 1 file changed, 51 insertions(+), 29 deletions(-) diff --git a/src/Gtk/Avalonia.Cairo/Media/DrawingContext.cs b/src/Gtk/Avalonia.Cairo/Media/DrawingContext.cs index 07b544ad3b..c2f703918d 100644 --- a/src/Gtk/Avalonia.Cairo/Media/DrawingContext.cs +++ b/src/Gtk/Avalonia.Cairo/Media/DrawingContext.cs @@ -15,7 +15,7 @@ namespace Avalonia.Cairo.Media using Cairo = global::Cairo; /// - /// Draws using Direct2D1. + /// Draws using Cairo. /// public class DrawingContext : IDrawingContextImpl, IDisposable { @@ -24,6 +24,8 @@ namespace Avalonia.Cairo.Media /// private readonly Cairo.Context _context; + private readonly Stack _maskStack = new Stack(); + /// /// Initializes a new instance of the class. /// @@ -273,46 +275,53 @@ namespace Avalonia.Cairo.Media private IDisposable SetBrush(IBrush brush, Size destinationSize) { - _context.Save (); + _context.Save(); + + BrushImpl impl = CreateBrushImpl(brush, destinationSize); + _context.SetSource(impl.PlatformBrush); + return Disposable.Create(() => + { + impl.Dispose(); + _context.Restore(); + }); + } + + private BrushImpl CreateBrushImpl(IBrush brush, Size destinationSize) + { var solid = brush as SolidColorBrush; var linearGradientBrush = brush as LinearGradientBrush; var radialGradientBrush = brush as RadialGradientBrush; var imageBrush = brush as ImageBrush; var visualBrush = brush as VisualBrush; - BrushImpl impl = null; + BrushImpl impl = null; - if (solid != null) - { - impl = new SolidColorBrushImpl(solid, opacityOverride); - } - else if (linearGradientBrush != null) - { - impl = new LinearGradientBrushImpl(linearGradientBrush, destinationSize); - } + if (solid != null) + { + impl = new SolidColorBrushImpl(solid, opacityOverride); + } + else if (linearGradientBrush != null) + { + impl = new LinearGradientBrushImpl(linearGradientBrush, destinationSize); + } else if (radialGradientBrush != null) { impl = new RadialGradientBrushImpl(radialGradientBrush, destinationSize); } - else if (imageBrush != null) - { - impl = new ImageBrushImpl(imageBrush, destinationSize); - } - else if (visualBrush != null) - { - impl = new VisualBrushImpl(visualBrush, destinationSize); - } - else - { - impl = new SolidColorBrushImpl(null, opacityOverride); - } + else if (imageBrush != null) + { + impl = new ImageBrushImpl(imageBrush, destinationSize); + } + else if (visualBrush != null) + { + impl = new VisualBrushImpl(visualBrush, destinationSize); + } + else + { + impl = new SolidColorBrushImpl(null, opacityOverride); + } - _context.SetSource(impl.PlatformBrush); - return Disposable.Create(() => - { - impl.Dispose(); - _context.Restore(); - }); + return impl; } private IDisposable SetPen(Pen pen, Size destinationSize) @@ -352,5 +361,18 @@ namespace Avalonia.Cairo.Media { _context.Restore(); } + + public void PushOpacityMask(IBrush mask, Rect bounds) + { + _context.PushGroup(); + var impl = CreateBrushImpl(mask, bounds.Size); + _maskStack.Push(impl); + } + + public void PopOpacityMask() + { + _context.PopGroupToSource(); + _context.Mask(_maskStack.Pop().PlatformBrush); + } } }