• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
value_(value)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     // support percentage unit conversion
150     double ConvertToPxWithSize(double size) const;
151 
152     bool NormalizeToPx(double vpScale, double fpScale, double lpxScale, double parentLength, double& result) const;
153 
154     constexpr Dimension operator*(double value) const
155     {
156         return Dimension(value_ * value, unit_);
157     }
158 
159     constexpr Dimension operator/(double value) const
160     {
161         // NearZero cannot be used in a constant expression
162         if (NEAR_ZERO(value)) {
163             return {};
164         }
165         return Dimension(value_ / value, unit_);
166     }
167 
168     bool operator==(const Dimension& dimension) const
169     {
170         return (unit_ == dimension.unit_) && NearEqual(value_, dimension.value_);
171     }
172 
173     bool operator!=(const Dimension& dimension) const
174     {
175         return !operator==(dimension);
176     }
177 
178     /*
179      * Add two dimensions using the same unit.
180      */
181     constexpr Dimension operator+(const Dimension& dimension) const
182     {
183         if (NEAR_ZERO(dimension.Value())) {
184             return *this;
185         }
186         ACE_DCHECK(unit_ == dimension.unit_);
187         return Dimension(value_ + dimension.value_, unit_);
188     }
189 
190     /*
191      * Add a new dimension to itself using same unit.
192      */
193     Dimension& operator+=(const Dimension& dimension)
194     {
195         ACE_DCHECK(unit_ == dimension.unit_);
196         value_ += dimension.value_;
197         return *this;
198     }
199 
200     /*
201      * Minus a dimension using the same unit.
202      */
203     constexpr Dimension operator-(const Dimension& dimension) const
204     {
205         if (NEAR_ZERO(dimension.Value())) {
206             return *this;
207         }
208         ACE_DCHECK(unit_ == dimension.unit_);
209         return Dimension(value_ - dimension.value_, unit_);
210     }
211 
212     /*
213      * The opposite of dimension.
214      */
215     constexpr Dimension operator-() const
216     {
217         return Dimension(-value_, unit_);
218     }
219 
220     /*
221      * Minus a dimension to itself using the same unit.
222      */
223     Dimension& operator-=(const Dimension& dimension)
224     {
225         ACE_DCHECK(unit_ == dimension.unit_);
226         value_ -= dimension.value_;
227         return *this;
228     }
229 
230     bool operator>(const Dimension& dimension) const
231     {
232         ACE_DCHECK(unit_ == dimension.unit_);
233         return (value_ > dimension.value_);
234     }
235 
236     bool operator<(const Dimension& dimension) const
237     {
238         ACE_DCHECK(unit_ == dimension.unit_);
239         return (value_ < dimension.value_);
240     }
241 
242     std::string ToString() const;
243 
244     static Dimension FromString(const std::string& str);
245 
246 private:
247     double value_ = 0.0;
248     DimensionUnit unit_ = DimensionUnit::PX;
249 };
250 
251 // literal operators for dimension
252 inline constexpr Dimension operator""_vp(long double value)
253 {
254     return Dimension(static_cast<double>(value), DimensionUnit::VP);
255 }
256 
257 inline constexpr Dimension operator""_px(long double value)
258 {
259     return Dimension(static_cast<double>(value), DimensionUnit::PX);
260 }
261 
262 inline constexpr Dimension operator""_fp(long double value)
263 {
264     return Dimension(static_cast<double>(value), DimensionUnit::FP);
265 }
266 
267 inline constexpr Dimension operator""_pct(long double value)
268 {
269     return Dimension(static_cast<double>(value), DimensionUnit::PERCENT);
270 }
271 
272 } // namespace OHOS::Ace
273 
274 #endif // FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_DIMENSION_H
275