Mir
dimensions.h
Go to the documentation of this file.
1/*
2 * Copyright © Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 2 or 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef MIR_GEOMETRY_DIMENSIONS_H_
18#define MIR_GEOMETRY_DIMENSIONS_H_
19
20#include "forward.h"
21
22#include <iosfwd>
23#include <type_traits>
24#include <cstdint>
25
26namespace mir
27{
28namespace geometry
29{
30namespace generic
31{
32template<typename T, typename Tag>
33/// Wraps a geometry value and prevents it from being accidentally used for invalid operations (such as setting a
34/// width to a height or adding two x positions together). Of course, explicit casts are possible to get around
35/// these restrictions (see the as_*() functions).
36struct Value
37{
38 using ValueType = T;
39 using TagType = Tag;
40
41 template <typename Q = T>
42 constexpr typename std::enable_if<std::is_integral<Q>::value, int>::type as_int() const
43 {
44 return this->value;
45 }
46
47 template <typename Q = T>
48 constexpr typename std::enable_if<std::is_integral<Q>::value, uint32_t>::type as_uint32_t() const
49 {
50 return this->value;
51 }
52
53 constexpr T as_value() const noexcept
54 {
55 return value;
56 }
57
58 constexpr Value() noexcept : value{} {}
59
60 Value& operator=(Value const& that) noexcept
61 {
62 value = that.value;
63 return *this;
64 }
65
66 constexpr Value(Value const& that) noexcept
67 : value{that.value}
68 {
69 }
70
71 template<typename U>
72 explicit constexpr Value(Value<U, Tag> const& value) noexcept
73 : value{static_cast<T>(value.as_value())}
74 {
75 }
76
77 template<typename U, typename std::enable_if<std::is_scalar<U>::value, bool>::type = true>
78 explicit constexpr Value(U const& value) noexcept
79 : value{static_cast<T>(value)}
80 {
81 }
82
83 inline constexpr auto operator == (Value<T, Tag> const& rhs) const -> bool
84 {
85 return value == rhs.as_value();
86 }
87
88 inline constexpr auto operator != (Value<T, Tag> const& rhs) const -> bool
89 {
90 return value != rhs.as_value();
91 }
92
93 inline constexpr auto operator <= (Value<T, Tag> const& rhs) const -> bool
94 {
95 return value <= rhs.as_value();
96 }
97
98 inline constexpr auto operator >= (Value<T, Tag> const& rhs) const -> bool
99 {
100 return value >= rhs.as_value();
101 }
102
103 inline constexpr auto operator < (Value<T, Tag> const& rhs) const -> bool
104 {
105 return value < rhs.as_value();
106 }
107
108 inline constexpr auto operator > (Value<T, Tag> const& rhs) const -> bool
109 {
110 return value > rhs.as_value();
111 }
112
113protected:
115};
116
117template<typename T, typename Tag>
118std::ostream& operator<<(std::ostream& out, Value<T, Tag> const& value)
119{
120 out << value.as_value();
121 return out;
122}
123
124// Adding deltas is fine
125template<typename T>
126inline constexpr DeltaX<T> operator+(DeltaX<T> lhs, DeltaX<T> rhs){ return DeltaX<T>(lhs.as_value() + rhs.as_value()); }
127template<typename T>
128inline constexpr DeltaY<T> operator+(DeltaY<T> lhs, DeltaY<T> rhs) { return DeltaY<T>(lhs.as_value() + rhs.as_value()); }
129template<typename T>
130inline constexpr DeltaX<T> operator-(DeltaX<T> lhs, DeltaX<T> rhs) { return DeltaX<T>(lhs.as_value() - rhs.as_value()); }
131template<typename T>
132inline constexpr DeltaY<T> operator-(DeltaY<T> lhs, DeltaY<T> rhs) { return DeltaY<T>(lhs.as_value() - rhs.as_value()); }
133template<typename T>
134inline constexpr DeltaX<T> operator-(DeltaX<T> rhs) { return DeltaX<T>(-rhs.as_value()); }
135template<typename T>
136inline constexpr DeltaY<T> operator-(DeltaY<T> rhs) { return DeltaY<T>(-rhs.as_value()); }
137template<typename T>
138inline DeltaX<T>& operator+=(DeltaX<T>& lhs, DeltaX<T> rhs) { return lhs = lhs + rhs; }
139template<typename T>
140inline DeltaY<T>& operator+=(DeltaY<T>& lhs, DeltaY<T> rhs) { return lhs = lhs + rhs; }
141template<typename T>
142inline DeltaX<T>& operator-=(DeltaX<T>& lhs, DeltaX<T> rhs) { return lhs = lhs - rhs; }
143template<typename T>
144inline DeltaY<T>& operator-=(DeltaY<T>& lhs, DeltaY<T> rhs) { return lhs = lhs - rhs; }
145
146// Adding deltas to co-ordinates is fine
147template<typename T>
148inline constexpr X<T> operator+(X<T> lhs, DeltaX<T> rhs) { return X<T>(lhs.as_value() + rhs.as_value()); }
149template<typename T>
150inline constexpr Y<T> operator+(Y<T> lhs, DeltaY<T> rhs) { return Y<T>(lhs.as_value() + rhs.as_value()); }
151template<typename T>
152inline constexpr X<T> operator-(X<T> lhs, DeltaX<T> rhs) { return X<T>(lhs.as_value() - rhs.as_value()); }
153template<typename T>
154inline constexpr Y<T> operator-(Y<T> lhs, DeltaY<T> rhs) { return Y<T>(lhs.as_value() - rhs.as_value()); }
155template<typename T>
156inline X<T>& operator+=(X<T>& lhs, DeltaX<T> rhs) { return lhs = lhs + rhs; }
157template<typename T>
158inline Y<T>& operator+=(Y<T>& lhs, DeltaY<T> rhs) { return lhs = lhs + rhs; }
159template<typename T>
160inline X<T>& operator-=(X<T>& lhs, DeltaX<T> rhs) { return lhs = lhs - rhs; }
161template<typename T>
162inline Y<T>& operator-=(Y<T>& lhs, DeltaY<T> rhs) { return lhs = lhs - rhs; }
163
164// Adding deltas to generic::Width and generic::Height is fine
165template<typename T>
166inline constexpr Width<T> operator+(Width<T> lhs, DeltaX<T> rhs) { return Width<T>(lhs.as_value() + rhs.as_value()); }
167template<typename T>
168inline constexpr Height<T> operator+(Height<T> lhs, DeltaY<T> rhs) { return Height<T>(lhs.as_value() + rhs.as_value()); }
169template<typename T>
170inline constexpr Width<T> operator-(Width<T> lhs, DeltaX<T> rhs) { return Width<T>(lhs.as_value() - rhs.as_value()); }
171template<typename T>
172inline constexpr Height<T> operator-(Height<T> lhs, DeltaY<T> rhs) { return Height<T>(lhs.as_value() - rhs.as_value()); }
173template<typename T>
174inline Width<T>& operator+=(Width<T>& lhs, DeltaX<T> rhs) { return lhs = lhs + rhs; }
175template<typename T>
176inline Height<T>& operator+=(Height<T>& lhs, DeltaY<T> rhs) { return lhs = lhs + rhs; }
177template<typename T>
178inline Width<T>& operator-=(Width<T>& lhs, DeltaX<T> rhs) { return lhs = lhs - rhs; }
179template<typename T>
180inline Height<T>& operator-=(Height<T>& lhs, DeltaY<T> rhs) { return lhs = lhs - rhs; }
181
182// Adding Widths and Heights is fine
183template<typename T>
184inline constexpr Width<T> operator+(Width<T> lhs, Width<T> rhs) { return Width<T>(lhs.as_value() + rhs.as_value()); }
185template<typename T>
186inline constexpr Height<T> operator+(Height<T> lhs, Height<T> rhs) { return Height<T>(lhs.as_value() + rhs.as_value()); }
187template<typename T>
188inline Width<T>& operator+=(Width<T>& lhs, Width<T> rhs) { return lhs = lhs + rhs; }
189template<typename T>
190inline Height<T>& operator+=(Height<T>& lhs, Height<T> rhs) { return lhs = lhs + rhs; }
191
192// Subtracting coordinates is fine
193template<typename T>
194inline constexpr DeltaX<T> operator-(X<T> lhs, X<T> rhs) { return DeltaX<T>(lhs.as_value() - rhs.as_value()); }
195template<typename T>
196inline constexpr DeltaY<T> operator-(Y<T> lhs, Y<T> rhs) { return DeltaY<T>(lhs.as_value() - rhs.as_value()); }
197
198//Subtracting Width<T> and Height<T> is fine
199template<typename T>
200inline constexpr DeltaX<T> operator-(Width<T> lhs, Width<T> rhs) { return DeltaX<T>(lhs.as_value() - rhs.as_value()); }
201template<typename T>
202inline constexpr DeltaY<T> operator-(Height<T> lhs, Height<T> rhs) { return DeltaY<T>(lhs.as_value() - rhs.as_value()); }
203
204// Multiplying by a scalar value is fine
205template<typename T, typename Scalar>
206inline constexpr Width<T> operator*(Scalar scale, Width<T> const& w) { return Width<T>{scale*w.as_value()}; }
207template<typename T, typename Scalar>
208inline constexpr Height<T> operator*(Scalar scale, Height<T> const& h) { return Height<T>{scale*h.as_value()}; }
209template<typename T, typename Scalar>
210inline constexpr DeltaX<T> operator*(Scalar scale, DeltaX<T> const& dx) { return DeltaX<T>{scale*dx.as_value()}; }
211template<typename T, typename Scalar>
212inline constexpr DeltaY<T> operator*(Scalar scale, DeltaY<T> const& dy) { return DeltaY<T>{scale*dy.as_value()}; }
213template<typename T, typename Scalar>
214inline constexpr Width<T> operator*(Width<T> const& w, Scalar scale) { return scale*w; }
215template<typename T, typename Scalar>
216inline constexpr Height<T> operator*(Height<T> const& h, Scalar scale) { return scale*h; }
217template<typename T, typename Scalar>
218inline constexpr DeltaX<T> operator*(DeltaX<T> const& dx, Scalar scale) { return scale*dx; }
219template<typename T, typename Scalar>
220inline constexpr DeltaY<T> operator*(DeltaY<T> const& dy, Scalar scale) { return scale*dy; }
221
222// Dividing by a scaler value is fine
223template<typename T, typename Scalar>
224inline constexpr Width<T> operator/(Width<T> const& w, Scalar scale) { return Width<T>{w.as_value() / scale}; }
225template<typename T, typename Scalar>
226inline constexpr Height<T> operator/(Height<T> const& h, Scalar scale) { return Height<T>{h.as_value() / scale}; }
227template<typename T, typename Scalar>
228inline constexpr DeltaX<T> operator/(DeltaX<T> const& dx, Scalar scale) { return DeltaX<T>{dx.as_value() / scale}; }
229template<typename T, typename Scalar>
230inline constexpr DeltaY<T> operator/(DeltaY<T> const& dy, Scalar scale) { return DeltaY<T>{dy.as_value() / scale}; }
231} // namespace
232
233// Converting between types is fine, as long as they are along the same axis
234template<typename T>
235inline constexpr generic::Width<T> as_width(generic::DeltaX<T> const& dx) { return generic::Width<T>{dx.as_value()}; }
236template<typename T>
237inline constexpr generic::Height<T> as_height(generic::DeltaY<T> const& dy) { return generic::Height<T>{dy.as_value()}; }
238template<typename T>
239inline constexpr generic::X<T> as_x(generic::DeltaX<T> const& dx) { return generic::X<T>{dx.as_value()}; }
240template<typename T>
241inline constexpr generic::Y<T> as_y(generic::DeltaY<T> const& dy) { return generic::Y<T>{dy.as_value()}; }
242template<typename T>
243inline constexpr generic::DeltaX<T> as_delta(generic::X<T> const& x) { return generic::DeltaX<T>{x.as_value()}; }
244template<typename T>
245inline constexpr generic::DeltaY<T> as_delta(generic::Y<T> const& y) { return generic::DeltaY<T>{y.as_value()}; }
246template<typename T>
247inline constexpr generic::X<T> as_x(generic::Width<T> const& w) { return generic::X<T>{w.as_value()}; }
248template<typename T>
249inline constexpr generic::Y<T> as_y(generic::Height<T> const& h) { return generic::Y<T>{h.as_value()}; }
250template<typename T>
251inline constexpr generic::Width<T> as_width(generic::X<T> const& x) { return generic::Width<T>{x.as_value()}; }
252template<typename T>
253inline constexpr generic::Height<T> as_height(generic::Y<T> const& y) { return generic::Height<T>{y.as_value()}; }
254template<typename T>
255inline constexpr generic::DeltaX<T> as_delta(generic::Width<T> const& w) { return generic::DeltaX<T>{w.as_value()}; }
256template<typename T>
257inline constexpr generic::DeltaY<T> as_delta(generic::Height<T> const& h) { return generic::DeltaY<T>{h.as_value()}; }
258} // namespace geometry
259} // namespace mir
260
261#endif // MIR_GEOMETRY_DIMENSIONS_H_
Definition: size.h:29
Width< T > & operator-=(Width< T > &lhs, DeltaX< T > rhs)
Definition: dimensions.h:178
DeltaX< T > & operator-=(DeltaX< T > &lhs, DeltaX< T > rhs)
Definition: dimensions.h:142
constexpr DeltaX< T > operator*(DeltaX< T > const &dx, Scalar scale)
Definition: dimensions.h:218
Width< T > & operator+=(Width< T > &lhs, DeltaX< T > rhs)
Definition: dimensions.h:174
constexpr Height< T > operator*(Height< T > const &h, Scalar scale)
Definition: dimensions.h:216
constexpr X< T > operator-(X< T > lhs, DeltaX< T > rhs)
Definition: dimensions.h:152
constexpr Width< T > operator*(Width< T > const &w, Scalar scale)
Definition: dimensions.h:214
constexpr Y< T > operator+(Y< T > lhs, DeltaY< T > rhs)
Definition: dimensions.h:150
constexpr DeltaY< T > operator-(Height< T > lhs, Height< T > rhs)
Definition: dimensions.h:202
Width< T > & operator+=(Width< T > &lhs, Width< T > rhs)
Definition: dimensions.h:188
constexpr Width< T > operator+(Width< T > lhs, DeltaX< T > rhs)
Definition: dimensions.h:166
constexpr Y< T > operator-(Y< T > lhs, DeltaY< T > rhs)
Definition: dimensions.h:154
X< T > & operator-=(X< T > &lhs, DeltaX< T > rhs)
Definition: dimensions.h:160
Height< T > & operator+=(Height< T > &lhs, Height< T > rhs)
Definition: dimensions.h:190
constexpr Height< T > operator+(Height< T > lhs, DeltaY< T > rhs)
Definition: dimensions.h:168
constexpr DeltaX< T > operator/(DeltaX< T > const &dx, Scalar scale)
Definition: dimensions.h:228
constexpr DeltaY< T > operator+(DeltaY< T > lhs, DeltaY< T > rhs)
Definition: dimensions.h:128
DeltaY< T > & operator+=(DeltaY< T > &lhs, DeltaY< T > rhs)
Definition: dimensions.h:140
constexpr Height< T > operator-(Height< T > lhs, DeltaY< T > rhs)
Definition: dimensions.h:172
constexpr DeltaY< T > operator/(DeltaY< T > const &dy, Scalar scale)
Definition: dimensions.h:230
constexpr Width< T > operator/(Width< T > const &w, Scalar scale)
Definition: dimensions.h:224
Y< T > & operator-=(Y< T > &lhs, DeltaY< T > rhs)
Definition: dimensions.h:162
constexpr Width< T > operator-(Width< T > lhs, DeltaX< T > rhs)
Definition: dimensions.h:170
Height< T > & operator+=(Height< T > &lhs, DeltaY< T > rhs)
Definition: dimensions.h:176
constexpr DeltaX< T > operator+(DeltaX< T > lhs, DeltaX< T > rhs)
Definition: dimensions.h:126
constexpr DeltaY< T > operator*(Scalar scale, DeltaY< T > const &dy)
Definition: dimensions.h:212
DeltaX< T > & operator+=(DeltaX< T > &lhs, DeltaX< T > rhs)
Definition: dimensions.h:138
constexpr DeltaX< T > operator-(DeltaX< T > rhs)
Definition: dimensions.h:134
Y< T > & operator+=(Y< T > &lhs, DeltaY< T > rhs)
Definition: dimensions.h:158
constexpr Width< T > operator+(Width< T > lhs, Width< T > rhs)
Definition: dimensions.h:184
constexpr X< T > operator+(X< T > lhs, DeltaX< T > rhs)
Definition: dimensions.h:148
constexpr DeltaY< T > operator-(DeltaY< T > rhs)
Definition: dimensions.h:136
constexpr Width< T > operator*(Scalar scale, Width< T > const &w)
Definition: dimensions.h:206
constexpr DeltaY< T > operator-(Y< T > lhs, Y< T > rhs)
Definition: dimensions.h:196
constexpr DeltaX< T > operator*(Scalar scale, DeltaX< T > const &dx)
Definition: dimensions.h:210
constexpr DeltaX< T > operator-(DeltaX< T > lhs, DeltaX< T > rhs)
Definition: dimensions.h:130
constexpr DeltaY< T > operator-(DeltaY< T > lhs, DeltaY< T > rhs)
Definition: dimensions.h:132
constexpr DeltaX< T > operator-(Width< T > lhs, Width< T > rhs)
Definition: dimensions.h:200
X< T > & operator+=(X< T > &lhs, DeltaX< T > rhs)
Definition: dimensions.h:156
DeltaY< T > & operator-=(DeltaY< T > &lhs, DeltaY< T > rhs)
Definition: dimensions.h:144
Height< T > & operator-=(Height< T > &lhs, DeltaY< T > rhs)
Definition: dimensions.h:180
constexpr Height< T > operator/(Height< T > const &h, Scalar scale)
Definition: dimensions.h:226
constexpr Height< T > operator+(Height< T > lhs, Height< T > rhs)
Definition: dimensions.h:186
constexpr DeltaY< T > operator*(DeltaY< T > const &dy, Scalar scale)
Definition: dimensions.h:220
constexpr DeltaX< T > operator-(X< T > lhs, X< T > rhs)
Definition: dimensions.h:194
constexpr Height< T > operator*(Scalar scale, Height< T > const &h)
Definition: dimensions.h:208
Basic geometry types. Types for dimensions, displacements, etc. and the operations that they support.
Definition: size.h:27
constexpr generic::DeltaY< T > as_delta(generic::Y< T > const &y)
Definition: dimensions.h:245
constexpr generic::Width< T > as_width(generic::X< T > const &x)
Definition: dimensions.h:251
constexpr generic::Height< T > as_height(generic::Y< T > const &y)
Definition: dimensions.h:253
constexpr generic::DeltaX< T > as_delta(generic::X< T > const &x)
Definition: dimensions.h:243
constexpr generic::X< T > as_x(generic::DeltaX< T > const &dx)
Definition: dimensions.h:239
constexpr generic::Width< T > as_width(generic::DeltaX< T > const &dx)
Definition: dimensions.h:235
constexpr generic::X< T > as_x(generic::Width< T > const &w)
Definition: dimensions.h:247
constexpr generic::DeltaY< T > as_delta(generic::Height< T > const &h)
Definition: dimensions.h:257
constexpr generic::DeltaX< T > as_delta(generic::Width< T > const &w)
Definition: dimensions.h:255
constexpr generic::Height< T > as_height(generic::DeltaY< T > const &dy)
Definition: dimensions.h:237
constexpr generic::Y< T > as_y(generic::Height< T > const &h)
Definition: dimensions.h:249
constexpr generic::Y< T > as_y(generic::DeltaY< T > const &dy)
Definition: dimensions.h:241
Definition: runner.h:27
constexpr Value(Value const &that) noexcept
Definition: dimensions.h:66
constexpr T as_value() const noexcept
Definition: dimensions.h:53
constexpr auto operator<(Value< T, Tag > const &rhs) const -> bool
Definition: dimensions.h:103
constexpr auto operator>=(Value< T, Tag > const &rhs) const -> bool
Definition: dimensions.h:98
constexpr Value() noexcept
Definition: dimensions.h:58
constexpr std::enable_if< std::is_integral< Q >::value, uint32_t >::type as_uint32_t() const
Definition: dimensions.h:48
constexpr auto operator<=(Value< T, Tag > const &rhs) const -> bool
Definition: dimensions.h:93
Value & operator=(Value const &that) noexcept
Definition: dimensions.h:60
constexpr Value(Value< U, Tag > const &value) noexcept
Definition: dimensions.h:72
constexpr auto operator!=(Value< T, Tag > const &rhs) const -> bool
Definition: dimensions.h:88
constexpr auto operator>(Value< T, Tag > const &rhs) const -> bool
Definition: dimensions.h:108
constexpr std::enable_if< std::is_integral< Q >::value, int >::type as_int() const
Definition: dimensions.h:42
constexpr Value(U const &value) noexcept
Definition: dimensions.h:78
constexpr auto operator==(Value< T, Tag > const &rhs) const -> bool
Definition: dimensions.h:83
T value
Definition: dimensions.h:114

Copyright © 2012-2023 Canonical Ltd.
Generated on Tue 2 May 10:01:24 UTC 2023
This documentation is licensed under the GPL version 2 or 3.