// "Therefore those skilled at the unorthodox
// are infinite as heaven and earth,
// inexhaustible as the great rivers.
// When they come to an end,
// they begin again,
// like the days and months;
// they die and are reborn,
// like the four seasons."
//
// - Sun Tsu,
// "The Art of War"
using System;
namespace TheArtOfDev.HtmlRenderer.Adapters.Entities
{
///
/// Stores a set of four floating-point numbers that represent the location and size of a rectangle.
///
public struct RRect
{
#region Fields and Consts
///
/// Represents an instance of the class with its members uninitialized.
///
public static readonly RRect Empty = new RRect();
private double _height;
private double _width;
private double _x;
private double _y;
#endregion
///
/// Initializes a new instance of the class with the specified location and size.
///
/// The x-coordinate of the upper-left corner of the rectangle.
/// The y-coordinate of the upper-left corner of the rectangle.
/// The width of the rectangle.
/// The height of the rectangle.
public RRect(double x, double y, double width, double height)
{
_x = x;
_y = y;
_width = width;
_height = height;
}
///
/// Initializes a new instance of the class with the specified location and size.
///
/// A that represents the upper-left corner of the rectangular region.
/// A that represents the width and height of the rectangular region.
public RRect(RPoint location, RSize size)
{
_x = location.X;
_y = location.Y;
_width = size.Width;
_height = size.Height;
}
///
/// Gets or sets the coordinates of the upper-left corner of this structure.
///
/// A that represents the upper-left corner of this structure.
public RPoint Location
{
get { return new RPoint(X, Y); }
set
{
X = value.X;
Y = value.Y;
}
}
///
/// Gets or sets the size of this .
///
/// A that represents the width and height of this structure.
public RSize Size
{
get { return new RSize(Width, Height); }
set
{
Width = value.Width;
Height = value.Height;
}
}
///
/// Gets or sets the x-coordinate of the upper-left corner of this structure.
///
///
/// The x-coordinate of the upper-left corner of this structure.
///
public double X
{
get { return _x; }
set { _x = value; }
}
///
/// Gets or sets the y-coordinate of the upper-left corner of this structure.
///
///
/// The y-coordinate of the upper-left corner of this structure.
///
public double Y
{
get { return _y; }
set { _y = value; }
}
///
/// Gets or sets the width of this structure.
///
///
/// The width of this structure.
///
public double Width
{
get { return _width; }
set { _width = value; }
}
///
/// Gets or sets the height of this structure.
///
///
/// The height of this structure.
///
public double Height
{
get { return _height; }
set { _height = value; }
}
///
/// Gets the x-coordinate of the left edge of this structure.
///
///
/// The x-coordinate of the left edge of this structure.
///
public double Left
{
get { return X; }
}
///
/// Gets the y-coordinate of the top edge of this structure.
///
///
/// The y-coordinate of the top edge of this structure.
///
public double Top
{
get { return 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.
///
public double Right
{
get { return 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.
///
public double Bottom
{
get { return Y + Height; }
}
///
/// 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.
///
public bool IsEmpty
{
get
{
if (Width > 0.0)
return Height <= 0.0;
else
return true;
}
}
///
/// 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 left of the equality operator.
///
///
/// The structure that is to the right of the equality operator.
///
public static bool operator ==(RRect left, RRect right)
{
if (Math.Abs(left.X - right.X) < 0.001 && Math.Abs(left.Y - right.Y) < 0.001 && Math.Abs(left.Width - right.Width) < 0.001)
return Math.Abs(left.Height - right.Height) < 0.001;
else
return false;
}
///
/// 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 left of the inequality operator.
///
///
/// The structure that is to the right of the inequality operator.
///
public static bool operator !=(RRect left, RRect right)
{
return !(left == right);
}
///
/// Creates a structure with upper-left corner and lower-right corner at the specified locations.
///
///
/// The new that this method creates.
///
/// The x-coordinate of the upper-left corner of the rectangular region.
/// The y-coordinate of the upper-left corner of the rectangular region.
/// The x-coordinate of the lower-right corner of the rectangular region.
/// The y-coordinate of the lower-right corner of the rectangular region.
public static RRect FromLTRB(double left, double top, double right, double bottom)
{
return new RRect(left, top, right - left, bottom - top);
}
///
/// Tests whether is a with the same location and size of this
/// .
///
///
/// This method returns true if is a and its X, Y, Width, and Height properties are equal to the corresponding properties of this
/// ; otherwise, false.
///
///
/// The to test.
///
public override bool Equals(object obj)
{
if (!(obj is RRect))
return false;
var rectangleF = (RRect)obj;
if (Math.Abs(rectangleF.X - X) < 0.001 && Math.Abs(rectangleF.Y - Y) < 0.001 && Math.Abs(rectangleF.Width - Width) < 0.001)
return Math.Abs(rectangleF.Height - Height) < 0.001;
else
return false;
}
///
/// Determines if the specified point is contained within this structure.
///
///
/// This method returns true if the point defined by and is contained within this
///
/// structure; otherwise false.
///
/// The x-coordinate of the point to test.
/// The y-coordinate of the point to test.
public bool Contains(double x, double y)
{
if (X <= x && x < X + Width && Y <= y)
return y < Y + Height;
else
return false;
}
///
/// Determines if the specified point is contained within this structure.
///
///
/// This method returns true if the point represented by the parameter is contained within this
///
/// structure; otherwise false.
///
/// The to test.
public bool Contains(RPoint pt)
{
return Contains(pt.X, pt.Y);
}
///
/// Determines if the rectangular region represented by is entirely contained within this
///
/// structure.
///
///
/// This method returns true if the rectangular region represented by is entirely contained within the rectangular region represented by this
///
/// ; otherwise false.
///
///
/// The to test.
///
public bool Contains(RRect rect)
{
if (X <= rect.X && rect.X + rect.Width <= X + Width && Y <= rect.Y)
return rect.Y + rect.Height <= Y + Height;
else
return false;
}
///
/// Inflates this structure by the specified amount.
///
///
/// The amount to inflate this structure horizontally.
///
///
/// The amount to inflate this structure vertically.
///
public void Inflate(double x, double y)
{
X -= x;
Y -= y;
Width += 2f * x;
Height += 2f * y;
}
///
/// Inflates this by the specified amount.
///
/// The amount to inflate this rectangle.
public void Inflate(RSize size)
{
Inflate(size.Width, size.Height);
}
///
/// Creates and returns an inflated copy of the specified structure. The copy is inflated by the specified amount. The original rectangle remains unmodified.
///
///
/// The inflated .
///
///
/// The to be copied. This rectangle is not modified.
///
/// The amount to inflate the copy of the rectangle horizontally.
/// The amount to inflate the copy of the rectangle vertically.
public static RRect Inflate(RRect rect, double x, double y)
{
RRect rectangleF = rect;
rectangleF.Inflate(x, y);
return rectangleF;
}
///
/// Replaces this structure with the intersection of itself and the specified
///
/// structure.
///
/// The rectangle to intersect.
public void Intersect(RRect rect)
{
RRect rectangleF = Intersect(rect, this);
X = rectangleF.X;
Y = rectangleF.Y;
Width = rectangleF.Width;
Height = rectangleF.Height;
}
///
/// 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.
public static RRect Intersect(RRect a, RRect b)
{
double x = Math.Max(a.X, b.X);
double num1 = Math.Min(a.X + a.Width, b.X + b.Width);
double y = Math.Max(a.Y, b.Y);
double num2 = Math.Min(a.Y + a.Height, b.Y + b.Height);
if (num1 >= x && num2 >= y)
return new RRect(x, y, num1 - x, num2 - y);
else
return Empty;
}
///
/// Determines if this rectangle intersects with .
///
///
/// This method returns true if there is any intersection.
///
/// The rectangle to test.
public bool IntersectsWith(RRect rect)
{
if (rect.X < X + Width && X < rect.X + rect.Width && rect.Y < Y + Height)
return Y < rect.Y + rect.Height;
else
return false;
}
///
/// 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.
public static RRect Union(RRect a, RRect b)
{
double x = Math.Min(a.X, b.X);
double num1 = Math.Max(a.X + a.Width, b.X + b.Width);
double y = Math.Min(a.Y, b.Y);
double num2 = Math.Max(a.Y + a.Height, b.Y + b.Height);
return new RRect(x, y, num1 - x, num2 - y);
}
///
/// Adjusts the location of this rectangle by the specified amount.
///
/// The amount to offset the location.
public void Offset(RPoint pos)
{
Offset(pos.X, pos.Y);
}
///
/// Adjusts the location of this rectangle by the specified amount.
///
/// The amount to offset the location horizontally.
/// The amount to offset the location vertically.
public void Offset(double x, double y)
{
X += x;
Y += y;
}
///
/// Gets the hash code for this structure. For information about the use of hash codes, see Object.GetHashCode.
///
/// The hash code for this
public override int GetHashCode()
{
return (int)(uint)X ^ ((int)(uint)Y << 13 | (int)((uint)Y >> 19)) ^ ((int)(uint)Width << 26 | (int)((uint)Width >> 6)) ^ ((int)(uint)Height << 7 | (int)((uint)Height >> 25));
}
///
/// Converts the Location and Size 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}".
///
public override string ToString()
{
return "{X=" + X + ",Y=" + Y + ",Width=" + Width + ",Height=" + Height + "}";
}
}
}