From 653abb3b3187e2b6f8753ad3b97616d590aa483f Mon Sep 17 00:00:00 2001 From: robloo Date: Sun, 20 Mar 2022 23:07:23 -0400 Subject: [PATCH] Add higher performance, mutable RGB and HSV structs These are only for internal use with the ColorSpectrum --- .../ColorPicker/ColorSpectrum/Hsv.cs | 87 +++++++++++++++++ .../ColorPicker/ColorSpectrum/Rgb.cs | 94 +++++++++++++++++++ 2 files changed, 181 insertions(+) create mode 100644 src/Avalonia.Controls/ColorPicker/ColorSpectrum/Hsv.cs create mode 100644 src/Avalonia.Controls/ColorPicker/ColorSpectrum/Rgb.cs diff --git a/src/Avalonia.Controls/ColorPicker/ColorSpectrum/Hsv.cs b/src/Avalonia.Controls/ColorPicker/ColorSpectrum/Hsv.cs new file mode 100644 index 0000000000..6d9f8440bf --- /dev/null +++ b/src/Avalonia.Controls/ColorPicker/ColorSpectrum/Hsv.cs @@ -0,0 +1,87 @@ +// Portions of this source file are adapted from the WinUI project. +// (https://github.com/microsoft/microsoft-ui-xaml) +// +// Licensed to The Avalonia Project under the MIT License. + +using System.Numerics; +using Avalonia.Media; + +namespace Avalonia.Controls.Primitives +{ + /// + /// Contains and allows modification of Hue, Saturation and Value channel values. + /// + /// + /// The is a specialized struct optimized for permanence and memory: + /// + /// This is not a read-only struct like and allows editing the fields + /// Removes the alpha component unnecessary in core calculations + /// No channel value bounds checks or clamping is done. + /// + /// + internal struct Hsv + { + /// + /// The Hue channel value in the range from 0..359. + /// + public double H; + + /// + /// The Saturation channel value in the range from 0..1. + /// + public double S; + + /// + /// The Value channel value in the range from 0..1. + /// + public double V; + + /// + /// Initializes a new instance of the struct. + /// + /// The Hue channel value in the range from 0..360. + /// The Saturation channel value in the range from 0..1. + /// The Value channel value in the range from 0..1. + public Hsv(double h, double s, double v) + { + H = h; + S = s; + V = v; + } + + /// + /// Initializes a new instance of the struct. + /// + /// An existing to convert to . + public Hsv(HsvColor hsvColor) + { + H = hsvColor.H; + S = hsvColor.S; + V = hsvColor.V; + } + + /// + /// Converts this struct into a standard . + /// + /// The Alpha channel value in the range from 0..1. + /// A new representing this struct. + public HsvColor ToHsvColor(double alpha = 1.0) + { + // Clamping is done automatically in the constructor + return HsvColor.FromAhsv(alpha, H, S, V); + } + + /// + /// Returns the color model equivalent of this color. + /// + /// The equivalent color. + public Rgb ToRgb() + { + // Instantiating a Color is unfortunately necessary to use existing conversions + // Clamping is done internally in the conversion method + Color color = HsvColor.ToRgb(H, S, V); + + return new Rgb(color); + } + } +} diff --git a/src/Avalonia.Controls/ColorPicker/ColorSpectrum/Rgb.cs b/src/Avalonia.Controls/ColorPicker/ColorSpectrum/Rgb.cs new file mode 100644 index 0000000000..c2358b7bee --- /dev/null +++ b/src/Avalonia.Controls/ColorPicker/ColorSpectrum/Rgb.cs @@ -0,0 +1,94 @@ +// Portions of this source file are adapted from the WinUI project. +// (https://github.com/microsoft/microsoft-ui-xaml) +// +// Licensed to The Avalonia Project under the MIT License. + +using System; +using Avalonia.Media; +using Avalonia.Utilities; + +namespace Avalonia.Controls.Primitives +{ + /// + /// Contains and allows modification of Red, Green and Blue channel values. + /// + /// + /// The is a specialized struct optimized for permanence and memory: + /// + /// This is not a read-only struct like and allows editing the fields + /// Removes the alpha component unnecessary in core calculations + /// Normalizes RGB channel values in the range of 0..1 to simplify calculations. + /// No channel value bounds checks or clamping is done. + /// + /// + internal struct Rgb + { + /// + /// The Red channel value in the range from 0..1. + /// + public double R; + + /// + /// The Green channel value in the range from 0..1. + /// + public double G; + + /// + /// The Blue channel value in the range from 0..1. + /// + public double B; + + /// + /// Initializes a new instance of the struct. + /// + /// The Red channel value in the range from 0..1. + /// The Green channel value in the range from 0..1. + /// The Blue channel value in the range from 0..1. + public Rgb(double r, double g, double b) + { + R = r; + G = g; + B = b; + } + + /// + /// Initializes a new instance of the struct. + /// + /// An existing to convert to . + public Rgb(Color color) + { + R = color.R / 255.0; + G = color.G / 255.0; + B = color.B / 255.0; + } + + /// + /// Converts this struct into a standard . + /// + /// The Alpha channel value in the range from 0..1. + /// A new representing this struct. + public Color ToColor(double alpha = 1.0) + { + return Color.FromArgb( + (byte)MathUtilities.Clamp(alpha * 255.0, 0x00, 0xFF), + (byte)MathUtilities.Clamp(R * 255.0, 0x00, 0xFF), + (byte)MathUtilities.Clamp(G * 255.0, 0x00, 0xFF), + (byte)MathUtilities.Clamp(B * 255.0, 0x00, 0xFF)); + } + + /// + /// Returns the color model equivalent of this color. + /// + /// The equivalent color. + public Hsv ToHsv() + { + // Instantiating an HsvColor is unfortunately necessary to use existing conversions + HsvColor hsvColor = HsvColor.FromRgb( + MathUtilities.Clamp(R, 0.0, 1.0), + MathUtilities.Clamp(G, 0.0, 1.0), + MathUtilities.Clamp(B, 0.0, 1.0)); + + return new Hsv(hsvColor); + } + } +}