using System.Numerics; namespace Dashboard { public record struct LayoutUnits(LayoutUnit All) { public LayoutUnit XUnit { get => (LayoutUnit)(((int)All & 0xF) >> 0); set => All = (LayoutUnit)(((int)All & ~(0xF << 0)) | ((int)value << 0)); } public LayoutUnit YUnit { get => (LayoutUnit)(((int)All & 0xF) >> 4); set => All = (LayoutUnit)(((int)All & ~(0xF << 4)) | ((int)value << 4)); } public LayoutUnit ZUnit { get => (LayoutUnit)(((int)All & 0xF) >> 8); set => All = (LayoutUnit)(((int)All & ~(0xF << 8)) | ((int)value << 8)); } public LayoutUnit WUnit { get => (LayoutUnit)(((int)All & 0xF) >> 12); set => All = (LayoutUnit)(((int)All & ~(0xF << 12)) | ((int)value << 12)); } } public record struct Metric(LayoutUnit Units, float Value) { public float Compute(float dpi, float rel, float star) { switch (Units) { case LayoutUnit.Auto: return -1; case LayoutUnit.Millimeter: float mm2Px = dpi / 25.4f; return Value * mm2Px; case LayoutUnit.Pixel: return Value; case LayoutUnit.Point: float pt2Px = 72 / dpi; return Value * pt2Px; case LayoutUnit.Percent: return rel * Value; case LayoutUnit.Star: return star * Value; default: throw new Exception("Unrecognized unit."); } } } public record struct Metric2D(LayoutUnits Units, Vector2 Value) { public float X { get => Value.X; set => Value = new Vector2(value, Value.Y); } public LayoutUnit XUnits { get => Units.XUnit; set => Units = Units with { XUnit = value }; } public float Y { get => Value.Y; set => Value = new Vector2(Value.X, value); } public LayoutUnit YUnits { get => Units.YUnit; set => Units = Units with { YUnit = value }; } } public record struct BoxMetric(LayoutUnit Units, Box2d Value); public record struct AdvancedMetric(LayoutUnit Unit, float Value) { public AdvancedMetric Convert(LayoutUnit target, float dpi, float rel, int stars) { if (Unit == target) return this; float pixels = Unit switch { LayoutUnit.Pixel => Value, LayoutUnit.Point => Value * (72f / dpi), LayoutUnit.Millimeter => Value * (28.3464566929f / dpi), LayoutUnit.Star => Value * rel / stars, LayoutUnit.Percent => Value * rel / 100, _ => throw new Exception(), }; float value = target switch { LayoutUnit.Pixel => pixels, LayoutUnit.Point => Value * (dpi / 72f), // MeasurementUnit.Millimeter => }; return new AdvancedMetric(target, value); } public override string ToString() { return $"{Value} {Unit.ToShortString()}"; } public static bool TryParse(ReadOnlySpan str, out AdvancedMetric metric) { metric = default; return false; } public static AdvancedMetric Parse(ReadOnlySpan str) => TryParse(str, out AdvancedMetric metric) ? metric : throw new Exception($"Could not parse the value '{str}'."); } }