From 7485ec5eaa849e7f8bf7814a59650515023e0967 Mon Sep 17 00:00:00 2001 From: "H. Utku Maden" Date: Tue, 24 Dec 2024 21:58:51 +0300 Subject: [PATCH] Add Gradient. --- Dashboard/Gradient.cs | 159 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 Dashboard/Gradient.cs diff --git a/Dashboard/Gradient.cs b/Dashboard/Gradient.cs new file mode 100644 index 0000000..5536742 --- /dev/null +++ b/Dashboard/Gradient.cs @@ -0,0 +1,159 @@ +using System.Collections; +using System.Collections.Generic; +using System.Drawing; +using System.Numerics; + +namespace Dashboard +{ + /// + /// Enumeration of the kinds of gradients available. + /// + public enum GradientType + { + /// + /// A gradient which transitions over a set axis. + /// + Axial, + /// + /// A gradient which transitions along elliptical curves. + /// + Radial, + } + + /// + /// A single gradient stop. + /// + /// The position of the gradient stop. Must be [0,1]. + /// The color value for the stop. + public record struct GradientStop(float Position, Color Color); + + /// + /// Represents a linear gradient. + /// + public struct Gradient : ICollection + { + private readonly List _stops = new List(); + + /// + /// Gradient type. + /// + public GradientType Type { get; set; } = GradientType.Axial; + + /// + /// First gradient control point. + /// + public Vector2 C0 { get; set; } = Vector2.Zero; + + /// + /// Second gradient control point. + /// + public Vector2 C1 { get; set; } = Vector2.One; + + /// + /// Number of stops in a gradient. + /// + public int Count => _stops.Count; + public bool IsReadOnly => false; + + /// + /// Get a gradient control point. + /// + /// The index to get the control point for. + public GradientStop this[int index] + { + get => _stops[index]; + set + { + RemoveAt(index); + Add(value); + } + } + + public Gradient() + { + } + + public Gradient(Color a, Color b) + { + Add(new GradientStop(0, a)); + Add(new GradientStop(1, b)); + } + + public Color GetColor(float position) + { + if (Count == 0) + return Color.Black; + else if (Count == 1) + return _stops[0].Color; + + int pivot = _stops.FindIndex(x => x.Position < position); + + GradientStop left, right; + if (pivot == -1) + { + left = right = _stops[^1]; + } + else if (pivot == 0) + { + left = right = _stops[0]; + } + else + { + left = _stops[pivot-1]; + right = _stops[pivot]; + } + + float weight = (position - left.Position) / (right.Position - left.Position); + + Vector4 lcolor = new Vector4(left.Color.R, left.Color.G, left.Color.B, left.Color.A) * (1-weight); + Vector4 rcolor = new Vector4(right.Color.R, right.Color.G, right.Color.B, right.Color.A) * weight; + Vector4 color = lcolor + rcolor; + + return Color.FromArgb((byte)color.W, (byte)color.X, (byte)color.Y, (byte)color.Z); + } + + public IEnumerator GetEnumerator() + { + return _stops.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable)_stops).GetEnumerator(); + } + + public void Add(GradientStop item) + { + int index = _stops.FindIndex(x => x.Position > item.Position); + if (index == -1) + index = _stops.Count; + + _stops.Insert(index, item); + } + + public void Clear() + { + _stops.Clear(); + } + + public bool Contains(GradientStop item) + { + return _stops.Contains(item); + } + + public void CopyTo(GradientStop[] array, int arrayIndex) + { + _stops.CopyTo(array, arrayIndex); + } + + public bool Remove(GradientStop item) + { + return _stops.Remove(item); + } + + public void RemoveAt(int index) + { + _stops.RemoveAt(index); + } + } +}