mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-26 07:35:41 +00:00
Common: Remove Rectangle class
This commit is contained in:
parent
29533650a8
commit
e0509ebd9f
|
@ -1,86 +1,79 @@
|
||||||
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
|
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
|
||||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||||
|
|
||||||
#include "common/rectangle.h"
|
#include "common/gsvector.h"
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
using Common::Rectangle;
|
|
||||||
using IntRectangle = Rectangle<int>;
|
|
||||||
|
|
||||||
TEST(Rectangle, DefaultConstructorIsInvalid)
|
|
||||||
{
|
|
||||||
IntRectangle r;
|
|
||||||
ASSERT_FALSE(r.Valid());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Rectangle, AdjacentRectanglesNotIntersecting)
|
TEST(Rectangle, AdjacentRectanglesNotIntersecting)
|
||||||
{
|
{
|
||||||
IntRectangle r1(0, 0, 10, 10);
|
GSVector4i r1(0, 0, 10, 10);
|
||||||
IntRectangle r2(10, 10, 20, 20);
|
GSVector4i r2(10, 10, 20, 20);
|
||||||
ASSERT_FALSE(r1.Intersects(r2));
|
ASSERT_FALSE(r1.rintersects(r2));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Rectangle, IntersectingRectanglesIntersecting)
|
TEST(Rectangle, IntersectingRectanglesIntersecting)
|
||||||
{
|
{
|
||||||
IntRectangle r1(0, 0, 10, 10);
|
GSVector4i r1(0, 0, 10, 10);
|
||||||
IntRectangle r2(9, 9, 4, 4);
|
GSVector4i r2(9, 9, 14, 14);
|
||||||
ASSERT_TRUE(r1.Intersects(r2));
|
ASSERT_TRUE(r1.rintersects(r2));
|
||||||
ASSERT_TRUE(r2.Intersects(r1));
|
ASSERT_TRUE(r2.rintersects(r1));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Rectangle, PointContainedInRectangle)
|
TEST(Rectangle, PointContainedInRectangle)
|
||||||
{
|
{
|
||||||
IntRectangle r1(0, 0, 10, 10);
|
GSVector4i r1(0, 0, 10, 10);
|
||||||
ASSERT_TRUE(r1.Contains(5, 5));
|
GSVector4i r2(5, 5, 6, 6);
|
||||||
|
ASSERT_TRUE(r1.rcontains(r2));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Rectangle, PointOutsideRectangleNotContained)
|
TEST(Rectangle, PointOutsideRectangleNotContained)
|
||||||
{
|
{
|
||||||
IntRectangle r1(0, 0, 10, 10);
|
GSVector4i r1(0, 0, 10, 10);
|
||||||
ASSERT_FALSE(r1.Contains(10, 10));
|
GSVector4i r2(10, 10, 11, 11);
|
||||||
|
ASSERT_FALSE(r1.rcontains(r2));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Rectangle, RectangleSize)
|
TEST(Rectangle, RectangleSize)
|
||||||
{
|
{
|
||||||
IntRectangle r(0, 0, 10, 10);
|
GSVector4i r(0, 0, 10, 10);
|
||||||
ASSERT_EQ(r.GetWidth(), 10);
|
ASSERT_EQ(r.width(), 10);
|
||||||
ASSERT_EQ(r.GetHeight(), 10);
|
ASSERT_EQ(r.height(), 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Rectangle, IncludeAfterInvalid)
|
TEST(Rectangle, IncludeAfterInvalid)
|
||||||
{
|
{
|
||||||
IntRectangle r;
|
GSVector4i r(0, 0, 1, 1);
|
||||||
IntRectangle r2(0, 0, 10, 10);
|
GSVector4i r2(5, 5, 10, 10);
|
||||||
ASSERT_FALSE(r.Valid());
|
GSVector4i ru(0, 0, 10, 10);
|
||||||
ASSERT_TRUE(r2.Valid());
|
ASSERT_TRUE(r.runion(r2).eq(ru));
|
||||||
r.Include(r2);
|
|
||||||
ASSERT_EQ(r, r2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Rectangle, EmptyRectangleHasNoExtents)
|
TEST(Rectangle, EmptyRectangleHasNoExtents)
|
||||||
{
|
{
|
||||||
IntRectangle r(0, 0, 0, 0);
|
GSVector4i r(0, 0, 0, 0);
|
||||||
ASSERT_FALSE(r.HasExtents());
|
ASSERT_EQ(r.width(), 0);
|
||||||
|
ASSERT_EQ(r.height(), 0);
|
||||||
|
ASSERT_TRUE(r.rempty());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Rectangle, NonEmptyRectangleHasExtents)
|
TEST(Rectangle, NonEmptyRectangleHasExtents)
|
||||||
{
|
{
|
||||||
IntRectangle r(0, 0, 1, 1);
|
GSVector4i r(0, 0, 1, 1);
|
||||||
ASSERT_TRUE(r.HasExtents());
|
ASSERT_EQ(r.width(), 1);
|
||||||
|
ASSERT_EQ(r.height(), 1);
|
||||||
|
ASSERT_FALSE(r.rempty());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Rectangle, RelationalOperators)
|
TEST(Rectangle, RelationalOperators)
|
||||||
{
|
{
|
||||||
IntRectangle r1(0, 0, 1, 1);
|
GSVector4i r1(0, 0, 1, 1);
|
||||||
IntRectangle r2(1, 1, 2, 2);
|
GSVector4i r2(1, 1, 2, 2);
|
||||||
|
|
||||||
ASSERT_EQ(r1, r1);
|
ASSERT_TRUE(r1.eq(r1));
|
||||||
ASSERT_LE(r1, r1);
|
ASSERT_TRUE(r1.lt32(r2).alltrue());
|
||||||
ASSERT_LE(r1, r2);
|
ASSERT_TRUE(r2.eq(r2));
|
||||||
ASSERT_LT(r1, r2);
|
ASSERT_TRUE(r2.gt32(r1).alltrue());
|
||||||
ASSERT_EQ(r2, r2);
|
ASSERT_FALSE(r2.lt32(r1).alltrue());
|
||||||
ASSERT_GE(r2, r1);
|
ASSERT_FALSE(r1.eq(r2));
|
||||||
ASSERT_GT(r2, r1);
|
|
||||||
ASSERT_NE(r1, r2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,6 @@ add_library(common
|
||||||
perf_scope.h
|
perf_scope.h
|
||||||
progress_callback.cpp
|
progress_callback.cpp
|
||||||
progress_callback.h
|
progress_callback.h
|
||||||
rectangle.h
|
|
||||||
scoped_guard.h
|
scoped_guard.h
|
||||||
settings_interface.h
|
settings_interface.h
|
||||||
sha1_digest.cpp
|
sha1_digest.cpp
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
<ClInclude Include="path.h" />
|
<ClInclude Include="path.h" />
|
||||||
<ClInclude Include="perf_scope.h" />
|
<ClInclude Include="perf_scope.h" />
|
||||||
<ClInclude Include="progress_callback.h" />
|
<ClInclude Include="progress_callback.h" />
|
||||||
<ClInclude Include="rectangle.h" />
|
|
||||||
<ClInclude Include="scoped_guard.h" />
|
<ClInclude Include="scoped_guard.h" />
|
||||||
<ClInclude Include="settings_interface.h" />
|
<ClInclude Include="settings_interface.h" />
|
||||||
<ClInclude Include="sha1_digest.h" />
|
<ClInclude Include="sha1_digest.h" />
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
<ClInclude Include="types.h" />
|
<ClInclude Include="types.h" />
|
||||||
<ClInclude Include="fifo_queue.h" />
|
<ClInclude Include="fifo_queue.h" />
|
||||||
<ClInclude Include="heap_array.h" />
|
<ClInclude Include="heap_array.h" />
|
||||||
<ClInclude Include="rectangle.h" />
|
|
||||||
<ClInclude Include="log.h" />
|
<ClInclude Include="log.h" />
|
||||||
<ClInclude Include="small_string.h" />
|
<ClInclude Include="small_string.h" />
|
||||||
<ClInclude Include="byte_stream.h" />
|
<ClInclude Include="byte_stream.h" />
|
||||||
|
|
|
@ -1,220 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
|
|
||||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cmath>
|
|
||||||
#include <cstring>
|
|
||||||
#include <limits>
|
|
||||||
#include <tuple>
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
namespace Common {
|
|
||||||
|
|
||||||
/// Templated rectangle class. Assumes an upper-left origin, that is (0,0) is the top-left corner.
|
|
||||||
template<typename T>
|
|
||||||
struct Rectangle
|
|
||||||
{
|
|
||||||
static constexpr T InvalidMinCoord = std::numeric_limits<T>::max();
|
|
||||||
static constexpr T InvalidMaxCoord = std::numeric_limits<T>::min();
|
|
||||||
|
|
||||||
/// Default constructor - initializes to an invalid coordinate range suitable for including points.
|
|
||||||
constexpr Rectangle() : left(InvalidMinCoord), top(InvalidMinCoord), right(InvalidMaxCoord), bottom(InvalidMaxCoord)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Construct with values.
|
|
||||||
constexpr Rectangle(T left_, T top_, T right_, T bottom_) : left(left_), top(top_), right(right_), bottom(bottom_) {}
|
|
||||||
|
|
||||||
/// Copy constructor.
|
|
||||||
constexpr Rectangle(const Rectangle& copy) : left(copy.left), top(copy.top), right(copy.right), bottom(copy.bottom) {}
|
|
||||||
|
|
||||||
/// Sets the rectangle using the specified values.
|
|
||||||
constexpr void Set(T left_, T top_, T right_, T bottom_)
|
|
||||||
{
|
|
||||||
left = left_;
|
|
||||||
top = top_;
|
|
||||||
right = right_;
|
|
||||||
bottom = bottom_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets the rectangle using the specified top-left position and extents.
|
|
||||||
constexpr void SetExtents(T x, T y, T width, T height)
|
|
||||||
{
|
|
||||||
left = x;
|
|
||||||
top = y;
|
|
||||||
right = x + width;
|
|
||||||
bottom = y + height;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a new rectangle from the specified position and size.
|
|
||||||
static Rectangle FromExtents(T x, T y, T width, T height) { return Rectangle(x, y, x + width, y + height); }
|
|
||||||
|
|
||||||
/// Sets the rectangle to invalid coordinates (right < left, top < bottom).
|
|
||||||
constexpr void SetInvalid() { Set(InvalidMinCoord, InvalidMinCoord, InvalidMaxCoord, InvalidMaxCoord); }
|
|
||||||
|
|
||||||
/// Returns the width of the rectangle.
|
|
||||||
constexpr T GetWidth() const { return right - left; }
|
|
||||||
|
|
||||||
/// Returns the height of the rectangle.
|
|
||||||
constexpr T GetHeight() const { return bottom - top; }
|
|
||||||
|
|
||||||
/// Returns true if the rectangles's width/height can be considered valid.
|
|
||||||
constexpr bool Valid() const { return left <= right && top <= bottom; }
|
|
||||||
|
|
||||||
/// Returns false if the rectangle does not have any extents (zero size).
|
|
||||||
constexpr bool HasExtents() const { return left < right && top < bottom; }
|
|
||||||
|
|
||||||
/// Assignment operator.
|
|
||||||
constexpr Rectangle& operator=(const Rectangle& rhs)
|
|
||||||
{
|
|
||||||
std::memcpy(this, &rhs, sizeof(Rectangle));
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Relational operators.
|
|
||||||
#define RELATIONAL_OPERATOR(op) \
|
|
||||||
constexpr bool operator op(const Rectangle& rhs) const \
|
|
||||||
{ \
|
|
||||||
return std::tie(left, top, right, bottom) op std::tie(rhs.left, rhs.top, rhs.right, rhs.bottom); \
|
|
||||||
}
|
|
||||||
|
|
||||||
RELATIONAL_OPERATOR(==);
|
|
||||||
RELATIONAL_OPERATOR(!=);
|
|
||||||
RELATIONAL_OPERATOR(<);
|
|
||||||
RELATIONAL_OPERATOR(<=);
|
|
||||||
RELATIONAL_OPERATOR(>);
|
|
||||||
RELATIONAL_OPERATOR(>=);
|
|
||||||
|
|
||||||
#undef RELATIONAL_OPERATOR
|
|
||||||
|
|
||||||
// Arithmetic operators.
|
|
||||||
#define ARITHMETIC_OPERATOR(op) \
|
|
||||||
constexpr Rectangle& operator op##=(const T amount) \
|
|
||||||
{ \
|
|
||||||
left op## = amount; \
|
|
||||||
top op## = amount; \
|
|
||||||
right op## = amount; \
|
|
||||||
bottom op## = amount; \
|
|
||||||
} \
|
|
||||||
constexpr Rectangle operator op(const T amount) const \
|
|
||||||
{ \
|
|
||||||
return Rectangle(left op amount, top op amount, right op amount, bottom op amount); \
|
|
||||||
}
|
|
||||||
|
|
||||||
ARITHMETIC_OPERATOR(+);
|
|
||||||
ARITHMETIC_OPERATOR(-);
|
|
||||||
ARITHMETIC_OPERATOR(*);
|
|
||||||
ARITHMETIC_OPERATOR(/);
|
|
||||||
ARITHMETIC_OPERATOR(%);
|
|
||||||
ARITHMETIC_OPERATOR(>>);
|
|
||||||
ARITHMETIC_OPERATOR(<<);
|
|
||||||
ARITHMETIC_OPERATOR(|);
|
|
||||||
ARITHMETIC_OPERATOR(&);
|
|
||||||
ARITHMETIC_OPERATOR(^);
|
|
||||||
|
|
||||||
#undef ARITHMETIC_OPERATOR
|
|
||||||
|
|
||||||
#ifdef _WINDEF_
|
|
||||||
/// Casts this rectangle to a Win32 RECT structure if compatible.
|
|
||||||
template<bool _ = true, typename = typename std::enable_if_t<std::is_same_v<T, s32> && _>>
|
|
||||||
const RECT* AsRECT() const
|
|
||||||
{
|
|
||||||
return reinterpret_cast<const RECT*>(this);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// Tests for intersection between two rectangles.
|
|
||||||
constexpr bool Intersects(const Rectangle& rhs) const
|
|
||||||
{
|
|
||||||
return !(left >= rhs.right || rhs.left >= right || top >= rhs.bottom || rhs.top >= bottom);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Tests whether the specified point is contained in the rectangle.
|
|
||||||
constexpr bool Contains(T x, T y) const { return (x >= left && x < right && y >= top && y < bottom); }
|
|
||||||
constexpr bool Contains(const Rectangle& rhs) const
|
|
||||||
{
|
|
||||||
return (left <= rhs.left && right >= rhs.right && top <= rhs.top && bottom >= rhs.bottom);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the middle point of the rectangle.
|
|
||||||
constexpr T GetCenterX() const { return left + ((right - left) / 2); }
|
|
||||||
constexpr T GetCenterY() const { return top + ((bottom - top) / 2); }
|
|
||||||
|
|
||||||
/// Returns the distance between two rectangles.
|
|
||||||
T GetDistance(const Rectangle& rhs) const
|
|
||||||
{
|
|
||||||
const T lcx = GetCenterX();
|
|
||||||
const T lcy = GetCenterY();
|
|
||||||
const T rcx = rhs.GetCenterX();
|
|
||||||
const T rcy = rhs.GetCenterY();
|
|
||||||
const T dx = (lcx - rcx);
|
|
||||||
const T dy = (lcy - rcy);
|
|
||||||
const T distsq = (dx * dx) + (dy * dy);
|
|
||||||
const float dist = std::sqrt(static_cast<float>(distsq));
|
|
||||||
return static_cast<T>(dist);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Expands the bounds of the rectangle to contain the specified point.
|
|
||||||
constexpr void Include(T x, T y)
|
|
||||||
{
|
|
||||||
left = std::min(left, x);
|
|
||||||
right = std::max(right, x + static_cast<T>(1));
|
|
||||||
top = std::min(top, y);
|
|
||||||
bottom = std::max(bottom, y + static_cast<T>(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Expands the bounds of the rectangle to contain another rectangle.
|
|
||||||
constexpr void Include(const Rectangle& rhs)
|
|
||||||
{
|
|
||||||
left = std::min(left, rhs.left);
|
|
||||||
right = std::max(right, rhs.right);
|
|
||||||
top = std::min(top, rhs.top);
|
|
||||||
bottom = std::max(bottom, rhs.bottom);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Expands the bounds of the rectangle to contain another rectangle.
|
|
||||||
constexpr void Include(T other_left, T other_right, T other_top, T other_bottom)
|
|
||||||
{
|
|
||||||
left = std::min(left, other_left);
|
|
||||||
right = std::max(right, other_right);
|
|
||||||
top = std::min(top, other_top);
|
|
||||||
bottom = std::max(bottom, other_bottom);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Clamps the rectangle to the specified coordinates.
|
|
||||||
constexpr void Clamp(T x1, T y1, T x2, T y2)
|
|
||||||
{
|
|
||||||
left = std::clamp(left, x1, x2);
|
|
||||||
right = std::clamp(right, x1, x2);
|
|
||||||
top = std::clamp(top, y1, y2);
|
|
||||||
bottom = std::clamp(bottom, y1, y2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Clamps the rectangle to the specified size.
|
|
||||||
constexpr void ClampSize(T width, T height)
|
|
||||||
{
|
|
||||||
right = std::min(right, left + width);
|
|
||||||
bottom = std::min(bottom, top + height);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a new rectangle with clamped coordinates.
|
|
||||||
constexpr Rectangle Clamped(T x1, T y1, T x2, T y2) const
|
|
||||||
{
|
|
||||||
return Rectangle(std::clamp(left, x1, x2), std::clamp(top, y1, y2), std::clamp(right, x1, x2),
|
|
||||||
std::clamp(bottom, y1, y2));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a new rectangle with clamped size.
|
|
||||||
constexpr Rectangle ClampedSize(T width, T height) const
|
|
||||||
{
|
|
||||||
return Rectangle(left, top, std::min(right, left + width), std::min(bottom, top + height));
|
|
||||||
}
|
|
||||||
|
|
||||||
T left;
|
|
||||||
T top;
|
|
||||||
T right;
|
|
||||||
T bottom;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Common
|
|
Loading…
Reference in a new issue