Static properties for black and white

This commit is contained in:
Jeremy Pritts committed 2023-11-17 11:44:08 -05:00
1 parent bed45ee60e
commit 07002c77ee
7 files changed
+131 -11

No files matched your search

@@ -137,11 +137,70 @@ internal static partial class Program
writer.WriteLine($"static Type IColor.ChannelType => typeof({typeName});");
}
private static void WriteBlackWhiteStaticProperties(IndentedTextWriter writer, bool hasRed, bool hasGreen, bool hasBlue, bool hasAlpha, string colorTypeName, string channelTypeName)
{
string minValue = $"NumericConversion.GetMinimumValueSafe<{channelTypeName}>()";
string maxValue = $"NumericConversion.GetMaximumValueSafe<{channelTypeName}>()";
//Black
{
writer.Write($"public static {colorTypeName}<{channelTypeName}> Black => new(");
int rgbCount = CountRGB(hasRed, hasGreen, hasBlue);
for (int i = 0; i < rgbCount; i++)
{
if (i != 0)
{
writer.Write(", ");
}
writer.Write(minValue);
}
if (hasAlpha)
{
if (rgbCount != 0)
{
writer.Write(", ");
}
writer.Write(maxValue);
}
writer.WriteLine(");");
}
//White
if (hasRed || hasGreen || hasBlue)
{
writer.Write($"public static {colorTypeName}<{channelTypeName}> White => new(");
int rgbaCount = CountRGBA(hasRed, hasGreen, hasBlue, hasAlpha);
for (int i = 0; i < rgbaCount; i++)
{
if (i != 0)
{
writer.Write(", ");
}
writer.Write(maxValue);
}
writer.WriteLine(");");
}
else
{
writer.WriteLine($"static {colorTypeName}<{channelTypeName}> IColor<{colorTypeName}<{channelTypeName}>, {channelTypeName}>.White => throw new NotSupportedException();");
}
static int CountRGB(bool hasRed, bool hasGreen, bool hasBlue)
{
return (hasRed ? 1 : 0) + (hasGreen ? 1 : 0) + (hasBlue ? 1 : 0);
}
static int CountRGBA(bool hasRed, bool hasGreen, bool hasBlue, bool hasAlpha)
{
return CountRGB(hasRed, hasGreen, hasBlue) + (hasAlpha ? 1 : 0);
}
}
private static void WriteGenericColor(IndentedTextWriter writer, string name, bool hasRed, bool hasGreen, bool hasBlue, bool hasAlpha)
{
const string typeName = "T";
const string minValue = $"NumericConversion.GetMinimumValueSafe<T>()";
const string maxValue = $"NumericConversion.GetMaximumValueSafe<T>()";
const string minValue = "NumericConversion.GetMinimumValueSafe<T>()";
const string maxValue = "NumericConversion.GetMaximumValueSafe<T>()";
writer.WriteGeneratedCodeWarning();
writer.WriteLineNoTabs();
@@ -149,10 +208,7 @@ internal static partial class Program
writer.WriteFileScopedNamespace(OutputNamespace);
writer.WriteLineNoTabs();
string constraints = hasRed && hasGreen && hasBlue && hasAlpha
? "unmanaged"
: "unmanaged, INumberBase<T>, IMinMaxValue<T>";
writer.WriteLine($"public partial struct {name}<T> : IColor<{typeName}> where T : {constraints}");
writer.WriteLine($"public partial struct {name}<T> : IColor<{name}<T>, T> where T : unmanaged, INumberBase<T>, IMinMaxValue<T>");
using (new CurlyBrackets(writer))
{
WriteProperty(writer, hasRed, typeName, 'R', minValue);
@@ -172,6 +228,8 @@ internal static partial class Program
writer.WriteLineNoTabs();
WriteNonGenericStaticProperties(writer, hasRed, hasGreen, hasBlue, hasAlpha, true, typeName);
writer.WriteLineNoTabs();
WriteBlackWhiteStaticProperties(writer, hasRed, hasGreen, hasBlue, hasAlpha, name, typeName);
writer.WriteLineNoTabs();
WriteToString(writer, hasRed, hasGreen, hasBlue, hasAlpha);
}
}
@@ -2,7 +2,7 @@
namespace AssetRipper.TextureDecoder.Rgb.Formats;
public partial struct ColorA<T> : IColor<T> where T : unmanaged, INumberBase<T>, IMinMaxValue<T>
public partial struct ColorA<T> : IColor<ColorA<T>, T> where T : unmanaged, INumberBase<T>, IMinMaxValue<T>
{
public readonly T R
{
@@ -49,6 +49,9 @@ public partial struct ColorA<T> : IColor<T> where T : unmanaged, INumberBase<T>,
static bool IColor.ChannelsAreFullyUtilized => true;
static Type IColor.ChannelType => typeof(T);
public static ColorA<T> Black => new(NumericConversion.GetMaximumValueSafe<T>());
static ColorA<T> IColor<ColorA<T>, T>.White => throw new NotSupportedException();
public override string ToString()
{
return $"{{ A: {A} }}";
@@ -2,7 +2,7 @@
namespace AssetRipper.TextureDecoder.Rgb.Formats;
public partial struct ColorR<T> : IColor<T> where T : unmanaged, INumberBase<T>, IMinMaxValue<T>
public partial struct ColorR<T> : IColor<ColorR<T>, T> where T : unmanaged, INumberBase<T>, IMinMaxValue<T>
{
public T R { get; set; }
@@ -49,6 +49,9 @@ public partial struct ColorR<T> : IColor<T> where T : unmanaged, INumberBase<T>,
static bool IColor.ChannelsAreFullyUtilized => true;
static Type IColor.ChannelType => typeof(T);
public static ColorR<T> Black => new(NumericConversion.GetMinimumValueSafe<T>());
public static ColorR<T> White => new(NumericConversion.GetMaximumValueSafe<T>());
public override string ToString()
{
return $"{{ R: {R} }}";
@@ -2,7 +2,7 @@
namespace AssetRipper.TextureDecoder.Rgb.Formats;
public partial struct ColorRG<T> : IColor<T> where T : unmanaged, INumberBase<T>, IMinMaxValue<T>
public partial struct ColorRG<T> : IColor<ColorRG<T>, T> where T : unmanaged, INumberBase<T>, IMinMaxValue<T>
{
public T R { get; set; }
@@ -47,6 +47,9 @@ public partial struct ColorRG<T> : IColor<T> where T : unmanaged, INumberBase<T>
static bool IColor.ChannelsAreFullyUtilized => true;
static Type IColor.ChannelType => typeof(T);
public static ColorRG<T> Black => new(NumericConversion.GetMinimumValueSafe<T>(), NumericConversion.GetMinimumValueSafe<T>());
public static ColorRG<T> White => new(NumericConversion.GetMaximumValueSafe<T>(), NumericConversion.GetMaximumValueSafe<T>());
public override string ToString()
{
return $"{{ R: {R}, G: {G} }}";
@@ -2,7 +2,7 @@
namespace AssetRipper.TextureDecoder.Rgb.Formats;
public partial struct ColorRGB<T> : IColor<T> where T : unmanaged, INumberBase<T>, IMinMaxValue<T>
public partial struct ColorRGB<T> : IColor<ColorRGB<T>, T> where T : unmanaged, INumberBase<T>, IMinMaxValue<T>
{
public T R { get; set; }
@@ -45,6 +45,9 @@ public partial struct ColorRGB<T> : IColor<T> where T : unmanaged, INumberBase<T
static bool IColor.ChannelsAreFullyUtilized => true;
static Type IColor.ChannelType => typeof(T);
public static ColorRGB<T> Black => new(NumericConversion.GetMinimumValueSafe<T>(), NumericConversion.GetMinimumValueSafe<T>(), NumericConversion.GetMinimumValueSafe<T>());
public static ColorRGB<T> White => new(NumericConversion.GetMaximumValueSafe<T>(), NumericConversion.GetMaximumValueSafe<T>(), NumericConversion.GetMaximumValueSafe<T>());
public override string ToString()
{
return $"{{ R: {R}, G: {G}, B: {B} }}";
@@ -2,7 +2,7 @@
namespace AssetRipper.TextureDecoder.Rgb.Formats;
public partial struct ColorRGBA<T> : IColor<T> where T : unmanaged
public partial struct ColorRGBA<T> : IColor<ColorRGBA<T>, T> where T : unmanaged, INumberBase<T>, IMinMaxValue<T>
{
public T R { get; set; }
@@ -43,6 +43,9 @@ public partial struct ColorRGBA<T> : IColor<T> where T : unmanaged
static bool IColor.ChannelsAreFullyUtilized => true;
static Type IColor.ChannelType => typeof(T);
public static ColorRGBA<T> Black => new(NumericConversion.GetMinimumValueSafe<T>(), NumericConversion.GetMinimumValueSafe<T>(), NumericConversion.GetMinimumValueSafe<T>(), NumericConversion.GetMaximumValueSafe<T>());
public static ColorRGBA<T> White => new(NumericConversion.GetMaximumValueSafe<T>(), NumericConversion.GetMaximumValueSafe<T>(), NumericConversion.GetMaximumValueSafe<T>(), NumericConversion.GetMaximumValueSafe<T>());
public override string ToString()
{
return $"{{ R: {R}, G: {G}, B: {B}, A: {A} }}";
@@ -0,0 +1,47 @@
namespace AssetRipper.TextureDecoder.Rgb;
/// <summary>
/// An <see langword="interface"/> for handling color formats with up to 4 channels.
/// </summary>
/// <remarks>
/// When used as a generic type constraint, the methods and properties get devirtualized by the JIT compiler.
/// This prevents boxing when the implementing type is a <see langword="struct"/>.
/// </remarks>
/// <typeparam name="TSelf">
/// The implementing type.
/// </typeparam>
/// <typeparam name="TChannel">
/// Supported types are:
/// <list type="bullet">
/// <item><see cref="sbyte"/></item>
/// <item><see cref="byte"/></item>
/// <item><see cref="short"/></item>
/// <item><see cref="ushort"/></item>
/// <item><see cref="int"/></item>
/// <item><see cref="uint"/></item>
/// <item><see cref="nint"/></item>
/// <item><see cref="nuint"/></item>
/// <item><see cref="long"/></item>
/// <item><see cref="ulong"/></item>
/// <item><see cref="Int128"/></item>
/// <item><see cref="UInt128"/></item>
/// <item><see cref="Half"/></item>
/// <item><see cref="float"/></item>
/// <item><see cref="NFloat"/></item>
/// <item><see cref="double"/></item>
/// <item><see cref="decimal"/></item>
/// </list>
/// </typeparam>
public interface IColor<TSelf, TChannel> : IColor<TChannel>
where TSelf : unmanaged, IColor<TSelf, TChannel>
where TChannel : unmanaged
{
/// <summary>
/// A black pixel.
/// </summary>
static abstract TSelf Black { get; }
/// <summary>
/// A white pixel.
/// </summary>
static abstract TSelf White { get; }
}