From 2a87dbd6caf4e90bef242fb49562e494546d048f Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 6 Dec 2017 10:53:55 +0100 Subject: [PATCH] Fix opacity mask rendering. We're potentially creating a new immutable version of the opacity mask each time the `VisualNode` is updated. Need to implement comparison between mutable and immutable brushes. --- .../Rendering/SceneGraph/SceneBuilder.cs | 4 ++- .../Rendering/SceneGraph/VisualNode.cs | 10 +++++++ .../Rendering/DeferredRendererTests.cs | 26 +++++++++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs index 4f5f094e29..8f4f487e08 100644 --- a/src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs +++ b/src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs @@ -178,7 +178,9 @@ namespace Avalonia.Rendering.SceneGraph node.ClipToBounds = clipToBounds; node.GeometryClip = visual.Clip?.PlatformImpl; node.Opacity = opacity; - node.OpacityMask = visual.OpacityMask; + + // TODO: Check equality between node.OpacityMask and visual.OpacityMask before assigning. + node.OpacityMask = visual.OpacityMask?.ToImmutable(); if (ShouldStartLayer(visual)) { diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs index e9e20557bd..ecff1a1077 100644 --- a/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs +++ b/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs @@ -231,6 +231,11 @@ namespace Avalonia.Rendering.SceneGraph context.PushOpacity(Opacity); } + if (OpacityMask != null) + { + context.PushOpacityMask(OpacityMask, ClipBounds); + } + context.Transform = Transform; if (GeometryClip != null) @@ -247,6 +252,11 @@ namespace Avalonia.Rendering.SceneGraph context.PopGeometryClip(); } + if (OpacityMask != null) + { + context.PopOpacityMask(); + } + if (Opacity != 1 && !skipOpacity) { context.PopOpacity(); diff --git a/tests/Avalonia.Visuals.UnitTests/Rendering/DeferredRendererTests.cs b/tests/Avalonia.Visuals.UnitTests/Rendering/DeferredRendererTests.cs index 21065cb6b5..c97070a2aa 100644 --- a/tests/Avalonia.Visuals.UnitTests/Rendering/DeferredRendererTests.cs +++ b/tests/Avalonia.Visuals.UnitTests/Rendering/DeferredRendererTests.cs @@ -165,6 +165,32 @@ namespace Avalonia.Visuals.UnitTests.Rendering context.Verify(x => x.PopOpacity(), Times.Never); } + [Fact] + public void Should_Push_Opacity_Mask() + { + var root = new TestRoot + { + Width = 100, + Height = 100, + Child = new Border + { + Background = Brushes.Red, + OpacityMask = Brushes.Green, + } + }; + + root.Measure(Size.Infinity); + root.Arrange(new Rect(root.DesiredSize)); + + var target = CreateTargetAndRunFrame(root); + var context = GetLayerContext(target, root); + var animation = new BehaviorSubject(0.5); + + context.Verify(x => x.PushOpacityMask(Brushes.Green, new Rect(0, 0, 100, 100)), Times.Once); + context.Verify(x => x.FillRectangle(Brushes.Red, new Rect(0, 0, 100, 100), 0), Times.Once); + context.Verify(x => x.PopOpacityMask(), Times.Once); + } + [Fact] public void Should_Create_Layer_For_Root() {