Mir
dimensions.h
Go to the documentation of this file.
1 /*
2  * Copyright © 2020 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 
26 namespace mir
27 {
28 namespace geometry
29 {
30 namespace generic
31 {
32 template<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).
36 struct 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 
113 protected:
114  T value;
115 };
116 
117 template<typename T, typename Tag>
118 std::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
125 template<typename T>
126 inline constexpr DeltaX<T> operator+(DeltaX<T> lhs, DeltaX<T> rhs){ return DeltaX<T>(lhs.as_value() + rhs.as_value()); }
127 template<typename T>
128 inline constexpr DeltaY<T> operator+(DeltaY<T> lhs, DeltaY<T> rhs) { return DeltaY<T>(lhs.as_value() + rhs.as_value()); }
129 template<typename T>
130 inline constexpr DeltaX<T> operator-(DeltaX<T> lhs, DeltaX<T> rhs) { return DeltaX<T>(lhs.as_value() - rhs.as_value()); }
131 template<typename T>
132 inline constexpr DeltaY<T> operator-(DeltaY<T> lhs, DeltaY<T> rhs) { return DeltaY<T>(lhs.as_value() - rhs.as_value()); }
133 template<typename T>
134 inline constexpr DeltaX<T> operator-(DeltaX<T> rhs) { return DeltaX<T>(-rhs.as_value()); }
135 template<typename T>
136 inline constexpr DeltaY<T> operator-(DeltaY<T> rhs) { return DeltaY<T>(-rhs.as_value()); }
137 template<typename T>
138 inline DeltaX<T>& operator+=(DeltaX<T>& lhs, DeltaX<T> rhs) { return lhs = lhs + rhs; }
139 template<typename T>
140 inline DeltaY<T>& operator+=(DeltaY<T>& lhs, DeltaY<T> rhs) { return lhs = lhs + rhs; }
141 template<typename T>
142 inline DeltaX<T>& operator-=(DeltaX<T>& lhs, DeltaX<T> rhs) { return lhs = lhs - rhs; }
143 template<typename T>
144 inline DeltaY<T>& operator-=(DeltaY<T>& lhs, DeltaY<T> rhs) { return lhs = lhs - rhs; }
145 
146 // Adding deltas to co-ordinates is fine
147 template<typename T>
148 inline constexpr X<T> operator+(X<T> lhs, DeltaX<T> rhs) { return X<T>(lhs.as_value() + rhs.as_value()); }
149 template<typename T>
150 inline constexpr Y<T> operator+(Y<T> lhs, DeltaY<T> rhs) { return Y<T>(lhs.as_value() + rhs.as_value()); }
151 template<typename T>
152 inline constexpr X<T> operator-(X<T> lhs, DeltaX<T> rhs) { return X<T>(lhs.as_value() - rhs.as_value()); }
153 template<typename T>
154 inline constexpr Y<T> operator-(Y<T> lhs, DeltaY<T> rhs) { return Y<T>(lhs.as_value() - rhs.as_value()); }
155 template<typename T>
156 inline X<T>& operator+=(X<T>& lhs, DeltaX<T> rhs) { return lhs = lhs + rhs; }
157 template<typename T>
158 inline Y<T>& operator+=(Y<T>& lhs, DeltaY<T> rhs) { return lhs = lhs + rhs; }
159 template<typename T>
160 inline X<T>& operator-=(X<T>& lhs, DeltaX<T> rhs) { return lhs = lhs - rhs; }
161 template<typename T>
162 inline 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
165 template<typename T>
166 inline constexpr Width<T> operator+(Width<T> lhs, DeltaX<T> rhs) { return Width<T>(lhs.as_value() + rhs.as_value()); }
167 template<typename T>
168 inline constexpr Height<T> operator+(Height<T> lhs, DeltaY<T> rhs) { return Height<T>(lhs.as_value() + rhs.as_value()); }
169 template<typename T>
170 inline constexpr Width<T> operator-(Width<T> lhs, DeltaX<T> rhs) { return Width<T>(lhs.as_value() - rhs.as_value()); }
171 template<typename T>
172 inline constexpr Height<T> operator-(Height<T> lhs, DeltaY<T> rhs) { return Height<T>(lhs.as_value() - rhs.as_value()); }
173 template<typename T>
174 inline Width<T>& operator+=(Width<T>& lhs, DeltaX<T> rhs) { return lhs = lhs + rhs; }
175 template<typename T>
176 inline Height<T>& operator+=(Height<T>& lhs, DeltaY<T> rhs) { return lhs = lhs + rhs; }
177 template<typename T>
178 inline Width<T>& operator-=(Width<T>& lhs, DeltaX<T> rhs) { return lhs = lhs - rhs; }
179 template<typename T>
180 inline Height<T>& operator-=(Height<T>& lhs, DeltaY<T> rhs) { return lhs = lhs - rhs; }
181 
182 // Adding Widths and Heights is fine
183 template<typename T>
184 inline constexpr Width<T> operator+(Width<T> lhs, Width<T> rhs) { return Width<T>(lhs.as_value() + rhs.as_value()); }
185 template<typename T>
186 inline constexpr Height<T> operator+(Height<T> lhs, Height<T> rhs) { return Height<T>(lhs.as_value() + rhs.as_value()); }
187 template<typename T>
188 inline Width<T>& operator+=(Width<T>& lhs, Width<T> rhs) { return lhs = lhs + rhs; }
189 template<typename T>
190 inline Height<T>& operator+=(Height<T>& lhs, Height<T> rhs) { return lhs = lhs + rhs; }
191 
192 // Subtracting coordinates is fine
193 template<typename T>
194 inline constexpr DeltaX<T> operator-(X<T> lhs, X<T> rhs) { return DeltaX<T>(lhs.as_value() - rhs.as_value()); }
195 template<typename T>
196 inline 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
199 template<typename T>
200 inline constexpr DeltaX<T> operator-(Width<T> lhs, Width<T> rhs) { return DeltaX<T>(lhs.as_value() - rhs.as_value()); }
201 template<typename T>
202 inline 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
205 template<typename T, typename Scalar>
206 inline constexpr Width<T> operator*(Scalar scale, Width<T> const& w) { return Width<T>{scale*w.as_value()}; }
207 template<typename T, typename Scalar>
208 inline constexpr Height<T> operator*(Scalar scale, Height<T> const& h) { return Height<T>{scale*h.as_value()}; }
209 template<typename T, typename Scalar>
210 inline constexpr DeltaX<T> operator*(Scalar scale, DeltaX<T> const& dx) { return DeltaX<T>{scale*dx.as_value()}; }
211 template<typename T, typename Scalar>
212 inline constexpr DeltaY<T> operator*(Scalar scale, DeltaY<T> const& dy) { return DeltaY<T>{scale*dy.as_value()}; }
213 template<typename T, typename Scalar>
214 inline constexpr Width<T> operator*(Width<T> const& w, Scalar scale) { return scale*w; }
215 template<typename T, typename Scalar>
216 inline constexpr Height<T> operator*(Height<T> const& h, Scalar scale) { return scale*h; }
217 template<typename T, typename Scalar>
218 inline constexpr DeltaX<T> operator*(DeltaX<T> const& dx, Scalar scale) { return scale*dx; }
219 template<typename T, typename Scalar>
220 inline constexpr DeltaY<T> operator*(DeltaY<T> const& dy, Scalar scale) { return scale*dy; }
221 
222 // Dividing by a scaler value is fine
223 template<typename T, typename Scalar>
224 inline constexpr Width<T> operator/(Width<T> const& w, Scalar scale) { return Width<T>{w.as_value() / scale}; }
225 template<typename T, typename Scalar>
226 inline constexpr Height<T> operator/(Height<T> const& h, Scalar scale) { return Height<T>{h.as_value() / scale}; }
227 template<typename T, typename Scalar>
228 inline constexpr DeltaX<T> operator/(DeltaX<T> const& dx, Scalar scale) { return DeltaX<T>{dx.as_value() / scale}; }
229 template<typename T, typename Scalar>
230 inline 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
234 template<typename T>
235 inline constexpr generic::Width<T> as_width(generic::DeltaX<T> const& dx) { return generic::Width<T>{dx.as_value()}; }
236 template<typename T>
237 inline constexpr generic::Height<T> as_height(generic::DeltaY<T> const& dy) { return generic::Height<T>{dy.as_value()}; }
238 template<typename T>
239 inline constexpr generic::X<T> as_x(generic::DeltaX<T> const& dx) { return generic::X<T>{dx.as_value()}; }
240 template<typename T>
241 inline constexpr generic::Y<T> as_y(generic::DeltaY<T> const& dy) { return generic::Y<T>{dy.as_value()}; }
242 template<typename T>
243 inline constexpr generic::DeltaX<T> as_delta(generic::X<T> const& x) { return generic::DeltaX<T>{x.as_value()}; }
244 template<typename T>
245 inline constexpr generic::DeltaY<T> as_delta(generic::Y<T> const& y) { return generic::DeltaY<T>{y.as_value()}; }
246 template<typename T>
247 inline constexpr generic::X<T> as_x(generic::Width<T> const& w) { return generic::X<T>{w.as_value()}; }
248 template<typename T>
249 inline constexpr generic::Y<T> as_y(generic::Height<T> const& h) { return generic::Y<T>{h.as_value()}; }
250 template<typename T>
251 inline constexpr generic::Width<T> as_width(generic::X<T> const& x) { return generic::Width<T>{x.as_value()}; }
252 template<typename T>
253 inline constexpr generic::Height<T> as_height(generic::Y<T> const& y) { return generic::Height<T>{y.as_value()}; }
254 template<typename T>
255 inline constexpr generic::DeltaX<T> as_delta(generic::Width<T> const& w) { return generic::DeltaX<T>{w.as_value()}; }
256 template<typename T>
257 inline 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_

Copyright © 2012-2022 Canonical Ltd.
Generated on Thu Sep 8 12:37:23 UTC 2022
This documentation is licensed under the GPL version 2 or 3.