The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
rect.hpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2014 - 2025
3 by Mark de Wever <koraq@xs4all.nl>
4 Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY.
12
13 See the COPYING file for more details.
14*/
15
16#pragma once
17
18/**
19 * @file
20 * Contains the SDL_Rect helper code.
21 */
22
23#include "sdl/point.hpp"
24
25#include <SDL3/SDL_rect.h>
26
27#include <algorithm>
28
29namespace sdl
30{
31
32constexpr const SDL_Rect empty_rect { 0, 0, 0, 0 };
33
34} // namespace sdl
35
36bool operator==(const SDL_Rect& a, const SDL_Rect& b);
37bool operator!=(const SDL_Rect& a, const SDL_Rect& b);
38
39std::ostream& operator<<(std::ostream& s, const SDL_Rect& rect);
40
41/**
42 * An abstract description of a rectangle with integer coordinates.
43 *
44 * This is a thin wrapper over SDL_Rect, furnished with utility functions.
45 *
46 * As for SDL_Rect, member variables x, y, w and h are public.
47 */
48struct rect : SDL_Rect
49{
50public:
51 /** Explicitly initialize rects to 0. */
52 constexpr rect() : SDL_Rect{0, 0, 0, 0} {}
53
54 /** There's nothing extra when converting an SDL_Rect. */
55 constexpr rect(const SDL_Rect& r) : SDL_Rect{r} {}
56
57 /** Specify via (x, y, w, h). */
58 constexpr rect(int x, int y, int w, int h) : SDL_Rect{x, y, w, h} {}
59
60 /** Specify via top-left corner position and size. */
61 constexpr rect(const point& pos, const point& size)
62 : SDL_Rect{pos.x, pos.y, size.x, size.y}
63 {}
64
65 // subcomponent access
66 constexpr point origin() const { return {x, y}; }
67 constexpr point size() const { return {w, h}; }
68
69 // Comparisons
70 bool operator==(const rect& r) const;
71 bool operator==(const SDL_Rect& r) const;
72
73 // Scalar multiplication and division
74 constexpr rect operator*(int s) const
75 {
76 return {x * s, y * s, w * s, h * s};
77 }
78
79 constexpr rect& operator*=(int s)
80 {
81 x *= s;
82 y *= s;
83 w *= s;
84 h *= s;
85 return *this;
86 }
87
88 constexpr rect operator/(int s) const
89 {
90 return {x / s, y / s, w / s, h / s};
91 }
92
93 constexpr rect& operator/=(int s)
94 {
95 x /= s;
96 y /= s;
97 w /= s;
98 h /= s;
99 return *this;
100 }
101
102 /** The area of this rectangle, in square pixels. */
103 constexpr int area() const { return w * h; }
104
105 /** The center point of the rectangle, accounting for origin. */
106 constexpr point center() const
107 {
108 return {x + w / 2, y + h / 2};
109 }
110
111 /** False if both w and h are > 0, true otherwise. */
112 bool empty() const;
113
114 /** Whether the given point lies within the rectangle. */
115 bool contains(int x, int y) const;
116 bool contains(const point& p) const;
117
118 /** Whether the given rectangle is completely contained by this one. */
119 bool contains(const rect& r) const;
120
121 /** Whether the given rectangle and this rectangle overlap. */
122 bool overlaps(const rect& r) const;
123
124 /**
125 * Calculates the minimal rectangle that completely contains both
126 * this rectangle and the given rectangle.
127 */
128 rect minimal_cover(const rect& r) const;
129
130 /** Minimally expand this rect to fully contain another. */
131 rect& expand_to_cover(const rect& r);
132
133 /**
134 * Calculates the intersection of this rectangle and another;
135 * that is, the maximal rectangle that is contained by both.
136 */
137 rect intersect(const rect& r) const;
138
139 /**
140 * Clip this rectangle by the given rectangle.
141 *
142 * This rectangle will be reduced to the intersection of both rectangles.
143 */
144 void clip(const rect& r);
145
146 /**
147 * Shift the rectangle by the given relative position.
148 *
149 * The point's X and Y coordinates will be added to the rectangle's.
150 */
151 void shift(const point& p);
152
153 /** Returns a new rectangle shifted by the given relative position. */
154 rect shifted_by(int x, int y) const;
155 rect shifted_by(const point& p) const;
156
157 /** Returns a new rectangle with @a dx horizontal padding and @a dy vertical padding. */
158 constexpr rect padded_by(int dx, int dy) const
159 {
160 return { x - dx, y - dy, w + dx * 2, h + dy * 2 };
161 }
162
163 /** Returns a new rectangle with equal @a amount horizontal and vertical padding. */
164 constexpr rect padded_by(int amount) const
165 {
166 return padded_by(amount, amount);
167 }
168
169 /** Returns the proper point that corresponds to the given [0.0, 1.0] coordinates. */
170 point point_at(double x, double y) const;
171};
172
173std::ostream& operator<<(std::ostream&, const rect&);
174
175namespace sdl
176{
177#ifdef __cpp_concepts
178template<typename T>
179concept Rectangle = requires(T r)
180{
181 r.x;
182 r.y;
183 r.w;
184 r.h;
185};
186
187/** Returns the sub-rect bounded to the top left and bottom right by the given [0.0, 1.0] coordinates. */
188constexpr SDL_FRect precise_subrect(const Rectangle auto& base, const SDL_FPoint& tl, const SDL_FPoint& br)
189#else
190template<typename Rect>
191constexpr SDL_FRect precise_subrect(const Rect& base, const SDL_FPoint& tl, const SDL_FPoint& br)
192#endif
193{
194 const auto point_at = [&base](auto x, auto y) -> SDL_FPoint {
195 return {
196 base.x + base.w * std::clamp(x, 0.0f, 1.0f),
197 base.y + base.h * std::clamp(y, 0.0f, 1.0f)
198 };
199 };
200
201 SDL_FPoint p1 = point_at(tl.x, tl.y);
202 SDL_FPoint p2 = point_at(br.x, br.y);
203
204 return { p1.x, p1.y, p2.x - p1.x, p2.y - p1.y };
205}
206
207} // namespace sdl
constexpr const SDL_Rect empty_rect
Definition rect.hpp:32
constexpr SDL_FRect precise_subrect(const Rect &base, const SDL_FPoint &tl, const SDL_FPoint &br)
Definition rect.hpp:191
int w
Definition pathfind.cpp:188
bool operator==(const SDL_Rect &a, const SDL_Rect &b)
Definition rect.cpp:23
std::ostream & operator<<(std::ostream &s, const SDL_Rect &rect)
Definition rect.cpp:33
bool operator!=(const SDL_Rect &a, const SDL_Rect &b)
Definition rect.cpp:28
Holds a 2D point.
Definition point.hpp:25
An abstract description of a rectangle with integer coordinates.
Definition rect.hpp:49
void clip(const rect &r)
Clip this rectangle by the given rectangle.
Definition rect.cpp:101
constexpr point center() const
The center point of the rectangle, accounting for origin.
Definition rect.hpp:106
rect minimal_cover(const rect &r) const
Calculates the minimal rectangle that completely contains both this rectangle and the given rectangle...
Definition rect.cpp:79
bool empty() const
False if both w and h are > 0, true otherwise.
Definition rect.cpp:49
rect shifted_by(int x, int y) const
Returns a new rectangle shifted by the given relative position.
Definition rect.cpp:112
constexpr point origin() const
Definition rect.hpp:66
constexpr rect(const SDL_Rect &r)
There's nothing extra when converting an SDL_Rect.
Definition rect.hpp:55
point point_at(double x, double y) const
Returns the proper point that corresponds to the given [0.0, 1.0] coordinates.
Definition rect.cpp:125
constexpr rect & operator*=(int s)
Definition rect.hpp:79
constexpr rect(int x, int y, int w, int h)
Specify via (x, y, w, h).
Definition rect.hpp:58
constexpr rect operator/(int s) const
Definition rect.hpp:88
constexpr rect()
Explicitly initialize rects to 0.
Definition rect.hpp:52
bool contains(int x, int y) const
Whether the given point lies within the rectangle.
Definition rect.cpp:54
constexpr rect padded_by(int amount) const
Returns a new rectangle with equal amount horizontal and vertical padding.
Definition rect.hpp:164
bool operator==(const rect &r) const
Definition rect.cpp:39
constexpr rect padded_by(int dx, int dy) const
Returns a new rectangle with dx horizontal padding and dy vertical padding.
Definition rect.hpp:158
constexpr rect(const point &pos, const point &size)
Specify via top-left corner position and size.
Definition rect.hpp:61
constexpr int area() const
The area of this rectangle, in square pixels.
Definition rect.hpp:103
rect intersect(const rect &r) const
Calculates the intersection of this rectangle and another; that is, the maximal rectangle that is con...
Definition rect.cpp:92
constexpr point size() const
Definition rect.hpp:67
void shift(const point &p)
Shift the rectangle by the given relative position.
Definition rect.cpp:106
constexpr rect & operator/=(int s)
Definition rect.hpp:93
rect & expand_to_cover(const rect &r)
Minimally expand this rect to fully contain another.
Definition rect.cpp:86
constexpr rect operator*(int s) const
Definition rect.hpp:74
bool overlaps(const rect &r) const
Whether the given rectangle and this rectangle overlap.
Definition rect.cpp:74
mock_party p
static map_location::direction s
#define h
#define b