diff --git a/src/Avalonia.Base/Rendering/Composition/CompositingRenderer.cs b/src/Avalonia.Base/Rendering/Composition/CompositingRenderer.cs index c67142648a..8cb7daca6b 100644 --- a/src/Avalonia.Base/Rendering/Composition/CompositingRenderer.cs +++ b/src/Avalonia.Base/Rendering/Composition/CompositingRenderer.cs @@ -189,6 +189,7 @@ public class CompositingRenderer : RendererBase, IRendererWithCompositor comp.Opacity = (float)visual.Opacity; comp.ClipToBounds = visual.ClipToBounds; comp.Clip = visual.Clip?.PlatformImpl; + comp.OpacityMask = visual.OpacityMask; var renderTransform = Matrix.Identity; diff --git a/src/Avalonia.Base/Rendering/Composition/Server/ServerVisual.cs b/src/Avalonia.Base/Rendering/Composition/Server/ServerVisual.cs index 0b2ba6922b..d42bcae7e7 100644 --- a/src/Avalonia.Base/Rendering/Composition/Server/ServerVisual.cs +++ b/src/Avalonia.Base/Rendering/Composition/Server/ServerVisual.cs @@ -24,10 +24,13 @@ namespace Avalonia.Rendering.Composition.Server canvas.Transform = Matrix.Identity; if (Opacity != 1) canvas.PushOpacity(Opacity); + var boundsRect = new Rect(new Size(Size.X, Size.Y)); if(ClipToBounds) - canvas.PushClip(new Rect(new Size(Size.X, Size.Y))); + canvas.PushClip(boundsRect); if (Clip != null) canvas.PushGeometryClip(Clip); + if(OpacityMaskBrush != null) + canvas.PushOpacityMask(OpacityMaskBrush, boundsRect); //TODO: Check clip RenderCore(canvas); @@ -35,7 +38,9 @@ namespace Avalonia.Rendering.Composition.Server // Hack to force invalidation of SKMatrix canvas.PreTransform = MatrixUtils.ToMatrix(transform); canvas.Transform = Matrix.Identity; - + + if (OpacityMaskBrush != null) + canvas.PopOpacityMask(); if (Clip != null) canvas.PopGeometryClip(); if (ClipToBounds) diff --git a/src/Avalonia.Base/Rendering/Composition/Visual.cs b/src/Avalonia.Base/Rendering/Composition/Visual.cs index 3d6e3fdaeb..f092029457 100644 --- a/src/Avalonia.Base/Rendering/Composition/Visual.cs +++ b/src/Avalonia.Base/Rendering/Composition/Visual.cs @@ -1,11 +1,14 @@ using System; using System.Numerics; +using Avalonia.Media; using Avalonia.VisualTree; namespace Avalonia.Rendering.Composition { public abstract partial class CompositionVisual { + private IBrush? _opacityMask; + private protected virtual void OnRootChangedCore() { } @@ -14,6 +17,16 @@ namespace Avalonia.Rendering.Composition partial void OnParentChanged() => Root = Parent?.Root; + public IBrush? OpacityMask + { + get => _opacityMask; + set + { + if (_opacityMask == value) + return; + OpacityMaskBrush = (_opacityMask = value)?.ToImmutable(); + } + } internal Matrix4x4? TryGetServerTransform() { diff --git a/src/Avalonia.Base/composition-schema.xml b/src/Avalonia.Base/composition-schema.xml index b86ce35d5f..2b555359c6 100644 --- a/src/Avalonia.Base/composition-schema.xml +++ b/src/Avalonia.Base/composition-schema.xml @@ -6,13 +6,15 @@ Avalonia.Rendering.Composition.Animations + - + + @@ -23,6 +25,7 @@ +