// ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedMember.Global using System; using System.Diagnostics; namespace RGB.NET.Core; /// /// Represents a size consisting of a width and a height. /// [DebuggerDisplay("[Width: {Width}, Height: {Height}]")] public readonly struct Size : IEquatable { #region Constants private static readonly Size INVALID = new(float.NaN, float.NaN); /// /// Gets a [NaN,NaN]-Size. /// public static ref readonly Size Invalid => ref INVALID; #endregion #region Properties & Fields /// /// Gets or sets the width component value of this . /// public float Width { get; } /// /// Gets or sets the height component value of this . /// public float Height { get; } #endregion #region Constructors /// /// /// Initializes a new instance of the using the provided size to define a square. /// /// The size used for the component value and the component value. public Size(float size) : this(size, size) { } /// /// Initializes a new instance of the class using the provided values. /// /// The size used for the component value. /// The size used for the component value. public Size(float width, float height) { this.Width = width; this.Height = height; } #endregion #region Methods /// /// Converts the and of this to a human-readable string. /// /// A string that contains the and of this . For example "[Width: 100, Height: 20]". public override string ToString() => $"[Width: {Width}, Height: {Height}]"; /// /// Tests whether the specified is equivalent to this . /// /// The size to test. /// true if is equivalent to this ; otherwise, false. public bool Equals(Size other) => ((float.IsNaN(Width) && float.IsNaN(other.Width)) || Width.EqualsInTolerance(other.Width)) && ((float.IsNaN(Height) && float.IsNaN(other.Height)) || Height.EqualsInTolerance(other.Height)); /// /// Tests whether the specified object is a and is equivalent to this . /// /// The object to test. /// true if is a equivalent to this ; otherwise, false. public override bool Equals(object? obj) => obj is Size other && Equals(other); /// /// Returns a hash code for this . /// /// An integer value that specifies the hash code for this . public override int GetHashCode() => HashCode.Combine(Width, Height); /// /// Deconstructs the size into the width and height value. /// /// The width. /// The height. public void Deconstruct(out float width, out float height) { width = Width; height = Height; } #endregion #region Operators /// /// Returns a value that indicates whether two specified are equal. /// /// The first to compare. /// The second to compare. /// true if and are equal; otherwise, false. public static bool operator ==(Size size1, Size size2) => size1.Equals(size2); /// /// Returns a value that indicates whether two specified are equal. /// /// The first to compare. /// The second to compare. /// true if and are not equal; otherwise, false. public static bool operator !=(Size size1, Size size2) => !(size1 == size2); /// /// Returns a new representing the addition of the two provided . /// /// The first . /// The second . /// A new representing the addition of the two provided . public static Size operator +(Size size1, Size size2) => new(size1.Width + size2.Width, size1.Height + size2.Height); /// /// Returns a new created from the provided and . /// /// The of the rectangle. /// The of the rectangle. /// The rectangle created from the provided and . public static Rectangle operator +(Size size, Point point) => new(point, size); /// /// Returns a new representing the subtraction of the two provided . /// /// The first . /// The second . /// A new representing the subtraction of the two provided . public static Size operator -(Size size1, Size size2) => new(size1.Width - size2.Width, size1.Height - size2.Height); /// /// Returns a new representing the multiplication of the two provided . /// /// The first . /// The second . /// A new representing the multiplication of the two provided . public static Size operator *(Size size1, Size size2) => new(size1.Width * size2.Width, size1.Height * size2.Height); /// /// Returns a new representing the multiplication of the and the provided factor. /// /// The . /// The factor by which the should be multiplied. /// A new representing the multiplication of the and the provided factor. public static Size operator *(Size size, float factor) => new(size.Width * factor, size.Height * factor); /// /// Returns a new representing the division of the two provided . /// /// The first . /// The second . /// A new representing the division of the two provided . public static Size operator /(Size size1, Size size2) => size2.Width.EqualsInTolerance(0) || size2.Height.EqualsInTolerance(0) ? Invalid : new Size(size1.Width / size2.Width, size1.Height / size2.Height); /// /// Returns a new representing the division of the and the provided factor. /// /// The . /// The factor by which the should be divided. /// A new representing the division of the and the provided factor. public static Size operator /(Size size, float factor) => factor.EqualsInTolerance(0) ? Invalid : new Size(size.Width / factor, size.Height / factor); /// /// Returns a new representing the multiplication of the and the specified . /// /// The to scale. /// The scaling factor. /// A new representing the multiplication of the and the specified . public static Size operator *(Size size, Scale scale) => new(size.Width * scale.Horizontal, size.Height * scale.Vertical); #endregion }