The Battle for Wesnoth  1.19.8+dev
rect.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2024
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 <SDL2/SDL_rect.h>
26 
27 #include <algorithm>
28 
29 namespace sdl
30 {
31 
32 constexpr const SDL_Rect empty_rect { 0, 0, 0, 0 };
33 
34 } // namespace sdl
35 
36 bool operator==(const SDL_Rect& a, const SDL_Rect& b);
37 bool operator!=(const SDL_Rect& a, const SDL_Rect& b);
38 
39 std::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  */
48 struct rect : SDL_Rect
49 {
50 public:
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 SDL_Rect& r) const;
120 
121  /** Whether the given rectangle and this rectangle overlap. */
122  bool overlaps(const SDL_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 SDL_Rect& r) const;
129 
130  /** Minimally expand this rect to fully contain another. */
131  rect& expand_to_cover(const SDL_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 SDL_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 SDL_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 
173 std::ostream& operator<<(std::ostream&, const rect&);
174 
175 namespace sdl
176 {
177 #ifdef __cpp_concepts
178 template<typename T>
179 concept 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. */
188 constexpr SDL_FRect precise_subrect(const Rectangle auto& base, const SDL_FPoint& tl, const SDL_FPoint& br)
189 #else
190 template<typename Rect>
191 constexpr 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
int w
constexpr std::string_view br
A Help markup tag corresponding to a linebreak.
Definition: markup.hpp:35
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
bool operator==(const SDL_Rect &a, const SDL_Rect &b)
Definition: rect.cpp:22
std::ostream & operator<<(std::ostream &s, const SDL_Rect &rect)
Definition: rect.cpp:32
bool operator!=(const SDL_Rect &a, const SDL_Rect &b)
Definition: rect.cpp:27
Holds a 2D point.
Definition: point.hpp:25
An abstract description of a rectangle with integer coordinates.
Definition: rect.hpp:49
constexpr point center() const
The center point of the rectangle, accounting for origin.
Definition: rect.hpp:106
bool empty() const
False if both w and h are > 0, true otherwise.
Definition: rect.cpp:48
rect & expand_to_cover(const SDL_Rect &r)
Minimally expand this rect to fully contain another.
Definition: rect.cpp:85
rect shifted_by(int x, int y) const
Returns a new rectangle shifted by the given relative position.
Definition: rect.cpp:111
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:124
constexpr rect & operator*=(int s)
Definition: rect.hpp:79
rect minimal_cover(const SDL_Rect &r) const
Calculates the minimal rectangle that completely contains both this rectangle and the given rectangle...
Definition: rect.cpp:78
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:53
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:38
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
void clip(const SDL_Rect &r)
Clip this rectangle by the given rectangle.
Definition: rect.cpp:100
constexpr int area() const
The area of this rectangle, in square pixels.
Definition: rect.hpp:103
constexpr rect & operator/=(int s)
Definition: rect.hpp:93
constexpr point size() const
Definition: rect.hpp:67
void shift(const point &p)
Shift the rectangle by the given relative position.
Definition: rect.cpp:105
constexpr rect operator*(int s) const
Definition: rect.hpp:74
rect intersect(const SDL_Rect &r) const
Calculates the intersection of this rectangle and another; that is, the maximal rectangle that is con...
Definition: rect.cpp:91
bool overlaps(const SDL_Rect &r) const
Whether the given rectangle and this rectangle overlap.
Definition: rect.cpp:73
mock_party p
static map_location::direction s
#define h
#define b