// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Runtime.InteropServices; using osuTK; namespace osu.Framework.Graphics.Primitives { /// Stores a set of four integer numbers that represent the location and size of a rectangle. The code was duplicated from . /// 1 [Serializable, StructLayout(LayoutKind.Sequential)] public struct RectangleI : IEquatable { /// Represents an instance of the class with its members uninitialized. /// 1 public static readonly RectangleI Empty; public int X; public int Y; public int Width; public int Height; /// Initializes a new instance of the class with the specified location and size. /// The y-coordinate of the upper-left corner of the rectangle. /// The width of the rectangle. /// The height of the rectangle. /// The x-coordinate of the upper-left corner of the rectangle. public RectangleI(int x, int y, int width, int height) { X = x; Y = y; Width = width; Height = height; } /// Gets or sets the coordinates of the upper-left corner of this structure. /// A that represents the upper-left corner of this structure. /// 1 [Browsable(false)] public Vector2I Location => new Vector2I(X, Y); /// Gets or sets the size of this . /// A that represents the width and height of this structure. /// 1 [Browsable(false)] public Vector2I Size => new Vector2I(Width, Height); /// Gets the y-coordinate of the top edge of this structure. /// The y-coordinate of the top edge of this structure. /// 1 [Browsable(false)] public int Left => X; /// Gets the y-coordinate of the top edge of this structure. /// The y-coordinate of the top edge of this structure. /// 1 [Browsable(false)] public int Top => Y; /// Gets the x-coordinate that is the sum of and of this structure. /// The x-coordinate that is the sum of and of this structure. /// 1 [Browsable(false)] public int Right => X + Width; /// Gets the y-coordinate that is the sum of and of this structure. /// The y-coordinate that is the sum of and of this structure. /// 1 [Browsable(false)] public int Bottom => Y + Height; [Browsable(false)] public Vector2I TopLeft => new Vector2I(Left, Top); [Browsable(false)] public Vector2I TopRight => new Vector2I(Right, Top); [Browsable(false)] public Vector2I BottomLeft => new Vector2I(Left, Bottom); [Browsable(false)] public Vector2I BottomRight => new Vector2I(Right, Bottom); /// Tests whether the or property of this has a value of zero. /// This property returns true if the or property of this has a value of zero; otherwise, false. /// 1 [Browsable(false)] public bool IsEmpty => Width <= 0 || Height <= 0; /// Tests whether obj is a with the same location and size of this . /// This method returns true if obj is a and its X, Y, Width, and Height properties are equal to the corresponding properties of this ; otherwise, false. /// The to test. /// 1 public override bool Equals(object obj) => obj is RectangleI rec && Equals(rec); /// Tests whether two structures have equal location and size. /// This operator returns true if the two specified structures have equal , , , and properties. /// The structure that is to the right of the equality operator. /// The structure that is to the left of the equality operator. /// 3 public static bool operator ==(RectangleI left, RectangleI right) => left.X == right.X && left.Y == right.Y && left.Width == right.Width && left.Height == right.Height; /// Tests whether two structures differ in location or size. /// This operator returns true if any of the , , , or properties of the two structures are unequal; otherwise false. /// The structure that is to the right of the inequality operator. /// The structure that is to the left of the inequality operator. /// 3 public static bool operator !=(RectangleI left, RectangleI right) => !(left == right); /// Determines if the specified point is contained within this structure. /// This method returns true if the point defined by x and y is contained within this structure; otherwise false. /// The y-coordinate of the point to test. /// The x-coordinate of the point to test. /// 1 public bool Contains(float x, float y) => X <= x && x < X + Width && Y <= y && y < Y + Height; public bool Contains(Vector2 pt) => Contains(pt.X, pt.Y); public bool Contains(int x, int y) => X <= x && x < X + Width && Y <= y && y < Y + Height; public bool Contains(Vector2I pt) => Contains(pt.X, pt.Y); /// Determines if the rectangular region represented by rect is entirely contained within this structure. /// This method returns true if the rectangular region represented by rect is entirely contained within the rectangular region represented by this ; otherwise false. /// The to test. /// 1 public bool Contains(RectangleI rect) => X <= rect.X && rect.X + rect.Width <= X + Width && Y <= rect.Y && rect.Y + rect.Height <= Y + Height; /// Gets the hash code for this structure. For information about the use of hash codes, see Object.GetHashCode. /// The hash code for this . /// 1 [SuppressMessage("ReSharper", "NonReadonlyMemberInGetHashCode")] public override int GetHashCode() => (int)(((uint)X ^ ((uint)Y << 13)) | (((uint)Y >> 0x13) ^ ((uint)Width << 0x1a)) | (((uint)Width >> 6) ^ ((uint)Height << 7)) | ((uint)Height >> 0x19)); public int Area => Width * Height; public RectangleI WithPositiveExtent { get { RectangleI result = this; if (result.Width < 0) { result.Width = -result.Width; result.X -= result.Width; } if (Height < 0) { result.Height = -result.Height; result.Y -= result.Height; } return result; } } public RectangleI Inflate(int amount) => Inflate(new Vector2I(amount)); public RectangleI Inflate(Vector2I amount) => Inflate(amount.X, amount.X, amount.Y, amount.Y); public RectangleI Inflate(int left, int right, int top, int bottom) => new RectangleI( X - left, Y - top, Width + left + right, Height + top + bottom); public RectangleI Shrink(int amount) => Shrink(new Vector2I(amount)); public RectangleI Shrink(Vector2I amount) => Shrink(amount.X, amount.X, amount.Y, amount.Y); public RectangleI Shrink(int left, int right, int top, int bottom) => Inflate(-left, -right, -top, -bottom); /// Intersects this structure with the specified structure. /// The intersected rectangle. /// The rectangle to intersect. /// 1 public RectangleI Intersect(RectangleI rect) => Intersect(rect, this); /// Returns a structure that represents the intersection of two rectangles. If there is no intersection, and empty is returned. /// A third structure the size of which represents the overlapped area of the two specified rectangles. /// A rectangle to intersect. /// A rectangle to intersect. /// 1 public static RectangleI Intersect(RectangleI a, RectangleI b) { int x = Math.Max(a.X, b.X); int num2 = Math.Min(a.X + a.Width, b.X + b.Width); int y = Math.Max(a.Y, b.Y); int num4 = Math.Min(a.Y + a.Height, b.Y + b.Height); if (num2 >= x && num4 >= y) return new RectangleI(x, y, num2 - x, num4 - y); return Empty; } /// Determines if this rectangle intersects with rect. /// This method returns true if there is any intersection. /// The rectangle to test. /// 1 public bool IntersectsWith(RectangleI rect) => rect.X <= X + Width && X <= rect.X + rect.Width && rect.Y <= Y + Height && Y <= rect.Y + rect.Height; /// Creates the smallest possible third rectangle that can contain both of two rectangles that form a union. /// A third structure that contains both of the two rectangles that form the union. /// A rectangle to union. /// A rectangle to union. /// 1 public static RectangleI Union(RectangleI a, RectangleI b) { int x = Math.Min(a.X, b.X); int num2 = Math.Max(a.X + a.Width, b.X + b.Width); int y = Math.Min(a.Y, b.Y); int num4 = Math.Max(a.Y + a.Height, b.Y + b.Height); return new RectangleI(x, y, num2 - x, num4 - y); } /// Adjusts the location of this rectangle by the specified amount. /// This method does not return a value. /// The amount to offset the location vertically. /// The amount to offset the location horizontally. /// 1 public RectangleI Offset(int x, int y) => new RectangleI(X + x, Y + y, Width, Height); public static implicit operator RectangleI(RectangleF r) => r.AABB; /// Converts the Location and of this to a human-readable string. /// A string that contains the position, width, and height of this structure¾for example, "{X=20, Y=20, Width=100, Height=50}". /// 1 public override string ToString() => $"X={X.ToString(CultureInfo.CurrentCulture)}, " + $"Y={Y.ToString(CultureInfo.CurrentCulture)}, " + $"Width={Width.ToString(CultureInfo.CurrentCulture)}, " + $"Height={Height.ToString(CultureInfo.CurrentCulture)}"; public bool Equals(RectangleI other) => X == other.X && Y == other.Y && Width == other.Width && Height == other.Height; } }