• 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 
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