diff --git a/src/Perspex.Base/Threading/DispatcherTimer.cs b/src/Perspex.Base/Threading/DispatcherTimer.cs index 159151dc79..d84bcf519e 100644 --- a/src/Perspex.Base/Threading/DispatcherTimer.cs +++ b/src/Perspex.Base/Threading/DispatcherTimer.cs @@ -18,12 +18,13 @@ namespace Perspex.Threading private TimeSpan _interval; + private readonly Action _raiseTickAction; + /// /// Initializes a new instance of the class. /// - public DispatcherTimer() + public DispatcherTimer() : this(DispatcherPriority.Normal) { - _priority = DispatcherPriority.Normal; } /// @@ -34,6 +35,7 @@ namespace Perspex.Threading public DispatcherTimer(DispatcherPriority priority) { _priority = priority; + _raiseTickAction = RaiseTick; } /// @@ -43,7 +45,7 @@ namespace Perspex.Threading /// The priority to use. /// The dispatcher to use. /// The event to call when the timer ticks. - public DispatcherTimer(TimeSpan interval, DispatcherPriority priority, EventHandler callback) + public DispatcherTimer(TimeSpan interval, DispatcherPriority priority, EventHandler callback) : this(priority) { _priority = priority; Interval = interval; @@ -172,12 +174,14 @@ namespace Perspex.Threading } } + + /// /// Raises the event on the dispatcher thread. /// private void InternalTick() { - Dispatcher.UIThread.InvokeAsync(RaiseTick, _priority); + Dispatcher.UIThread.InvokeAsync(_raiseTickAction, _priority); } /// diff --git a/src/Perspex.SceneGraph/Media/DrawingContext.cs b/src/Perspex.SceneGraph/Media/DrawingContext.cs index bd5b11a19f..28cfeb77a7 100644 --- a/src/Perspex.SceneGraph/Media/DrawingContext.cs +++ b/src/Perspex.SceneGraph/Media/DrawingContext.cs @@ -13,8 +13,17 @@ namespace Perspex.Media private readonly IDrawingContextImpl _impl; private int _currentLevel; - private Stack _transformContainers = new Stack(); - private Stack _states = new Stack(); + + + static readonly Stack> StateStackPool = new Stack>(); + static readonly Stack> TransformStackPool = new Stack>(); + + private Stack _states = StateStackPool.Count == 0 ? new Stack() : StateStackPool.Pop(); + + private Stack _transformContainers = TransformStackPool.Count == 0 + ? new Stack() + : TransformStackPool.Pop(); + struct TransformContainer { public Matrix LocalTransform; @@ -206,6 +215,10 @@ namespace Perspex.Media { while (_states.Count != 0) _states.Peek().Dispose(); + StateStackPool.Push(_states); + _states = null; + TransformStackPool.Push(_transformContainers); + _transformContainers = null; _impl.Dispose(); } } diff --git a/src/Perspex.SceneGraph/Rendering/RendererBase.cs b/src/Perspex.SceneGraph/Rendering/RendererBase.cs index 7a7db8f842..9ebe830f90 100644 --- a/src/Perspex.SceneGraph/Rendering/RendererBase.cs +++ b/src/Perspex.SceneGraph/Rendering/RendererBase.cs @@ -2,6 +2,8 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Perspex.Media; using Perspex.Platform; @@ -14,6 +16,8 @@ namespace Perspex.Rendering /// /// This class provides implements the platform-independent parts of . /// + [SuppressMessage("ReSharper", "LoopCanBeConvertedToQuery")] + [SuppressMessage("ReSharper", "ForCanBeConvertedToForeach")] public static class RendererMixin { /// @@ -58,12 +62,39 @@ namespace Perspex.Rendering using (context.PushTransformContainer()) { visual.Render(context); - foreach (var child in visual.VisualChildren.OrderBy(x => x.ZIndex)) + var lst = GetSortedVisualList(visual.VisualChildren); + foreach (var child in lst) { context.Render(child); } + ReturnListToPool(lst); } } } + + static readonly Stack> ListPool = new Stack>(); + static readonly ZIndexComparer VisualComparer = new ZIndexComparer(); + class ZIndexComparer : IComparer + { + public int Compare(IVisual x, IVisual y) => x.ZIndex.CompareTo(y.ZIndex); + } + + static void ReturnListToPool(List lst) + { + lst.Clear(); + ListPool.Push(lst); + } + + static List GetSortedVisualList(IReadOnlyList source) + { + var lst = ListPool.Count == 0 ? new List() : ListPool.Pop(); + for (var c = 0; c < source.Count; c++) + lst.Add(source[c]); + lst.Sort(VisualComparer); + return lst; + } + + + } } diff --git a/src/Skia/Perspex.Skia/FormattedTextImpl.cs b/src/Skia/Perspex.Skia/FormattedTextImpl.cs index 211da7bbc1..5e267099b5 100644 --- a/src/Skia/Perspex.Skia/FormattedTextImpl.cs +++ b/src/Skia/Perspex.Skia/FormattedTextImpl.cs @@ -114,6 +114,8 @@ namespace Perspex.Skia get { return _constraint; } set { + if(_constraint == value) + return; _constraint = value; _shared->WidthConstraint = (_constraint.Width != double.PositiveInfinity)