xref: /aosp_15_r20/system/teeui/libteeui/include/teeui/utils.h (revision 20bfefbe1966c142a35ae1ab84a8af250b3fd403)
1*20bfefbeSAndroid Build Coastguard Worker /*
2*20bfefbeSAndroid Build Coastguard Worker  *
3*20bfefbeSAndroid Build Coastguard Worker  * Copyright 2019, The Android Open Source Project
4*20bfefbeSAndroid Build Coastguard Worker  *
5*20bfefbeSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
6*20bfefbeSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
7*20bfefbeSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
8*20bfefbeSAndroid Build Coastguard Worker  *
9*20bfefbeSAndroid Build Coastguard Worker  *     http://www.apache.org/licenses/LICENSE-2.0
10*20bfefbeSAndroid Build Coastguard Worker  *
11*20bfefbeSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
12*20bfefbeSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
13*20bfefbeSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*20bfefbeSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
15*20bfefbeSAndroid Build Coastguard Worker  * limitations under the License.
16*20bfefbeSAndroid Build Coastguard Worker  */
17*20bfefbeSAndroid Build Coastguard Worker 
18*20bfefbeSAndroid Build Coastguard Worker #ifndef TEEUI_LIBTEEUI_UTILS_H_
19*20bfefbeSAndroid Build Coastguard Worker #define TEEUI_LIBTEEUI_UTILS_H_
20*20bfefbeSAndroid Build Coastguard Worker 
21*20bfefbeSAndroid Build Coastguard Worker #include <math.h>
22*20bfefbeSAndroid Build Coastguard Worker #include <stddef.h>
23*20bfefbeSAndroid Build Coastguard Worker #include <stdint.h>
24*20bfefbeSAndroid Build Coastguard Worker #include <sys/types.h>
25*20bfefbeSAndroid Build Coastguard Worker 
26*20bfefbeSAndroid Build Coastguard Worker #include <algorithm>
27*20bfefbeSAndroid Build Coastguard Worker #include <initializer_list>
28*20bfefbeSAndroid Build Coastguard Worker #include <optional>
29*20bfefbeSAndroid Build Coastguard Worker #include <tuple>
30*20bfefbeSAndroid Build Coastguard Worker #include <type_traits>
31*20bfefbeSAndroid Build Coastguard Worker 
32*20bfefbeSAndroid Build Coastguard Worker #include <teeui/error.h>
33*20bfefbeSAndroid Build Coastguard Worker #include <teeui/log.h>
34*20bfefbeSAndroid Build Coastguard Worker 
35*20bfefbeSAndroid Build Coastguard Worker namespace teeui {
36*20bfefbeSAndroid Build Coastguard Worker 
37*20bfefbeSAndroid Build Coastguard Worker using std::optional;
38*20bfefbeSAndroid Build Coastguard Worker 
39*20bfefbeSAndroid Build Coastguard Worker template <typename T, size_t elements> class Array {
40*20bfefbeSAndroid Build Coastguard Worker     using array_type = T[elements];
41*20bfefbeSAndroid Build Coastguard Worker 
42*20bfefbeSAndroid Build Coastguard Worker   public:
Array()43*20bfefbeSAndroid Build Coastguard Worker     constexpr Array() : data_{} {}
Array(const T (& data)[elements])44*20bfefbeSAndroid Build Coastguard Worker     constexpr Array(const T (&data)[elements]) { std::copy(data, data + elements, data_); }
Array(const std::initializer_list<uint8_t> & li)45*20bfefbeSAndroid Build Coastguard Worker     constexpr Array(const std::initializer_list<uint8_t>& li) {
46*20bfefbeSAndroid Build Coastguard Worker         size_t i = 0;
47*20bfefbeSAndroid Build Coastguard Worker         for (auto& item : li) {
48*20bfefbeSAndroid Build Coastguard Worker             data_[i] = item;
49*20bfefbeSAndroid Build Coastguard Worker             ++i;
50*20bfefbeSAndroid Build Coastguard Worker             if (i == elements) break;
51*20bfefbeSAndroid Build Coastguard Worker         }
52*20bfefbeSAndroid Build Coastguard Worker         for (; i < elements; ++i) {
53*20bfefbeSAndroid Build Coastguard Worker             data_[i] = {};
54*20bfefbeSAndroid Build Coastguard Worker         }
55*20bfefbeSAndroid Build Coastguard Worker     }
56*20bfefbeSAndroid Build Coastguard Worker 
data()57*20bfefbeSAndroid Build Coastguard Worker     T* data() { return data_; }
data()58*20bfefbeSAndroid Build Coastguard Worker     const T* data() const { return data_; }
size()59*20bfefbeSAndroid Build Coastguard Worker     constexpr size_t size() const { return elements; }
60*20bfefbeSAndroid Build Coastguard Worker 
begin()61*20bfefbeSAndroid Build Coastguard Worker     T* begin() { return data_; }
end()62*20bfefbeSAndroid Build Coastguard Worker     T* end() { return data_ + elements; }
begin()63*20bfefbeSAndroid Build Coastguard Worker     const T* begin() const { return data_; }
end()64*20bfefbeSAndroid Build Coastguard Worker     const T* end() const { return data_ + elements; }
65*20bfefbeSAndroid Build Coastguard Worker 
fill(const T & v)66*20bfefbeSAndroid Build Coastguard Worker     static constexpr Array fill(const T& v) {
67*20bfefbeSAndroid Build Coastguard Worker         Array result;
68*20bfefbeSAndroid Build Coastguard Worker         for (size_t i = 0; i < elements; ++i) {
69*20bfefbeSAndroid Build Coastguard Worker             result.data_[i] = v;
70*20bfefbeSAndroid Build Coastguard Worker         }
71*20bfefbeSAndroid Build Coastguard Worker         return result;
72*20bfefbeSAndroid Build Coastguard Worker     }
73*20bfefbeSAndroid Build Coastguard Worker 
74*20bfefbeSAndroid Build Coastguard Worker   private:
75*20bfefbeSAndroid Build Coastguard Worker     array_type data_;
76*20bfefbeSAndroid Build Coastguard Worker };
77*20bfefbeSAndroid Build Coastguard Worker 
78*20bfefbeSAndroid Build Coastguard Worker template <typename T> auto bytesCast(const T& v) -> const uint8_t (&)[sizeof(T)] {
79*20bfefbeSAndroid Build Coastguard Worker     return *reinterpret_cast<const uint8_t(*)[sizeof(T)]>(&v);
80*20bfefbeSAndroid Build Coastguard Worker }
81*20bfefbeSAndroid Build Coastguard Worker template <typename T> auto bytesCast(T& v) -> uint8_t (&)[sizeof(T)] {
82*20bfefbeSAndroid Build Coastguard Worker     return *reinterpret_cast<uint8_t(*)[sizeof(T)]>(&v);
83*20bfefbeSAndroid Build Coastguard Worker }
84*20bfefbeSAndroid Build Coastguard Worker 
85*20bfefbeSAndroid Build Coastguard Worker class ByteBufferProxy {
86*20bfefbeSAndroid Build Coastguard Worker     template <typename T> struct has_data {
fhas_data87*20bfefbeSAndroid Build Coastguard Worker         template <typename U> static int f(const U*, const void*) { return 0; }
88*20bfefbeSAndroid Build Coastguard Worker         template <typename U> static int* f(const U* u, decltype(u->data())) { return nullptr; }
89*20bfefbeSAndroid Build Coastguard Worker         static constexpr bool value = std::is_pointer<decltype(f((T*)nullptr, ""))>::value;
90*20bfefbeSAndroid Build Coastguard Worker     };
91*20bfefbeSAndroid Build Coastguard Worker 
92*20bfefbeSAndroid Build Coastguard Worker   public:
93*20bfefbeSAndroid Build Coastguard Worker     template <typename T>
94*20bfefbeSAndroid Build Coastguard Worker     ByteBufferProxy(const T& buffer, decltype(buffer.data()) = nullptr)
95*20bfefbeSAndroid Build Coastguard Worker         : data_(reinterpret_cast<const uint8_t*>(buffer.data())), size_(buffer.size()) {
96*20bfefbeSAndroid Build Coastguard Worker         static_assert(sizeof(decltype(*buffer.data())) == 1, "elements to large");
97*20bfefbeSAndroid Build Coastguard Worker     }
98*20bfefbeSAndroid Build Coastguard Worker 
99*20bfefbeSAndroid Build Coastguard Worker     template <size_t size>
ByteBufferProxy(const char (& buffer)[size])100*20bfefbeSAndroid Build Coastguard Worker     ByteBufferProxy(const char (&buffer)[size])
101*20bfefbeSAndroid Build Coastguard Worker         : data_(reinterpret_cast<const uint8_t*>(buffer)), size_(size - 1) {
102*20bfefbeSAndroid Build Coastguard Worker         static_assert(size > 0, "even an empty string must be 0-terminated");
103*20bfefbeSAndroid Build Coastguard Worker     }
104*20bfefbeSAndroid Build Coastguard Worker 
105*20bfefbeSAndroid Build Coastguard Worker     template <size_t size>
ByteBufferProxy(const uint8_t (& buffer)[size])106*20bfefbeSAndroid Build Coastguard Worker     ByteBufferProxy(const uint8_t (&buffer)[size]) : data_(buffer), size_(size) {}
107*20bfefbeSAndroid Build Coastguard Worker 
ByteBufferProxy()108*20bfefbeSAndroid Build Coastguard Worker     ByteBufferProxy() : data_(nullptr), size_(0) {}
109*20bfefbeSAndroid Build Coastguard Worker 
data()110*20bfefbeSAndroid Build Coastguard Worker     const uint8_t* data() const { return data_; }
size()111*20bfefbeSAndroid Build Coastguard Worker     size_t size() const { return size_; }
112*20bfefbeSAndroid Build Coastguard Worker 
begin()113*20bfefbeSAndroid Build Coastguard Worker     const uint8_t* begin() const { return data_; }
end()114*20bfefbeSAndroid Build Coastguard Worker     const uint8_t* end() const { return data_ + size_; }
115*20bfefbeSAndroid Build Coastguard Worker 
116*20bfefbeSAndroid Build Coastguard Worker   private:
117*20bfefbeSAndroid Build Coastguard Worker     const uint8_t* data_;
118*20bfefbeSAndroid Build Coastguard Worker     size_t size_;
119*20bfefbeSAndroid Build Coastguard Worker };
120*20bfefbeSAndroid Build Coastguard Worker 
121*20bfefbeSAndroid Build Coastguard Worker constexpr const uint8_t kAuthTokenKeySize = 32;
122*20bfefbeSAndroid Build Coastguard Worker constexpr const uint8_t kHmacKeySize = kAuthTokenKeySize;
123*20bfefbeSAndroid Build Coastguard Worker using AuthTokenKey = Array<uint8_t, kAuthTokenKeySize>;
124*20bfefbeSAndroid Build Coastguard Worker using Hmac = AuthTokenKey;
125*20bfefbeSAndroid Build Coastguard Worker 
126*20bfefbeSAndroid Build Coastguard Worker /**
127*20bfefbeSAndroid Build Coastguard Worker  * Implementer are expected to provide an implementation with the following prototype:
128*20bfefbeSAndroid Build Coastguard Worker  *  static optional<array<uint8_t, 32>> hmac256(const uint8_t key[32],
129*20bfefbeSAndroid Build Coastguard Worker  *                                     std::initializer_list<ByteBufferProxy> buffers);
130*20bfefbeSAndroid Build Coastguard Worker  */
131*20bfefbeSAndroid Build Coastguard Worker template <typename Impl> class HMac {
132*20bfefbeSAndroid Build Coastguard Worker   public:
133*20bfefbeSAndroid Build Coastguard Worker     template <typename... Data>
hmac256(const AuthTokenKey & key,const Data &...data)134*20bfefbeSAndroid Build Coastguard Worker     static optional<Hmac> hmac256(const AuthTokenKey& key, const Data&... data) {
135*20bfefbeSAndroid Build Coastguard Worker         return Impl::hmac256(key, {data...});
136*20bfefbeSAndroid Build Coastguard Worker     }
137*20bfefbeSAndroid Build Coastguard Worker };
138*20bfefbeSAndroid Build Coastguard Worker 
139*20bfefbeSAndroid Build Coastguard Worker bool operator==(const ByteBufferProxy& lhs, const ByteBufferProxy& rhs);
140*20bfefbeSAndroid Build Coastguard Worker 
141*20bfefbeSAndroid Build Coastguard Worker template <typename IntType, uint32_t byteOrder> struct choose_hton;
142*20bfefbeSAndroid Build Coastguard Worker 
143*20bfefbeSAndroid Build Coastguard Worker template <typename IntType> struct choose_hton<IntType, __ORDER_LITTLE_ENDIAN__> {
144*20bfefbeSAndroid Build Coastguard Worker     inline static IntType hton(const IntType& value) {
145*20bfefbeSAndroid Build Coastguard Worker         IntType result = {};
146*20bfefbeSAndroid Build Coastguard Worker         const unsigned char* inbytes = reinterpret_cast<const unsigned char*>(&value);
147*20bfefbeSAndroid Build Coastguard Worker         unsigned char* outbytes = reinterpret_cast<unsigned char*>(&result);
148*20bfefbeSAndroid Build Coastguard Worker         for (int i = sizeof(IntType) - 1; i >= 0; --i) {
149*20bfefbeSAndroid Build Coastguard Worker             *(outbytes++) = inbytes[i];
150*20bfefbeSAndroid Build Coastguard Worker         }
151*20bfefbeSAndroid Build Coastguard Worker         return result;
152*20bfefbeSAndroid Build Coastguard Worker     }
153*20bfefbeSAndroid Build Coastguard Worker };
154*20bfefbeSAndroid Build Coastguard Worker 
155*20bfefbeSAndroid Build Coastguard Worker template <typename IntType> struct choose_hton<IntType, __ORDER_BIG_ENDIAN__> {
156*20bfefbeSAndroid Build Coastguard Worker     inline static IntType hton(const IntType& value) { return value; }
157*20bfefbeSAndroid Build Coastguard Worker };
158*20bfefbeSAndroid Build Coastguard Worker 
159*20bfefbeSAndroid Build Coastguard Worker template <typename IntType> inline IntType hton(const IntType& value) {
160*20bfefbeSAndroid Build Coastguard Worker     return choose_hton<IntType, __BYTE_ORDER__>::hton(value);
161*20bfefbeSAndroid Build Coastguard Worker }
162*20bfefbeSAndroid Build Coastguard Worker 
163*20bfefbeSAndroid Build Coastguard Worker template <typename IntType> inline IntType ntoh(const IntType& value) {
164*20bfefbeSAndroid Build Coastguard Worker     // same operation as hton
165*20bfefbeSAndroid Build Coastguard Worker     return choose_hton<IntType, __BYTE_ORDER__>::hton(value);
166*20bfefbeSAndroid Build Coastguard Worker }
167*20bfefbeSAndroid Build Coastguard Worker 
168*20bfefbeSAndroid Build Coastguard Worker enum class Unit : uint8_t {
169*20bfefbeSAndroid Build Coastguard Worker     PX,
170*20bfefbeSAndroid Build Coastguard Worker     DP,
171*20bfefbeSAndroid Build Coastguard Worker     MM,
172*20bfefbeSAndroid Build Coastguard Worker };
173*20bfefbeSAndroid Build Coastguard Worker 
174*20bfefbeSAndroid Build Coastguard Worker template <Unit unit> struct UnitT { constexpr static const Unit value = unit; };
175*20bfefbeSAndroid Build Coastguard Worker 
176*20bfefbeSAndroid Build Coastguard Worker using px = UnitT<Unit::PX>;
177*20bfefbeSAndroid Build Coastguard Worker using dp = UnitT<Unit::DP>;
178*20bfefbeSAndroid Build Coastguard Worker using mm = UnitT<Unit::MM>;
179*20bfefbeSAndroid Build Coastguard Worker 
180*20bfefbeSAndroid Build Coastguard Worker template <typename Unit> static constexpr const char* str = "N/A";
181*20bfefbeSAndroid Build Coastguard Worker 
182*20bfefbeSAndroid Build Coastguard Worker template <> static constexpr const char* str<px> = "px";
183*20bfefbeSAndroid Build Coastguard Worker template <> static constexpr const char* str<dp> = "dp";
184*20bfefbeSAndroid Build Coastguard Worker template <> static constexpr const char* str<mm> = "mm";
185*20bfefbeSAndroid Build Coastguard Worker 
186*20bfefbeSAndroid Build Coastguard Worker using DefaultNumericType = float;
187*20bfefbeSAndroid Build Coastguard Worker 
188*20bfefbeSAndroid Build Coastguard Worker namespace bits {
189*20bfefbeSAndroid Build Coastguard Worker 
190*20bfefbeSAndroid Build Coastguard Worker inline long double abs(long double v) {
191*20bfefbeSAndroid Build Coastguard Worker     return ::fabsl(v);
192*20bfefbeSAndroid Build Coastguard Worker }
193*20bfefbeSAndroid Build Coastguard Worker inline double abs(double v) {
194*20bfefbeSAndroid Build Coastguard Worker     return ::fabs(v);
195*20bfefbeSAndroid Build Coastguard Worker }
196*20bfefbeSAndroid Build Coastguard Worker 
197*20bfefbeSAndroid Build Coastguard Worker inline long double ceil(long double v) {
198*20bfefbeSAndroid Build Coastguard Worker     return ::ceill(v);
199*20bfefbeSAndroid Build Coastguard Worker }
200*20bfefbeSAndroid Build Coastguard Worker 
201*20bfefbeSAndroid Build Coastguard Worker inline double ceil(double v) {
202*20bfefbeSAndroid Build Coastguard Worker     return ::ceil(v);
203*20bfefbeSAndroid Build Coastguard Worker }
204*20bfefbeSAndroid Build Coastguard Worker 
205*20bfefbeSAndroid Build Coastguard Worker inline long double floor(long double v) {
206*20bfefbeSAndroid Build Coastguard Worker     return ::floorl(v);
207*20bfefbeSAndroid Build Coastguard Worker }
208*20bfefbeSAndroid Build Coastguard Worker 
209*20bfefbeSAndroid Build Coastguard Worker inline double floor(double v) {
210*20bfefbeSAndroid Build Coastguard Worker     return ::floor(v);
211*20bfefbeSAndroid Build Coastguard Worker }
212*20bfefbeSAndroid Build Coastguard Worker 
213*20bfefbeSAndroid Build Coastguard Worker inline long double sqrt(long double v) {
214*20bfefbeSAndroid Build Coastguard Worker     return ::sqrtl(v);
215*20bfefbeSAndroid Build Coastguard Worker }
216*20bfefbeSAndroid Build Coastguard Worker 
217*20bfefbeSAndroid Build Coastguard Worker inline double sqrt(double v) {
218*20bfefbeSAndroid Build Coastguard Worker     return ::sqrt(v);
219*20bfefbeSAndroid Build Coastguard Worker }
220*20bfefbeSAndroid Build Coastguard Worker 
221*20bfefbeSAndroid Build Coastguard Worker inline float round(float v) {
222*20bfefbeSAndroid Build Coastguard Worker     return ::roundf(v);
223*20bfefbeSAndroid Build Coastguard Worker }
224*20bfefbeSAndroid Build Coastguard Worker 
225*20bfefbeSAndroid Build Coastguard Worker inline long double round(long double v) {
226*20bfefbeSAndroid Build Coastguard Worker     return ::roundl(v);
227*20bfefbeSAndroid Build Coastguard Worker }
228*20bfefbeSAndroid Build Coastguard Worker 
229*20bfefbeSAndroid Build Coastguard Worker inline double round(double v) {
230*20bfefbeSAndroid Build Coastguard Worker     return ::round(v);
231*20bfefbeSAndroid Build Coastguard Worker }
232*20bfefbeSAndroid Build Coastguard Worker 
233*20bfefbeSAndroid Build Coastguard Worker }  // namespace bits
234*20bfefbeSAndroid Build Coastguard Worker 
235*20bfefbeSAndroid Build Coastguard Worker template <typename Unit, typename Numeric = DefaultNumericType> class Coordinate;
236*20bfefbeSAndroid Build Coastguard Worker 
237*20bfefbeSAndroid Build Coastguard Worker template <typename Numeric> struct Add {
238*20bfefbeSAndroid Build Coastguard Worker     constexpr static Coordinate<px, Numeric> eval(const Coordinate<px, Numeric>& v1,
239*20bfefbeSAndroid Build Coastguard Worker                                                   const Coordinate<px, Numeric>& v2) {
240*20bfefbeSAndroid Build Coastguard Worker         return v1 + v2;
241*20bfefbeSAndroid Build Coastguard Worker     }
242*20bfefbeSAndroid Build Coastguard Worker };
243*20bfefbeSAndroid Build Coastguard Worker template <typename Numeric> struct Sub {
244*20bfefbeSAndroid Build Coastguard Worker     constexpr static Coordinate<px, Numeric> eval(const Coordinate<px, Numeric>& v1,
245*20bfefbeSAndroid Build Coastguard Worker                                                   const Coordinate<px, Numeric>& v2) {
246*20bfefbeSAndroid Build Coastguard Worker         return v1 - v2;
247*20bfefbeSAndroid Build Coastguard Worker     }
248*20bfefbeSAndroid Build Coastguard Worker };
249*20bfefbeSAndroid Build Coastguard Worker template <typename Numeric> struct Mul {
250*20bfefbeSAndroid Build Coastguard Worker     constexpr static Coordinate<px, Numeric> eval(const Coordinate<px, Numeric>& v1,
251*20bfefbeSAndroid Build Coastguard Worker                                                   const Coordinate<px, Numeric>& v2) {
252*20bfefbeSAndroid Build Coastguard Worker         return v1 * v2;
253*20bfefbeSAndroid Build Coastguard Worker     }
254*20bfefbeSAndroid Build Coastguard Worker };
255*20bfefbeSAndroid Build Coastguard Worker template <typename Numeric> struct Div {
256*20bfefbeSAndroid Build Coastguard Worker     constexpr static Coordinate<px, Numeric> eval(const Coordinate<px, Numeric>& v1,
257*20bfefbeSAndroid Build Coastguard Worker                                                   const Coordinate<px, Numeric>& v2) {
258*20bfefbeSAndroid Build Coastguard Worker         return v1 / v2;
259*20bfefbeSAndroid Build Coastguard Worker     }
260*20bfefbeSAndroid Build Coastguard Worker };
261*20bfefbeSAndroid Build Coastguard Worker 
262*20bfefbeSAndroid Build Coastguard Worker template <typename T1, typename T2, typename Numeric, template <typename> class Op> struct BinOp;
263*20bfefbeSAndroid Build Coastguard Worker 
264*20bfefbeSAndroid Build Coastguard Worker template <typename T1, typename T2, typename Numeric> using add = BinOp<T1, T2, Numeric, Add>;
265*20bfefbeSAndroid Build Coastguard Worker template <typename T1, typename T2, typename Numeric> using sub = BinOp<T1, T2, Numeric, Sub>;
266*20bfefbeSAndroid Build Coastguard Worker template <typename T1, typename T2, typename Numeric> using mul = BinOp<T1, T2, Numeric, Mul>;
267*20bfefbeSAndroid Build Coastguard Worker template <typename T1, typename T2, typename Numeric> using div = BinOp<T1, T2, Numeric, Div>;
268*20bfefbeSAndroid Build Coastguard Worker 
269*20bfefbeSAndroid Build Coastguard Worker template <typename T1, typename T2, typename Numeric, template <typename> class Op> struct BinOp {
270*20bfefbeSAndroid Build Coastguard Worker   private:
271*20bfefbeSAndroid Build Coastguard Worker     T1 v1_;
272*20bfefbeSAndroid Build Coastguard Worker     T2 v2_;
273*20bfefbeSAndroid Build Coastguard Worker 
274*20bfefbeSAndroid Build Coastguard Worker   public:
275*20bfefbeSAndroid Build Coastguard Worker     constexpr BinOp(const T1& v1, const T2& v2) : v1_(v1), v2_(v2) {}
276*20bfefbeSAndroid Build Coastguard Worker     BinOp(const BinOp&) = default;
277*20bfefbeSAndroid Build Coastguard Worker     BinOp(BinOp&&) = default;
278*20bfefbeSAndroid Build Coastguard Worker 
279*20bfefbeSAndroid Build Coastguard Worker     template <typename Context> Coordinate<px, Numeric> eval(const Context& ctx) const {
280*20bfefbeSAndroid Build Coastguard Worker         Coordinate<px, Numeric> v1 = ctx = v1_;
281*20bfefbeSAndroid Build Coastguard Worker         Coordinate<px, Numeric> v2 = ctx = v2_;
282*20bfefbeSAndroid Build Coastguard Worker         return Op<Numeric>::eval(v1, v2);
283*20bfefbeSAndroid Build Coastguard Worker     }
284*20bfefbeSAndroid Build Coastguard Worker     template <typename T> constexpr add<BinOp, T, Numeric> operator+(const T& v) const {
285*20bfefbeSAndroid Build Coastguard Worker         return {*this, v};
286*20bfefbeSAndroid Build Coastguard Worker     }
287*20bfefbeSAndroid Build Coastguard Worker     template <typename T> constexpr sub<BinOp, T, Numeric> operator-(const T& v) const {
288*20bfefbeSAndroid Build Coastguard Worker         return {*this, v};
289*20bfefbeSAndroid Build Coastguard Worker     }
290*20bfefbeSAndroid Build Coastguard Worker     template <typename T> constexpr mul<BinOp, T, Numeric> operator*(const T& v) const {
291*20bfefbeSAndroid Build Coastguard Worker         return {*this, v};
292*20bfefbeSAndroid Build Coastguard Worker     }
293*20bfefbeSAndroid Build Coastguard Worker     template <typename T> constexpr div<BinOp, T, Numeric> operator/(const T& v) const {
294*20bfefbeSAndroid Build Coastguard Worker         return {*this, v};
295*20bfefbeSAndroid Build Coastguard Worker     }
296*20bfefbeSAndroid Build Coastguard Worker };
297*20bfefbeSAndroid Build Coastguard Worker 
298*20bfefbeSAndroid Build Coastguard Worker template <typename Name, typename ParamType> struct MetaParam {};
299*20bfefbeSAndroid Build Coastguard Worker 
300*20bfefbeSAndroid Build Coastguard Worker template <typename Name, typename Unit, typename Numeric>
301*20bfefbeSAndroid Build Coastguard Worker struct MetaParam<Name, Coordinate<Unit, Numeric>> {
302*20bfefbeSAndroid Build Coastguard Worker     template <typename T> constexpr add<MetaParam, T, Numeric> operator+(const T& v) const {
303*20bfefbeSAndroid Build Coastguard Worker         return {*this, v};
304*20bfefbeSAndroid Build Coastguard Worker     }
305*20bfefbeSAndroid Build Coastguard Worker     template <typename T> constexpr sub<MetaParam, T, Numeric> operator-(const T& v) const {
306*20bfefbeSAndroid Build Coastguard Worker         return {*this, v};
307*20bfefbeSAndroid Build Coastguard Worker     }
308*20bfefbeSAndroid Build Coastguard Worker     template <typename T> constexpr mul<MetaParam, T, Numeric> operator*(const T& v) const {
309*20bfefbeSAndroid Build Coastguard Worker         return {*this, v};
310*20bfefbeSAndroid Build Coastguard Worker     }
311*20bfefbeSAndroid Build Coastguard Worker     template <typename T> constexpr div<MetaParam, T, Numeric> operator/(const T& v) const {
312*20bfefbeSAndroid Build Coastguard Worker         return {*this, v};
313*20bfefbeSAndroid Build Coastguard Worker     }
314*20bfefbeSAndroid Build Coastguard Worker };
315*20bfefbeSAndroid Build Coastguard Worker 
316*20bfefbeSAndroid Build Coastguard Worker template <typename Name, typename ParamType> class Param {
317*20bfefbeSAndroid Build Coastguard Worker   private:
318*20bfefbeSAndroid Build Coastguard Worker     ParamType param_;
319*20bfefbeSAndroid Build Coastguard Worker 
320*20bfefbeSAndroid Build Coastguard Worker   public:
321*20bfefbeSAndroid Build Coastguard Worker     Param() : param_{} {}
322*20bfefbeSAndroid Build Coastguard Worker     Param(const Param&) = default;
323*20bfefbeSAndroid Build Coastguard Worker     Param(Param&&) = default;
324*20bfefbeSAndroid Build Coastguard Worker     Param& operator=(const Param&) = default;
325*20bfefbeSAndroid Build Coastguard Worker     Param& operator=(Param&&) = default;
326*20bfefbeSAndroid Build Coastguard Worker     inline const ParamType& operator*() const { return param_; }
327*20bfefbeSAndroid Build Coastguard Worker     inline ParamType& operator*() { return param_; }
328*20bfefbeSAndroid Build Coastguard Worker     inline const ParamType* operator->() const { return &param_; }
329*20bfefbeSAndroid Build Coastguard Worker     inline ParamType* operator->() { return &param_; }
330*20bfefbeSAndroid Build Coastguard Worker };
331*20bfefbeSAndroid Build Coastguard Worker 
332*20bfefbeSAndroid Build Coastguard Worker template <typename Unit, typename Numeric> class Coordinate {
333*20bfefbeSAndroid Build Coastguard Worker     Numeric value_;
334*20bfefbeSAndroid Build Coastguard Worker 
335*20bfefbeSAndroid Build Coastguard Worker   public:
336*20bfefbeSAndroid Build Coastguard Worker     using unit_t = Unit;
337*20bfefbeSAndroid Build Coastguard Worker     constexpr Coordinate() : value_{} {}
338*20bfefbeSAndroid Build Coastguard Worker     constexpr Coordinate(Numeric value) : value_(value) {}
339*20bfefbeSAndroid Build Coastguard Worker     Coordinate(const Coordinate&) = default;
340*20bfefbeSAndroid Build Coastguard Worker     Coordinate(Coordinate&&) = default;
341*20bfefbeSAndroid Build Coastguard Worker     template <typename N> Coordinate(const Coordinate<Unit, N>& other) {
342*20bfefbeSAndroid Build Coastguard Worker         if constexpr (std::is_floating_point<N>::value && std::is_integral<Numeric>::value) {
343*20bfefbeSAndroid Build Coastguard Worker             value_ = bits::round(other.count());
344*20bfefbeSAndroid Build Coastguard Worker         } else {
345*20bfefbeSAndroid Build Coastguard Worker             value_ = other.count();
346*20bfefbeSAndroid Build Coastguard Worker         }
347*20bfefbeSAndroid Build Coastguard Worker     }
348*20bfefbeSAndroid Build Coastguard Worker     Coordinate& operator=(const Coordinate& rhs) = default;
349*20bfefbeSAndroid Build Coastguard Worker     Coordinate& operator=(Coordinate&& rhs) = default;
350*20bfefbeSAndroid Build Coastguard Worker 
351*20bfefbeSAndroid Build Coastguard Worker     constexpr Coordinate operator-(const Coordinate& v) const { return value_ - v.value_; }
352*20bfefbeSAndroid Build Coastguard Worker     constexpr Coordinate operator+(const Coordinate& v) const { return value_ + v.value_; }
353*20bfefbeSAndroid Build Coastguard Worker     constexpr Coordinate& operator-=(const Coordinate& v) {
354*20bfefbeSAndroid Build Coastguard Worker         value_ -= v.value_;
355*20bfefbeSAndroid Build Coastguard Worker         return *this;
356*20bfefbeSAndroid Build Coastguard Worker     }
357*20bfefbeSAndroid Build Coastguard Worker     constexpr Coordinate& operator+=(const Coordinate& v) {
358*20bfefbeSAndroid Build Coastguard Worker         value_ += v.value_;
359*20bfefbeSAndroid Build Coastguard Worker         return *this;
360*20bfefbeSAndroid Build Coastguard Worker     }
361*20bfefbeSAndroid Build Coastguard Worker     constexpr Coordinate operator*(const Coordinate& v) const { return value_ * v.value_; }
362*20bfefbeSAndroid Build Coastguard Worker     constexpr Coordinate& operator*=(const Coordinate& v) {
363*20bfefbeSAndroid Build Coastguard Worker         value_ *= v.value_;
364*20bfefbeSAndroid Build Coastguard Worker         return *this;
365*20bfefbeSAndroid Build Coastguard Worker     }
366*20bfefbeSAndroid Build Coastguard Worker     constexpr Coordinate operator/(const Coordinate& v) const { return value_ / v.value_; }
367*20bfefbeSAndroid Build Coastguard Worker     constexpr Coordinate& operator/=(const Coordinate& v) {
368*20bfefbeSAndroid Build Coastguard Worker         value_ /= v.value_;
369*20bfefbeSAndroid Build Coastguard Worker         return *this;
370*20bfefbeSAndroid Build Coastguard Worker     }
371*20bfefbeSAndroid Build Coastguard Worker     constexpr Coordinate operator-() const { return -value_; }
372*20bfefbeSAndroid Build Coastguard Worker 
373*20bfefbeSAndroid Build Coastguard Worker     Coordinate abs() const { return bits::abs(value_); }
374*20bfefbeSAndroid Build Coastguard Worker     Coordinate ceil() const { return bits::ceil(value_); }
375*20bfefbeSAndroid Build Coastguard Worker     Coordinate floor() const { return bits::floor(value_); }
376*20bfefbeSAndroid Build Coastguard Worker     Coordinate sqrt() const { return bits::sqrt(value_); }
377*20bfefbeSAndroid Build Coastguard Worker 
378*20bfefbeSAndroid Build Coastguard Worker     constexpr bool operator==(const Coordinate& v) const { return value_ == v.value_; }
379*20bfefbeSAndroid Build Coastguard Worker     constexpr bool operator!=(const Coordinate& v) const { return !(*this == v); }
380*20bfefbeSAndroid Build Coastguard Worker     constexpr bool operator<(const Coordinate& v) const { return value_ < v.value_; }
381*20bfefbeSAndroid Build Coastguard Worker     constexpr bool operator>(const Coordinate& v) const { return v < *this; }
382*20bfefbeSAndroid Build Coastguard Worker     constexpr bool operator<=(const Coordinate& v) const { return !(v < *this); }
383*20bfefbeSAndroid Build Coastguard Worker     constexpr bool operator>=(const Coordinate& v) const { return !(*this < v); }
384*20bfefbeSAndroid Build Coastguard Worker 
385*20bfefbeSAndroid Build Coastguard Worker     template <typename T> constexpr add<Coordinate, T, Numeric> operator+(const T& v) const {
386*20bfefbeSAndroid Build Coastguard Worker         return {*this, v};
387*20bfefbeSAndroid Build Coastguard Worker     }
388*20bfefbeSAndroid Build Coastguard Worker     template <typename T> constexpr sub<Coordinate, T, Numeric> operator-(const T& v) const {
389*20bfefbeSAndroid Build Coastguard Worker         return {*this, v};
390*20bfefbeSAndroid Build Coastguard Worker     }
391*20bfefbeSAndroid Build Coastguard Worker     template <typename T> constexpr mul<Coordinate, T, Numeric> operator*(const T& v) const {
392*20bfefbeSAndroid Build Coastguard Worker         return {*this, v};
393*20bfefbeSAndroid Build Coastguard Worker     }
394*20bfefbeSAndroid Build Coastguard Worker     template <typename T> constexpr div<Coordinate, T, Numeric> operator/(const T& v) const {
395*20bfefbeSAndroid Build Coastguard Worker         return {*this, v};
396*20bfefbeSAndroid Build Coastguard Worker     }
397*20bfefbeSAndroid Build Coastguard Worker 
398*20bfefbeSAndroid Build Coastguard Worker     Numeric count() const { return value_; }
399*20bfefbeSAndroid Build Coastguard Worker };
400*20bfefbeSAndroid Build Coastguard Worker 
401*20bfefbeSAndroid Build Coastguard Worker template <typename... T> struct MetaList {};
402*20bfefbeSAndroid Build Coastguard Worker 
403*20bfefbeSAndroid Build Coastguard Worker template <typename MetaParam> struct metaParam2Param;
404*20bfefbeSAndroid Build Coastguard Worker 
405*20bfefbeSAndroid Build Coastguard Worker template <typename ParamName, typename ParamType>
406*20bfefbeSAndroid Build Coastguard Worker struct metaParam2Param<MetaParam<ParamName, ParamType>> {
407*20bfefbeSAndroid Build Coastguard Worker     using type = Param<ParamName, ParamType>;
408*20bfefbeSAndroid Build Coastguard Worker };
409*20bfefbeSAndroid Build Coastguard Worker 
410*20bfefbeSAndroid Build Coastguard Worker template <typename MetaParam> struct metaParam2ParamType;
411*20bfefbeSAndroid Build Coastguard Worker 
412*20bfefbeSAndroid Build Coastguard Worker template <typename ParamName, typename ParamType>
413*20bfefbeSAndroid Build Coastguard Worker struct metaParam2ParamType<MetaParam<ParamName, ParamType>> {
414*20bfefbeSAndroid Build Coastguard Worker     using type = ParamType;
415*20bfefbeSAndroid Build Coastguard Worker };
416*20bfefbeSAndroid Build Coastguard Worker 
417*20bfefbeSAndroid Build Coastguard Worker template <typename T> struct isCoordinateType { constexpr static const bool value = false; };
418*20bfefbeSAndroid Build Coastguard Worker 
419*20bfefbeSAndroid Build Coastguard Worker template <typename Unit, typename Numeric> struct isCoordinateType<Coordinate<Unit, Numeric>> {
420*20bfefbeSAndroid Build Coastguard Worker     constexpr static const bool value = true;
421*20bfefbeSAndroid Build Coastguard Worker };
422*20bfefbeSAndroid Build Coastguard Worker 
423*20bfefbeSAndroid Build Coastguard Worker template <typename MetaParam> struct isCoordinateParam;
424*20bfefbeSAndroid Build Coastguard Worker 
425*20bfefbeSAndroid Build Coastguard Worker template <typename ParamName, typename ParamType>
426*20bfefbeSAndroid Build Coastguard Worker struct isCoordinateParam<MetaParam<ParamName, ParamType>> {
427*20bfefbeSAndroid Build Coastguard Worker     constexpr static const bool value = isCoordinateType<ParamType>::value;
428*20bfefbeSAndroid Build Coastguard Worker };
429*20bfefbeSAndroid Build Coastguard Worker 
430*20bfefbeSAndroid Build Coastguard Worker template <typename T> struct isMetaParam { constexpr static const bool value = false; };
431*20bfefbeSAndroid Build Coastguard Worker 
432*20bfefbeSAndroid Build Coastguard Worker template <typename ParamName, typename ParamType>
433*20bfefbeSAndroid Build Coastguard Worker struct isMetaParam<MetaParam<ParamName, ParamType>> {
434*20bfefbeSAndroid Build Coastguard Worker     constexpr static const bool value = true;
435*20bfefbeSAndroid Build Coastguard Worker };
436*20bfefbeSAndroid Build Coastguard Worker 
437*20bfefbeSAndroid Build Coastguard Worker template <typename Param, typename Numeric = DefaultNumericType> class context;
438*20bfefbeSAndroid Build Coastguard Worker 
439*20bfefbeSAndroid Build Coastguard Worker template <typename... ParamsNames, typename... ParamTypes, typename Numeric>
440*20bfefbeSAndroid Build Coastguard Worker class context<MetaList<MetaParam<ParamsNames, ParamTypes>...>, Numeric> {
441*20bfefbeSAndroid Build Coastguard Worker     Numeric mm2px_;
442*20bfefbeSAndroid Build Coastguard Worker     Numeric dp2px_;
443*20bfefbeSAndroid Build Coastguard Worker     std::tuple<Param<ParamsNames, ParamTypes>...> params_;
444*20bfefbeSAndroid Build Coastguard Worker 
445*20bfefbeSAndroid Build Coastguard Worker     class Proxy {
446*20bfefbeSAndroid Build Coastguard Worker         Numeric valuepx_;
447*20bfefbeSAndroid Build Coastguard Worker         Numeric mm2px_, dp2px_;
448*20bfefbeSAndroid Build Coastguard Worker 
449*20bfefbeSAndroid Build Coastguard Worker       public:
450*20bfefbeSAndroid Build Coastguard Worker         Proxy(Numeric valuepx, Numeric mm2px, Numeric dp2px)
451*20bfefbeSAndroid Build Coastguard Worker             : valuepx_(valuepx), mm2px_(mm2px), dp2px_(dp2px) {}
452*20bfefbeSAndroid Build Coastguard Worker         Proxy(const Proxy&) = default;
453*20bfefbeSAndroid Build Coastguard Worker         Proxy(Proxy&&) = default;
454*20bfefbeSAndroid Build Coastguard Worker 
455*20bfefbeSAndroid Build Coastguard Worker         operator Coordinate<px, Numeric>() const { return valuepx_; }
456*20bfefbeSAndroid Build Coastguard Worker         operator Coordinate<mm, Numeric>() const { return valuepx_ / mm2px_; }
457*20bfefbeSAndroid Build Coastguard Worker         operator Coordinate<dp, Numeric>() const { return valuepx_ / dp2px_; }
458*20bfefbeSAndroid Build Coastguard Worker     };
459*20bfefbeSAndroid Build Coastguard Worker 
460*20bfefbeSAndroid Build Coastguard Worker   public:
461*20bfefbeSAndroid Build Coastguard Worker     explicit context(Numeric mm2px) {
462*20bfefbeSAndroid Build Coastguard Worker         mm2px_ = mm2px;
463*20bfefbeSAndroid Build Coastguard Worker         dp2px_ = (mm2px * 25.4) / 160.0; /* 1dp = 1/160th of an inch */
464*20bfefbeSAndroid Build Coastguard Worker     }
465*20bfefbeSAndroid Build Coastguard Worker 
466*20bfefbeSAndroid Build Coastguard Worker     context(Numeric mm2px, Numeric dp2px) : mm2px_(mm2px), dp2px_(dp2px) {}
467*20bfefbeSAndroid Build Coastguard Worker 
468*20bfefbeSAndroid Build Coastguard Worker     context(const context&) = default;
469*20bfefbeSAndroid Build Coastguard Worker     context(context&&) = default;
470*20bfefbeSAndroid Build Coastguard Worker     context& operator=(const context&) = default;
471*20bfefbeSAndroid Build Coastguard Worker     context& operator=(context&&) = default;
472*20bfefbeSAndroid Build Coastguard Worker 
473*20bfefbeSAndroid Build Coastguard Worker     template <typename MetaParam> auto& getParam() {
474*20bfefbeSAndroid Build Coastguard Worker         return std::get<typename metaParam2Param<MetaParam>::type>(params_);
475*20bfefbeSAndroid Build Coastguard Worker     }
476*20bfefbeSAndroid Build Coastguard Worker     template <typename MetaParam> const auto& getParam() const {
477*20bfefbeSAndroid Build Coastguard Worker         return std::get<typename metaParam2Param<MetaParam>::type>(params_);
478*20bfefbeSAndroid Build Coastguard Worker     }
479*20bfefbeSAndroid Build Coastguard Worker 
480*20bfefbeSAndroid Build Coastguard Worker     template <typename MetaParam, typename = std::enable_if_t<isCoordinateParam<MetaParam>::value>>
481*20bfefbeSAndroid Build Coastguard Worker     void setParam(const Coordinate<px, Numeric>& v) {
482*20bfefbeSAndroid Build Coastguard Worker         *getParam<MetaParam>() = v;
483*20bfefbeSAndroid Build Coastguard Worker     }
484*20bfefbeSAndroid Build Coastguard Worker 
485*20bfefbeSAndroid Build Coastguard Worker     template <typename MetaParam, typename Unit, typename N,
486*20bfefbeSAndroid Build Coastguard Worker               typename = std::enable_if_t<isCoordinateParam<MetaParam>::value>>
487*20bfefbeSAndroid Build Coastguard Worker     void setParam(const Coordinate<Unit, N>& v) {
488*20bfefbeSAndroid Build Coastguard Worker         *getParam<MetaParam>() = *this = v;
489*20bfefbeSAndroid Build Coastguard Worker     }
490*20bfefbeSAndroid Build Coastguard Worker 
491*20bfefbeSAndroid Build Coastguard Worker     template <typename MetaParam>
492*20bfefbeSAndroid Build Coastguard Worker     void setParam(std::enable_if_t<!isCoordinateParam<MetaParam>::value,
493*20bfefbeSAndroid Build Coastguard Worker                                    const typename metaParam2ParamType<MetaParam>::type>& v) {
494*20bfefbeSAndroid Build Coastguard Worker         *getParam<MetaParam>() = v;
495*20bfefbeSAndroid Build Coastguard Worker     }
496*20bfefbeSAndroid Build Coastguard Worker 
497*20bfefbeSAndroid Build Coastguard Worker     Proxy operator=(const Coordinate<px, Numeric>& rhs) const {
498*20bfefbeSAndroid Build Coastguard Worker         return {rhs.count(), mm2px_, dp2px_};
499*20bfefbeSAndroid Build Coastguard Worker     }
500*20bfefbeSAndroid Build Coastguard Worker     Proxy operator=(const Coordinate<mm, Numeric>& rhs) const {
501*20bfefbeSAndroid Build Coastguard Worker         return {rhs.count() * mm2px_, mm2px_, dp2px_};
502*20bfefbeSAndroid Build Coastguard Worker     }
503*20bfefbeSAndroid Build Coastguard Worker     Proxy operator=(const Coordinate<dp, Numeric>& rhs) const {
504*20bfefbeSAndroid Build Coastguard Worker         return {rhs.count() * dp2px_, mm2px_, dp2px_};
505*20bfefbeSAndroid Build Coastguard Worker     }
506*20bfefbeSAndroid Build Coastguard Worker     template <typename T1, typename T2, template <typename> class Op>
507*20bfefbeSAndroid Build Coastguard Worker     Proxy operator=(const BinOp<T1, T2, Numeric, Op>& rhs) const {
508*20bfefbeSAndroid Build Coastguard Worker         return {rhs.eval(*this).count(), mm2px_, dp2px_};
509*20bfefbeSAndroid Build Coastguard Worker     }
510*20bfefbeSAndroid Build Coastguard Worker     template <typename ParamName, typename ParamType>
511*20bfefbeSAndroid Build Coastguard Worker     std::enable_if_t<isCoordinateParam<MetaParam<ParamName, ParamType>>::value, Proxy>
512*20bfefbeSAndroid Build Coastguard Worker     operator=(const MetaParam<ParamName, ParamType>&) const {
513*20bfefbeSAndroid Build Coastguard Worker         return {getParam<MetaParam<ParamName, ParamType>>()->count(), mm2px_, dp2px_};
514*20bfefbeSAndroid Build Coastguard Worker     }
515*20bfefbeSAndroid Build Coastguard Worker     template <typename ParamName, typename ParamType>
516*20bfefbeSAndroid Build Coastguard Worker     std::enable_if_t<!isCoordinateParam<MetaParam<ParamName, ParamType>>::value, const ParamType&>
517*20bfefbeSAndroid Build Coastguard Worker     operator=(const MetaParam<ParamName, ParamType>&) const {
518*20bfefbeSAndroid Build Coastguard Worker         return *getParam<MetaParam<ParamName, ParamType>>();
519*20bfefbeSAndroid Build Coastguard Worker     }
520*20bfefbeSAndroid Build Coastguard Worker     template <typename T,
521*20bfefbeSAndroid Build Coastguard Worker               typename = std::enable_if_t<!(isMetaParam<T>::value || isCoordinateType<T>::value)>>
522*20bfefbeSAndroid Build Coastguard Worker     inline T&& operator=(T&& v) const {
523*20bfefbeSAndroid Build Coastguard Worker         return std::forward<T>(v);
524*20bfefbeSAndroid Build Coastguard Worker     }
525*20bfefbeSAndroid Build Coastguard Worker };
526*20bfefbeSAndroid Build Coastguard Worker 
527*20bfefbeSAndroid Build Coastguard Worker using dps = Coordinate<dp>;
528*20bfefbeSAndroid Build Coastguard Worker using mms = Coordinate<mm>;
529*20bfefbeSAndroid Build Coastguard Worker using pxs = Coordinate<px>;
530*20bfefbeSAndroid Build Coastguard Worker 
531*20bfefbeSAndroid Build Coastguard Worker constexpr dps operator""_dp(long double dp) {
532*20bfefbeSAndroid Build Coastguard Worker     return dps(dp);
533*20bfefbeSAndroid Build Coastguard Worker }
534*20bfefbeSAndroid Build Coastguard Worker constexpr mms operator""_mm(long double mm) {
535*20bfefbeSAndroid Build Coastguard Worker     return mms(mm);
536*20bfefbeSAndroid Build Coastguard Worker }
537*20bfefbeSAndroid Build Coastguard Worker constexpr pxs operator""_px(long double px) {
538*20bfefbeSAndroid Build Coastguard Worker     return pxs(px);
539*20bfefbeSAndroid Build Coastguard Worker }
540*20bfefbeSAndroid Build Coastguard Worker constexpr dps operator""_dp(unsigned long long dp) {
541*20bfefbeSAndroid Build Coastguard Worker     return dps(dp);
542*20bfefbeSAndroid Build Coastguard Worker }
543*20bfefbeSAndroid Build Coastguard Worker constexpr mms operator""_mm(unsigned long long mm) {
544*20bfefbeSAndroid Build Coastguard Worker     return mms(mm);
545*20bfefbeSAndroid Build Coastguard Worker }
546*20bfefbeSAndroid Build Coastguard Worker constexpr pxs operator""_px(unsigned long long px) {
547*20bfefbeSAndroid Build Coastguard Worker     return pxs(px);
548*20bfefbeSAndroid Build Coastguard Worker }
549*20bfefbeSAndroid Build Coastguard Worker 
550*20bfefbeSAndroid Build Coastguard Worker template <typename Coord> class Vec2d {
551*20bfefbeSAndroid Build Coastguard Worker     Coord x_, y_;
552*20bfefbeSAndroid Build Coastguard Worker 
553*20bfefbeSAndroid Build Coastguard Worker   public:
554*20bfefbeSAndroid Build Coastguard Worker     constexpr Vec2d() : x_{}, y_{} {}
555*20bfefbeSAndroid Build Coastguard Worker     constexpr Vec2d(Coord x, Coord y) : x_(x), y_(y) {}
556*20bfefbeSAndroid Build Coastguard Worker     Vec2d(const Vec2d&) = default;
557*20bfefbeSAndroid Build Coastguard Worker     Vec2d(Vec2d&&) = default;
558*20bfefbeSAndroid Build Coastguard Worker     template <typename N>
559*20bfefbeSAndroid Build Coastguard Worker     Vec2d(const Vec2d<Coordinate<typename Coord::unit_t, N>>& other)
560*20bfefbeSAndroid Build Coastguard Worker         : x_(other.x()), y_(other.y()) {}
561*20bfefbeSAndroid Build Coastguard Worker 
562*20bfefbeSAndroid Build Coastguard Worker     Vec2d& operator=(const Vec2d& rhs) = default;
563*20bfefbeSAndroid Build Coastguard Worker     Vec2d& operator=(Vec2d&& rhs) = default;
564*20bfefbeSAndroid Build Coastguard Worker 
565*20bfefbeSAndroid Build Coastguard Worker     Vec2d operator-(const Vec2d& rhs) const { return Vec2d(*this) -= rhs; }
566*20bfefbeSAndroid Build Coastguard Worker     Vec2d operator+(const Vec2d& rhs) const { return Vec2d(*this) += rhs; }
567*20bfefbeSAndroid Build Coastguard Worker     Vec2d& operator-=(const Vec2d& rhs) {
568*20bfefbeSAndroid Build Coastguard Worker         x_ -= rhs.x_;
569*20bfefbeSAndroid Build Coastguard Worker         y_ -= rhs.y_;
570*20bfefbeSAndroid Build Coastguard Worker         return *this;
571*20bfefbeSAndroid Build Coastguard Worker     }
572*20bfefbeSAndroid Build Coastguard Worker     Vec2d& operator+=(const Vec2d& rhs) {
573*20bfefbeSAndroid Build Coastguard Worker         x_ += rhs.x_;
574*20bfefbeSAndroid Build Coastguard Worker         y_ += rhs.y_;
575*20bfefbeSAndroid Build Coastguard Worker         return *this;
576*20bfefbeSAndroid Build Coastguard Worker     }
577*20bfefbeSAndroid Build Coastguard Worker     Coord operator*(const Vec2d& rhs) const { return (x_ * rhs.x_ + y_ * rhs.y_).count(); }
578*20bfefbeSAndroid Build Coastguard Worker     Vec2d operator*(const Coord& f) const { return Vec2d(*this) *= f; }
579*20bfefbeSAndroid Build Coastguard Worker     Vec2d& operator*=(const Coord& f) {
580*20bfefbeSAndroid Build Coastguard Worker         x_ *= f;
581*20bfefbeSAndroid Build Coastguard Worker         y_ *= f;
582*20bfefbeSAndroid Build Coastguard Worker         return *this;
583*20bfefbeSAndroid Build Coastguard Worker     }
584*20bfefbeSAndroid Build Coastguard Worker     Vec2d operator/(const Coord& f) { return Vec2d(*this) /= f; }
585*20bfefbeSAndroid Build Coastguard Worker     Vec2d& operator/=(const Coord& f) {
586*20bfefbeSAndroid Build Coastguard Worker         x_ /= f;
587*20bfefbeSAndroid Build Coastguard Worker         y_ /= f;
588*20bfefbeSAndroid Build Coastguard Worker         return *this;
589*20bfefbeSAndroid Build Coastguard Worker     }
590*20bfefbeSAndroid Build Coastguard Worker     bool operator==(const Vec2d& rhs) const { return x_ == rhs.x() && y_ == rhs.y(); }
591*20bfefbeSAndroid Build Coastguard Worker     Coord length() const {
592*20bfefbeSAndroid Build Coastguard Worker         Coord factor = *this * *this;
593*20bfefbeSAndroid Build Coastguard Worker         return bits::sqrt(factor.count());
594*20bfefbeSAndroid Build Coastguard Worker     }
595*20bfefbeSAndroid Build Coastguard Worker     Vec2d unit() const { return Vec2d(*this) /= length(); }
596*20bfefbeSAndroid Build Coastguard Worker     Coord x() const { return x_; }
597*20bfefbeSAndroid Build Coastguard Worker     Coord y() const { return y_; }
598*20bfefbeSAndroid Build Coastguard Worker };
599*20bfefbeSAndroid Build Coastguard Worker 
600*20bfefbeSAndroid Build Coastguard Worker #ifdef TEEUI_DO_LOG_DEBUG
601*20bfefbeSAndroid Build Coastguard Worker template <typename Unit, typename Numeric>
602*20bfefbeSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& out, const Coordinate<Unit, Numeric>& p) {
603*20bfefbeSAndroid Build Coastguard Worker     out << std::setprecision(10) << p.count() << str<Unit>;
604*20bfefbeSAndroid Build Coastguard Worker     return out;
605*20bfefbeSAndroid Build Coastguard Worker }
606*20bfefbeSAndroid Build Coastguard Worker 
607*20bfefbeSAndroid Build Coastguard Worker template <typename Coord> std::ostream& operator<<(std::ostream& out, const Vec2d<Coord>& p) {
608*20bfefbeSAndroid Build Coastguard Worker     out << "Vec2d(" << p.x() << ", " << p.y() << ")";
609*20bfefbeSAndroid Build Coastguard Worker     return out;
610*20bfefbeSAndroid Build Coastguard Worker }
611*20bfefbeSAndroid Build Coastguard Worker #endif
612*20bfefbeSAndroid Build Coastguard Worker 
613*20bfefbeSAndroid Build Coastguard Worker using Color = uint32_t;
614*20bfefbeSAndroid Build Coastguard Worker 
615*20bfefbeSAndroid Build Coastguard Worker template <typename Coord> using Point = Vec2d<Coord>;
616*20bfefbeSAndroid Build Coastguard Worker 
617*20bfefbeSAndroid Build Coastguard Worker Color drawLinePoint(Point<pxs> a, Point<pxs> b, Point<pxs> px_origin, Color c,
618*20bfefbeSAndroid Build Coastguard Worker                     pxs width = pxs(1.0));
619*20bfefbeSAndroid Build Coastguard Worker 
620*20bfefbeSAndroid Build Coastguard Worker Color drawCirclePoint(Point<pxs> center, pxs r, Point<pxs> px_origin, Color c);
621*20bfefbeSAndroid Build Coastguard Worker 
622*20bfefbeSAndroid Build Coastguard Worker using PxPoint = Point<pxs>;
623*20bfefbeSAndroid Build Coastguard Worker using PxVec = Vec2d<pxs>;
624*20bfefbeSAndroid Build Coastguard Worker 
625*20bfefbeSAndroid Build Coastguard Worker /*
626*20bfefbeSAndroid Build Coastguard Worker  * Computes the intersection of the lines given by ax + b and cy + d.
627*20bfefbeSAndroid Build Coastguard Worker  * The result may be empty if there is no solution.
628*20bfefbeSAndroid Build Coastguard Worker  */
629*20bfefbeSAndroid Build Coastguard Worker optional<PxPoint> intersect(const PxVec& a, const PxPoint& b, const PxVec& c, const PxPoint& d);
630*20bfefbeSAndroid Build Coastguard Worker 
631*20bfefbeSAndroid Build Coastguard Worker namespace bits {
632*20bfefbeSAndroid Build Coastguard Worker 
633*20bfefbeSAndroid Build Coastguard Worker static constexpr const ssize_t kIntersectEmpty = -1;
634*20bfefbeSAndroid Build Coastguard Worker /**
635*20bfefbeSAndroid Build Coastguard Worker  * Returned by the intersect if the object is in the positive half plane of the given line.
636*20bfefbeSAndroid Build Coastguard Worker  */
637*20bfefbeSAndroid Build Coastguard Worker static constexpr const ssize_t kIntersectAllPositive = -2;
638*20bfefbeSAndroid Build Coastguard Worker 
639*20bfefbeSAndroid Build Coastguard Worker ssize_t intersect(const PxPoint* oBegin, const PxPoint* oEnd, const PxPoint& lineA,
640*20bfefbeSAndroid Build Coastguard Worker                   const PxPoint& lineB, PxPoint* nBegin, PxPoint* nEnd);
641*20bfefbeSAndroid Build Coastguard Worker 
642*20bfefbeSAndroid Build Coastguard Worker pxs area(const PxPoint* begin, const PxPoint* end);
643*20bfefbeSAndroid Build Coastguard Worker 
644*20bfefbeSAndroid Build Coastguard Worker }  // namespace bits
645*20bfefbeSAndroid Build Coastguard Worker 
646*20bfefbeSAndroid Build Coastguard Worker /**
647*20bfefbeSAndroid Build Coastguard Worker  * A ConvexObject is given by a list of 2D vertexes. Each vertex must lie on the positive half-plane
648*20bfefbeSAndroid Build Coastguard Worker  * of the line denoted by its two predecessors. A point is considered inside of the convex object
649*20bfefbeSAndroid Build Coastguard Worker  * if it is on the positive half-plane of all lines given by any two subsequent vertexes.
650*20bfefbeSAndroid Build Coastguard Worker  *
651*20bfefbeSAndroid Build Coastguard Worker  * ConvexObjects have fixed size given by the capacity template argument. The geometric object
652*20bfefbeSAndroid Build Coastguard Worker  * that they describe may have any number of vertexes between 3 and capacity.
653*20bfefbeSAndroid Build Coastguard Worker  */
654*20bfefbeSAndroid Build Coastguard Worker template <size_t capacity> class ConvexObject {
655*20bfefbeSAndroid Build Coastguard Worker     template <size_t other_cap> friend class ConvexObject;
656*20bfefbeSAndroid Build Coastguard Worker 
657*20bfefbeSAndroid Build Coastguard Worker   protected:
658*20bfefbeSAndroid Build Coastguard Worker     PxPoint points_[capacity];
659*20bfefbeSAndroid Build Coastguard Worker     size_t fill_;
660*20bfefbeSAndroid Build Coastguard Worker 
661*20bfefbeSAndroid Build Coastguard Worker   public:
662*20bfefbeSAndroid Build Coastguard Worker     ConvexObject() : fill_(0) {}
663*20bfefbeSAndroid Build Coastguard Worker     explicit constexpr ConvexObject(std::initializer_list<PxPoint> l) : fill_(0) {
664*20bfefbeSAndroid Build Coastguard Worker         if (l.size() > capacity) return;
665*20bfefbeSAndroid Build Coastguard Worker         for (const auto& p : l) {
666*20bfefbeSAndroid Build Coastguard Worker             points_[fill_++] = p;
667*20bfefbeSAndroid Build Coastguard Worker         }
668*20bfefbeSAndroid Build Coastguard Worker     }
669*20bfefbeSAndroid Build Coastguard Worker     ConvexObject(const ConvexObject& other) = default;
670*20bfefbeSAndroid Build Coastguard Worker     ConvexObject(ConvexObject&& other) = default;
671*20bfefbeSAndroid Build Coastguard Worker     ConvexObject& operator=(const ConvexObject& other) = default;
672*20bfefbeSAndroid Build Coastguard Worker     ConvexObject& operator=(ConvexObject&& other) = default;
673*20bfefbeSAndroid Build Coastguard Worker 
674*20bfefbeSAndroid Build Coastguard Worker     constexpr size_t size() const { return fill_; }
675*20bfefbeSAndroid Build Coastguard Worker 
676*20bfefbeSAndroid Build Coastguard Worker     constexpr const PxPoint* begin() const { return &points_[0]; }
677*20bfefbeSAndroid Build Coastguard Worker     constexpr const PxPoint* end() const { return &points_[fill_]; }
678*20bfefbeSAndroid Build Coastguard Worker 
679*20bfefbeSAndroid Build Coastguard Worker     template <size_t result_cap>
680*20bfefbeSAndroid Build Coastguard Worker     optional<ConvexObject<result_cap>> intersect(const PxPoint& A, const PxPoint& B) const {
681*20bfefbeSAndroid Build Coastguard Worker         static_assert(result_cap >= capacity,
682*20bfefbeSAndroid Build Coastguard Worker                       "resulting capacity must be at least as large as the original");
683*20bfefbeSAndroid Build Coastguard Worker         ConvexObject<result_cap> result;
684*20bfefbeSAndroid Build Coastguard Worker         ssize_t vCount =
685*20bfefbeSAndroid Build Coastguard Worker             bits::intersect(begin(), end(), A, B, &result.points_[0], &result.points_[result_cap]);
686*20bfefbeSAndroid Build Coastguard Worker         if (vCount == bits::kIntersectEmpty) return {};
687*20bfefbeSAndroid Build Coastguard Worker         // -2 is returned if the object is in the positive half plane of the line (may be tangent)
688*20bfefbeSAndroid Build Coastguard Worker         if (vCount == bits::kIntersectAllPositive) {
689*20bfefbeSAndroid Build Coastguard Worker             std::copy(begin(), end(), &result.points_[0]);
690*20bfefbeSAndroid Build Coastguard Worker             vCount = fill_;
691*20bfefbeSAndroid Build Coastguard Worker         }
692*20bfefbeSAndroid Build Coastguard Worker         result.fill_ = vCount;
693*20bfefbeSAndroid Build Coastguard Worker         return result;
694*20bfefbeSAndroid Build Coastguard Worker     }
695*20bfefbeSAndroid Build Coastguard Worker 
696*20bfefbeSAndroid Build Coastguard Worker     template <size_t result_cap, size_t arg_cap>
697*20bfefbeSAndroid Build Coastguard Worker     optional<ConvexObject<result_cap>> intersect(const ConvexObject<arg_cap>& other) const {
698*20bfefbeSAndroid Build Coastguard Worker         return intersect<result_cap>(other.begin(), other.end());
699*20bfefbeSAndroid Build Coastguard Worker     }
700*20bfefbeSAndroid Build Coastguard Worker 
701*20bfefbeSAndroid Build Coastguard Worker     template <size_t result_cap>
702*20bfefbeSAndroid Build Coastguard Worker     optional<ConvexObject<result_cap>> intersect(const PxPoint* begin, const PxPoint* end) const {
703*20bfefbeSAndroid Build Coastguard Worker         if (end - begin < 3) return {};
704*20bfefbeSAndroid Build Coastguard Worker         auto b = begin;
705*20bfefbeSAndroid Build Coastguard Worker         auto a = end - 1;
706*20bfefbeSAndroid Build Coastguard Worker         auto result = intersect<result_cap>(*a, *b);
707*20bfefbeSAndroid Build Coastguard Worker         a = b++;
708*20bfefbeSAndroid Build Coastguard Worker         while (result && b != end) {
709*20bfefbeSAndroid Build Coastguard Worker             result = result->template intersect<result_cap>(*a, *b);
710*20bfefbeSAndroid Build Coastguard Worker             a = b++;
711*20bfefbeSAndroid Build Coastguard Worker         }
712*20bfefbeSAndroid Build Coastguard Worker         return result;
713*20bfefbeSAndroid Build Coastguard Worker     }
714*20bfefbeSAndroid Build Coastguard Worker 
715*20bfefbeSAndroid Build Coastguard Worker     pxs area() const { return bits::area(begin(), end()); }
716*20bfefbeSAndroid Build Coastguard Worker 
717*20bfefbeSAndroid Build Coastguard Worker     void push_back(const PxPoint& p) {
718*20bfefbeSAndroid Build Coastguard Worker         if (fill_ < capacity) {
719*20bfefbeSAndroid Build Coastguard Worker             points_[fill_++] = p;
720*20bfefbeSAndroid Build Coastguard Worker         }
721*20bfefbeSAndroid Build Coastguard Worker     }
722*20bfefbeSAndroid Build Coastguard Worker };
723*20bfefbeSAndroid Build Coastguard Worker 
724*20bfefbeSAndroid Build Coastguard Worker #ifdef TEEUI_DO_LOG_DEBUG
725*20bfefbeSAndroid Build Coastguard Worker template <size_t capacity>
726*20bfefbeSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& out, const ConvexObject<capacity>& o) {
727*20bfefbeSAndroid Build Coastguard Worker     out << "ConvexObject(";
728*20bfefbeSAndroid Build Coastguard Worker     bool first = true;
729*20bfefbeSAndroid Build Coastguard Worker     for (const auto& p : o) {
730*20bfefbeSAndroid Build Coastguard Worker         if (first)
731*20bfefbeSAndroid Build Coastguard Worker             first = false;
732*20bfefbeSAndroid Build Coastguard Worker         else
733*20bfefbeSAndroid Build Coastguard Worker             out << ", ";
734*20bfefbeSAndroid Build Coastguard Worker         out << p;
735*20bfefbeSAndroid Build Coastguard Worker     }
736*20bfefbeSAndroid Build Coastguard Worker     out << ")";
737*20bfefbeSAndroid Build Coastguard Worker     return out;
738*20bfefbeSAndroid Build Coastguard Worker }
739*20bfefbeSAndroid Build Coastguard Worker #endif
740*20bfefbeSAndroid Build Coastguard Worker 
741*20bfefbeSAndroid Build Coastguard Worker template <typename Coord> class Box {
742*20bfefbeSAndroid Build Coastguard Worker     Point<Coord> topLeft_;
743*20bfefbeSAndroid Build Coastguard Worker     Vec2d<Coord> extend_;
744*20bfefbeSAndroid Build Coastguard Worker 
745*20bfefbeSAndroid Build Coastguard Worker   public:
746*20bfefbeSAndroid Build Coastguard Worker     Box() {}
747*20bfefbeSAndroid Build Coastguard Worker     template <typename N>
748*20bfefbeSAndroid Build Coastguard Worker     Box(const Box<Coordinate<typename Coord::unit_t, N>>& other)
749*20bfefbeSAndroid Build Coastguard Worker         : topLeft_(other.topLeft()), extend_(other.extend()) {}
750*20bfefbeSAndroid Build Coastguard Worker     Box(const Coord& x, const Coord& y, const Coord& w, const Coord& h)
751*20bfefbeSAndroid Build Coastguard Worker         : topLeft_(x, y), extend_(w, h) {}
752*20bfefbeSAndroid Build Coastguard Worker     Box(const Point<Coord>& topLeft, const Vec2d<Coord>& extend)
753*20bfefbeSAndroid Build Coastguard Worker         : topLeft_(topLeft), extend_(extend) {}
754*20bfefbeSAndroid Build Coastguard Worker     bool contains(Point<Coord> p) const {
755*20bfefbeSAndroid Build Coastguard Worker         p -= topLeft_;
756*20bfefbeSAndroid Build Coastguard Worker         return p.y().count() >= 0 && p.y().count() <= extend_.y().count() && p.x().count() >= 0 &&
757*20bfefbeSAndroid Build Coastguard Worker                p.x().count() <= extend_.x().count();
758*20bfefbeSAndroid Build Coastguard Worker     }
759*20bfefbeSAndroid Build Coastguard Worker     bool contains(const Box& other) const {
760*20bfefbeSAndroid Build Coastguard Worker         auto br = bottomRight();
761*20bfefbeSAndroid Build Coastguard Worker         auto obr = other.bottomRight();
762*20bfefbeSAndroid Build Coastguard Worker         return topLeft_.x() <= other.topLeft_.x() && br.x() >= obr.x() &&
763*20bfefbeSAndroid Build Coastguard Worker                topLeft_.y() <= other.topLeft_.y() && br.y() >= obr.y();
764*20bfefbeSAndroid Build Coastguard Worker     }
765*20bfefbeSAndroid Build Coastguard Worker     bool overlaps(const Box& other) const {
766*20bfefbeSAndroid Build Coastguard Worker         auto br = bottomRight();
767*20bfefbeSAndroid Build Coastguard Worker         auto obr = other.bottomRight();
768*20bfefbeSAndroid Build Coastguard Worker         return topLeft_.x() < obr.x() && other.topLeft_.x() < br.x() && topLeft_.y() < obr.y() &&
769*20bfefbeSAndroid Build Coastguard Worker                other.topLeft_.y() < obr.y();
770*20bfefbeSAndroid Build Coastguard Worker     }
771*20bfefbeSAndroid Build Coastguard Worker 
772*20bfefbeSAndroid Build Coastguard Worker     /**
773*20bfefbeSAndroid Build Coastguard Worker      * fitsInside only compares the extend of the boxes. It returns true if this box would fit
774*20bfefbeSAndroid Build Coastguard Worker      * inside the other box regardless of their absolute positions.
775*20bfefbeSAndroid Build Coastguard Worker      */
776*20bfefbeSAndroid Build Coastguard Worker     bool fitsInside(const Box& other) const { return w() <= other.w() && h() <= other.w(); }
777*20bfefbeSAndroid Build Coastguard Worker     Point<Coord> bottomRight() const { return topLeft_ + extend_; }
778*20bfefbeSAndroid Build Coastguard Worker     Point<Coord> topLeft() const { return topLeft_; }
779*20bfefbeSAndroid Build Coastguard Worker     Vec2d<Coord> extend() const { return extend_; }
780*20bfefbeSAndroid Build Coastguard Worker     Coord x() const { return topLeft_.x(); }
781*20bfefbeSAndroid Build Coastguard Worker     Coord y() const { return topLeft_.y(); }
782*20bfefbeSAndroid Build Coastguard Worker     Coord w() const { return extend_.x(); }
783*20bfefbeSAndroid Build Coastguard Worker     Coord h() const { return extend_.y(); }
784*20bfefbeSAndroid Build Coastguard Worker 
785*20bfefbeSAndroid Build Coastguard Worker     Box merge(const Box& other) const {
786*20bfefbeSAndroid Build Coastguard Worker         Coord x = std::min(topLeft_.x(), other.topLeft_.x());
787*20bfefbeSAndroid Build Coastguard Worker         Coord y = std::min(topLeft_.y(), other.topLeft_.y());
788*20bfefbeSAndroid Build Coastguard Worker         auto br = bottomRight();
789*20bfefbeSAndroid Build Coastguard Worker         auto obr = other.bottomRight();
790*20bfefbeSAndroid Build Coastguard Worker         Coord w = std::max(br.x(), obr.x()) - x;
791*20bfefbeSAndroid Build Coastguard Worker         Coord h = std::max(br.y(), obr.y()) - y;
792*20bfefbeSAndroid Build Coastguard Worker         return {x, y, w, h};
793*20bfefbeSAndroid Build Coastguard Worker     }
794*20bfefbeSAndroid Build Coastguard Worker 
795*20bfefbeSAndroid Build Coastguard Worker     /**
796*20bfefbeSAndroid Build Coastguard Worker      * Returns a box that contains the this box and the given point.
797*20bfefbeSAndroid Build Coastguard Worker      */
798*20bfefbeSAndroid Build Coastguard Worker     Box merge(const Point<Coord>& p) const {
799*20bfefbeSAndroid Build Coastguard Worker         auto br = bottomRight();
800*20bfefbeSAndroid Build Coastguard Worker         TEEUI_LOG << "A tl: " << topLeft_ << " br: " << br << " new: " << p << ENDL;
801*20bfefbeSAndroid Build Coastguard Worker         Coord x = std::min(topLeft_.x(), p.x());
802*20bfefbeSAndroid Build Coastguard Worker         Coord y = std::min(topLeft_.y(), p.y());
803*20bfefbeSAndroid Build Coastguard Worker         Coord w = std::max(br.x(), p.x()) - x;
804*20bfefbeSAndroid Build Coastguard Worker         Coord h = std::max(br.y(), p.y()) - y;
805*20bfefbeSAndroid Build Coastguard Worker         TEEUI_LOG << "B x: " << x << " y: " << y << " w: " << w << " h: " << h << ENDL;
806*20bfefbeSAndroid Build Coastguard Worker         return {x, y, w, h};
807*20bfefbeSAndroid Build Coastguard Worker     }
808*20bfefbeSAndroid Build Coastguard Worker 
809*20bfefbeSAndroid Build Coastguard Worker     /**
810*20bfefbeSAndroid Build Coastguard Worker      * Returns a box that contains this box and all of the given points.
811*20bfefbeSAndroid Build Coastguard Worker      */
812*20bfefbeSAndroid Build Coastguard Worker     Box merge(const Point<Coord>* begin, const Point<Coord>* end) const {
813*20bfefbeSAndroid Build Coastguard Worker         auto tl = topLeft();
814*20bfefbeSAndroid Build Coastguard Worker         auto br = bottomRight();
815*20bfefbeSAndroid Build Coastguard Worker         while (begin != end) {
816*20bfefbeSAndroid Build Coastguard Worker             TEEUI_LOG << "A tl: " << tl << " br: " << br << " new: " << *begin << ENDL;
817*20bfefbeSAndroid Build Coastguard Worker             tl = {std::min(tl.x(), begin->x()), std::min(tl.y(), begin->y())};
818*20bfefbeSAndroid Build Coastguard Worker             br = {std::max(br.x(), begin->x()), std::max(br.y(), begin->y())};
819*20bfefbeSAndroid Build Coastguard Worker             TEEUI_LOG << "B tl: " << tl << " br: " << br << " new: " << *begin << ENDL;
820*20bfefbeSAndroid Build Coastguard Worker             ++begin;
821*20bfefbeSAndroid Build Coastguard Worker         }
822*20bfefbeSAndroid Build Coastguard Worker         return {tl, br - tl};
823*20bfefbeSAndroid Build Coastguard Worker     }
824*20bfefbeSAndroid Build Coastguard Worker 
825*20bfefbeSAndroid Build Coastguard Worker     /**
826*20bfefbeSAndroid Build Coastguard Worker      * Creates a box that contains all of the given points.
827*20bfefbeSAndroid Build Coastguard Worker      */
828*20bfefbeSAndroid Build Coastguard Worker     static Box boundingBox(const Point<Coord>* begin, const Point<Coord>* end) {
829*20bfefbeSAndroid Build Coastguard Worker         if (begin == end) return {};
830*20bfefbeSAndroid Build Coastguard Worker         Box result(*begin, {0, 0});
831*20bfefbeSAndroid Build Coastguard Worker         result.merge(begin + 1, end);
832*20bfefbeSAndroid Build Coastguard Worker         return result;
833*20bfefbeSAndroid Build Coastguard Worker     }
834*20bfefbeSAndroid Build Coastguard Worker 
835*20bfefbeSAndroid Build Coastguard Worker     /*
836*20bfefbeSAndroid Build Coastguard Worker      * Translates the Box by the given offset. And returns a reference to itself
837*20bfefbeSAndroid Build Coastguard Worker      */
838*20bfefbeSAndroid Build Coastguard Worker     Box& translateSelf(const Point<Coord>& offset) {
839*20bfefbeSAndroid Build Coastguard Worker         topLeft_ += offset;
840*20bfefbeSAndroid Build Coastguard Worker         return *this;
841*20bfefbeSAndroid Build Coastguard Worker     }
842*20bfefbeSAndroid Build Coastguard Worker     /*
843*20bfefbeSAndroid Build Coastguard Worker      * Returns copy of this box translated by offset.
844*20bfefbeSAndroid Build Coastguard Worker      */
845*20bfefbeSAndroid Build Coastguard Worker     Box translate(const Point<Coord>& offset) const& {
846*20bfefbeSAndroid Build Coastguard Worker         Box result = *this;
847*20bfefbeSAndroid Build Coastguard Worker         result.topLeft_ += offset;
848*20bfefbeSAndroid Build Coastguard Worker         return result;
849*20bfefbeSAndroid Build Coastguard Worker     }
850*20bfefbeSAndroid Build Coastguard Worker     /*
851*20bfefbeSAndroid Build Coastguard Worker      * When called on a temporary just reuse this box.
852*20bfefbeSAndroid Build Coastguard Worker      */
853*20bfefbeSAndroid Build Coastguard Worker     Box translate(const Point<Coord>& offset) && {
854*20bfefbeSAndroid Build Coastguard Worker         topLeft_ += offset;
855*20bfefbeSAndroid Build Coastguard Worker         return *this;
856*20bfefbeSAndroid Build Coastguard Worker     }
857*20bfefbeSAndroid Build Coastguard Worker };
858*20bfefbeSAndroid Build Coastguard Worker 
859*20bfefbeSAndroid Build Coastguard Worker #ifdef TEEUI_DO_LOG_DEBUG
860*20bfefbeSAndroid Build Coastguard Worker template <typename Coord> std::ostream& operator<<(std::ostream& out, const Box<Coord>& p) {
861*20bfefbeSAndroid Build Coastguard Worker     out << "Box(x: " << p.x().count() << " y: " << p.y().count() << " w: " << p.w().count()
862*20bfefbeSAndroid Build Coastguard Worker         << " h: " << p.h().count() << ")";
863*20bfefbeSAndroid Build Coastguard Worker     return out;
864*20bfefbeSAndroid Build Coastguard Worker }
865*20bfefbeSAndroid Build Coastguard Worker #endif
866*20bfefbeSAndroid Build Coastguard Worker 
867*20bfefbeSAndroid Build Coastguard Worker enum class EventType : uint8_t {
868*20bfefbeSAndroid Build Coastguard Worker     KeyDown,
869*20bfefbeSAndroid Build Coastguard Worker     KeyUp,
870*20bfefbeSAndroid Build Coastguard Worker     KeyMoved,
871*20bfefbeSAndroid Build Coastguard Worker };
872*20bfefbeSAndroid Build Coastguard Worker 
873*20bfefbeSAndroid Build Coastguard Worker struct Event {
874*20bfefbeSAndroid Build Coastguard Worker     uint32_t x_;
875*20bfefbeSAndroid Build Coastguard Worker     uint32_t y_;
876*20bfefbeSAndroid Build Coastguard Worker     EventType event_;
877*20bfefbeSAndroid Build Coastguard Worker };
878*20bfefbeSAndroid Build Coastguard Worker 
879*20bfefbeSAndroid Build Coastguard Worker template <typename Fn> struct Callback;
880*20bfefbeSAndroid Build Coastguard Worker 
881*20bfefbeSAndroid Build Coastguard Worker template <typename Ret, typename... Args> struct Callback<Ret(Args...)> {
882*20bfefbeSAndroid Build Coastguard Worker     Ret (*callback_)(Args... args, void* priv_data);
883*20bfefbeSAndroid Build Coastguard Worker     void* priv_data_;
884*20bfefbeSAndroid Build Coastguard Worker     Ret operator()(Args... args) const { return callback_(args..., priv_data_); }
885*20bfefbeSAndroid Build Coastguard Worker };
886*20bfefbeSAndroid Build Coastguard Worker 
887*20bfefbeSAndroid Build Coastguard Worker template <typename Ret, typename... Args>
888*20bfefbeSAndroid Build Coastguard Worker Callback<Ret(Args...)> makeCallback(Ret (*fn)(Args..., void*), void* priv_data) {
889*20bfefbeSAndroid Build Coastguard Worker     return {fn, priv_data};
890*20bfefbeSAndroid Build Coastguard Worker }
891*20bfefbeSAndroid Build Coastguard Worker 
892*20bfefbeSAndroid Build Coastguard Worker template <typename Fn, typename Ret, typename... Args> struct CallbackHelper {
893*20bfefbeSAndroid Build Coastguard Worker     Fn fn_;
894*20bfefbeSAndroid Build Coastguard Worker     operator Callback<Ret(Args...)>() {
895*20bfefbeSAndroid Build Coastguard Worker         return makeCallback<Ret, Args...>(
896*20bfefbeSAndroid Build Coastguard Worker             [](Args... args, void* priv_data) -> Ret {
897*20bfefbeSAndroid Build Coastguard Worker                 return reinterpret_cast<CallbackHelper*>(priv_data)->fn_(args...);
898*20bfefbeSAndroid Build Coastguard Worker             },
899*20bfefbeSAndroid Build Coastguard Worker             this);
900*20bfefbeSAndroid Build Coastguard Worker     }
901*20bfefbeSAndroid Build Coastguard Worker };
902*20bfefbeSAndroid Build Coastguard Worker 
903*20bfefbeSAndroid Build Coastguard Worker using CallbackEvent = Callback<Error(Event)>;
904*20bfefbeSAndroid Build Coastguard Worker using PixelDrawer = Callback<Error(uint32_t, uint32_t, Color)>;
905*20bfefbeSAndroid Build Coastguard Worker 
906*20bfefbeSAndroid Build Coastguard Worker template <typename Fn>
907*20bfefbeSAndroid Build Coastguard Worker using PixelDrawerHelper = CallbackHelper<Fn, Error, uint32_t, uint32_t, Color>;
908*20bfefbeSAndroid Build Coastguard Worker 
909*20bfefbeSAndroid Build Coastguard Worker template <typename Fn> PixelDrawerHelper<Fn> makePixelDrawer(Fn fn) {
910*20bfefbeSAndroid Build Coastguard Worker     return PixelDrawerHelper<Fn>{fn};
911*20bfefbeSAndroid Build Coastguard Worker }
912*20bfefbeSAndroid Build Coastguard Worker 
913*20bfefbeSAndroid Build Coastguard Worker template <typename Derived> struct LayoutElement {
914*20bfefbeSAndroid Build Coastguard Worker     Box<pxs> bounds_;
915*20bfefbeSAndroid Build Coastguard Worker     LayoutElement() = default;
916*20bfefbeSAndroid Build Coastguard Worker     template <typename Context>
917*20bfefbeSAndroid Build Coastguard Worker     LayoutElement(const Context& context)
918*20bfefbeSAndroid Build Coastguard Worker         : bounds_{context = Derived::pos_x, context = Derived::pos_y, context = Derived::dim_w,
919*20bfefbeSAndroid Build Coastguard Worker                   context = Derived::dim_h} {}
920*20bfefbeSAndroid Build Coastguard Worker 
921*20bfefbeSAndroid Build Coastguard Worker     Error draw(const PixelDrawer&) { return Error::OK; }
922*20bfefbeSAndroid Build Coastguard Worker     Error hit(const Event&) { return Error::OK; }
923*20bfefbeSAndroid Build Coastguard Worker };
924*20bfefbeSAndroid Build Coastguard Worker 
925*20bfefbeSAndroid Build Coastguard Worker template <typename... Elements, typename Context>
926*20bfefbeSAndroid Build Coastguard Worker std::tuple<Elements...> instantiateLayout(MetaList<Elements...>, const Context& context) {
927*20bfefbeSAndroid Build Coastguard Worker     std::tuple<Elements...> result{Elements(context)...};
928*20bfefbeSAndroid Build Coastguard Worker     return result;
929*20bfefbeSAndroid Build Coastguard Worker }
930*20bfefbeSAndroid Build Coastguard Worker 
931*20bfefbeSAndroid Build Coastguard Worker template <typename T> struct MetaList2Layout;
932*20bfefbeSAndroid Build Coastguard Worker 
933*20bfefbeSAndroid Build Coastguard Worker template <typename... Elements> struct MetaList2Layout<MetaList<Elements...>> {
934*20bfefbeSAndroid Build Coastguard Worker     using type = std::tuple<Elements...>;
935*20bfefbeSAndroid Build Coastguard Worker };
936*20bfefbeSAndroid Build Coastguard Worker 
937*20bfefbeSAndroid Build Coastguard Worker template <typename T> using layout_t = typename MetaList2Layout<T>::type;
938*20bfefbeSAndroid Build Coastguard Worker 
939*20bfefbeSAndroid Build Coastguard Worker template <typename... Coords>
940*20bfefbeSAndroid Build Coastguard Worker constexpr inline std::tuple<Vec2d<Coords>...> makeConvexObject(const Vec2d<Coords>&... points) {
941*20bfefbeSAndroid Build Coastguard Worker     return {points...};
942*20bfefbeSAndroid Build Coastguard Worker }
943*20bfefbeSAndroid Build Coastguard Worker 
944*20bfefbeSAndroid Build Coastguard Worker template <size_t capacity, typename Tuple, typename Context, size_t... I>
945*20bfefbeSAndroid Build Coastguard Worker constexpr inline ConvexObject<capacity>
946*20bfefbeSAndroid Build Coastguard Worker initConvexObject(const Context& context, const Tuple& outline, std::index_sequence<I...>) {
947*20bfefbeSAndroid Build Coastguard Worker     return ConvexObject<capacity>(
948*20bfefbeSAndroid Build Coastguard Worker         {PxVec(context = std::get<I>(outline).x(), context = std::get<I>(outline).y())...});
949*20bfefbeSAndroid Build Coastguard Worker }
950*20bfefbeSAndroid Build Coastguard Worker 
951*20bfefbeSAndroid Build Coastguard Worker template <size_t capacity, typename... Points, typename Context>
952*20bfefbeSAndroid Build Coastguard Worker constexpr inline ConvexObject<capacity> initConvexObject(const Context& context,
953*20bfefbeSAndroid Build Coastguard Worker                                                          const std::tuple<Points...>& outline) {
954*20bfefbeSAndroid Build Coastguard Worker     return initConvexObject<capacity>(context, outline, std::index_sequence_for<Points...>{});
955*20bfefbeSAndroid Build Coastguard Worker }
956*20bfefbeSAndroid Build Coastguard Worker 
957*20bfefbeSAndroid Build Coastguard Worker template <size_t capacity, typename Tuple, typename Context, size_t... I, size_t size>
958*20bfefbeSAndroid Build Coastguard Worker constexpr inline void initConvexObjectArray(const Context& context,
959*20bfefbeSAndroid Build Coastguard Worker                                             ConvexObject<capacity> (&out)[size], const Tuple& t,
960*20bfefbeSAndroid Build Coastguard Worker                                             std::index_sequence<I...>) {
961*20bfefbeSAndroid Build Coastguard Worker     static_assert(sizeof...(I) <= size,
962*20bfefbeSAndroid Build Coastguard Worker                   "Array to initialize must be big enough to hold all tuple elements");
963*20bfefbeSAndroid Build Coastguard Worker     [](auto...) {}((out[I] = initConvexObject<capacity>(context, std::get<I>(t)))...);
964*20bfefbeSAndroid Build Coastguard Worker }
965*20bfefbeSAndroid Build Coastguard Worker 
966*20bfefbeSAndroid Build Coastguard Worker template <size_t capacity, typename... COs, typename Context, size_t size>
967*20bfefbeSAndroid Build Coastguard Worker constexpr inline void initConvexObjectArray(const Context& context,
968*20bfefbeSAndroid Build Coastguard Worker                                             ConvexObject<capacity> (&out)[size],
969*20bfefbeSAndroid Build Coastguard Worker                                             const std::tuple<COs...>& t) {
970*20bfefbeSAndroid Build Coastguard Worker     initConvexObjectArray(context, out, t, std::index_sequence_for<COs...>());
971*20bfefbeSAndroid Build Coastguard Worker }
972*20bfefbeSAndroid Build Coastguard Worker 
973*20bfefbeSAndroid Build Coastguard Worker template <typename Iterator> class Range {
974*20bfefbeSAndroid Build Coastguard Worker     Iterator begin_;
975*20bfefbeSAndroid Build Coastguard Worker     Iterator end_;
976*20bfefbeSAndroid Build Coastguard Worker 
977*20bfefbeSAndroid Build Coastguard Worker   public:
978*20bfefbeSAndroid Build Coastguard Worker     Range(Iterator begin, Iterator end) : begin_(begin), end_(end) {}
979*20bfefbeSAndroid Build Coastguard Worker     const Iterator begin() const { return begin_; }
980*20bfefbeSAndroid Build Coastguard Worker     const Iterator end() const { return end_; }
981*20bfefbeSAndroid Build Coastguard Worker };
982*20bfefbeSAndroid Build Coastguard Worker 
983*20bfefbeSAndroid Build Coastguard Worker template <typename Iterator> Range<Iterator> makeRange(Iterator begin, Iterator end) {
984*20bfefbeSAndroid Build Coastguard Worker     return {begin, end};
985*20bfefbeSAndroid Build Coastguard Worker }
986*20bfefbeSAndroid Build Coastguard Worker 
987*20bfefbeSAndroid Build Coastguard Worker }  // namespace teeui
988*20bfefbeSAndroid Build Coastguard Worker 
989*20bfefbeSAndroid Build Coastguard Worker #define Position(x, y)                                                                             \
990*20bfefbeSAndroid Build Coastguard Worker     static const constexpr auto pos_x = x;                                                         \
991*20bfefbeSAndroid Build Coastguard Worker     static const constexpr auto pos_y = y
992*20bfefbeSAndroid Build Coastguard Worker 
993*20bfefbeSAndroid Build Coastguard Worker #define Dimension(w, h)                                                                            \
994*20bfefbeSAndroid Build Coastguard Worker     static const constexpr auto dim_w = w;                                                         \
995*20bfefbeSAndroid Build Coastguard Worker     static const constexpr auto dim_h = h
996*20bfefbeSAndroid Build Coastguard Worker 
997*20bfefbeSAndroid Build Coastguard Worker #define BEGIN_ELEMENT(name, type, ...)                                                             \
998*20bfefbeSAndroid Build Coastguard Worker     struct name : public type<name, ##__VA_ARGS__> {                                               \
999*20bfefbeSAndroid Build Coastguard Worker         name() = default;                                                                          \
1000*20bfefbeSAndroid Build Coastguard Worker         template <typename Context>                                                                \
1001*20bfefbeSAndroid Build Coastguard Worker         name(const Context& context) : type<name, ##__VA_ARGS__>(context) {}
1002*20bfefbeSAndroid Build Coastguard Worker 
1003*20bfefbeSAndroid Build Coastguard Worker #define END_ELEMENT() }
1004*20bfefbeSAndroid Build Coastguard Worker 
1005*20bfefbeSAndroid Build Coastguard Worker #define DECLARE_TYPED_PARAMETER(name, type)                                                        \
1006*20bfefbeSAndroid Build Coastguard Worker     struct Param_##name {};                                                                        \
1007*20bfefbeSAndroid Build Coastguard Worker     using name = ::teeui::MetaParam<Param_##name, type>
1008*20bfefbeSAndroid Build Coastguard Worker 
1009*20bfefbeSAndroid Build Coastguard Worker #define DECLARE_PARAMETER(name) DECLARE_TYPED_PARAMETER(name, ::teeui::pxs)
1010*20bfefbeSAndroid Build Coastguard Worker 
1011*20bfefbeSAndroid Build Coastguard Worker #define CONSTANT(name, value) static constexpr const auto name = value
1012*20bfefbeSAndroid Build Coastguard Worker 
1013*20bfefbeSAndroid Build Coastguard Worker #define BOTTOM_EDGE_OF(name) (name::pos_y + name::dim_h)
1014*20bfefbeSAndroid Build Coastguard Worker 
1015*20bfefbeSAndroid Build Coastguard Worker #define CONVEX_OBJECT(...) makeConvexObject(__VA_ARGS__)
1016*20bfefbeSAndroid Build Coastguard Worker 
1017*20bfefbeSAndroid Build Coastguard Worker #define CONVEX_OBJECTS(...) std::make_tuple(__VA_ARGS__)
1018*20bfefbeSAndroid Build Coastguard Worker 
1019*20bfefbeSAndroid Build Coastguard Worker /**
1020*20bfefbeSAndroid Build Coastguard Worker  * Creates a new Layout with the name "name" followed by a list of Layout elements as defined with
1021*20bfefbeSAndroid Build Coastguard Worker  * BEGIN_ELEMENT(name).
1022*20bfefbeSAndroid Build Coastguard Worker  */
1023*20bfefbeSAndroid Build Coastguard Worker #define NEW_LAYOUT(name, ...) using name = ::teeui::MetaList<__VA_ARGS__>
1024*20bfefbeSAndroid Build Coastguard Worker 
1025*20bfefbeSAndroid Build Coastguard Worker #define NEW_PARAMETER_SET(name, ...) using name = ::teeui::MetaList<__VA_ARGS__>
1026*20bfefbeSAndroid Build Coastguard Worker 
1027*20bfefbeSAndroid Build Coastguard Worker #define LABELS(name, ...) using ::teeui::MetaList<__VA_ARGS__>
1028*20bfefbeSAndroid Build Coastguard Worker 
1029*20bfefbeSAndroid Build Coastguard Worker #define TEXT_ID(textId) static_cast<uint32_t>(textId)
1030*20bfefbeSAndroid Build Coastguard Worker #endif  // TEEUI_LIBTEEUI_UTILS_H_
1031