Mir
dimensions_generic.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  * Authored by: William Wold <william.wold@canonical.com>
17  */
18 
19 #ifndef MIR_GEOMETRY_DIMENSIONS_GENERIC_H_
20 #define MIR_GEOMETRY_DIMENSIONS_GENERIC_H_
21 
22 #include <iosfwd>
23 #include <type_traits>
24 
25 namespace mir
26 {
29 namespace geometry
30 {
31 
36 struct WidthTag{};
37 struct HeightTag{};
38 struct XTag{};
39 struct YTag{};
40 struct DeltaXTag{};
41 struct DeltaYTag{};
43 
44 namespace detail
45 {
46 struct ValueWrapperBase{}; // Used for determining if a type is a wrapper
47 }
48 
49 namespace generic
50 {
51 template<typename T>
52 struct Value
53 {
58  template<typename Tag>
60  {
61  using ValueType = T;
62  using TagType = Tag;
63  template<typename OtherTag>
65 
66  template <typename Q = T>
67  constexpr typename std::enable_if<std::is_integral<Q>::value, int>::type as_int() const
68  {
69  return this->value;
70  }
71 
72  constexpr T as_value() const noexcept
73  {
74  return value;
75  }
76 
77  constexpr Wrapper() noexcept : value{} {}
78 
79  Wrapper& operator=(Wrapper const& that) noexcept
80  {
81  value = that.value;
82  return *this;
83  }
84 
85  constexpr Wrapper(Wrapper const& that) noexcept
86  : value{that.value}
87  {
88  }
89 
90  template<typename W, typename std::enable_if<std::is_same<typename W::TagType, Tag>::value, bool>::type = true>
91  explicit constexpr Wrapper(W const& value) noexcept
92  : value{static_cast<T>(value.as_value())}
93  {
94  }
95 
96  template<typename U, typename std::enable_if<std::is_scalar<U>::value, bool>::type = true>
97  explicit constexpr Wrapper(U const& value) noexcept
98  : value{static_cast<T>(value)}
99  {
100  }
101 
102  inline constexpr auto operator == (Wrapper<Tag> const& rhs) const -> bool
103  {
104  return value == rhs.as_value();
105  }
106 
107  inline constexpr auto operator != (Wrapper<Tag> const& rhs) const -> bool
108  {
109  return value != rhs.as_value();
110  }
111 
112  inline constexpr auto operator <= (Wrapper<Tag> const& rhs) const -> bool
113  {
114  return value <= rhs.as_value();
115  }
116 
117  inline constexpr auto operator >= (Wrapper<Tag> const& rhs) const -> bool
118  {
119  return value >= rhs.as_value();
120  }
121 
122  inline constexpr auto operator < (Wrapper<Tag> const& rhs) const -> bool
123  {
124  return value < rhs.as_value();
125  }
126 
127  inline constexpr auto operator > (Wrapper<Tag> const& rhs) const -> bool
128  {
129  return value > rhs.as_value();
130  }
131 
132  protected:
133  T value;
134  };
135 
136 private:
137  Value();
138 };
139 
140 template<class GeometricType, typename Tag>
141 using Corresponding = typename GeometricType::template Corresponding<Tag>;
142 
143 template<typename W, typename std::enable_if<std::is_base_of<detail::ValueWrapperBase, W>::value, bool>::type = true>
144 std::ostream& operator<<(std::ostream& out, W const& value)
145 {
146  out << value.as_value();
147  return out;
148 }
149 
150 template<typename T> using Width = typename Value<T>::template Wrapper<WidthTag>;
151 template<typename T> using Height = typename Value<T>::template Wrapper<HeightTag>;
152 template<typename T> using X = typename Value<T>::template Wrapper<XTag>;
153 template<typename T> using Y = typename Value<T>::template Wrapper<YTag>;
154 template<typename T> using DeltaX = typename Value<T>::template Wrapper<DeltaXTag>;
155 template<typename T> using DeltaY = typename Value<T>::template Wrapper<DeltaYTag>;
156 } // namespace generic
157 
158 // Adding deltas is fine
159 template<template<typename> typename T>
160 inline constexpr T<DeltaXTag> operator+(T<DeltaXTag> lhs, T<DeltaXTag> rhs){ return T<DeltaXTag>(lhs.as_value() + rhs.as_value()); }
161 template<template<typename> typename T>
162 inline constexpr T<DeltaYTag> operator+(T<DeltaYTag> lhs, T<DeltaYTag> rhs) { return T<DeltaYTag>(lhs.as_value() + rhs.as_value()); }
163 template<template<typename> typename T>
164 inline constexpr T<DeltaXTag> operator-(T<DeltaXTag> lhs, T<DeltaXTag> rhs) { return T<DeltaXTag>(lhs.as_value() - rhs.as_value()); }
165 template<template<typename> typename T>
166 inline constexpr T<DeltaYTag> operator-(T<DeltaYTag> lhs, T<DeltaYTag> rhs) { return T<DeltaYTag>(lhs.as_value() - rhs.as_value()); }
167 template<template<typename> typename T>
168 inline constexpr T<DeltaXTag> operator-(T<DeltaXTag> rhs) { return T<DeltaXTag>(-rhs.as_value()); }
169 template<template<typename> typename T>
170 inline constexpr T<DeltaYTag> operator-(T<DeltaYTag> rhs) { return T<DeltaYTag>(-rhs.as_value()); }
171 template<template<typename> typename T>
172 inline T<DeltaXTag>& operator+=(T<DeltaXTag>& lhs, T<DeltaXTag> rhs) { return lhs = lhs + rhs; }
173 template<template<typename> typename T>
174 inline T<DeltaYTag>& operator+=(T<DeltaYTag>& lhs, T<DeltaYTag> rhs) { return lhs = lhs + rhs; }
175 template<template<typename> typename T>
176 inline T<DeltaXTag>& operator-=(T<DeltaXTag>& lhs, T<DeltaXTag> rhs) { return lhs = lhs - rhs; }
177 template<template<typename> typename T>
178 inline T<DeltaYTag>& operator-=(T<DeltaYTag>& lhs, T<DeltaYTag> rhs) { return lhs = lhs - rhs; }
179 
180 // Adding deltas to co-ordinates is fine
181 template<template<typename> typename T>
182 inline constexpr T<XTag> operator+(T<XTag> lhs, T<DeltaXTag> rhs) { return T<XTag>(lhs.as_value() + rhs.as_value()); }
183 template<template<typename> typename T>
184 inline constexpr T<YTag> operator+(T<YTag> lhs, T<DeltaYTag> rhs) { return T<YTag>(lhs.as_value() + rhs.as_value()); }
185 template<template<typename> typename T>
186 inline constexpr T<XTag> operator-(T<XTag> lhs, T<DeltaXTag> rhs) { return T<XTag>(lhs.as_value() - rhs.as_value()); }
187 template<template<typename> typename T>
188 inline constexpr T<YTag> operator-(T<YTag> lhs, T<DeltaYTag> rhs) { return T<YTag>(lhs.as_value() - rhs.as_value()); }
189 template<template<typename> typename T>
190 inline T<XTag>& operator+=(T<XTag>& lhs, T<DeltaXTag> rhs) { return lhs = lhs + rhs; }
191 template<template<typename> typename T>
192 inline T<YTag>& operator+=(T<YTag>& lhs, T<DeltaYTag> rhs) { return lhs = lhs + rhs; }
193 template<template<typename> typename T>
194 inline T<XTag>& operator-=(T<XTag>& lhs, T<DeltaXTag> rhs) { return lhs = lhs - rhs; }
195 template<template<typename> typename T>
196 inline T<YTag>& operator-=(T<YTag>& lhs, T<DeltaYTag> rhs) { return lhs = lhs - rhs; }
197 
198 // Adding deltas to generic::Width and generic::Height is fine
199 template<template<typename> typename T>
200 inline constexpr T<WidthTag> operator+(T<WidthTag> lhs, T<DeltaXTag> rhs) { return T<WidthTag>(lhs.as_value() + rhs.as_value()); }
201 template<template<typename> typename T>
202 inline constexpr T<HeightTag> operator+(T<HeightTag> lhs, T<DeltaYTag> rhs) { return T<HeightTag>(lhs.as_value() + rhs.as_value()); }
203 template<template<typename> typename T>
204 inline constexpr T<WidthTag> operator-(T<WidthTag> lhs, T<DeltaXTag> rhs) { return T<WidthTag>(lhs.as_value() - rhs.as_value()); }
205 template<template<typename> typename T>
206 inline constexpr T<HeightTag> operator-(T<HeightTag> lhs, T<DeltaYTag> rhs) { return T<HeightTag>(lhs.as_value() - rhs.as_value()); }
207 template<template<typename> typename T>
208 inline T<WidthTag>& operator+=(T<WidthTag>& lhs, T<DeltaXTag> rhs) { return lhs = lhs + rhs; }
209 template<template<typename> typename T>
210 inline T<HeightTag>& operator+=(T<HeightTag>& lhs, T<DeltaYTag> rhs) { return lhs = lhs + rhs; }
211 template<template<typename> typename T>
212 inline T<WidthTag>& operator-=(T<WidthTag>& lhs, T<DeltaXTag> rhs) { return lhs = lhs - rhs; }
213 template<template<typename> typename T>
214 inline T<HeightTag>& operator-=(T<HeightTag>& lhs, T<DeltaYTag> rhs) { return lhs = lhs - rhs; }
215 
216 // Adding Widths and Heights is fine
217 template<template<typename> typename T>
218 inline constexpr T<WidthTag> operator+(T<WidthTag> lhs, T<WidthTag> rhs) { return T<WidthTag>(lhs.as_value() + rhs.as_value()); }
219 template<template<typename> typename T>
220 inline constexpr T<HeightTag> operator+(T<HeightTag> lhs, T<HeightTag> rhs) { return T<HeightTag>(lhs.as_value() + rhs.as_value()); }
221 template<template<typename> typename T>
222 inline T<WidthTag>& operator+=(T<WidthTag>& lhs, T<WidthTag> rhs) { return lhs = lhs + rhs; }
223 template<template<typename> typename T>
224 inline T<HeightTag>& operator+=(T<HeightTag>& lhs, T<HeightTag> rhs) { return lhs = lhs + rhs; }
225 
226 // Subtracting coordinates is fine
227 template<template<typename> typename T>
228 inline constexpr T<DeltaXTag> operator-(T<XTag> lhs, T<XTag> rhs) { return T<DeltaXTag>(lhs.as_value() - rhs.as_value()); }
229 template<template<typename> typename T>
230 inline constexpr T<DeltaYTag> operator-(T<YTag> lhs, T<YTag> rhs) { return T<DeltaYTag>(lhs.as_value() - rhs.as_value()); }
231 
232 //Subtracting T<WidthTag> and T<HeightTag> is fine
233 template<template<typename> typename T>
234 inline constexpr T<DeltaXTag> operator-(T<WidthTag> lhs, T<WidthTag> rhs) { return T<DeltaXTag>(lhs.as_value() - rhs.as_value()); }
235 template<template<typename> typename T>
236 inline constexpr T<DeltaYTag> operator-(T<HeightTag> lhs, T<HeightTag> rhs) { return T<DeltaYTag>(lhs.as_value() - rhs.as_value()); }
237 
238 // Multiplying by a scalar value is fine
239 template<template<typename> typename T, typename Scalar>
240 inline constexpr T<WidthTag> operator*(Scalar scale, T<WidthTag> const& w) { return T<WidthTag>{scale*w.as_value()}; }
241 template<template<typename> typename T, typename Scalar>
242 inline constexpr T<HeightTag> operator*(Scalar scale, T<HeightTag> const& h) { return T<HeightTag>{scale*h.as_value()}; }
243 template<template<typename> typename T, typename Scalar>
244 inline constexpr T<DeltaXTag> operator*(Scalar scale, T<DeltaXTag> const& dx) { return T<DeltaXTag>{scale*dx.as_value()}; }
245 template<template<typename> typename T, typename Scalar>
246 inline constexpr T<DeltaYTag> operator*(Scalar scale, T<DeltaYTag> const& dy) { return T<DeltaYTag>{scale*dy.as_value()}; }
247 template<template<typename> typename T, typename Scalar>
248 inline constexpr T<WidthTag> operator*(T<WidthTag> const& w, Scalar scale) { return scale*w; }
249 template<template<typename> typename T, typename Scalar>
250 inline constexpr T<HeightTag> operator*(T<HeightTag> const& h, Scalar scale) { return scale*h; }
251 template<template<typename> typename T, typename Scalar>
252 inline constexpr T<DeltaXTag> operator*(T<DeltaXTag> const& dx, Scalar scale) { return scale*dx; }
253 template<template<typename> typename T, typename Scalar>
254 inline constexpr T<DeltaYTag> operator*(T<DeltaYTag> const& dy, Scalar scale) { return scale*dy; }
255 
256 // Dividing by a scaler value is fine
257 template<template<typename> typename T, typename Scalar>
258 inline constexpr T<WidthTag> operator/(T<WidthTag> const& w, Scalar scale) { return T<WidthTag>{w.as_value() / scale}; }
259 template<template<typename> typename T, typename Scalar>
260 inline constexpr T<HeightTag> operator/(T<HeightTag> const& h, Scalar scale) { return T<HeightTag>{h.as_value() / scale}; }
261 template<template<typename> typename T, typename Scalar>
262 inline constexpr T<DeltaXTag> operator/(T<DeltaXTag> const& dx, Scalar scale) { return T<DeltaXTag>{dx.as_value() / scale}; }
263 template<template<typename> typename T, typename Scalar>
264 inline constexpr T<DeltaYTag> operator/(T<DeltaYTag> const& dy, Scalar scale) { return T<DeltaYTag>{dy.as_value() / scale}; }
265 
266 // Converting between types is fine, as long as they are along the same axis
267 template<template<typename> typename T>
268 inline constexpr T<WidthTag> as_width(T<DeltaXTag> const& dx) { return T<WidthTag>{dx.as_value()}; }
269 template<template<typename> typename T>
270 inline constexpr T<HeightTag> as_height(T<DeltaYTag> const& dy) { return T<HeightTag>{dy.as_value()}; }
271 template<template<typename> typename T>
272 inline constexpr T<XTag> as_x(T<DeltaXTag> const& dx) { return T<XTag>{dx.as_value()}; }
273 template<template<typename> typename T>
274 inline constexpr T<YTag> as_y(T<DeltaYTag> const& dy) { return T<YTag>{dy.as_value()}; }
275 template<template<typename> typename T>
276 inline constexpr T<DeltaXTag> as_delta(T<XTag> const& x) { return T<DeltaXTag>{x.as_value()}; }
277 template<template<typename> typename T>
278 inline constexpr T<DeltaYTag> as_delta(T<YTag> const& y) { return T<DeltaYTag>{y.as_value()}; }
279 template<template<typename> typename T>
280 inline constexpr T<XTag> as_x(T<WidthTag> const& w) { return T<XTag>{w.as_value()}; }
281 template<template<typename> typename T>
282 inline constexpr T<YTag> as_y(T<HeightTag> const& h) { return T<YTag>{h.as_value()}; }
283 template<template<typename> typename T>
284 inline constexpr T<WidthTag> as_width(T<XTag> const& x) { return T<WidthTag>{x.as_value()}; }
285 template<template<typename> typename T>
286 inline constexpr T<HeightTag> as_height(T<YTag> const& y) { return T<HeightTag>{y.as_value()}; }
287 template<template<typename> typename T>
288 inline constexpr T<DeltaXTag> as_delta(T<WidthTag> const& w) { return T<DeltaXTag>{w.as_value()}; }
289 template<template<typename> typename T>
290 inline constexpr T<DeltaYTag> as_delta(T<HeightTag> const& h) { return T<DeltaYTag>{h.as_value()}; }
291 
292 template<typename Target, typename Source>
293 inline constexpr Target dim_cast(Source s) { return Target(s.as_value()); }
294 } // namespace geometry
295 } // namespace mir
296 
297 #endif // MIR_GEOMETRY_DIMENSIONS_GENERIC_H_
typename Value< T >::template Wrapper< WidthTag > Width
Definition: dimensions_generic.h:150
std::ostream & operator<<(std::ostream &out, W const &value)
Definition: dimensions_generic.h:144
typename Value< T >::template Wrapper< DeltaYTag > DeltaY
Definition: dimensions_generic.h:155
typename GeometricType::template Corresponding< Tag > Corresponding
Definition: dimensions_generic.h:141
typename Value< T >::template Wrapper< YTag > Y
Definition: dimensions_generic.h:153
typename Value< T >::template Wrapper< DeltaXTag > DeltaX
Definition: dimensions_generic.h:154
typename Value< T >::template Wrapper< XTag > X
Definition: dimensions_generic.h:152
typename Value< T >::template Wrapper< HeightTag > Height
Definition: dimensions_generic.h:151
constexpr T< WidthTag > operator*(Scalar scale, T< WidthTag > const &w)
Definition: dimensions_generic.h:240
constexpr T< HeightTag > as_height(T< DeltaYTag > const &dy)
Definition: dimensions_generic.h:270
constexpr T< XTag > as_x(T< DeltaXTag > const &dx)
Definition: dimensions_generic.h:272
constexpr T< DeltaXTag > as_delta(T< XTag > const &x)
Definition: dimensions_generic.h:276
constexpr T< DeltaXTag > operator+(T< DeltaXTag > lhs, T< DeltaXTag > rhs)
Definition: dimensions_generic.h:160
constexpr T< WidthTag > as_width(T< DeltaXTag > const &dx)
Definition: dimensions_generic.h:268
constexpr T< YTag > as_y(T< DeltaYTag > const &dy)
Definition: dimensions_generic.h:274
constexpr T< WidthTag > operator/(T< WidthTag > const &w, Scalar scale)
Definition: dimensions_generic.h:258
T< DeltaXTag > & operator-=(T< DeltaXTag > &lhs, T< DeltaXTag > rhs)
Definition: dimensions_generic.h:176
constexpr Target dim_cast(Source s)
Definition: dimensions_generic.h:293
constexpr T< DeltaXTag > operator-(T< DeltaXTag > lhs, T< DeltaXTag > rhs)
Definition: dimensions_generic.h:164
T< DeltaXTag > & operator+=(T< DeltaXTag > &lhs, T< DeltaXTag > rhs)
Definition: dimensions_generic.h:172
Definition: splash_session.h:24
Definition: dimensions_generic.h:40
Definition: dimensions_generic.h:41
Definition: dimensions_generic.h:37
These tag types determine what type of dimension a value holds and what operations are possible with ...
Definition: dimensions_generic.h:36
Definition: dimensions_generic.h:38
Definition: dimensions_generic.h:39
Definition: dimensions_generic.h:46
Wraps a geometry value and prevents it from being accidentally used for invalid operations (such as s...
Definition: dimensions_generic.h:60
constexpr std::enable_if< std::is_integral< Q >::value, int >::type as_int() const
Definition: dimensions_generic.h:67
constexpr auto operator<(Wrapper< Tag > const &rhs) const -> bool
Definition: dimensions_generic.h:122
constexpr auto operator!=(Wrapper< Tag > const &rhs) const -> bool
Definition: dimensions_generic.h:107
constexpr Wrapper(W const &value) noexcept
Definition: dimensions_generic.h:91
constexpr Wrapper(U const &value) noexcept
Definition: dimensions_generic.h:97
constexpr Wrapper(Wrapper const &that) noexcept
Definition: dimensions_generic.h:85
Wrapper & operator=(Wrapper const &that) noexcept
Definition: dimensions_generic.h:79
constexpr T as_value() const noexcept
Definition: dimensions_generic.h:72
T value
Definition: dimensions_generic.h:133
constexpr auto operator>(Wrapper< Tag > const &rhs) const -> bool
Definition: dimensions_generic.h:127
constexpr auto operator==(Wrapper< Tag > const &rhs) const -> bool
Definition: dimensions_generic.h:102
T ValueType
Definition: dimensions_generic.h:61
Tag TagType
Definition: dimensions_generic.h:62
constexpr auto operator<=(Wrapper< Tag > const &rhs) const -> bool
Definition: dimensions_generic.h:112
constexpr auto operator>=(Wrapper< Tag > const &rhs) const -> bool
Definition: dimensions_generic.h:117
constexpr Wrapper() noexcept
Definition: dimensions_generic.h:77
Definition: dimensions_generic.h:53

Copyright © 2012-2021 Canonical Ltd.
Generated on Mon Jul 5 13:30:06 UTC 2021
This documentation is licensed under the GPL version 2 or 3.