1
0
mirror of https://github.com/DarthAffe/RGB.NET.git synced 2025-12-13 01:58:30 +00:00

Added caching to the linear gradient for a small performance gain

This commit is contained in:
Darth Affe 2018-01-30 20:47:21 +01:00
parent 98331d0241
commit 575461ec5e

View File

@ -1,6 +1,7 @@
// ReSharper disable UnusedMember.Global // ReSharper disable UnusedMember.Global
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.Linq; using System.Linq;
using RGB.NET.Core; using RGB.NET.Core;
@ -12,6 +13,13 @@ namespace RGB.NET.Brushes.Gradients
/// </summary> /// </summary>
public class LinearGradient : AbstractGradient public class LinearGradient : AbstractGradient
{ {
#region Properties & Fields
private bool _isOrderedGradientListDirty = true;
private LinkedList<GradientStop> _orderedGradientStops;
#endregion
#region Constructors #region Constructors
/// <inheritdoc /> /// <inheritdoc />
@ -19,7 +27,9 @@ namespace RGB.NET.Brushes.Gradients
/// Initializes a new instance of the <see cref="T:RGB.NET.Brushes.Gradients.LinearGradient" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Brushes.Gradients.LinearGradient" /> class.
/// </summary> /// </summary>
public LinearGradient() public LinearGradient()
{ } {
Initialize();
}
/// <inheritdoc /> /// <inheritdoc />
/// <summary> /// <summary>
@ -28,7 +38,9 @@ namespace RGB.NET.Brushes.Gradients
/// <param name="gradientStops">The stops with which the gradient should be initialized.</param> /// <param name="gradientStops">The stops with which the gradient should be initialized.</param>
public LinearGradient(params GradientStop[] gradientStops) public LinearGradient(params GradientStop[] gradientStops)
: base(gradientStops) : base(gradientStops)
{ } {
Initialize();
}
/// <inheritdoc /> /// <inheritdoc />
/// <summary> /// <summary>
@ -38,12 +50,33 @@ namespace RGB.NET.Brushes.Gradients
/// <param name="gradientStops">The stops with which the gradient should be initialized.</param> /// <param name="gradientStops">The stops with which the gradient should be initialized.</param>
public LinearGradient(bool wrapGradient, params GradientStop[] gradientStops) public LinearGradient(bool wrapGradient, params GradientStop[] gradientStops)
: base(wrapGradient, gradientStops) : base(wrapGradient, gradientStops)
{ } {
Initialize();
}
#endregion #endregion
#region Methods #region Methods
private void Initialize()
{
void OnGradientStopOnPropertyChanged(object sender, PropertyChangedEventArgs args) => _isOrderedGradientListDirty = true;
foreach (GradientStop gradientStop in GradientStops)
gradientStop.PropertyChanged += OnGradientStopOnPropertyChanged;
GradientStops.CollectionChanged += (sender, args) =>
{
if (args.OldItems != null)
foreach (GradientStop gradientStop in args.OldItems)
gradientStop.PropertyChanged -= OnGradientStopOnPropertyChanged;
if (args.NewItems != null)
foreach (GradientStop gradientStop in args.NewItems)
gradientStop.PropertyChanged += OnGradientStopOnPropertyChanged;
};
}
/// <inheritdoc /> /// <inheritdoc />
/// <summary> /// <summary>
/// Gets the linear interpolated <see cref="T:RGB.NET.Core.Color" /> at the given offset. /// Gets the linear interpolated <see cref="T:RGB.NET.Core.Color" /> at the given offset.
@ -55,7 +88,10 @@ namespace RGB.NET.Brushes.Gradients
if (GradientStops.Count == 0) return Color.Transparent; if (GradientStops.Count == 0) return Color.Transparent;
if (GradientStops.Count == 1) return GradientStops[0].Color; if (GradientStops.Count == 1) return GradientStops[0].Color;
(GradientStop gsBefore, GradientStop gsAfter) = GetEnclosingGradientStops(offset, GradientStops, WrapGradient); if (_isOrderedGradientListDirty)
_orderedGradientStops = new LinkedList<GradientStop>(GradientStops.OrderBy(x => x.Offset));
(GradientStop gsBefore, GradientStop gsAfter) = GetEnclosingGradientStops(offset, _orderedGradientStops, WrapGradient);
double blendFactor = 0; double blendFactor = 0;
if (!gsBefore.Offset.Equals(gsAfter.Offset)) if (!gsBefore.Offset.Equals(gsAfter.Offset))
@ -73,12 +109,12 @@ namespace RGB.NET.Brushes.Gradients
/// Get the two <see cref="GradientStop"/>s encapsulating the given offset. /// Get the two <see cref="GradientStop"/>s encapsulating the given offset.
/// </summary> /// </summary>
/// <param name="offset">The reference offset.</param> /// <param name="offset">The reference offset.</param>
/// <param name="stops">The <see cref="GradientStop"/> to choose from.</param> /// <param name="orderedStops">The ordered list of <see cref="GradientStop"/> to choose from.</param>
/// <param name="wrap">Bool indicating if the gradient should be wrapped or not.</param> /// <param name="wrap">Bool indicating if the gradient should be wrapped or not.</param>
/// <returns></returns> /// <returns></returns>
protected virtual (GradientStop gsBefore, GradientStop gsAfter) GetEnclosingGradientStops(double offset, IEnumerable<GradientStop> stops, bool wrap) protected virtual (GradientStop gsBefore, GradientStop gsAfter) GetEnclosingGradientStops(double offset, LinkedList<GradientStop> orderedStops, bool wrap)
{ {
LinkedList<GradientStop> orderedStops = new LinkedList<GradientStop>(stops.OrderBy(x => x.Offset)); LinkedList<GradientStop> gradientStops = new LinkedList<GradientStop>(orderedStops);
if (wrap) if (wrap)
{ {
@ -86,20 +122,20 @@ namespace RGB.NET.Brushes.Gradients
do do
{ {
gsBefore = orderedStops.LastOrDefault(n => n.Offset <= offset); gsBefore = gradientStops.LastOrDefault(n => n.Offset <= offset);
if (gsBefore == null) if (gsBefore == null)
{ {
GradientStop lastStop = orderedStops.Last.Value; GradientStop lastStop = gradientStops.Last.Value;
orderedStops.AddFirst(new GradientStop(lastStop.Offset - 1, lastStop.Color)); gradientStops.AddFirst(new GradientStop(lastStop.Offset - 1, lastStop.Color));
orderedStops.RemoveLast(); gradientStops.RemoveLast();
} }
gsAfter = orderedStops.FirstOrDefault(n => n.Offset >= offset); gsAfter = gradientStops.FirstOrDefault(n => n.Offset >= offset);
if (gsAfter == null) if (gsAfter == null)
{ {
GradientStop firstStop = orderedStops.First.Value; GradientStop firstStop = gradientStops.First.Value;
orderedStops.AddLast(new GradientStop(firstStop.Offset + 1, firstStop.Color)); gradientStops.AddLast(new GradientStop(firstStop.Offset + 1, firstStop.Color));
orderedStops.RemoveFirst(); gradientStops.RemoveFirst();
} }
} while ((gsBefore == null) || (gsAfter == null)); } while ((gsBefore == null) || (gsAfter == null));
@ -108,7 +144,7 @@ namespace RGB.NET.Brushes.Gradients
} }
offset = ClipOffset(offset); offset = ClipOffset(offset);
return (orderedStops.Last(n => n.Offset <= offset), orderedStops.First(n => n.Offset >= offset)); return (gradientStops.Last(n => n.Offset <= offset), gradientStops.First(n => n.Offset >= offset));
} }
#endregion #endregion