1
0
mirror of https://github.com/DarthAffe/RGB.NET.git synced 2025-12-12 17:48:31 +00:00

Changed color to be an immutable value-type

This commit is contained in:
Darth Affe 2017-12-04 10:13:58 +01:00
parent b9e443b3b6
commit 50cfd296be
16 changed files with 1014 additions and 410 deletions

View File

@ -37,10 +37,7 @@ namespace RGB.NET.Brushes
#region Methods
/// <inheritdoc />
protected override Color GetColorAtPoint(Rectangle rectangle, BrushRenderTarget renderTarget)
{
return Color;
}
protected override Color GetColorAtPoint(Rectangle rectangle, BrushRenderTarget renderTarget) => Color;
#endregion
@ -50,19 +47,13 @@ namespace RGB.NET.Brushes
/// Converts a <see cref="Color" /> to a <see cref="SolidColorBrush" />.
/// </summary>
/// <param name="color">The <see cref="Color"/> to convert.</param>
public static explicit operator SolidColorBrush(Color color)
{
return new SolidColorBrush(color);
}
public static explicit operator SolidColorBrush(Color color) => new SolidColorBrush(color);
/// <summary>
/// Converts a <see cref="SolidColorBrush" /> to a <see cref="Color" />.
/// </summary>
/// <param name="brush">The <see cref="Color"/> to convert.</param>
public static implicit operator Color(SolidColorBrush brush)
{
return brush.Color;
}
public static implicit operator Color(SolidColorBrush brush) => brush.Color;
#endregion
}

View File

@ -53,7 +53,7 @@ namespace RGB.NET.Brushes.Gradients
public override Color GetColor(double offset)
{
if (GradientStops.Count == 0) return Color.Transparent;
if (GradientStops.Count == 1) return new Color(GradientStops[0].Color);
if (GradientStops.Count == 1) return GradientStops[0].Color;
(GradientStop gsBefore, GradientStop gsAfter) = GetEnclosingGradientStops(offset, GradientStops, WrapGradient);

View File

@ -56,7 +56,7 @@ namespace RGB.NET.Brushes.Gradients
double hue = (StartHue + (range * offset)) % 360f;
if (hue < 0)
hue += 360;
return new Color(hue, 1f, 1f);
return Color.FromHSV(hue, 1, 1);
}
/// <inheritdoc />

View File

