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

Copyright © 2012-2023 Canonical Ltd.
Generated on Tue Jan 24 16:42:22 UTC 2023
This documentation is licensed under the GPL version 2 or 3.