1 /* 2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_DIMENSION_H 17 #define FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_DIMENSION_H 18 19 #include <string> 20 21 #include "base/utils/macros.h" 22 #include "base/utils/system_properties.h" 23 #include "base/utils/utils.h" 24 25 #define NEAR_ZERO(value) ((value > 0.0) ? ((value - 0.0) <= 0.000001f) : ((0.0 - value) <= 0.000001f)) 26 27 namespace OHOS::Ace { 28 29 enum class DimensionUnit { 30 /* 31 * Logical pixel used in Ace1.0. It's based on frontend design width. 32 * For example, when a frontend with 750px design width running on a 33 * device with 1080 pixels width, 1px represents 1.44 pixels. 34 */ 35 PX = 0, 36 /* 37 * Density independent pixels, one vp is one pixel on a 160 dpi screen. 38 */ 39 VP, 40 /* 41 * Scale independent pixels. This is like VP but will be scaled by 42 * user's font size preference. 43 */ 44 FP, 45 /* 46 * The percentage of either a value from the element's parent or from 47 * another property of the element itself. 48 */ 49 PERCENT, 50 /* 51 * logic pixels used in ACE2.0 instead of PX, and PX is the physical pixels in ACE2.0 52 */ 53 LPX, 54 /* 55 * The value is calculated from the element's parent and another property of the element itself. 56 */ 57 AUTO, 58 /* 59 * The value is expression. 60 */ 61 CALC, 62 }; 63 64 /* 65 * Dimension contains a value and an unit to represent different 66 * scales in one class. 67 */ 68 class Dimension { 69 public: 70 constexpr Dimension() = default; 71 ~Dimension() = default; value_(value)72 constexpr explicit Dimension(double value, DimensionUnit unit = DimensionUnit::PX) : value_(value), unit_(unit) {} 73 Value()74 constexpr double Value() const 75 { 76 return value_; 77 } 78 SetValue(double value)79 void SetValue(double value) 80 { 81 value_ = value; 82 } 83 Unit()84 constexpr DimensionUnit Unit() const 85 { 86 return unit_; 87 } 88 SetUnit(DimensionUnit unit)89 void SetUnit(DimensionUnit unit) 90 { 91 unit_ = unit; 92 } 93 IsValid()94 bool IsValid() const 95 { 96 return (value_ > 0.0) && (!NearZero(value_)); 97 } 98 ConvertToPx(double dipScale)99 double ConvertToPx(double dipScale) const 100 { 101 if (unit_ == DimensionUnit::VP || unit_ == DimensionUnit::FP) { 102 return value_ * dipScale; 103 } else { 104 return value_; 105 } 106 } 107 ConvertToVp()108 double ConvertToVp() const 109 { 110 if (unit_ == DimensionUnit::VP) { 111 return value_; 112 } 113 if (unit_ == DimensionUnit::PX) { 114 return SystemProperties::Px2Vp(value_); 115 } 116 // TODO: add fp and lpx convert. 117 return 0; 118 } 119 ConvertToPx()120 double ConvertToPx() const 121 { 122 if (unit_ == DimensionUnit::PX) { 123 return value_; 124 } 125 if (unit_ == DimensionUnit::VP) { 126 return SystemProperties::Vp2Px(value_); 127 } 128 return 0; 129 } 130 131 constexpr Dimension operator*(double value) const 132 { 133 return Dimension(value_ * value, unit_); 134 } 135 136 constexpr Dimension operator/(double value) const 137 { 138 // NearZero cannot be used in a constant expression 139 if (NEAR_ZERO(value)) { 140 return Dimension(); 141 } 142 return Dimension(value_ / value, unit_); 143 } 144 145 bool operator==(const Dimension& dimension) const 146 { 147 return (unit_ == dimension.unit_) && NearEqual(value_, dimension.value_); 148 } 149 150 bool operator!=(const Dimension& dimension) const 151 { 152 return !operator==(dimension); 153 } 154 155 /* 156 * Add two dimensions using the same unit. 157 */ 158 constexpr Dimension operator+(const Dimension& dimension) const 159 { 160 if (NEAR_ZERO(dimension.Value())) { 161 return *this; 162 } 163 ACE_DCHECK(unit_ == dimension.unit_); 164 return Dimension(value_ + dimension.value_, unit_); 165 } 166 167 /* 168 * Add a new dimension to itself using same unit. 169 */ 170 Dimension& operator+=(const Dimension& dimension) 171 { 172 ACE_DCHECK(unit_ == dimension.unit_); 173 value_ += dimension.value_; 174 return *this; 175 } 176 177 /* 178 * Minus a dimension using the same unit. 179 */ 180 constexpr Dimension operator-(const Dimension& dimension) const 181 { 182 if (NEAR_ZERO(dimension.Value())) { 183 return *this; 184 } 185 ACE_DCHECK(unit_ == dimension.unit_); 186 return Dimension(value_ - dimension.value_, unit_); 187 } 188 189 /* 190 * The opposite of dimension. 191 */ 192 constexpr Dimension operator-() const 193 { 194 return Dimension(-value_, unit_); 195 } 196 197 /* 198 * Minus a dimension to itself using the same unit. 199 */ 200 Dimension& operator-=(const Dimension& dimension) 201 { 202 ACE_DCHECK(unit_ == dimension.unit_); 203 value_ -= dimension.value_; 204 return *this; 205 } 206 207 bool operator>(const Dimension& dimension) const 208 { 209 ACE_DCHECK(unit_ == dimension.unit_); 210 return (value_ > dimension.value_); 211 } 212 213 bool operator<(const Dimension& dimension) const 214 { 215 ACE_DCHECK(unit_ == dimension.unit_); 216 return (value_ < dimension.value_); 217 } 218 219 std::string ToString() const; 220 221 private: 222 double value_ = 0.0; 223 DimensionUnit unit_ = DimensionUnit::PX; 224 }; 225 226 // literal operators for dimension 227 inline constexpr Dimension operator""_vp(long double value) 228 { 229 return Dimension(static_cast<double>(value), DimensionUnit::VP); 230 } 231 232 inline constexpr Dimension operator""_px(long double value) 233 { 234 return Dimension(static_cast<double>(value), DimensionUnit::PX); 235 } 236 237 inline constexpr Dimension operator""_fp(long double value) 238 { 239 return Dimension(static_cast<double>(value), DimensionUnit::FP); 240 } 241 242 inline constexpr Dimension operator""_pct(long double value) 243 { 244 return Dimension(static_cast<double>(value), DimensionUnit::PERCENT); 245 } 246 247 } // namespace OHOS::Ace 248 249 #endif // FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_DIMENSION_H 250