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 enum class DimensionUnit { 29 /* 30 * Unit is invalid. 31 */ 32 INVALID = -2, 33 /* 34 * Unit is empty. 35 */ 36 NONE = -1, 37 /* 38 * Logical pixel used in Ace1.0. It's based on frontend design width. 39 * For example, when a frontend with 750px design width running on a 40 * device with 1080 pixels width, 1px represents 1.44 pixels. 41 */ 42 PX = 0, 43 /* 44 * Density independent pixels, one vp is one pixel on a 160 dpi screen. 45 */ 46 VP, 47 /* 48 * Scale independent pixels. This is like VP but will be scaled by 49 * user's font size preference. 50 */ 51 FP, 52 /* 53 * The percentage of either a value from the element's parent or from 54 * another property of the element itself. 55 */ 56 PERCENT, 57 /* 58 * logic pixels used in ACE2.0 instead of PX, and PX is the physical pixels in ACE2.0 59 */ 60 LPX, 61 /* 62 * The value is calculated from the element's parent and another property of the element itself. 63 */ 64 AUTO, 65 /* 66 * The value is expression. 67 */ 68 CALC, 69 }; 70 71 /* 72 * Dimension contains a value and an unit to represent different 73 * scales in one class. 74 */ 75 class ACE_FORCE_EXPORT Dimension { 76 public: 77 constexpr Dimension() = default; 78 ~Dimension() = default; 79 constexpr explicit Dimension(double value, DimensionUnit unit = DimensionUnit::PX) : value_(value), unit_(unit) {} 80 Reset()81 void Reset() 82 { 83 value_ = 0.0; 84 unit_ = DimensionUnit::PX; 85 } 86 ResetInvalidValue()87 void ResetInvalidValue() 88 { 89 if (std::isnan(value_)) { 90 Reset(); 91 } 92 } 93 Value()94 constexpr double Value() const 95 { 96 return value_; 97 } 98 SetValue(double value)99 void SetValue(double value) 100 { 101 value_ = value; 102 } 103 Unit()104 constexpr DimensionUnit Unit() const 105 { 106 return unit_; 107 } 108 SetUnit(DimensionUnit unit)109 void SetUnit(DimensionUnit unit) 110 { 111 unit_ = unit; 112 } 113 IsValid()114 bool IsValid() const 115 { 116 return GreatNotEqual(value_, 0.0); 117 } 118 IsNonNegative()119 bool IsNonNegative() const 120 { 121 return NonNegative(value_); 122 } 123 IsNonPositive()124 bool IsNonPositive() const 125 { 126 return NonPositive(value_); 127 } 128 IsNegative()129 bool IsNegative() const 130 { 131 return !NonNegative(value_); 132 } 133 134 // Deprecated: don't use this to covert to px. ConvertToPx(double dipScale)135 double ConvertToPx(double dipScale) const 136 { 137 if (unit_ == DimensionUnit::VP || unit_ == DimensionUnit::FP) { 138 return value_ * dipScale; 139 } 140 return value_; 141 } 142 143 // Percentage unit conversion is not supported. 144 double ConvertToVp() const; 145 146 // Percentage unit conversion is not supported. 147 double ConvertToPx() const; 148 149 // Percentage unit conversion is not supported. 150 double ConvertToFp() const; 151 152 DimensionUnit GetAdaptDimensionUnit(const Dimension& dimension); 153 154 double ConvertToPxDistribute( 155 std::optional<float> minOptional, std::optional<float> maxOptional, bool allowScale = true) const; 156 157 double ConvertToPxByCustomFontScale(float minFontScale, float maxFontScale) const; 158 159 double ConvertToPxByAppFontScale(float minFontScale) const; 160 161 double ConvertToVpByAppFontScale() const; 162 GetNativeValue(DimensionUnit unit)163 double GetNativeValue(DimensionUnit unit) const 164 { 165 if (unit_ == unit || unit == DimensionUnit::PERCENT) { 166 return value_; 167 } else if (unit == DimensionUnit::PX) { 168 return ConvertToPx(); 169 } else if (unit == DimensionUnit::FP) { 170 return ConvertToFp(); 171 } else { 172 return ConvertToVp(); 173 } 174 } 175 176 // support percentage unit conversion 177 double ConvertToPxWithSize(double size) const; 178 179 bool NormalizeToPx(double vpScale, double fpScale, double lpxScale, double parentLength, double& result) const; 180 181 constexpr Dimension operator*(double value) const 182 { 183 return Dimension(value_ * value, unit_); 184 } 185 186 constexpr Dimension operator/(double value) const 187 { 188 // NearZero cannot be used in a constant expression 189 if (NEAR_ZERO(value)) { 190 return {}; 191 } 192 return Dimension(value_ / value, unit_); 193 } 194 195 bool operator==(const Dimension& dimension) const 196 { 197 return (unit_ == dimension.unit_) && NearEqual(value_, dimension.value_); 198 } 199 200 bool operator!=(const Dimension& dimension) const 201 { 202 return !operator==(dimension); 203 } 204 205 /* 206 * Add two dimensions using the same unit. 207 */ 208 constexpr Dimension operator+(const Dimension& dimension) const 209 { 210 if (NEAR_ZERO(dimension.Value())) { 211 return *this; 212 } 213 ACE_DCHECK(unit_ == dimension.unit_); 214 return Dimension(value_ + dimension.value_, unit_); 215 } 216 217 /* 218 * Add a new dimension to itself using same unit. 219 */ 220 Dimension& operator+=(const Dimension& dimension) 221 { 222 ACE_DCHECK(unit_ == dimension.unit_); 223 value_ += dimension.value_; 224 return *this; 225 } 226 227 /* 228 * Minus a dimension using the same unit. 229 */ 230 constexpr Dimension operator-(const Dimension& dimension) const 231 { 232 if (NEAR_ZERO(dimension.Value())) { 233 return *this; 234 } 235 ACE_DCHECK(unit_ == dimension.unit_); 236 return Dimension(value_ - dimension.value_, unit_); 237 } 238 239 /* 240 * The opposite of dimension. 241 */ 242 constexpr Dimension operator-() const 243 { 244 return Dimension(-value_, unit_); 245 } 246 247 /* 248 * Minus a dimension to itself using the same unit. 249 */ 250 Dimension& operator-=(const Dimension& dimension) 251 { 252 ACE_DCHECK(unit_ == dimension.unit_); 253 value_ -= dimension.value_; 254 return *this; 255 } 256 257 bool operator>(const Dimension& dimension) const 258 { 259 ACE_DCHECK(unit_ == dimension.unit_); 260 return (value_ > dimension.value_); 261 } 262 263 bool operator<(const Dimension& dimension) const 264 { 265 ACE_DCHECK(unit_ == dimension.unit_); 266 return (value_ < dimension.value_); 267 } 268 269 std::string ToString() const; 270 271 static Dimension FromString(const std::string& str); 272 273 private: 274 double value_ = 0.0; 275 DimensionUnit unit_ = DimensionUnit::PX; 276 }; 277 278 // literal operators for dimension 279 inline constexpr Dimension operator""_vp(long double value) 280 { 281 return Dimension(static_cast<double>(value), DimensionUnit::VP); 282 } 283 284 inline constexpr Dimension operator""_px(long double value) 285 { 286 return Dimension(static_cast<double>(value), DimensionUnit::PX); 287 } 288 289 inline constexpr Dimension operator""_fp(long double value) 290 { 291 return Dimension(static_cast<double>(value), DimensionUnit::FP); 292 } 293 294 inline constexpr Dimension operator""_pct(long double value) 295 { 296 return Dimension(static_cast<double>(value), DimensionUnit::PERCENT); 297 } 298 299 } // namespace OHOS::Ace 300 301 #endif // FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_DIMENSION_H 302