@ -64,8 +64,8 @@ namespace RGB.NET.Core
foreach (BrushRenderTarget renderTarget in renderTargets)
{
Color color = new Color(GetColorAtPoint(rectangle, renderTarget)); // Clone the color, we don't want to have reference issues here and brushes might return the same color multiple times!}
ApplyDecorators(rectangle, renderTarget, ref color);
Color color = GetColorAtPoint(rectangle, renderTarget);
color = ApplyDecorators(rectangle, renderTarget, color);
RenderedTargets[renderTarget] = color;
}
}
@ -76,11 +76,13 @@ namespace RGB.NET.Core
/// <param name="rectangle">The rectangle in which the brush should be drawn.</param>
/// <param name="renderTarget">The target (key/point) from which the color should be taken.</param>
/// <param name="color">The <see cref="Color"/> to be modified.</param>
protected virtual void ApplyDecorators(Rectangle rectangle, BrushRenderTarget renderTarget, ref Color color)
protected virtual Color ApplyDecorators(Rectangle rectangle, BrushRenderTarget renderTarget, Color color)
{
foreach (IBrushDecorator decorator in Decorators)
if (decorator.IsEnabled)
decorator.ManipulateColor(rectangle, renderTarget, ref color);
color = decorator.ManipulateColor(rectangle, renderTarget, color);
return color;
}
/// <inheritdoc />
@ -88,7 +90,7 @@ namespace RGB.NET.Core
{
List<BrushRenderTarget> renderTargets = RenderedTargets.Keys.ToList();
foreach (BrushRenderTarget renderTarget in renderTargets)
FinalizeColor(RenderedTargets[renderTarget]); // Cloning here again shouldn't be needed since we did this above.
RenderedTargets[renderTarget] = FinalizeColor(RenderedTargets[renderTarget]);
}
/// <summary>
@ -102,20 +104,19 @@ namespace RGB.NET.Core
/// <summary>
/// Finalizes the color by appliing the overall brightness and opacity.<br/>
/// This method should always be the last call of a <see cref="GetColorAtPoint" /> implementation.
/// If you overwrite this method please make sure that you never return the same color-object twice to prevent reference-issues!
/// </summary>
/// <param name="color">The color to finalize.</param>
/// <returns>The finalized color.</returns>
protected virtual void FinalizeColor(Color color)
protected virtual Color FinalizeColor(Color color)
{
foreach (IColorCorrection colorCorrection in ColorCorrections)
colorCorrection.ApplyTo(color);
color = colorCorrection.ApplyTo(color);
// Since we use HSV to calculate there is no way to make a color 'brighter' than 100%
// Be carefull with the naming: Since we use HSV the correct term is 'value' but outside we call it 'brightness'
// THIS IS NOT A HSB CALCULATION!!!
color.Value *= Brightness <= 0 ? 0 : (Brightness >= 1.0 ? 1.0 : Brightness);
color.A = (byte)(color.A * (Opacity <= 0 ? 0 : (Opacity >= 1.0 ? 1.0 : Opacity)));
return color.MultiplyValue(Brightness.Clamp(0, 1))
.MultiplyA(Opacity.Clamp(0, 1));
}
#endregion

View File

@ -11,6 +11,6 @@ namespace RGB.NET.Core
/// Applies the <see cref="IColorCorrection"/> to the given <see cref="Color"/>.
/// </summary>
/// <param name="color">The <see cref="Color"/> to correct.</param>
void ApplyTo(Color color);
Color ApplyTo(Color color);
}
}

View File

@ -12,6 +12,6 @@
/// <param name="rectangle">The rectangle in which the <see cref="IBrush"/> should be drawn.</param>
/// <param name="renderTarget">The target (key/point) from which the <see cref="Color"/> should be taken.</param>
/// <param name="color">The <see cref="Color"/> to be modified.</param>
void ManipulateColor(Rectangle rectangle, BrushRenderTarget renderTarget, ref Color color);
Color ManipulateColor(Rectangle rectangle, BrushRenderTarget renderTarget, Color color);
}
}

View File

@ -1,49 +0,0 @@
using System;
using System.Runtime.CompilerServices;
namespace RGB.NET.Core
{
/// <summary>
/// Offers some extensions and helper-methods for the work with doubles
/// </summary>
public static class DoubleExtensions
{
#region Constants
/// <summary>
/// Defines the precision RGB.NET processes floating point comparisons in.
/// </summary>
public const double TOLERANCE = 1E-10;
#endregion
#region Methods
/// <summary>
/// Checks if two values are equal respecting the <see cref="TOLERANCE"/>.
/// </summary>
/// <param name="value1">The first value to compare.</param>
/// <param name="value2">The first value to compare.</param>
/// <returns><c>true</c> if the difference is smaller than the <see cref="TOLERANCE"/>; otherwise, <c>false</c>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool EqualsInTolerance(this double value1, double value2)
{
return Math.Abs(value1 - value2) < TOLERANCE;
}
/// <summary>
/// Camps the provided value to be bigger or equal min and smaller or equal max.
/// </summary>
/// <param name="value">The value to clamp.</param>
/// <param name="min">The lower value of the range the value is clamped to.</param>
/// <param name="max">The higher value of the range the value is clamped to.</param>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double Clamp(this double value, double min, double max)
{
return Math.Max(min, Math.Min(max, value));
}
#endregion
}
}

View File

