From 85966d3ecf926325ac2af44b883c760f4d4c6ac5 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 30 Jan 2018 19:30:59 -0600 Subject: [PATCH] Ref-count the draw operations collection in VisualNode so it correctly keeps the elements alive when only the collection is cloned (aka no changes are made by a cloned VisualNode) and the original VisualNode is disposed. --- .../Rendering/SceneGraph/VisualNode.cs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs index 0208511c4c..c651fee67f 100644 --- a/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs +++ b/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reactive.Disposables; using Avalonia.Media; using Avalonia.Platform; using Avalonia.Utilities; @@ -23,6 +24,7 @@ namespace Avalonia.Rendering.SceneGraph private double _opacity; private List _children; private List> _drawOperations; + private IRef _drawOperationsRefCounter; private bool _drawOperationsCloned; private Matrix transformRestore; @@ -214,6 +216,7 @@ namespace Avalonia.Rendering.SceneGraph _opacity = Opacity, OpacityMask = OpacityMask, _drawOperations = _drawOperations, + _drawOperationsRefCounter = _drawOperationsRefCounter?.Clone(), _drawOperationsCloned = true, LayerRoot= LayerRoot, }; @@ -315,10 +318,14 @@ namespace Avalonia.Rendering.SceneGraph if (_drawOperations == null) { _drawOperations = new List>(); + _drawOperationsRefCounter = RefCountable.Create(Disposable.Create(DisposeDrawOperations)); + _drawOperationsCloned = false; } else if (_drawOperationsCloned) { _drawOperations = new List>(_drawOperations.Select(op => op.Clone())); + _drawOperationsRefCounter.Dispose(); + _drawOperationsRefCounter = RefCountable.Create(Disposable.Create(DisposeDrawOperations)); _drawOperationsCloned = false; } } @@ -329,12 +336,14 @@ namespace Avalonia.Rendering.SceneGraph { child.Dispose(); } - if (!_drawOperationsCloned) + _drawOperationsRefCounter?.Dispose(); + } + + private void DisposeDrawOperations() + { + foreach (var operation in DrawOperations) { - foreach (var operation in DrawOperations) - { - operation.Dispose(); - } + operation.Dispose(); } } }