Graphics.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. namespace Terminal.Gui.TextEffects;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. public class Color
  6. {
  7. public string RgbColor { get; private set; }
  8. public int? XtermColor { get; private set; }
  9. public Color (string rgbColor)
  10. {
  11. if (!ColorUtils.IsValidHexColor (rgbColor))
  12. throw new ArgumentException ("Invalid RGB hex color format.");
  13. RgbColor = rgbColor.StartsWith ("#") ? rgbColor.Substring (1).ToUpper () : rgbColor.ToUpper ();
  14. XtermColor = ColorUtils.HexToXterm (RgbColor); // Convert RGB to XTerm-256
  15. }
  16. public Color (int xtermColor)
  17. {
  18. if (!ColorUtils.IsValidXtermColor (xtermColor))
  19. throw new ArgumentException ("Invalid XTerm-256 color code.");
  20. XtermColor = xtermColor;
  21. RgbColor = ColorUtils.XtermToHex (xtermColor); // Perform the actual conversion
  22. }
  23. public int R => Convert.ToInt32 (RgbColor.Substring (0, 2), 16);
  24. public int G => Convert.ToInt32 (RgbColor.Substring (2, 2), 16);
  25. public int B => Convert.ToInt32 (RgbColor.Substring (4, 2), 16);
  26. public (int R, int G, int B) GetRgbInts ()
  27. {
  28. return (
  29. Convert.ToInt32 (RgbColor.Substring (0, 2), 16),
  30. Convert.ToInt32 (RgbColor.Substring (2, 2), 16),
  31. Convert.ToInt32 (RgbColor.Substring (4, 2), 16)
  32. );
  33. }
  34. public override string ToString () => $"#{RgbColor}";
  35. public static Color FromRgb (int r, int g, int b)
  36. {
  37. // Validate the RGB values to ensure they are within the 0-255 range
  38. if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255)
  39. throw new ArgumentOutOfRangeException ("RGB values must be between 0 and 255.");
  40. // Convert RGB values to a hexadecimal string
  41. string rgbColor = $"#{r:X2}{g:X2}{b:X2}";
  42. // Create and return a new Color instance using the hexadecimal string
  43. return new Color (rgbColor);
  44. }
  45. }
  46. public class Gradient
  47. {
  48. public List<Color> Spectrum { get; private set; }
  49. // Constructor now accepts IEnumerable<int> for steps.
  50. public Gradient (IEnumerable<Color> stops, IEnumerable<int> steps, bool loop = false)
  51. {
  52. if (stops == null || !stops.Any () || stops.Count () < 2)
  53. throw new ArgumentException ("At least two color stops are required to create a gradient.");
  54. if (steps == null || !steps.Any ())
  55. throw new ArgumentException ("Steps are required to define the transitions between colors.");
  56. Spectrum = GenerateGradient (stops.ToList (), steps.ToList (), loop);
  57. }
  58. private List<Color> GenerateGradient (List<Color> stops, List<int> steps, bool loop)
  59. {
  60. List<Color> gradient = new List<Color> ();
  61. if (loop)
  62. stops.Add (stops [0]); // Loop the gradient back to the first color.
  63. for (int i = 0; i < stops.Count - 1; i++)
  64. {
  65. int currentSteps = i < steps.Count ? steps [i] : steps.Last ();
  66. gradient.AddRange (InterpolateColors (stops [i], stops [i + 1], currentSteps));
  67. }
  68. return gradient;
  69. }
  70. private IEnumerable<Color> InterpolateColors (Color start, Color end, int steps)
  71. {
  72. for (int step = 0; step <= steps; step++)
  73. {
  74. int r = Interpolate (start.R, end.R, steps, step);
  75. int g = Interpolate (start.G, end.G, steps, step);
  76. int b = Interpolate (start.B, end.B, steps, step);
  77. yield return Color.FromRgb (r, g, b);
  78. }
  79. }
  80. private int Interpolate (int start, int end, int steps, int currentStep)
  81. {
  82. return start + (int)((end - start) * (double)currentStep / steps);
  83. }
  84. public Color GetColorAtFraction (double fraction)
  85. {
  86. if (fraction < 0 || fraction > 1)
  87. throw new ArgumentOutOfRangeException (nameof (fraction), "Fraction must be between 0 and 1.");
  88. int index = (int)(fraction * (Spectrum.Count - 1));
  89. return Spectrum [index];
  90. }
  91. }