diff --git a/src/framework/util/point.h b/src/framework/util/point.h index 0c5bf72a84..e521bbc0f1 100644 --- a/src/framework/util/point.h +++ b/src/framework/util/point.h @@ -32,16 +32,18 @@ template class TPoint { public: - TPoint() : x(0), y(0) {} - TPoint(T xy) : x(xy), y(xy) {} - TPoint(T x, T y) : x(x), y(y) {} - TPoint(const TPoint& other) : x(other.x), y(other.y) {} - - bool isNull() const { return x == 0 && y == 0; } - TSize toSize() const { return TSize(x, y); } - TPoint translated(T dx, T dy) const { TPoint point = *this; point.x += dx; point.y += dy; return point; } - - TPoint scale(const float v) { + T x{}, y{}; + constexpr TPoint() = default; + constexpr TPoint(T x, T y) : x{ x }, y{ y } {} + constexpr TPoint(T xy) : x{ xy }, y{ xy } {} + + constexpr bool isNull() const noexcept { return x == 0 && y == 0; } + constexpr T manhattanLength() const noexcept { return std::abs(x) + std::abs(y); } + constexpr float length() const noexcept { return std::sqrt(static_cast(x * x + y * y)); } + constexpr float distanceFrom(const TPoint& other) const noexcept { return (*this - other).length(); } + constexpr TPoint translated(T dx, T dy) const noexcept { return { x + dx, y + dy }; } + constexpr TSize toSize() const noexcept { return { x, y }; } + constexpr TPoint scale(float v) noexcept { if (v != 1.f) { float factor = (1.f - (1.f / v)); x -= x * factor; @@ -50,62 +52,49 @@ class TPoint return *this; } - TPoint operator-() const { return TPoint(-x, -y); } + constexpr TPoint operator-() const noexcept { return { -x, -y }; } - TPoint operator+(const TPoint& other) const { return TPoint(x + other.x, y + other.y); } - TPoint& operator+=(const TPoint& other) { x += other.x; y += other.y; return *this; } - TPoint operator-(const TPoint& other) const { return TPoint(x - other.x, y - other.y); } - TPoint& operator-=(const TPoint& other) { x -= other.x; y -= other.y; return *this; } - TPoint operator*(const TPoint& other) const { return TPoint(x * other.x, y * other.y); } - TPoint& operator*=(const TPoint& other) { x *= other.x; y *= other.y; return *this; } - TPoint operator/(const TPoint& other) const { return TPoint(x / other.x, y / other.y); } - TPoint& operator/=(const TPoint& other) { x /= other.x; y /= other.y; return *this; } + constexpr TPoint operator+(const TPoint& other) const { return { x + other.x, y + other.y }; } + constexpr TPoint& operator+=(const TPoint& other) { x += other.x; y += other.y; return *this; } + constexpr TPoint operator-(const TPoint& other) const { return { x - other.x, y - other.y }; } + constexpr TPoint& operator-=(const TPoint& other) { x -= other.x; y -= other.y; return *this; } + constexpr TPoint operator*(const TPoint& other) const { return { x * other.x, y * other.y }; } + constexpr TPoint& operator*=(const TPoint& other) { x *= other.x; y *= other.y; return *this; } + constexpr TPoint operator/(const TPoint& other) const { return { x / other.x, y / other.y }; } + constexpr TPoint& operator/=(const TPoint& other) { x /= other.x; y /= other.y; return *this; } - TPoint operator+(T other) const { return TPoint(x + other, y + other); } - TPoint& operator+=(T other) { x += other; y += other; return *this; } - TPoint operator-(T other) const { return TPoint(x - other, y - other); } - TPoint& operator-=(T other) { x -= other; y -= other; return *this; } - TPoint operator*(float v) const { return TPoint(x * v, y * v); } - TPoint& operator*=(float v) { x *= v; y *= v; return *this; } - TPoint operator/(float v) const { return TPoint(x / v, y / v); } - TPoint& operator/=(float v) { x /= v; y /= v; return *this; } + constexpr TPoint operator+(T other) const { return { x + other, y + other }; } + constexpr TPoint& operator+=(T other) { x += other; y += other; return *this; } + constexpr TPoint operator-(T other) const { return { x - other, y - other }; } + constexpr TPoint& operator-=(T other) { x -= other; y -= other; return *this; } + constexpr TPoint operator*(T v) const { return { x * v, y * v }; } + constexpr TPoint& operator*=(T v) { x *= v; y *= v; return *this; } + constexpr TPoint operator/(T v) const { return { x / v, y / v }; } + constexpr TPoint& operator/=(T v) { x /= v; y /= v; return *this; } - TPoint operator&(int a) { return TPoint(x & a, y & a); } - TPoint& operator&=(int a) { x &= a; y &= a; return *this; } + constexpr TPoint operator&(int a) const { return { x & a, y & a }; } + constexpr TPoint& operator&=(int a) { x &= a; y &= a; return *this; } - bool operator<=(const TPoint& other) const { return x <= other.x && y <= other.y; } - bool operator>=(const TPoint& other) const { return x >= other.x && y >= other.y; } - bool operator<(const TPoint& other) const { return x < other.x && y < other.y; } - bool operator>(const TPoint& other) const { return x > other.x && y > other.y; } + constexpr bool operator<=(const TPoint& other) const { return x <= other.x && y <= other.y; } + constexpr bool operator>=(const TPoint& other) const { return x >= other.x && y >= other.y; } + constexpr bool operator<(const TPoint& other) const { return x < other.x && y < other.y; } + constexpr bool operator>(const TPoint& other) const { return x > other.x && y > other.y; } - TPoint& operator=(const TPoint& other) = default; - bool operator==(const TPoint& other) const { return other.x == x && other.y == y; } - bool operator!=(const TPoint& other) const { return other.x != x || other.y != y; } + constexpr TPoint& operator=(const TPoint& other) = default; - float length() const { return sqrt(static_cast(x * x + y * y)); } - T manhattanLength() const { return std::abs(x) + std::abs(y); } + constexpr bool operator==(const TPoint& other) const { return other.x == x && other.y == y; } + constexpr bool operator!=(const TPoint& other) const { return other.x != x || other.y != y; } - float distanceFrom(const TPoint& other) const { return TPoint(x - other.x, y - other.y).length(); } + constexpr std::size_t hash() const noexcept { return (7 * 15 + x) * 15 + y; } - std::size_t hash() const { return (7 * 15 + x) * 15 + y; } + friend std::ostream& operator<<(std::ostream& out, const TPoint& point) { + return out << point.x << " " << point.y; + } - T x, y; + friend std::istream& operator>>(std::istream& in, TPoint& point) { + return in >> point.x >> point.y; + } }; using Point = TPoint; -using PointF = TPoint; - -template -std::ostream& operator<<(std::ostream& out, const TPoint& point) -{ - out << point.x << " " << point.y; - return out; -} - -template -std::istream& operator>>(std::istream& in, TPoint& point) -{ - in >> point.x; - in >> point.y; - return in; -} +using PointF = TPoint; \ No newline at end of file diff --git a/src/framework/util/rect.h b/src/framework/util/rect.h index 417306c5d0..4e0cfa1a5d 100644 --- a/src/framework/util/rect.h +++ b/src/framework/util/rect.h @@ -24,114 +24,103 @@ #include "../const.h" -template +template class TPoint; -template +template class TSize; -template +template class TRect { public: - TRect() : x1(0), y1(0), x2(-1), y2(-1) {} - TRect(T x, T y, T width, T height) : x1(x), y1(y), x2(x + width - 1), y2(y + height - 1) {} - TRect(const TPoint& topLeft, const TPoint& bottomRight) : x1(topLeft.x), y1(topLeft.y), x2(bottomRight.x), y2(bottomRight.y) {} - TRect(const TRect& other) : x1(other.x1), y1(other.y1), x2(other.x2), y2(other.y2) {} - TRect(T x, T y, const TSize& size) : x1(x), y1(y), x2(x + size.width() - 1), y2(y + size.height() - 1) {} - TRect(const TPoint& topLeft, const TSize& size) : x1(topLeft.x), y1(topLeft.y), x2(x1 + size.width() - 1), y2(y1 + size.height() - 1) {} - TRect(const TPoint& topLeft, int width, int height) : x1(topLeft.x), y1(topLeft.y), x2(x1 + width - 1), y2(y1 + height - 1) {} - - bool isNull() const { return x2 == x1 - 1 && y2 == y1 - 1; } - bool isEmpty() const { return x1 > x2 || y1 > y2; } - bool isValid() const { return x1 <= x2 && y1 <= y2; } - - T left() const { return x1; } - T top() const { return y1; } - T right() const { return x2; } - T bottom() const { return y2; } - T horizontalCenter() const { return x1 + (x2 - x1) / 2; } - T verticalCenter() const { return y1 + (y2 - y1) / 2; } - T x() const { return x1; } - T y() const { return y1; } - TPoint topLeft() const { return TPoint(x1, y1); } - TPoint bottomRight() const { return TPoint(x2, y2); } - TPoint topRight() const { return TPoint(x2, y1); } - TPoint bottomLeft() const { return TPoint(x1, y2); } - TPoint topCenter() const { return TPoint((x1 + x2) / 2, y1); } - TPoint bottomCenter() const { return TPoint((x1 + x2) / 2, y2); } - TPoint centerLeft() const { return TPoint(x1, (y1 + y2) / 2); } - TPoint centerRight() const { return TPoint(x2, (y1 + y2) / 2); } - TPoint center() const { return TPoint((x1 + x2) / 2, (y1 + y2) / 2); } - T width() const { return x2 - x1 + 1; } - T height() const { return y2 - y1 + 1; } - TSize size() const { return TSize(width(), height()); } - void reset() { x1 = y1 = 0; x2 = y2 = -1; } - void clear() { x2 = x1 - 1; y2 = y1 - 1; } - - void setLeft(T pos) { x1 = pos; } - void setTop(T pos) { y1 = pos; } - void setRight(T pos) { x2 = pos; } - void setBottom(T pos) { y2 = pos; } - void setX(T x) { x1 = x; } - void setY(T y) { y1 = y; } - void setTopLeft(const TPoint& p) { x1 = p.x; y1 = p.y; } - void setBottomRight(const TPoint& p) { x2 = p.x; y2 = p.y; } - void setTopRight(const TPoint& p) { x2 = p.x; y1 = p.y; } - void setBottomLeft(const TPoint& p) { x1 = p.x; y2 = p.y; } - void setWidth(T width) { x2 = x1 + width - 1; } - void setHeight(T height) { y2 = y1 + height - 1; } - void setSize(const TSize& size) { x2 = x1 + size.width() - 1; y2 = y1 + size.height() - 1; } - void setRect(T x, T y, T width, T height) { x1 = x; y1 = y; x2 = (x + width - 1); y2 = (y + height - 1); } - void setCoords(int left, int top, int right, int bottom) { x1 = left; y1 = top; x2 = right; y2 = bottom; } - - void expandLeft(T add) { x1 -= add; } - void expandTop(T add) { y1 -= add; } - void expandRight(T add) { x2 += add; } - void expandBottom(T add) { y2 += add; } - void expand(T top, T right, T bottom, T left) { x1 -= left; y1 -= top; x2 += right; y2 += bottom; } - void expand(T add) { x1 -= add; y1 -= add; x2 += add; y2 += add; } - - void translate(T x, T y) { x1 += x; y1 += y; x2 += x; y2 += y; } - void translate(const TPoint& p) { x1 += p.x; y1 += p.y; x2 += p.x; y2 += p.y; } - void resize(const TSize& size) { x2 = x1 + size.width() - 1; y2 = y1 + size.height() - 1; } - void resize(T width, T height) { x2 = x1 + width - 1; y2 = y1 + height - 1; } - void move(T x, T y) { x2 += x - x1; y2 += y - y1; x1 = x; y1 = y; } - void move(const TPoint& p) { x2 += p.x - x1; y2 += p.y - y1; x1 = p.x; y1 = p.y; } - void moveLeft(T pos) { x2 += (pos - x1); x1 = pos; } - void moveTop(T pos) { y2 += (pos - y1); y1 = pos; } - void moveRight(T pos) { x1 += (pos - x2); x2 = pos; } - void moveBottom(T pos) { y1 += (pos - y2); y2 = pos; } - void moveTopLeft(const TPoint& p) { moveLeft(p.x); moveTop(p.y); } - void moveBottomRight(const TPoint& p) { moveRight(p.x); moveBottom(p.y); } - void moveTopRight(const TPoint& p) { moveRight(p.x); moveTop(p.y); } - void moveBottomLeft(const TPoint& p) { moveLeft(p.x); moveBottom(p.y); } - void moveTopCenter(const TPoint& p) { moveHorizontalCenter(p.x); moveTop(p.y); } - void moveBottomCenter(const TPoint& p) { moveHorizontalCenter(p.x); moveBottom(p.y); } - void moveCenterLeft(const TPoint& p) { moveLeft(p.x); moveVerticalCenter(p.y); } - void moveCenterRight(const TPoint& p) { moveRight(p.x); moveVerticalCenter(p.y); } - - TRect translated(int x, int y) const { return TRect(TPoint(x1 + x, y1 + y), TPoint(x2 + x, y2 + y)); } - TRect translated(const TPoint& p) const { return TRect(TPoint(x1 + p.x, y1 + p.y), TPoint(x2 + p.x, y2 + p.y)); } - - TRect expanded(T add) const { return TRect(TPoint(x1 - add, y1 - add), TPoint(x2 + add, y2 + add)); } - - TRect clamp(const TSize& min, const TSize& max) const { + constexpr TRect() noexcept : x1{ 0 }, y1{ 0 }, x2{ -1 }, y2{ -1 } {} + constexpr TRect(T x, T y, T width, T height) noexcept : x1{ x }, y1{ y }, x2{ x + width - 1 }, y2{ y + height - 1 } {} + constexpr TRect(const TPoint& topLeft, const TPoint& bottomRight) noexcept : x1{ topLeft.x }, y1{ topLeft.y }, x2{ bottomRight.x }, y2{ bottomRight.y } {} + constexpr TRect(T x, T y, const TSize& size) : x1(x), y1(y), x2(x + size.width() - 1), y2(y + size.height() - 1) {} + constexpr TRect(const TPoint& topLeft, const TSize& size) noexcept : x1{ topLeft.x }, y1{ topLeft.y }, x2{ x1 + size.width() - 1 }, y2{ y1 + size.height() - 1 } {} + constexpr TRect(const TPoint& topLeft, T width, T height) noexcept : x1{ topLeft.x }, y1{ topLeft.y }, x2{ x1 + width - 1 }, y2{ y1 + height - 1 } {} + constexpr TRect(const TRect& other) noexcept = default; + + [[nodiscard]] constexpr bool isNull() const noexcept { return x2 == x1 - 1 && y2 == y1 - 1; } + [[nodiscard]] constexpr bool isEmpty() const noexcept { return x1 > x2 || y1 > y2; } + [[nodiscard]] constexpr bool isValid() const noexcept { return x1 <= x2 && y1 <= y2; } + + [[nodiscard]] constexpr T left() const noexcept { return x1; } + [[nodiscard]] constexpr T top() const noexcept { return y1; } + [[nodiscard]] constexpr T right() const noexcept { return x2; } + [[nodiscard]] constexpr T bottom() const noexcept { return y2; } + [[nodiscard]] constexpr T horizontalCenter() const noexcept { return x1 + (x2 - x1) / 2; } + [[nodiscard]] constexpr T verticalCenter() const noexcept { return y1 + (y2 - y1) / 2; } + [[nodiscard]] constexpr T x() const noexcept { return x1; } + [[nodiscard]] constexpr T y() const noexcept { return y1; } + [[nodiscard]] constexpr TPoint topLeft() const noexcept { return { x1, y1 }; } + [[nodiscard]] constexpr TPoint bottomRight() const noexcept { return { x2, y2 }; } + [[nodiscard]] constexpr TPoint topRight() const noexcept { return { x2, y1 }; } + [[nodiscard]] constexpr TPoint bottomLeft() const noexcept { return { x1, y2 }; } + [[nodiscard]] constexpr TPoint topCenter() const noexcept { return { (x1 + x2) / 2, y1 }; } + [[nodiscard]] constexpr TPoint bottomCenter() const noexcept { return { (x1 + x2) / 2, y2 }; } + [[nodiscard]] constexpr TPoint centerLeft() const noexcept { return { x1, (y1 + y2) / 2 }; } + [[nodiscard]] constexpr TPoint centerRight() const noexcept { return { x2, (y1 + y2) / 2 }; } + [[nodiscard]] constexpr TPoint center() const noexcept { return { (x1 + x2) / 2, (y1 + y2) / 2 }; } + [[nodiscard]] constexpr T width() const noexcept { return x2 - x1 + 1; } + [[nodiscard]] constexpr T height() const noexcept { return y2 - y1 + 1; } + [[nodiscard]] constexpr TSize size() const noexcept { return { width(), height() }; } + constexpr void reset() noexcept { x1 = y1 = 0; x2 = y2 = -1; } + constexpr void clear() noexcept { x2 = x1 - 1; y2 = y1 - 1; } + + constexpr void setLeft(T pos) noexcept { x1 = pos; } + constexpr void setTop(T pos) noexcept { y1 = pos; } + constexpr void setRight(T pos) noexcept { x2 = pos; } + constexpr void setBottom(T pos) noexcept { y2 = pos; } + constexpr void setX(T x) noexcept { x1 = x; } + constexpr void setY(T y) noexcept { y1 = y; } + constexpr void setTopLeft(const TPoint& p) noexcept { x1 = p.x; y1 = p.y; } + constexpr void setBottomRight(const TPoint& p) noexcept { x2 = p.x; y2 = p.y; } + constexpr void setTopRight(const TPoint& p) noexcept { x2 = p.x; y1 = p.y; } + constexpr void setBottomLeft(const TPoint& p) noexcept { x1 = p.x; y2 = p.y; } + constexpr void setWidth(T width) noexcept { x2 = x1 + width - 1; } + constexpr void setHeight(T height) noexcept { y2 = y1 + height - 1; } + constexpr void setSize(const TSize& size) noexcept { x2 = x1 + size.width - 1; y2 = y1 + size.height - 1; } + constexpr void setRect(T x, T y, T width, T height) noexcept { x1 = x; y1 = y; x2 = x + width - 1; y2 = y + height - 1; } + constexpr void setCoords(T left, T top, T right, T bottom) noexcept { x1 = left; y1 = top; x2 = right; y2 = bottom; } + + constexpr void expandLeft(T add) noexcept { x1 -= add; } + constexpr void expandTop(T add) noexcept { y1 -= add; } + constexpr void expandRight(T add) noexcept { x2 += add; } + constexpr void expandBottom(T add) noexcept { y2 += add; } + constexpr void expand(T top, T right, T bottom, T left) noexcept { x1 -= left; y1 -= top; x2 += right; y2 += bottom; } + constexpr void expand(T add) noexcept { x1 -= add; y1 -= add; x2 += add; y2 += add; } + + constexpr void translate(T x, T y) noexcept { x1 += x; y1 += y; x2 += x; y2 += y; } + constexpr void translate(const TPoint& p) noexcept { x1 += p.x; y1 += p.y; x2 += p.x; y2 += p.y; } + constexpr void resize(const TSize& size) noexcept { x2 = x1 + size.width() - 1; y2 = y1 + size.height() - 1; } + constexpr void resize(T width, T height) noexcept { x2 = x1 + width - 1; y2 = y1 + height - 1; } + constexpr void move(T x, T y) noexcept { x2 += x - x1; y2 += y - y1; x1 = x; y1 = y; } + constexpr void move(const TPoint& p) noexcept { x2 += p.x - x1; y2 += p.y - y1; x1 = p.x; y1 = p.y; } + constexpr void moveLeft(T pos) noexcept { x2 += (pos - x1); x1 = pos; } + constexpr void moveTop(T pos) noexcept { y2 += (pos - y1); y1 = pos; } + constexpr void moveRight(T pos) noexcept { x1 += (pos - x2); x2 = pos; } + constexpr void moveBottom(T pos) noexcept { y1 += (pos - y2); y2 = pos; } + constexpr void moveTopLeft(const TPoint& p) noexcept { moveLeft(p.x); moveTop(p.y); } + constexpr void moveBottomRight(const TPoint& p) noexcept { moveRight(p.x); moveBottom(p.y); } + constexpr void moveTopRight(const TPoint& p) noexcept { moveRight(p.x); moveTop(p.y); } + constexpr void moveBottomLeft(const TPoint& p) noexcept { moveLeft(p.x); moveBottom(p.y); } + constexpr void moveTopCenter(const TPoint& p) noexcept { moveHorizontalCenter(p.x); moveTop(p.y); } + constexpr void moveBottomCenter(const TPoint& p) noexcept { moveHorizontalCenter(p.x); moveBottom(p.y); } + constexpr void moveCenterLeft(const TPoint& p) noexcept { moveLeft(p.x); moveVerticalCenter(p.y); } + constexpr void moveCenterRight(const TPoint& p) noexcept { moveRight(p.x); moveVerticalCenter(p.y); } + + constexpr TRect translated(T x, T y) const noexcept { return TRect(TPoint(x1 + x, y1 + y), TPoint(x2 + x, y2 + y)); } + constexpr TRect translated(const TPoint& p) const noexcept { return TRect(TPoint(x1 + p.x, y1 + p.y), TPoint(x2 + p.x, y2 + p.y)); } + constexpr TRect expanded(T add) const noexcept { return TRect(TPoint(x1 - add, y1 - add), TPoint(x2 + add, y2 + add)); } + constexpr TRect clamp(const TSize& min, const TSize& max) const noexcept { return TRect(x1, y1, - std::min(max.width(), std::max(min.width(), width())), - std::min(max.height(), std::max(min.height(), height()))); - } - - std::size_t hash() const - { - size_t h = 37; - h = (h * 54059) ^ (x1 * 76963); - h = (h * 54059) ^ (y1 * 76963); - return h; + std::min(max.width(), std::max(min.width(), width())), + std::min(max.height(), std::max(min.height(), height()))); } - void moveCenter(const TPoint& p) - { + constexpr void moveCenter(const TPoint& p) noexcept { T w = x2 - x1; T h = y2 - y1; x1 = p.x - w / 2; @@ -139,172 +128,51 @@ class TRect x2 = x1 + w; y2 = y1 + h; } - void moveHorizontalCenter(T x) - { + constexpr void moveHorizontalCenter(T x) noexcept { T w = x2 - x1; x1 = x - w / 2; x2 = x1 + w; } - void moveVerticalCenter(T y) - { + constexpr void moveVerticalCenter(T y) noexcept { T h = y2 - y1; y1 = y - h / 2; y2 = y1 + h; } - bool contains(const TPoint& p, const bool insideOnly = false) const - { - T l, r; - if (x2 < x1 - 1) { - l = x2; - r = x1; - } else { - l = x1; - r = x2; - } - if (insideOnly) { - if (p.x <= l || p.x >= r) - return false; - } else { - if (p.x < l || p.x > r) - return false; - } - T t, b; - if (y2 < y1 - 1) { - t = y2; - b = y1; - } else { - t = y1; - b = y2; - } - if (insideOnly) { - if (p.y <= t || p.y >= b) - return false; - } else { - if (p.y < t || p.y > b) - return false; - } - return true; + constexpr std::size_t hash() const noexcept { + std::size_t h = 37; + h = (h * 54059) ^ (x1 * 76963); + h = (h * 54059) ^ (y1 * 76963); + return h; } - bool contains(const TRect& r, const bool insideOnly = false) const - { - if (contains(r.topLeft(), insideOnly) && contains(r.bottomRight(), insideOnly)) - return true; - return false; + constexpr bool contains(const TPoint& p, bool insideOnly = false) const noexcept { + return (insideOnly ? (p.x > x1 && p.x < x2) : (p.x >= x1 && p.x <= x2)) && + (insideOnly ? (p.y > y1 && p.y < y2) : (p.y >= y1 && p.y <= y2)); } - bool intersects(const TRect& r) const - { - if (isNull() || r.isNull()) - return false; - - int l1 = x1; - int r1 = x1; - if (x2 - x1 + 1 < 0) - l1 = x2; - else - r1 = x2; - - int l2 = r.x1; - int r2 = r.x1; - if (r.x2 - r.x1 + 1 < 0) - l2 = r.x2; - else - r2 = r.x2; - - if (l1 > r2 || l2 > r1) - return false; - - int t1 = y1; - int b1 = y1; - if (y2 - y1 + 1 < 0) - t1 = y2; - else - b1 = y2; - - int t2 = r.y1; - int b2 = r.y1; - if (r.y2 - r.y1 + 1 < 0) - t2 = r.y2; - else - b2 = r.y2; - - if (t1 > b2 || t2 > b1) - return false; - - return true; + constexpr bool contains(const TRect& r, bool insideOnly = false) const noexcept { + return contains(r.topLeft(), insideOnly) && contains(r.bottomRight(), insideOnly); } - TRect united(const TRect& r) const - { - TRect tmp; - tmp.x1 = std::min(x1, r.x1); - tmp.x2 = std::max(x2, r.x2); - tmp.y1 = std::min(y1, r.y1); - tmp.y2 = std::max(y2, r.y2); - return tmp; + constexpr bool intersects(const TRect& r) const noexcept { + return !(r.x2 < x1 || r.x1 > x2 || r.y2 < y1 || r.y1 > y2); } - TRect intersection(const TRect& r) const - { - if (isNull()) - return r; - if (r.isNull()) - return *this; - - int l1 = x1; - int r1 = x1; - if (x2 - x1 + 1 < 0) - l1 = x2; - else - r1 = x2; - - int l2 = r.x1; - int r2 = r.x1; - if (r.x2 - r.x1 + 1 < 0) - l2 = r.x2; - else - r2 = r.x2; - - int t1 = y1; - int b1 = y1; - if (y2 - y1 + 1 < 0) - t1 = y2; - else - b1 = y2; - - int t2 = r.y1; - int b2 = r.y1; - if (r.y2 - r.y1 + 1 < 0) - t2 = r.y2; - else - b2 = r.y2; - - TRect tmp; - tmp.x1 = std::max(l1, l2); - tmp.x2 = std::min(r1, r2); - tmp.y1 = std::max(t1, t2); - tmp.y2 = std::min(b1, b2); - return tmp; + constexpr TRect united(const TRect& r) const noexcept { + return { std::min(x1, r.x1), std::min(y1, r.y1), + std::max(x2, r.x2) - std::min(x1, r.x1) + 1, + std::max(y2, r.y2) - std::min(y1, r.y1) + 1 }; } - void bind(const TRect& r) - { - if (isNull() || r.isNull()) - return; - - if (right() > r.right()) - moveRight(r.right()); - if (bottom() > r.bottom()) - moveBottom(r.bottom()); - if (left() < r.left()) - moveLeft(r.left()); - if (top() < r.top()) - moveTop(r.top()); + constexpr TRect intersection(const TRect& r) const noexcept { + if (!intersects(r)) return {}; + return { std::max(x1, r.x1), std::max(y1, r.y1), + std::min(x2, r.x2) - std::max(x1, r.x1) + 1, + std::min(y2, r.y2) - std::max(y1, r.y1) + 1 }; } - void alignIn(const TRect& r, const Fw::AlignmentFlag align) + constexpr void alignIn(const TRect& r, const Fw::AlignmentFlag align) { if (align == Fw::AlignTopLeft) moveTopLeft(r.topLeft()); @@ -326,32 +194,42 @@ class TRect moveCenterRight(r.centerRight()); } - TRect& operator=(const TRect& other) = default; - bool operator==(const TRect& other) const { return (x1 == other.x1 && y1 == other.y1 && x2 == other.x2 && y2 == other.y2); } - bool operator!=(const TRect& other) const { return (x1 != other.x1 || y1 != other.y1 || x2 != other.x2 || y2 != other.y2); } + constexpr void bind(const TRect& r) + { + if (isNull() || r.isNull()) + return; + + if (right() > r.right()) + moveRight(r.right()); + if (bottom() > r.bottom()) + moveBottom(r.bottom()); + if (left() < r.left()) + moveLeft(r.left()); + if (top() < r.top()) + moveTop(r.top()); + } + + constexpr TRect& operator=(const TRect& other) noexcept = default; + constexpr bool operator!=(const TRect& other) const noexcept { return !(*this == other); } + constexpr TRect& operator|=(const TRect& other) noexcept { return *this = united(other); } + constexpr TRect& operator&=(const TRect& other) noexcept { return *this = intersection(other); } + + [[nodiscard]] constexpr bool operator==(const TRect& other) const noexcept = default; - TRect& operator|=(const TRect& other) { *this = united(other); return *this; } - TRect& operator&=(const TRect& other) { *this = intersection(other); return *this; } + friend std::ostream& operator<<(std::ostream& out, const TRect& rect) { + return out << rect.x1 << ' ' << rect.y1 << ' ' << rect.width() << ' ' << rect.height(); + } + + friend std::istream& operator>>(std::istream& in, TRect& rect) { + T x, y, w, h; + in >> x >> y >> w >> h; + rect.setRect(x, y, w, h); + return in; + } private: T x1, y1, x2, y2; }; using Rect = TRect; -using RectF = TRect; - -template -std::ostream& operator<<(std::ostream& out, const TRect& rect) -{ - out << rect.left() << " " << rect.top() << " " << rect.width() << " " << rect.height(); - return out; -} - -template -std::istream& operator>>(std::istream& in, TRect& rect) -{ - T x, y, w, h; - in >> x >> y >> w >> h; - rect.setRect(x, y, w, h); - return in; -} +using RectF = TRect; \ No newline at end of file diff --git a/src/framework/util/size.h b/src/framework/util/size.h index 1ec4abcacd..f84188066e 100644 --- a/src/framework/util/size.h +++ b/src/framework/util/size.h @@ -29,92 +29,100 @@ template class TSize { public: - TSize() : wd(-1), ht(-1) {}; - TSize(T widthHeight) : wd(widthHeight), ht(widthHeight) {}; - TSize(T width, T height) : wd(width), ht(height) {}; - TSize(const TSize& other) : wd(other.wd), ht(other.ht) {}; - - TPoint toPoint() const { return TPoint(wd, ht); } - - bool isNull() const { return wd == 0 && ht == 0; } - bool isEmpty() const { return wd < 1 || ht < 1; } - bool isValid() const { return wd >= 0 && ht >= 0; } - bool isUnset() const { return wd == -1 && ht == -1; } - - int width() const { return wd; } - int height() const { return ht; } - - void resize(T w, T h) { wd = w; ht = h; } - void setWidth(T w) { wd = w; } - void setHeight(T h) { ht = h; } - - TSize operator-() const { return TSize(-wd, -ht); } - TSize operator+(const TSize& other) const { return TSize(wd + other.wd, ht + other.ht); } - TSize& operator+=(const TSize& other) { wd += other.wd; ht += other.ht; return *this; } - TSize operator-(const TSize& other) const { return TSize(wd - other.wd, ht - other.ht); } - TSize& operator-=(const TSize& other) { wd -= other.wd; ht -= other.ht; return *this; } - TSize operator*(const TSize& other) const { return TSize(static_cast(other.wd) * wd, static_cast(ht) * other.ht); } - TSize& operator*=(const TSize& other) { wd = static_cast(other.wd) * wd; ht = static_cast(ht) * other.ht; return *this; } - TSize operator/(const TSize& other) const { return TSize(static_cast(wd) / other.wd, static_cast(ht) / other.ht); } - TSize& operator/=(const TSize& other) { static_cast(wd) /= other.wd; static_cast(ht) /= other.ht; return *this; } - TSize operator*(const float v) const { return TSize(static_cast(wd) * v, static_cast(ht) * v); } - TSize& operator*=(const float v) { wd = static_cast(wd) * v; ht = static_cast(ht) * v; return *this; } - TSize operator/(const float v) const { return TSize(static_cast(wd) / v, static_cast(ht) / v); } - TSize& operator/=(const float v) { wd /= v; ht /= v; return *this; } - - bool operator<=(const TSize& other) const { return wd <= other.wd || ht <= other.ht; } - bool operator>=(const TSize& other) const { return wd >= other.wd || ht >= other.ht; } - bool operator<(const TSize& other) const { return wd < other.wd || ht < other.ht; } - bool operator>(const TSize& other) const { return wd > other.wd || ht > other.ht; } - - TSize& operator=(const TSize& other) = default; - bool operator==(const TSize& other) const { return other.wd == wd && other.ht == ht; } - bool operator!=(const TSize& other) const { return other.wd != wd || other.ht != ht; } - - bool operator<=(const T other) const { return wd <= other || ht <= other; } - bool operator>=(const T other) const { return wd >= other || ht >= other; } - bool operator<(const T other) const { return wd < other || ht < other; } - bool operator>(const T other) const { return wd > other || ht > other; } - - TSize& operator=(const T other) { wd = other; ht = other; return *this; } - bool operator==(const T other) const { return other == wd && other == ht; } - bool operator!=(const T other) const { return other != wd || other != ht; } - - TSize expandedTo(const TSize& other) const { return TSize(std::max(wd, other.wd), std::max(ht, other.ht)); } - TSize boundedTo(const TSize& other) const { return TSize(std::min(wd, other.wd), std::min(ht, other.ht)); } - - void scale(const TSize& s, const Fw::AspectRatioMode mode) + constexpr TSize() : wd(-1), ht(-1) {} + constexpr TSize(T widthHeight) : wd(widthHeight), ht(widthHeight) {} + constexpr TSize(T width, T height) : wd(width), ht(height) {} + constexpr TSize(const TSize& other) = default; + + constexpr TPoint toPoint() const { return { wd, ht }; } + + constexpr bool isNull() const { return wd == 0 && ht == 0; } + constexpr bool isEmpty() const { return wd < 1 || ht < 1; } + constexpr bool isValid() const { return wd >= 0 && ht >= 0; } + constexpr bool isUnset() const { return wd == -1 && ht == -1; } + + constexpr T width() const { return wd; } + constexpr T height() const { return ht; } + + constexpr void resize(T w, T h) { wd = w; ht = h; } + constexpr void setWidth(T w) { wd = w; } + constexpr void setHeight(T h) { ht = h; } + + constexpr TSize operator-() const { return TSize(-wd, -ht); } + constexpr TSize operator+(const TSize& other) const { return TSize(wd + other.wd, ht + other.ht); } + constexpr TSize& operator+=(const TSize& other) { wd += other.wd; ht += other.ht; return *this; } + constexpr TSize operator-(const TSize& other) const { return TSize(wd - other.wd, ht - other.ht); } + constexpr TSize& operator-=(const TSize& other) { wd -= other.wd; ht -= other.ht; return *this; } + constexpr TSize operator*(const TSize& other) const { return TSize(static_cast(other.wd) * wd, static_cast(ht) * other.ht); } + constexpr TSize& operator*=(const TSize& other) { wd = static_cast(other.wd) * wd; ht = static_cast(ht) * other.ht; return *this; } + constexpr TSize operator/(const TSize& other) const { return TSize(static_cast(wd) / other.wd, static_cast(ht) / other.ht); } + constexpr TSize& operator/=(const TSize& other) { static_cast(wd) /= other.wd; static_cast(ht) /= other.ht; return *this; } + constexpr TSize operator*(const float v) const { return TSize(static_cast(wd) * v, static_cast(ht) * v); } + constexpr TSize& operator*=(const float v) { wd = static_cast(wd) * v; ht = static_cast(ht) * v; return *this; } + constexpr TSize operator/(const float v) const { return TSize(static_cast(wd) / v, static_cast(ht) / v); } + constexpr TSize& operator/=(const float v) { wd /= v; ht /= v; return *this; } + + constexpr bool operator<=(const TSize& other) const { return wd <= other.wd || ht <= other.ht; } + constexpr bool operator>=(const TSize& other) const { return wd >= other.wd || ht >= other.ht; } + constexpr bool operator<(const TSize& other) const { return wd < other.wd || ht < other.ht; } + constexpr bool operator>(const TSize& other) const { return wd > other.wd || ht > other.ht; } + + constexpr TSize& operator=(const TSize& other) = default; + constexpr bool operator==(const TSize& other) const { return other.wd == wd && other.ht == ht; } + constexpr bool operator!=(const TSize& other) const { return other.wd != wd || other.ht != ht; } + + constexpr bool operator<=(const T other) const { return wd <= other || ht <= other; } + constexpr bool operator>=(const T other) const { return wd >= other || ht >= other; } + constexpr bool operator<(const T other) const { return wd < other || ht < other; } + constexpr bool operator>(const T other) const { return wd > other || ht > other; } + + constexpr TSize& operator=(const T other) { wd = other; ht = other; return *this; } + constexpr bool operator==(const T other) const { return other == wd && other == ht; } + constexpr bool operator!=(const T other) const { return other != wd || other != ht; } + + constexpr TSize expandedTo(const TSize& other) const { return { std::max(wd, other.wd), std::max(ht, other.ht) }; } + constexpr TSize boundedTo(const TSize& other) const { return { std::min(wd, other.wd), std::min(ht, other.ht) }; } + + constexpr void scale(const TSize& s, const Fw::AspectRatioMode mode) { if (mode == Fw::IgnoreAspectRatio || wd == 0 || ht == 0) { wd = s.wd; ht = s.ht; + return; + } + + T rw = (s.ht * wd) / ht; + const bool useHeight = (mode == Fw::KeepAspectRatio) ? (rw <= s.wd) : (rw >= s.wd); + + if (useHeight) { + wd = rw; + ht = s.ht; } else { - bool useHeight; - T rw = (s.ht * wd) / ht; - - if (mode == Fw::KeepAspectRatio) - useHeight = (rw <= s.wd); - else // mode == Fw::KeepAspectRatioByExpanding - useHeight = (rw >= s.wd); - - if (useHeight) { - wd = rw; - ht = s.ht; - } else { - ht = (s.wd * ht) / wd; - wd = s.wd; - } + ht = (s.wd * ht) / wd; + wd = s.wd; } } - void scale(int w, int h, const Fw::AspectRatioMode mode) { scale(TSize(w, h), mode); } + constexpr void scale(int w, int h, const Fw::AspectRatioMode mode)const { scale(TSize(w, h), mode); } + + constexpr T smaller() const { return std::min(ht, wd); } + constexpr T bigger() const { return std::max(ht, wd); } - T smaller() const { return std::min(ht, wd); } - T bigger() const { return std::max(ht, wd); } + constexpr float ratio() const { return static_cast(wd) / ht; } + constexpr T area() const { return wd * ht; } + constexpr T dimension() const { return wd + ht; } - float ratio() const { return static_cast(wd) / ht; } - T area() const { return wd * ht; } - T dimension() const { return wd + ht; } + friend std::ostream& operator<<(std::ostream& out, const TSize& size) { + out << size.width() << " " << size.height(); + return out; + } + + friend std::istream& operator>>(std::istream& in, TSize& size) { + T w, h; + in >> w >> h; + size.resize(w, h); + return in; + } private: T wd, ht; @@ -122,19 +130,3 @@ class TSize using Size = TSize; using SizeF = TSize; - -template -std::ostream& operator<<(std::ostream& out, const TSize& size) -{ - out << size.width() << " " << size.height(); - return out; -} - -template -std::istream& operator>>(std::istream& in, TSize& size) -{ - T w, h; - in >> w >> h; - size.resize(w, h); - return in; -}