summaryrefslogtreecommitdiff
path: root/gfx/2d/BaseRect.h
diff options
context:
space:
mode:
authorPale Moon <git-repo@palemoon.org>2016-09-01 13:39:08 +0200
committerPale Moon <git-repo@palemoon.org>2016-09-01 13:39:08 +0200
commit3d8ce1a11a7347cc94a937719c4bc8df46fb8d14 (patch)
tree8c26ca375a6312751c00a27e1653fb6f189f0463 /gfx/2d/BaseRect.h
parente449bdb1ec3a82f204bffdd9c3c54069d086eee3 (diff)
downloadpalemoon-gre-3d8ce1a11a7347cc94a937719c4bc8df46fb8d14.tar.gz
Base import of Tycho code (warning: huge commit)
Diffstat (limited to 'gfx/2d/BaseRect.h')
-rw-r--r--gfx/2d/BaseRect.h158
1 files changed, 128 insertions, 30 deletions
diff --git a/gfx/2d/BaseRect.h b/gfx/2d/BaseRect.h
index f0f5efec2..0b6810cfd 100644
--- a/gfx/2d/BaseRect.h
+++ b/gfx/2d/BaseRect.h
@@ -6,9 +6,14 @@
#ifndef MOZILLA_GFX_BASERECT_H_
#define MOZILLA_GFX_BASERECT_H_
-#include <cmath>
-#include <mozilla/Assertions.h>
#include <algorithm>
+#include <cmath>
+#include <ostream>
+
+#include "mozilla/Assertions.h"
+#include "mozilla/FloatingPoint.h"
+#include "mozilla/TypeTraits.h"
+#include "Types.h"
namespace mozilla {
namespace gfx {
@@ -36,7 +41,7 @@ namespace gfx {
* Do not use this class directly. Subclass it, pass that subclass as the
* Sub parameter, and only use that subclass.
*/
-template <class T, class Sub, class Point, class SizeT, class Margin>
+template <class T, class Sub, class Point, class SizeT, class MarginT>
struct BaseRect {
T x, y, width, height;
@@ -59,10 +64,11 @@ struct BaseRect {
// "Finite" means not inf and not NaN
bool IsFinite() const
{
- return (std::isfinite(x) &&
- std::isfinite(y) &&
- std::isfinite(width) &&
- std::isfinite(height));
+ typedef typename mozilla::Conditional<mozilla::IsSame<T, float>::value, float, double>::Type FloatType;
+ return (mozilla::IsFinite(FloatType(x)) &&
+ mozilla::IsFinite(FloatType(y)) &&
+ mozilla::IsFinite(FloatType(width)) &&
+ mozilla::IsFinite(FloatType(height)));
}
// Returns true if this rectangle contains the interior of aRect. Always
@@ -74,13 +80,17 @@ struct BaseRect {
(x <= aRect.x && aRect.XMost() <= XMost() &&
y <= aRect.y && aRect.YMost() <= YMost());
}
- // Returns true if this rectangle contains the rectangle (aX,aY,1,1).
+ // Returns true if this rectangle contains the point. Points are considered
+ // in the rectangle if they are on the left or top edge, but outside if they
+ // are on the right or bottom edge.
bool Contains(T aX, T aY) const
{
- return x <= aX && aX + 1 <= XMost() &&
- y <= aY && aY + 1 <= YMost();
+ return x <= aX && aX < XMost() &&
+ y <= aY && aY < YMost();
}
- // Returns true if this rectangle contains the rectangle (aPoint.x,aPoint.y,1,1).
+ // Returns true if this rectangle contains the point. Points are considered
+ // in the rectangle if they are on the left or top edge, but outside if they
+ // are on the right or bottom edge.
bool Contains(const Point& aPoint) const { return Contains(aPoint.x, aPoint.y); }
// Intersection. Returns TRUE if the receiver's area has non-empty
@@ -88,7 +98,8 @@ struct BaseRect {
// Always returns false if aRect is empty or 'this' is empty.
bool Intersects(const Sub& aRect) const
{
- return x < aRect.XMost() && aRect.x < XMost() &&
+ return !IsEmpty() && !aRect.IsEmpty() &&
+ x < aRect.XMost() && aRect.x < XMost() &&
y < aRect.YMost() && aRect.y < YMost();
}
// Returns the rectangle containing the intersection of the points
@@ -166,6 +177,23 @@ struct BaseRect {
*static_cast<Sub*>(this) = aRect1.UnionEdges(aRect2);
}
+ // Expands the rect to include the point
+ void ExpandToEnclose(const Point& aPoint)
+ {
+ if (aPoint.x < x) {
+ width = XMost() - aPoint.x;
+ x = aPoint.x;
+ } else if (aPoint.x > XMost()) {
+ width = aPoint.x - x;
+ }
+ if (aPoint.y < y) {
+ height = YMost() - aPoint.y;
+ y = aPoint.y;
+ } else if (aPoint.y > YMost()) {
+ height = aPoint.y - y;
+ }
+ }
+
void SetRect(T aX, T aY, T aWidth, T aHeight)
{
x = aX; y = aY; width = aWidth; height = aHeight;
@@ -189,7 +217,7 @@ struct BaseRect {
width += 2 * aDx;
height += 2 * aDy;
}
- void Inflate(const Margin& aMargin)
+ void Inflate(const MarginT& aMargin)
{
x -= aMargin.left;
y -= aMargin.top;
@@ -198,6 +226,20 @@ struct BaseRect {
}
void Inflate(const SizeT& aSize) { Inflate(aSize.width, aSize.height); }
+ void InflateToMultiple(const SizeT& aMultiple)
+ {
+ T xMost = XMost();
+ T yMost = YMost();
+
+ x = static_cast<T>(floor(x / aMultiple.width)) * aMultiple.width;
+ y = static_cast<T>(floor(y / aMultiple.height)) * aMultiple.height;
+ xMost = static_cast<T>(ceil(x / aMultiple.width)) * aMultiple.width;
+ yMost = static_cast<T>(ceil(y / aMultiple.height)) * aMultiple.height;
+
+ width = xMost - x;
+ height = yMost - y;
+ }
+
void Deflate(T aD) { Deflate(aD, aD); }
void Deflate(T aDx, T aDy)
{
@@ -206,7 +248,7 @@ struct BaseRect {
width = std::max(T(0), width - 2 * aDx);
height = std::max(T(0), height - 2 * aDy);
}
- void Deflate(const Margin& aMargin)
+ void Deflate(const MarginT& aMargin)
{
x += aMargin.left;
y += aMargin.top;
@@ -231,13 +273,25 @@ struct BaseRect {
return IsEqualEdges(aRect) || (IsEmpty() && aRect.IsEmpty());
}
- Sub operator+(const Point& aPoint) const
+ friend Sub operator+(Sub aSub, const Point& aPoint)
+ {
+ aSub += aPoint;
+ return aSub;
+ }
+ friend Sub operator-(Sub aSub, const Point& aPoint)
{
- return Sub(x + aPoint.x, y + aPoint.y, width, height);
+ aSub -= aPoint;
+ return aSub;
}
- Sub operator-(const Point& aPoint) const
+ friend Sub operator+(Sub aSub, const SizeT& aSize)
{
- return Sub(x - aPoint.x, y - aPoint.y, width, height);
+ aSub += aSize;
+ return aSub;
+ }
+ friend Sub operator-(Sub aSub, const SizeT& aSize)
+ {
+ aSub -= aSize;
+ return aSub;
}
Sub& operator+=(const Point& aPoint)
{
@@ -249,14 +303,25 @@ struct BaseRect {
MoveBy(-aPoint);
return *static_cast<Sub*>(this);
}
-
+ Sub& operator+=(const SizeT& aSize)
+ {
+ width += aSize.width;
+ height += aSize.height;
+ return *static_cast<Sub*>(this);
+ }
+ Sub& operator-=(const SizeT& aSize)
+ {
+ width -= aSize.width;
+ height -= aSize.height;
+ return *static_cast<Sub*>(this);
+ }
// Find difference as a Margin
- Margin operator-(const Sub& aRect) const
+ MarginT operator-(const Sub& aRect) const
{
- return Margin(aRect.y - y,
- XMost() - aRect.XMost(),
- YMost() - aRect.YMost(),
- aRect.x - x);
+ return MarginT(aRect.y - y,
+ XMost() - aRect.XMost(),
+ YMost() - aRect.YMost(),
+ aRect.x - x);
}
// Helpers for accessing the vertices
@@ -264,6 +329,33 @@ struct BaseRect {
Point TopRight() const { return Point(XMost(), y); }
Point BottomLeft() const { return Point(x, YMost()); }
Point BottomRight() const { return Point(XMost(), YMost()); }
+ Point AtCorner(int aCorner) const {
+ switch (aCorner) {
+ case RectCorner::TopLeft: return TopLeft();
+ case RectCorner::TopRight: return TopRight();
+ case RectCorner::BottomRight: return BottomRight();
+ case RectCorner::BottomLeft: return BottomLeft();
+ }
+ MOZ_CRASH("Incomplete switch");
+ }
+ Point CCWCorner(mozilla::Side side) const {
+ switch (side) {
+ case NS_SIDE_TOP: return TopLeft();
+ case NS_SIDE_RIGHT: return TopRight();
+ case NS_SIDE_BOTTOM: return BottomRight();
+ case NS_SIDE_LEFT: return BottomLeft();
+ }
+ MOZ_CRASH("Incomplete switch");
+ }
+ Point CWCorner(mozilla::Side side) const {
+ switch (side) {
+ case NS_SIDE_TOP: return TopRight();
+ case NS_SIDE_RIGHT: return BottomRight();
+ case NS_SIDE_BOTTOM: return BottomLeft();
+ case NS_SIDE_LEFT: return TopLeft();
+ }
+ MOZ_CRASH("Incomplete switch");
+ }
Point Center() const { return Point(x, y) + Point(width, height)/2; }
SizeT Size() const { return SizeT(width, height); }
@@ -440,21 +532,27 @@ struct BaseRect {
}
/**
- * Clamp aRect to this rectangle. This returns aRect after it is forced
- * inside the bounds of this rectangle. It will attempt to retain the size
- * but will shrink the dimensions that don't fit.
+ * Clamp this rectangle to be inside aRect. The function returns a copy of
+ * this rect after it is forced inside the bounds of aRect. It will attempt to
+ * retain the size but will shrink the dimensions that don't fit.
*/
- Sub ClampRect(const Sub& aRect) const
+ Sub ForceInside(const Sub& aRect) const
{
Sub rect(std::max(aRect.x, x),
std::max(aRect.y, y),
std::min(aRect.width, width),
std::min(aRect.height, height));
- rect.x = std::min(rect.XMost(), XMost()) - rect.width;
- rect.y = std::min(rect.YMost(), YMost()) - rect.height;
+ rect.x = std::min(rect.XMost(), aRect.XMost()) - rect.width;
+ rect.y = std::min(rect.YMost(), aRect.YMost()) - rect.height;
return rect;
}
+ friend std::ostream& operator<<(std::ostream& stream,
+ const BaseRect<T, Sub, Point, SizeT, MarginT>& aRect) {
+ return stream << '(' << aRect.x << ',' << aRect.y << ','
+ << aRect.width << ',' << aRect.height << ')';
+ }
+
private:
// Do not use the default operator== or operator!= !
// Use IsEqualEdges or IsEqualInterior explicitly.