@ -0,0 +1,87 @@
using System;
using System.Runtime.CompilerServices;
namespace RGB.NET.Core
{
/// <summary>
/// Offers some extensions and helper-methods for the work with doubles
/// </summary>
public static class DoubleExtensions
{
#region Constants
/// <summary>
/// Defines the precision RGB.NET processes floating point comparisons in.
/// </summary>
public const double TOLERANCE = 1E-10;
#endregion
#region Methods
/// <summary>
/// Checks if two values are equal respecting the <see cref="TOLERANCE"/>.
/// </summary>
/// <param name="value1">The first value to compare.</param>
/// <param name="value2">The first value to compare.</param>
/// <returns><c>true</c> if the difference is smaller than the <see cref="TOLERANCE"/>; otherwise, <c>false</c>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool EqualsInTolerance(this double value1, double value2) => Math.Abs(value1 - value2) < TOLERANCE;
/// <summary>
/// Clamps the provided value to be bigger or equal min and smaller or equal max.
/// </summary>
/// <param name="value">The value to clamp.</param>
/// <param name="min">The lower value of the range the value is clamped to.</param>
/// <param name="max">The higher value of the range the value is clamped to.</param>
/// <returns>The clamped value.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double Clamp(this double value, double min, double max) => Math.Max(min, Math.Min(max, value));
/// <summary>
/// Clamps the provided value to be bigger or equal min and smaller or equal max.
/// </summary>
/// <param name="value">The value to clamp.</param>
/// <param name="min">The lower value of the range the value is clamped to.</param>
/// <param name="max">The higher value of the range the value is clamped to.</param>
/// <returns>The clamped value.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Clamp(this int value, int min, int max) => Math.Max(min, Math.Min(max, value));
/// <summary>
/// Enforces the provided value to be in the specified range by wrapping it around the edges if it exceeds them.
/// </summary>
/// <param name="value">The value to wrap.</param>
/// <param name="min">The lower value of the range the value is wrapped into.</param>
/// <param name="max">The higher value of the range the value is wrapped into.</param>
/// <returns>The wrapped value.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double Wrap(this double value, double min, double max)
{
double range = max - min;
while (value > max)
value -= range;
while (value < min)
value += range;
return value;
}
#region Internal
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static byte GetByteValueFromPercentage(this double percentage)
{
if (double.IsNaN(percentage)) return 0;
percentage = percentage.Clamp(0, 1.0);
return (byte)(percentage.Equals(1.0) ? 255 : percentage * 256.0);
}
#endregion
#endregion
}
}

File diff suppressed because it is too large Load Diff

View File

@ -60,7 +60,7 @@ namespace RGB.NET.Core
/// </summary>
public Color RequestedColor
{
get => new Color(_requestedColor);
get => _requestedColor;
private set
{
SetProperty(ref _requestedColor, value);
@ -80,15 +80,7 @@ namespace RGB.NET.Core
set
{
if (!IsLocked)
{
// DarthAffe 26.01.2017: DON'T USE THE PROPERTY HERE! Working on the copy doesn't work!
_requestedColor.Blend(value);
// ReSharper disable ExplicitCallerInfoArgument
OnPropertyChanged(nameof(RequestedColor));
OnPropertyChanged(nameof(IsDirty));
// ReSharper restore ExplicitCallerInfoArgument
}
RequestedColor += value;
}
}
@ -168,19 +160,13 @@ namespace RGB.NET.Core
/// Converts a <see cref="Led" /> to a <see cref="Core.Color" />.
/// </summary>
/// <param name="led">The <see cref="Led"/> to convert.</param>
public static implicit operator Color(Led led)
{
return led?.Color;
}
public static implicit operator Color(Led led) => led?.Color ?? Color.Transparent;
/// <summary>
/// Converts a <see cref="Led" /> to a <see cref="Rectangle" />.
/// </summary>
/// <param name="led">The <see cref="Led"/> to convert.</param>
public static implicit operator Rectangle(Led led)
{
return led?.LedRectangle;
}
public static implicit operator Rectangle(Led led) => led?.LedRectangle;
#endregion
}

