using System.Collections.Generic; using System.Collections.Immutable; using System.Text; namespace HPPH.Generators; internal class Colors : IGeneratorFeature { public IEnumerable<(string name, string source)> GenerateFor(ColorFormatData colorFormat) { string colorStructCode = GenerateColorStructCode(colorFormat); if (!string.IsNullOrWhiteSpace(colorStructCode)) { yield return (colorFormat.TypeName, colorStructCode!); yield return ($"ColorFormat{colorFormat.Format}", GenerateColorFormatCode(colorFormat)); } } public IEnumerable<(string name, string source)> GenerateFor(ImmutableArray colorFormats) { yield return ("IColorFormat.Instances", GenerateColorFormats(colorFormats)); } private static string GenerateColorStructCode(ColorFormatData colorFormat) => colorFormat.Bpp switch { 3 => $$""" // ReSharper disable ConvertToAutoProperty // ReSharper disable ConvertToAutoPropertyWhenPossible // ReSharper disable ReplaceWithPrimaryConstructorParameter using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace HPPH; /// /// Represents a color in 24 bit {{colorFormat.Format}}-format. /// /// /// Initializes a new instance of the class. /// /// The {{colorFormat.FirstEntryName}}-component of the color. /// The {{colorFormat.SecondEntryName}}-component of the color. /// The {{colorFormat.ThirdEntryName}}-component of the color. [DebuggerDisplay("[A: {A}, R: {R}, G: {G}, B: {B}]")] [SkipLocalsInit] [StructLayout(LayoutKind.Sequential)] public readonly partial struct {{colorFormat.TypeName}}(byte {{colorFormat.FirstEntry}}, byte {{colorFormat.SecondEntry}}, byte {{colorFormat.ThirdEntry}}): IColor { #region Properties & Fields /// public static IColorFormat ColorFormat => IColorFormat.{{colorFormat.Format}}; private readonly byte _{{colorFormat.FirstEntry}} = {{colorFormat.FirstEntry}}; private readonly byte _{{colorFormat.SecondEntry}} = {{colorFormat.SecondEntry}}; private readonly byte _{{colorFormat.ThirdEntry}} = {{colorFormat.ThirdEntry}}; /// public byte R => _r; /// public byte G => _g; /// public byte B => _b; /// public byte A => byte.MaxValue; #endregion #region Methods /// public bool Equals(IColor? other) => (other != null) && (R == other.R) && (G == other.G) && (B == other.B) && (A == other.A); /// public override string ToString() => $"[A: {A}, R: {R}, G: {G}, B: {B}]"; /// public static IColor Create(byte r, byte g, byte b, byte a) => new {{colorFormat.TypeName}}({{colorFormat.FirstEntry}}, {{colorFormat.SecondEntry}}, {{colorFormat.ThirdEntry}}); #endregion } """, 4 => $$""" // ReSharper disable ConvertToAutoProperty // ReSharper disable ConvertToAutoPropertyWhenPossible // ReSharper disable ReplaceWithPrimaryConstructorParameter using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace HPPH; /// /// Represents a color in 32 bit {{colorFormat.Format}}-format. /// /// /// Initializes a new instance of the class. /// /// The {{colorFormat.FirstEntryName}}-component of the color. /// The {{colorFormat.SecondEntryName}}-component of the color. /// The {{colorFormat.ThirdEntryName}}-component of the color. /// The {{colorFormat.FourthEntryName}}-component of the color. [DebuggerDisplay("[A: {A}, R: {R}, G: {G}, B: {B}]")] [SkipLocalsInit] [StructLayout(LayoutKind.Sequential)] public readonly partial struct {{colorFormat.TypeName}}(byte {{colorFormat.FirstEntry}}, byte {{colorFormat.SecondEntry}}, byte {{colorFormat.ThirdEntry}}, byte {{colorFormat.FourthEntry}}) : IColor { #region Properties & Fields /// public static IColorFormat ColorFormat => IColorFormat.{{colorFormat.Format}}; private readonly byte _{{colorFormat.FirstEntry}} = {{colorFormat.FirstEntry}}; private readonly byte _{{colorFormat.SecondEntry}} = {{colorFormat.SecondEntry}}; private readonly byte _{{colorFormat.ThirdEntry}} = {{colorFormat.ThirdEntry}}; private readonly byte _{{colorFormat.FourthEntry}} = {{colorFormat.FourthEntry}}; /// public byte R => _r; /// public byte G => _g; /// public byte B => _b; /// public byte A => _a; #endregion #region Methods /// public bool Equals(IColor? other) => (other != null) && (R == other.R) && (G == other.G) && (B == other.B) && (A == other.A); /// public override string ToString() => $"[A: {A}, R: {R}, G: {G}, B: {B}]"; /// public static IColor Create(byte r, byte g, byte b, byte a) => new {{colorFormat.TypeName}}({{colorFormat.FirstEntry}}, {{colorFormat.SecondEntry}}, {{colorFormat.ThirdEntry}}, {{colorFormat.FourthEntry}}); #endregion } """, _ => null }; private static string GenerateColorFormatCode(ColorFormatData colorFormat) { return $$""" namespace HPPH; public sealed partial class ColorFormat{{colorFormat.Format}} : IColorFormat { #region Properties & Fields public static ColorFormat{{colorFormat.Format}} Instance { get; } = new(); public int BytesPerPixel => {{colorFormat.Bpp}}; public string Name => "{{colorFormat.Format}}"; ReadOnlySpan IColorFormat.ByteMapping => [{{colorFormat.ByteMapping}}]; #endregion #region Constructors private ColorFormat{{colorFormat.Format}}() {} #endregion } """; } private static string GenerateColorFormats(ImmutableArray colorFormats) { StringBuilder sb = new(); sb.AppendLine(""" namespace HPPH; public partial interface IColorFormat { #region Instances """); sb.AppendLine(); foreach (ColorFormatData colorFormat in colorFormats) sb.AppendLine($" public static ColorFormat{colorFormat.Format} {colorFormat.Format} => ColorFormat{colorFormat.Format}.Instance;"); sb.AppendLine(); sb.AppendLine(""" #endregion } """); return sb.ToString(); } }