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 ¶m_; } 329*20bfefbeSAndroid Build Coastguard Worker inline ParamType* operator->() { return ¶m_; } 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