Geometry
The geometry classes provide the building blocks for positioning and layout inside a terminal buffer. They describe sizes, positions, rectangles, and directions, and let you derive new regions from existing ones.
Using explicit geometry types keeps layout code readable and makes it easier to build structured terminal interfaces.
Details about the example output on this page
The examples below were rendered with the dedicated documentation
helper doc/tools/geometry-reference.cpp at a fixed width of
72 terminal columns. This makes it easy to regenerate the visual
output together with the code snippets.
Usage
Deriving Layout Regions from a Canvas
The geometry types are designed to make screen layout explicit and easy to follow. Instead of calculating coordinates manually, you derive smaller regions from a larger canvas and keep each intermediate rectangle named.
const auto canvas = Rectangle{2, 3, 68, 8};
const auto header = canvas.subRectangle(Anchor::TopCenter, Size{0, 2}, Margins{0, 1, 0, 1});
const auto footer = canvas.subRectangle(Anchor::BottomCenter, Size{0, 1}, Margins{0, 1, 0, 1});
const auto body = canvas.insetBy(Margins{2, 1, 1, 1});
const auto sidebar = body.subRectangle(Anchor::Left, Size{18, 0}, Margins{0, 1, 0, 0});
const auto content = body.subRectangle(Anchor::Right, Size{body.width() - 19, 0}, Margins{0});
buffer.drawFrame(canvas, FrameStyle::Double, Color{fg::BrightWhite, bg::Inherited});
buffer.drawText("Header", header, Alignment::Center, Color{fg::BrightWhite, bg::Blue});
buffer.drawText("Sidebar", sidebar, Alignment::Center, Color{fg::BrightWhite, bg::Green});
buffer.drawText("Content", content, Alignment::Center, Color{fg::BrightWhite, bg::Magenta});
buffer.drawText("Footer", footer, Alignment::Center, Color{fg::BrightWhite, bg::BrightBlack});
Passing 0 as the width or height to
Rectangle::subRectangle()
means “use the full available size on that axis”. This is especially
useful for headers, footers, and sidebars that should stretch with the
parent rectangle.
subRectangle() + insetBy() keep layouts explicit One canvas can derive headers, sidebars, content, and footers cleanly. ╔╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤header╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╗ ║╰┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴╯║ ║╭────────────────╮ ╭─────────────────────────────────────────────╮║ ║│ │ │ │║ ║│ sidebar │ │ content │║ ║│ │ │ │║ ║╰────────────────╯ ╰─────────────────────────────────────────────╯║ ╚══════════════════════════════footer══════════════════════════════╝
Combining, Intersecting, and Testing Rectangles
Rectangle supports union and
intersection directly. This is useful when you need to compute redraw
regions, selection overlaps, or the visible area shared by two panels.
const auto a = Rectangle{4, 2, 13, 5};
const auto b = Rectangle{11, 4, 16, 5};
if (a.overlaps(b)) {
const auto dirtyRegion = a | b;
const auto sharedRegion = a & b;
buffer.drawFrame(dirtyRegion, FrameStyle::Heavy, Color{fg::BrightMagenta, bg::Inherited});
buffer.fill(sharedRegion, Char{" ", Color{fg::Inherited, bg::BrightBlack}});
buffer.drawFrame(sharedRegion, FrameStyle::Double, Color{fg::BrightGreen, bg::Inherited});
}
Use a | b when you need the combined area covered by both
rectangles. Use a & b when you need only their shared visible area.
The inexpensive
Rectangle::overlaps()
check is often the right guard before doing extra work.
A | B A & B ┏━━━━━━━━━━━┯━━━━━━━━━┓ ┌───────────┐ ┃ A │ ┃ │ A │ ┃ ┌────┼─────────┨ │ ╔════╗─────────┐ ┃ │ │ B ┃ │ ║ ║ B │ ┠──────┼────┘ ┃ └──────╚════╝ │ ┃ │ ┃ │ │ ┗━━━━━━┷━━━━━━━━━━━━━━┛ └──────────────┘ union intersection
Aligning Smaller Content and Cropping Larger Sources
There are two closely related alignment tools:
Rectangle::alignmentOffset()computes where a smaller block should start.Rectangle::alignedSource()returns anAlignedSourcewith both the effective target and the cropped source rectangle.
const auto badgeRect = Rectangle{
panel.alignmentOffset(Size{8, 3}, Alignment::BottomRight),
Size{8, 3}};
buffer.drawFrame(badgeRect, FrameStyle::Double, Color{fg::BrightCyan, bg::Inherited});
const auto aligned = panel.insetBy(Margins{1}).alignedSource(
Rectangle{0, 0, 18, 5},
Alignment::Center);
aligned.targetRect.forEach([&](const Position pos) {
const auto sourceX = aligned.sourceRect.x1() + (pos.x() - aligned.targetRect.x1());
const auto sourceY = aligned.sourceRect.y1() + (pos.y() - aligned.targetRect.y1());
// Sample from the centered source area here.
});
This saves you from writing separate “place when smaller” and “crop when larger” branches. The same alignment value handles both cases.
alignmentOffset() places smaller content; alignedSource() crops larger ╔══════╦───────────┐ ┌──────────────────┐ ┌──────────────────┐ ║ 8x3 ║ │ │ ╔══════╗ │ │ │ ╞══════╝ │ │ ║ 8x3 ║ │ │ ╔══════╡ │ │ │ ╚══════╝ │ │ ║ 8x3 ║ └──────────────────┘ └──────────────────┘ └───────────╩══════╝ TopLeft Center BottomRight ╔══════════════════════════════════════╗ ║ 234567890123456789 ║ ║ 456789012345678901 ║ ║ 678901234567890123 ║ ╚══════════════════════════════════════╝ center crop of 18x5 source
Splitting a Rectangle into Grid Cells
Rectangle::gridCells()
divides a larger canvas into evenly spaced sub-rectangles. This is
useful for dashboards, menu grids, option panels, and any row-major
layout where each cell should stay predictable.
const auto grid = Rectangle{2, 2, 68, 8};
const auto cells = grid.gridCells(2, 3, 2, 1);
for (std::size_t index = 0; index < cells.size(); ++index) {
const auto &cell = cells[index];
buffer.drawFrame(cell, FrameStyle::Light, Color{fg::BrightWhite, bg::Inherited});
buffer.drawText(
std::format("#{} {}x{}", index, cell.width(), cell.height()),
cell,
Alignment::Center);
}
Remainder pixels are distributed to the top-left cells first, and the resulting vector is returned in row-major order from left to right, then top to bottom.
If the requested number of rows, columns, and spacing no longer fits
into the rectangle, gridCells() throws std::invalid_argument.
gridCells() distributes remainder to the top-left cells and keeps ┌────────────────────┐ ┌───────────────────┐ ┌───────────────────┐ │ #0 22x4 │ │ #1 21x4 │ │ #2 21x4 │ │ │ │ │ │ │ └────────────────────┘ └───────────────────┘ └───────────────────┘ ┌────────────────────┐ ┌───────────────────┐ ┌───────────────────┐ │ #3 22x3 │ │ #4 21x3 │ │ #5 21x3 │ └────────────────────┘ └───────────────────┘ └───────────────────┘
Walking Neighbors and Frame Perimeters
Position and
Rectangle include traversal
helpers that are useful for custom layout logic, collision checks, and
procedural drawing.
const auto center = Position{12, 5};
for (const auto pos : center.cardinalFour()) {
buffer.set(pos, Char{U'+', Color{fg::BrightYellow, bg::Inherited}});
}
for (const auto pos : center.ringEight()) {
// ringEight() returns the eight surrounding positions clockwise.
}
const auto frame = Rectangle{46, 2, 18, 7};
frame.forEachInFrame([&](const Position pos, const int index) {
buffer.set(
pos,
Char{static_cast<char32_t>(U'0' + (index % 10)), Color{fg::BrightWhite, bg::Inherited}});
});
const auto currentIndex = frame.frameIndex(Position{63, 5});
The Direction wrapper fits into
the same workflow when directions come from configuration or input,
because it can convert to and from deltas and strings.
auto cursor = Position{10, 5};
cursor += Direction::fromString("east").toDelta();
Position::ringEight() Rectangle::forEachInFrame() 012345678901234567 5 8 5+7 4 9 +X+ 3 0 3+1 2 1 1 2 098765432109876543 0..7 clockwise around X index order around frame
Deriving Bounds and Keeping Cursors in Range
Two other helpers are worth using regularly:
Rectangle::bounds()creates the smallest rectangle that contains a set of positions.Rectangle::clamp()keeps a cursor or probe position inside a rectangle.
const auto points = PositionList{
Position{5, 5},
Position{9, 3},
Position{13, 6},
Position{17, 4},
Position{11, 7},
};
const auto highlight = Rectangle::bounds(points).expandedBy(Margins{1});
const auto viewport = Rectangle{46, 2, 16, 6};
const auto rawCursor = Position{66, 8};
const auto safeCursor = viewport.clamp(rawCursor);
if (viewport.contains(safeCursor)) {
buffer.set(safeCursor, Char{"@", Color{fg::BrightGreen, bg::Inherited}});
}
This pattern works well for drag selections, hit testing, and cursor movement that should stop cleanly at the viewport boundary instead of spilling outside the drawable area.
Rectangle::bounds() Rectangle::clamp() ╔═════════════╗ ┌───viewport───┐ ║ • ║ │ │ ║ •║ │ │ ║• ║ │ │ ║ • ║ │ │ ║ • ║ └──────────────@ ╚═════════════╝ raw X derive one enclosing rectangle clamped to nearest edge
Interface
-
enum class erbsland::cterm::Alignment : uint8_t
Alignment of text or graphics in a box.
Values:
-
enumerator Left
Aligned to the left edge of the box.
-
enumerator HCenter
Aligned to the horizontal center of the box.
-
enumerator Right
Aligned to the right edge of the box.
-
enumerator Top
Aligned to the top edge of the box.
-
enumerator VCenter
Aligned to the vertical center of the box.
-
enumerator Bottom
Aligned to the bottom edge of the box.
-
enumerator TopLeft
Aligned to the top-left corner of the box.
-
enumerator TopCenter
Aligned to the top-center of the box.
-
enumerator TopRight
Aligned to the top-right corner of the box.
-
enumerator CenterLeft
Aligned to the center-left of the box.
-
enumerator Center
Aligned to the center of the box.
-
enumerator CenterRight
Aligned to the center-right of the box.
-
enumerator BottomLeft
Aligned to the bottom-left corner of the box.
-
enumerator BottomCenter
Aligned to the bottom-center of the box.
-
enumerator BottomRight
Aligned to the bottom-right corner of the box.
-
enumerator HorizontalMask
Mask for extracting the horizontal component.
-
enumerator VerticalMask
Mask for extracting the vertical component.
-
enumerator Left
-
enum class erbsland::cterm::Anchor : uint8_t
Anchor describes a location inside a rectangular area using a combination of a vertical and a horizontal component.
Vertical components occupy the lower two bits (VMask).
Horizontal components occupy the next two bits (HMask). Common composite anchors (e.g. TopLeft, Center) are provided for convenience.
Values:
-
enumerator Top
Top aligned vertically.
-
enumerator VCenter
Vertically centered.
-
enumerator Bottom
Bottom aligned vertically.
-
enumerator Left
Left aligned horizontally.
-
enumerator HCenter
Horizontally centered.
-
enumerator Right
Right aligned horizontally.
-
enumerator TopLeft
-
enumerator TopCenter
-
enumerator TopRight
-
enumerator CenterLeft
-
enumerator Center
-
enumerator CenterRight
-
enumerator BottomLeft
-
enumerator BottomCenter
-
enumerator BottomRight
-
enumerator VMask
Mask for extracting the vertical component.
-
enumerator HMask
Mask for extracting the horizontal component.
-
class Direction
A direction in a 2D grid.
Public Types
-
enum Enum
The enum for the direction.
Values:
-
enumerator None
No direction.
-
enumerator North
North.
-
enumerator NorthEast
North-east.
-
enumerator East
East.
-
enumerator SouthEast
South-east.
-
enumerator South
South.
-
enumerator SouthWest
South-west.
-
enumerator West
West.
-
enumerator NorthWest
North-west.
-
enumerator _EnumCount
The number of directions enums.
-
enumerator None
Public Functions
-
constexpr Direction() noexcept = default
Create a direction with value
None.
-
~Direction() = default
Default destructor.
-
bool contains(Direction direction) const noexcept
Test if this direction contains (lexically) another direction.
Examples:
NW contains N
NW contains W
NW contains NW
NW does not contain S
NW does not contain SW (they just overlap).
-
inline constexpr std::size_t hash() const noexcept
Get a hash for this direction.
-
Position toDelta() const noexcept
Convert this direction into a position delta.
- Returns:
The unit delta for this direction, or
(0,0)forNone.
-
std::string_view toString() const noexcept
Convert this direction into a canonical lowercase string.
- Returns:
The normalized direction name.
Public Static Functions
Public Static Attributes
-
static constexpr auto cCount = static_cast<std::size_t>(_EnumCount)
The number of directions enums.
-
enum Enum
-
class Margins
Represents margins (top, right, bottom, left) around a rectangle.
Immutable-like value type for representing padding or insets.
Provides convenience constructors for uniform or symmetric margins.
Public Functions
-
Margins() = default
Default construct with uninitialized values (useful for aggregate-style construction).
-
inline explicit constexpr Margins(const int allSides)
Construct margins with the same value on all sides.
- Parameters:
allSides – Value applied to top, right, bottom and left.
-
inline constexpr Margins(const int horizontal, const int vertical)
Construct margins with separate horizontal and vertical values.
- Parameters:
horizontal – Value applied to left and right.
vertical – Value applied to top and bottom.
-
inline constexpr Margins(const int top, const int right, const int bottom, const int left)
Construct margins with individually specified sides.
- Parameters:
top – Top margin.
right – Right margin.
bottom – Bottom margin.
left – Left margin.
-
bool operator==(const Margins &other) const noexcept = default
Equality comparison (all sides must be equal).
-
inline Margins operator-() const noexcept
Unary negation producing margins with all sides negated.
Useful for reversing an inset/expansion operation.
-
inline constexpr int top() const noexcept
Get top margin.
-
inline constexpr int right() const noexcept
Get the right margin.
-
inline constexpr int bottom() const noexcept
Get the bottom margin.
-
inline constexpr int left() const noexcept
Get the left margin.
-
class Position
Represents a 2D integer position or vector (x, y).
Lightweight value type with default construction to (0,0).
Useful both for coordinates in a grid and for 2D vector arithmetic.
Public Functions
-
Position() = default
Default construct to (0,0).
-
inline constexpr Position(Coordinate x, Coordinate y) noexcept
Construct from explicit coordinates.
- Parameters:
x – The x-coordinate.
y – The y-coordinate.
-
bool operator==(const Position &other) const noexcept = default
Equality comparison (component-wise).
-
bool operator!=(const Position &other) const noexcept = default
Inequality comparison (component-wise).
-
Position operator+(const Position &other) const noexcept
Vector addition (component-wise).
- Parameters:
other – The other position to add.
- Returns:
A Position with coordinates (_x + other._x, _y + other._y).
-
Position operator-(const Position &other) const noexcept
Vector subtraction (component-wise).
- Parameters:
other – The other position to subtract.
- Returns:
A Position with coordinates (_x - other._x, _y - other._y).
-
Position &operator+=(const Position &other) noexcept
Add another position to this one in-place.
- Parameters:
other – The other position to add.
- Returns:
Reference to this position.
-
Position &operator-=(const Position &other) noexcept
Subtract another position from this one in-place.
- Parameters:
other – The other position to subtract.
- Returns:
Reference to this position.
-
inline constexpr Coordinate x() const noexcept
Get the x coordinate.
-
void setX(Coordinate x) noexcept
Set the x coordinate.
- Parameters:
x – New x value.
-
inline constexpr Coordinate y() const noexcept
Get the y coordinate.
-
void setY(Coordinate y) noexcept
Set the y coordinate.
- Parameters:
y – New y value.
-
inline constexpr std::size_t hash() const noexcept
Get a hash for this position.
This hash is designed to be fast and uniform for both 32-bit and 64-bit platforms. It is not only optimized to be used in a map but also as a source for pseudo-randomness.
-
Coordinate distanceTo(Position other) const noexcept
Manhattan (L1) distance to another position.
- Parameters:
other – The other position.
- Returns:
|x - other.x| + |y - other.y|.
-
Position componentMax(Position other) const noexcept
Component-wise maximum with another position.
- Parameters:
other – The other position.
- Returns:
A Position containing the max of each component.
-
Position componentMin(Position other) const noexcept
Component-wise minimum with another position.
- Parameters:
other – The other position.
- Returns:
A Position containing the min of each component.
-
inline std::array<Position, 4> cardinalFour() const noexcept
Get the four cardinal positions, relative to this one.
Order: right, down, left, up
Public Static Functions
-
static const std::array<Position, 4> &cardinalFourDeltas() noexcept
Get the four cardinal position deltas.
Order: right, down, left, up
-
class Rectangle
Axis-aligned rectangle represented by a top-left position and size.
Provides geometry utilities such as containment tests, expansion and iteration.
- Tested:
RectangleTest
Public Functions
-
Rectangle() = default
Construct an empty rectangle at (0,0).
-
inline constexpr Rectangle(Coordinate x, Coordinate y, Coordinate width, Coordinate height) noexcept
Construct from explicit position and size values.
-
inline constexpr Rectangle(Position pos, Size size) noexcept
Construct from position and size objects.
- Parameters:
pos – Top-left corner position.
size – Rectangle size.
-
inline constexpr Rectangle(const Position topLeft, const Position bottomRight) noexcept
Construct from a top-left and bottom-right (exclusive) corner position.
If the bottom right is left or above the top-left corner, the rectangle will be empty.
- Parameters:
topLeft – The top-left corner inside the new rectangle.
bottomRight – The bottom-right corner outside the new rectangle.
-
Rectangle operator|(const Rectangle &other) const noexcept
Merge two rectangles into a larger one that holds both rectangles.
-
Rectangle &operator|=(const Rectangle &other) noexcept
Expand this rectangle to include another rectangle.
- Parameters:
other – The other rectangle to merge.
- Returns:
Reference to this rectangle.
-
Rectangle operator&(const Rectangle &other) const noexcept
Intersect two rectangles to get only the overlapping part.
If the two rectangles don’t overlap, return an empty rectangle.
-
Rectangle &operator&=(const Rectangle &other) noexcept
Change this rectangle to the intersection of both rectangles.
If the two rectangles don’t overlap, its size will be (0,0).
-
inline void setPos(Position pos) noexcept
Set the top-left corner position.
- Parameters:
pos – New position value.
-
inline void setSize(Size size) noexcept
Set the size of the rectangle.
- Parameters:
size – New size value.
-
inline constexpr Coordinate x1() const noexcept
Left x-coordinate.
-
inline constexpr Coordinate y1() const noexcept
Top y-coordinate.
-
inline constexpr Coordinate x2() const noexcept
Right x-coordinate (exclusive).
-
inline constexpr Coordinate y2() const noexcept
Bottom y-coordinate (exclusive).
-
inline constexpr Position topLeft() const noexcept
Top-left corner position.
Is equivalent to
pos().
-
inline constexpr Position topRight() const noexcept
Top-right corner position (x-coordinate exclusive).
-
inline constexpr Position bottomLeft() const noexcept
Bottom-left corner position (y-coordinate exclusive).
-
inline constexpr Position bottomRight() const noexcept
Bottom-right corner position (x-coordinate exclusive, y-coordinate exclusive).
-
Position anchor(Anchor anchor = Anchor::TopLeft) const noexcept
Position of a given anchor within this rectangle.
- Parameters:
anchor – Anchor to query.
- Returns:
The position inside this rectangle matching the requested anchor.
-
inline Position center() const noexcept
Center position.
This is equal to the position of the
Anchor::Centeranchor.
-
bool contains(Position testedPosition) const noexcept
Check if a position is inside the rectangle.
- Parameters:
testedPosition – Position to test.
- Returns:
trueif the position lies inside the rectangle bounds.
-
bool contains(Rectangle testedRectangle) const noexcept
Checks if another rectangle fits into this one.
Only
trueif every position of the tested rectangle is inside this one.- Parameters:
testedRectangle – The rectangle to test for containment.
- Returns:
trueif the tested rectangle is fully contained within this one.
-
bool overlaps(Rectangle testedRectangle) const noexcept
Check if another rectangle overlaps this one.
Overlapping is when both rectangles share at least one position.
- Parameters:
testedRectangle – The rectangle to test for overlap.
-
bool isFrame(Position testedPosition) const noexcept
Check if a position lies on the rectangle frame.
- Parameters:
testedPosition – Position to test.
- Returns:
trueif the position lies on the outer frame of the rectangle.
-
inline constexpr std::size_t hash() const noexcept
Get a hash for this rectangle.
-
Position clamp(Position position) const noexcept
Clamp a position to this rectangle.
- Parameters:
position – The position to clamp.
- Returns:
The clamped position where (x1 <= position.x <= x2) && (y1 <= position.y <= y2)
-
Rectangle expandedBy(Margins margins) const noexcept
Create a rectangle expanded by the provided margins.
- Parameters:
margins – Margins to apply; positive values expand outward.
- Returns:
The expanded rectangle.
-
Rectangle insetBy(Margins margins) const noexcept
Create a rectangle inset by the provided margins.
- Parameters:
margins – Margins to remove from each side.
- Returns:
The inset rectangle.
-
Rectangle subRectangle(Anchor anchor, Size size, Margins margins) const noexcept
Create a sub-rectangle inside this rectangle.
- Parameters:
anchor – The anchor of the rectangle.
size – The size. Zero means full width/height.
margins – The margins around the sub rectangle.
- Returns:
The aligned sub-rectangle.
-
Position alignmentOffset(Size contentSize, Alignment alignment) const noexcept
Compute the position for content aligned inside this rectangle.
If
contentSizeis larger than this rectangle on an axis, the returned position on that axis lies beforetopLeft()on that axis.- Parameters:
contentSize – The aligned content size.
alignment – The alignment for the content.
- Returns:
The aligned content position relative to the global coordinate space.
-
AlignedSource alignedSource(Rectangle sourceRect, Alignment alignment) const noexcept
Align a source rectangle inside this rectangle and crop the larger side according to the alignment.
If the source is smaller than this rectangle on an axis, the returned target rectangle is moved inside this rectangle. If the source is larger on an axis, the returned source rectangle is cropped on that axis.
- Parameters:
sourceRect – The source rectangle before alignment and cropping.
alignment – The alignment used for placement or cropping.
- Returns:
The effective target rectangle and source rectangle after alignment.
-
int64_t frameIndex(Position testedPosition) const noexcept
Get the clockwise border index for a frame position.
The top-left corner has index
0, then the index increases clockwise around the perimeter. Degenerate rectangles with width or height1still produce a continuous index sequence.- Parameters:
testedPosition – The position on the frame.
- Returns:
The clockwise border index, or
-1if the position is not on the frame.
-
Direction frameDirection(Position testedPosition) const noexcept
Get the frame direction for a given position in this rectangle.
- Returns:
The direction of the frame at the given position, or Direction::None if the position is not on the frame.
-
auto gridCells(int rows, int columns, Coordinate horizontalSpacing = 0, Coordinate verticalSpacing = 0) const -> std::vector<Rectangle>
Divide this rectangle into equally spaced grid cells.
Each cell must be at least 1x1 in size, if this isn’t possible,
std::invalid_argumentis thrown.- Parameters:
rows – The number of rows. Minimum 1.
columns – The number of columns. Minimum 1
horizontalSpacing – The spacing between cells horizontally.
verticalSpacing – The spacing between cells vertically.
- Throws:
std::invalid_argument – if rows or columns are less than 1 or the chosen division is impossible.
- Returns:
A vector of rectangles representing the grid cells from left to right, top to bottom.
-
struct AlignedSource
Effective source and target rectangles after alignment.
-
class Size
A non-negative 2D size (width × height).
Width and height are clamped to be >= 0.
Many operations assume a grid indexed from (0,0) to (width-1,height-1).
Public Functions
-
Size() = default
Construct a zero size (0 × 0).
-
inline constexpr Size(Coordinate width, Coordinate height) noexcept
Construct a size from explicit width and height.
Negative inputs are clamped to 0.
- Parameters:
width – The desired width (clamped to >= 0).
height – The desired height (clamped to >= 0).
-
inline constexpr Size(Position pos1, Position pos2) noexcept
Construct a size from the axis-aligned distance between two positions.
Note
The order of the positions does not matter; absolute differences are used.
- Parameters:
pos1 – First position.
pos2 – Second position.
-
bool operator==(const Size &other) const noexcept = default
Equality comparison on width and height.
-
bool operator!=(const Size &other) const noexcept = default
Inequality comparison on width and height.
-
inline Size operator+(const Size &other) const noexcept
Add two sizes.
- Parameters:
other – The size to add.
- Returns:
The component-wise sum.
-
inline Size operator-(const Size &other) const noexcept
Subtract two sizes.
- Parameters:
other – The size to subtract.
- Returns:
The component-wise difference, clamped to non-negative values by the constructor.
-
inline constexpr Coordinate width() const noexcept
Get the width (>= 0).
-
inline void setWidth(Coordinate width) noexcept
Set the width.
Negative values are clamped to 0.
- Parameters:
width – New width (clamped to >= 0).
-
inline constexpr Coordinate height() const noexcept
Get the height (>= 0).
-
inline void setHeight(Coordinate height) noexcept
Set the height.
Negative values are clamped to 0.
- Parameters:
height – New height (clamped to >= 0).
-
Position anchor(Anchor anchor) const noexcept
Compute a position inside the rectangle defined by this size for a given anchor.
Bottom-right resolves to (width-1, height-1), top-left to (0,0), etc.
- Parameters:
anchor – The anchor describing the target corner/edge/center.
- Returns:
The position inside the [0,width-1]×[0,height-1] grid (or (0,0) for empty dimensions).
-
Position alignmentOffset(Size contentSize, Alignment alignment) const noexcept
Compute the offset for content aligned inside this size.
If
contentSizeis larger than this size on an axis, the returned offset on that axis is negative.- Parameters:
contentSize – The aligned content size.
alignment – The alignment for the content.
- Returns:
The zero-based offset for placing the content inside this size.
-
inline constexpr bool isZero() const noexcept
Test if this size is zero.
-
inline bool fitsInto(const Size other) const noexcept
Check if this size fits completely into another size (component-wise <=).
- Parameters:
other – The candidate container size.
- Returns:
true if width <= other.width and height <= other.height.
-
inline bool isInRange(const Size minimum, const Size maximum) const noexcept
Test if the width and height of this size is in the given range.
- Parameters:
minimum – The minimum size.
maximum – The maximum size.
- Returns:
true If this size is in the range
minimum-maximum.
-
inline constexpr bool contains(const Position &pos) const noexcept
Check if a position lies strictly inside the bounds [0,width) × [0,height).
- Parameters:
pos – The position to test.
- Returns:
true if 0 <= x < width and 0 <= y < height.
-
inline Size componentMax(const Size other) const noexcept
Component-wise maximum with another size.
- Parameters:
other – Other size.
- Returns:
A size whose width is max(this.width, other.width) and height is max(this.height, other.height).
-
inline Size componentMin(const Size other) const noexcept
Component-wise minimum with another size.
- Parameters:
other – Other size.
- Returns:
A size whose width is min(this.width, other.width) and height is min(this.height, other.height).
-
inline Size componentClamp(const Size minimum, const Size maximum) const noexcept
Component-wise clamp with a minimum and maximum size.
Warning
If minimum.width > maximum.width or minimum.height > maximum.height, the behavior is undefined.
- Parameters:
minimum – The minimum size.
maximum – The maximum size.
- Returns:
a size (min.width <= width <= max.width, min.height <= height <= max.height)
-
inline Position clamp(Position position) const noexcept
Clamp a position inside this size.
The resulting position is at least (0, 0) and less than (width, height).
-
inline int area() const noexcept
Compute the area (width * height).
- Returns:
The area. Note: returns 0 if either dimension is 0.