Files
2026-08-16 18:24:52 +07:00

436 lines
12 KiB
C++

// This file is part of VSTGUI. It is subject to the license terms
// in the LICENSE file found in the top-level directory of this
// distribution and at http://github.com/steinbergmedia/vstgui/LICENSE
#pragma once
#include "vstguibase.h"
#include "cpoint.h"
#include <cmath>
namespace VSTGUI {
//-----------------------------------------------------------------------------
//! @brief Rect structure
//-----------------------------------------------------------------------------
struct CRect
{
constexpr CRect () = default;
inline constexpr CRect (CCoord left, CCoord top, CCoord right, CCoord bottom);
inline constexpr CRect (const CRect& r) = default;
inline CRect& operator = (const CRect& r) = default;
inline CRect (const CPoint& origin, const CPoint& size);
inline CRect& operator () (CCoord left, CCoord top, CCoord right, CCoord bottom);
inline constexpr bool operator != (const CRect& other) const;
inline constexpr bool operator == (const CRect& other) const;
inline constexpr CCoord getWidth () const;
inline constexpr CCoord getHeight () const;
inline CRect& setWidth (CCoord width);
inline CRect& setHeight (CCoord height);
inline CPoint getTopLeft () const;
inline CPoint getTopRight () const;
inline CPoint getBottomLeft () const;
inline CPoint getBottomRight () const;
inline CPoint getTopCenter () const;
inline CPoint getBottomCenter () const;
inline CPoint getLeftCenter () const;
inline CPoint getRightCenter () const;
inline CRect& setTopLeft (const CPoint& inPoint);
inline CRect& setTopRight (const CPoint& inPoint);
inline CRect& setBottomLeft (const CPoint& inPoint);
inline CRect& setBottomRight (const CPoint& inPoint);
inline CPoint getCenter () const;
inline CPoint getSize () const;
inline CRect& setSize (const CPoint& size);
inline CRect& offset (CCoord c);
inline CRect& offset (CCoord x, CCoord y);
inline CRect& inset (CCoord deltaX, CCoord deltaY);
inline CRect& extend (CCoord deltaX, CCoord deltaY);
inline CRect& moveTo (CCoord x, CCoord y);
inline CRect& inset (const CPoint& p);
inline CRect& extend (const CPoint& p);
inline CRect& moveTo (const CPoint& p);
inline CRect& offset (const CPoint& p);
inline CRect& offsetInverse (const CPoint& p);
/** Checks if point is inside this rect */
inline constexpr bool pointInside (const CPoint& where) const;
inline constexpr bool isEmpty () const;
inline constexpr bool rectOverlap (const CRect& rect) const;
/** Checks if rect is inside this rect */
inline constexpr bool rectInside (const CRect& rect) const;
inline CRect& bound (const CRect& rect);
inline CRect& unite (const CRect& rect);
inline CRect& normalize ();
inline CRect& originize ();
/** moves this rect to the center of r */
inline CRect& centerInside (const CRect& r);
inline CRect& makeIntegral ();
CCoord left {0.};
CCoord top {0.};
CCoord right {0.};
CCoord bottom {0.};
};
//------------------------------------------------------------------------
inline constexpr CRect::CRect (CCoord left, CCoord top, CCoord right, CCoord bottom)
: left (left), top (top), right (right), bottom (bottom)
{}
//------------------------------------------------------------------------
inline CRect::CRect (const CPoint& origin, const CPoint& size)
{
setTopLeft (origin);
setSize (size);
}
//------------------------------------------------------------------------
inline CRect& CRect::operator () (CCoord _left, CCoord _top, CCoord _right, CCoord _bottom)
{
if (_left < _right)
{
left = _left;
right = _right;
}
else
{
left = _right;
right = _left;
}
if (_top < _bottom)
{
top = _top;
bottom = _bottom;
}
else
{
top = _bottom;
bottom = _top;
}
return *this;
}
//------------------------------------------------------------------------
inline constexpr bool CRect::operator != (const CRect& other) const
{
return (left != other.left || right != other.right ||
top != other.top || bottom != other.bottom);
}
//------------------------------------------------------------------------
inline constexpr bool CRect::operator == (const CRect& other) const
{
return (left == other.left && right == other.right &&
top == other.top && bottom == other.bottom);
}
//------------------------------------------------------------------------
inline constexpr CCoord CRect::getWidth () const
{
return right - left;
}
//------------------------------------------------------------------------
inline constexpr CCoord CRect::getHeight () const
{
return bottom - top;
}
//------------------------------------------------------------------------
inline CRect& CRect::setWidth (CCoord width)
{
right = left + width;
return *this;
}
//------------------------------------------------------------------------
inline CRect& CRect::setHeight (CCoord height)
{
bottom = top + height;
return *this;
}
//------------------------------------------------------------------------
inline CRect& CRect::offset (CCoord c)
{
return offset (c, c);
}
//------------------------------------------------------------------------
inline CRect& CRect::offset (CCoord x, CCoord y)
{
left += x;
right += x;
top += y;
bottom += y;
return *this;
}
//------------------------------------------------------------------------
inline CRect& CRect::inset (CCoord deltaX, CCoord deltaY)
{
left += deltaX;
right -= deltaX;
top += deltaY;
bottom -= deltaY;
return *this;
}
//------------------------------------------------------------------------
inline CRect& CRect::extend (CCoord deltaX, CCoord deltaY)
{
return inset (-deltaX, -deltaY);
}
//------------------------------------------------------------------------
inline CRect& CRect::moveTo (CCoord x, CCoord y)
{
CCoord vDiff = y - top;
CCoord hDiff = x - left;
top += vDiff;
bottom += vDiff;
left += hDiff;
right += hDiff;
return *this;
}
//------------------------------------------------------------------------
inline constexpr bool CRect::isEmpty () const
{
return right <= left || bottom <= top;
}
//------------------------------------------------------------------------
inline constexpr bool CRect::rectOverlap (const CRect& rect) const
{
return right >= rect.left && left <= rect.right && bottom >= rect.top && top <= rect.bottom;
}
//------------------------------------------------------------------------
inline CRect& CRect::bound (const CRect& rect)
{
if (left < rect.left)
left = rect.left;
if (top < rect.top)
top = rect.top;
if (right > rect.right)
right = rect.right;
if (bottom > rect.bottom)
bottom = rect.bottom;
if (bottom < top)
bottom = top;
if (right < left)
right = left;
return *this;
}
//------------------------------------------------------------------------
inline CRect& CRect::normalize ()
{
if (left > right)
std::swap (left, right);
if (top > bottom)
std::swap (top, bottom);
return *this;
}
//------------------------------------------------------------------------
inline CRect& CRect::originize ()
{
return offset (-left, -top);
}
//-----------------------------------------------------------------------------
inline CRect& CRect::unite (const CRect& rect)
{
if (left > rect.left)
left = rect.left;
if (right < rect.right)
right = rect.right;
if (top > rect.top)
top = rect.top;
if (bottom < rect.bottom)
bottom = rect.bottom;
return *this;
}
//------------------------------------------------------------------------
inline CRect& CRect::makeIntegral ()
{
left = std::floor (left);
right = std::ceil (right);
top = std::floor (top);
bottom = std::ceil (bottom);
return *this;
}
//-----------------------------------------------------------------------------
inline constexpr bool CRect::pointInside (const CPoint& where) const
{
return where.x >= left && where.x < right && where.y >= top && where.y < bottom;
}
//-----------------------------------------------------------------------------
inline constexpr bool CRect::rectInside (const CRect& rect) const
{
return rect.left >= left && rect.right <= right && rect.top >= top && rect.bottom <= bottom;
}
//-----------------------------------------------------------------------------
inline CPoint CRect::getTopLeft () const
{
return {left, top};
}
//-----------------------------------------------------------------------------
inline CPoint CRect::getTopRight () const
{
return {right, top};
}
//-----------------------------------------------------------------------------
inline CPoint CRect::getBottomLeft () const
{
return {left, bottom};
}
//-----------------------------------------------------------------------------
inline CPoint CRect::getBottomRight () const
{
return {right, bottom};
}
//-----------------------------------------------------------------------------
inline CPoint CRect::getTopCenter () const
{
auto p = getTopLeft ();
p.x += getWidth () * 0.5;
return p;
}
//-----------------------------------------------------------------------------
inline CPoint CRect::getBottomCenter () const
{
auto p = getBottomLeft ();
p.x += getWidth () * 0.5;
return p;
}
//-----------------------------------------------------------------------------
inline CPoint CRect::getLeftCenter () const
{
auto p = getTopLeft ();
p.y += getHeight () * 0.5;
return p;
}
//-----------------------------------------------------------------------------
inline CPoint CRect::getRightCenter () const
{
auto p = getTopRight ();
p.y += getHeight () * 0.5;
return p;
}
//-----------------------------------------------------------------------------
inline CRect& CRect::setTopLeft (const CPoint& inPoint)
{
left = inPoint.x;
top = inPoint.y;
return *this;
}
//-----------------------------------------------------------------------------
inline CRect& CRect::setTopRight (const CPoint& inPoint)
{
right = inPoint.x;
top = inPoint.y;
return *this;
}
//-----------------------------------------------------------------------------
inline CRect& CRect::setBottomLeft (const CPoint& inPoint)
{
left = inPoint.x;
bottom = inPoint.y;
return *this;
}
//-----------------------------------------------------------------------------
inline CRect& CRect::setBottomRight (const CPoint& inPoint)
{
right = inPoint.x;
bottom = inPoint.y;
return *this;
}
//-----------------------------------------------------------------------------
inline CPoint CRect::getCenter () const
{
CPoint myPoint (left + getWidth () / 2., top + getHeight () / 2.);
return myPoint;
}
//-----------------------------------------------------------------------------
inline CPoint CRect::getSize () const
{
CPoint myPoint (getWidth (), getHeight ());
return myPoint;
}
//-----------------------------------------------------------------------------
inline CRect& CRect::setSize (const CPoint& size)
{
setWidth (size.x);
return setHeight (size.y);
}
//-----------------------------------------------------------------------------
inline CRect& CRect::centerInside (const CRect& r)
{
CPoint cp = r.getCenter ();
CPoint cp2 = getCenter ();
return offset (cp.x - cp2.x, cp.y - cp2.y);
}
//-----------------------------------------------------------------------------
inline CRect& CRect::offset (const CPoint& p)
{
return offset (p.x, p.y);
}
//-----------------------------------------------------------------------------
inline CRect& CRect::inset (const CPoint& p)
{
return inset (p.x, p.y);
}
//-----------------------------------------------------------------------------
inline CRect& CRect::extend (const CPoint& p)
{
return extend (p.x, p.y);
}
//-----------------------------------------------------------------------------
inline CRect& CRect::moveTo (const CPoint& p)
{
return moveTo (p.x, p.y);
}
//-----------------------------------------------------------------------------
inline CRect& CRect::offsetInverse (const CPoint& p)
{
return offset (-p.x, -p.y);
}
} // VSTGUI