View File

@ -140,11 +140,11 @@ namespace RGB.NET.Core
}
/// <summary>
/// Returns a new <see cref="Point"/> representing the substraction of the two provided <see cref="Point"/>.
/// Returns a new <see cref="Point"/> representing the subtraction of the two provided <see cref="Point"/>.
/// </summary>
/// <param name="point1">The first <see cref="Point"/>.</param>
/// <param name="point2">The second <see cref="Point"/>.</param>
/// <returns>A new <see cref="Point"/> representing the substraction of the two provided <see cref="Point"/>.</returns>
/// <returns>A new <see cref="Point"/> representing the subtraction of the two provided <see cref="Point"/>.</returns>
public static Point operator -(Point point1, Point point2)
{
return new Point(point1.X - point2.X, point1.Y - point2.Y);

View File

@ -149,11 +149,11 @@ namespace RGB.NET.Core
}
/// <summary>
/// Returns a new <see cref="Size"/> representing the substraction of the two provided <see cref="Size"/>.
/// Returns a new <see cref="Size"/> representing the subtraction of the two provided <see cref="Size"/>.
/// </summary>
/// <param name="size1">The first <see cref="Size"/>.</param>
/// <param name="size2">The second <see cref="Size"/>.</param>
/// <returns>A new <see cref="Size"/> representing the substraction of the two provided <see cref="Size"/>.</returns>
/// <returns>A new <see cref="Size"/> representing the subtraction of the two provided <see cref="Size"/>.</returns>
public static Size operator -(Size size1, Size size2)
{
return new Size(size1.Width - size2.Width, size1.Height - size2.Height);

View File

@ -80,7 +80,7 @@
<Compile Include="Leds\ILedId.cs" />
<Compile Include="MVVM\AbstractBindable.cs" />
<Compile Include="Leds\Color.cs" />
<Compile Include="Extensions\DoubleExtensions.cs" />
<Compile Include="Extensions\MathExtensions.cs" />
<Compile Include="Devices\IRGBDevice.cs" />
<Compile Include="Leds\Led.cs" />
<Compile Include="MVVM\IBindable.cs" />

View File

@ -72,7 +72,7 @@ namespace RGB.NET.Decorators.Brush
#region Methods
/// <inheritdoc />
public void ManipulateColor(Rectangle rectangle, BrushRenderTarget renderTarget, ref Color color) => color.APercent = _currentValue;
public Color ManipulateColor(Rectangle rectangle, BrushRenderTarget renderTarget, Color color) => color.SetAPercent(_currentValue);
/// <inheritdoc />
protected override void Update(double deltaTime)

View File

@ -151,7 +151,7 @@ namespace RGB.NET.Devices.Corsair
for (int i = 0; i < LedMapping.Count; i++)
{
_CorsairLedColor ledColor = (_CorsairLedColor)Marshal.PtrToStructure(readPtr, typeof(_CorsairLedColor));
colorData.Add((CorsairLedIds)ledColor.ledId, new Color((byte)ledColor.r, (byte)ledColor.g, (byte)ledColor.b));
colorData.Add((CorsairLedIds)ledColor.ledId, new Color(ledColor.r, ledColor.g, ledColor.b));
readPtr = new IntPtr(readPtr.ToInt64() + structSize);
}

View File

@ -15,8 +15,7 @@ namespace RGB.NET.WPF.Converter
/// <inheritdoc />
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
Core.Color color = value as Core.Color;
return new SolidColorBrush(color == null
return new SolidColorBrush(!(value is Core.Color color)
? Color.FromArgb(0, 0, 0, 0)
: Color.FromArgb(color.A, color.R, color.G, color.B));
}