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_CORE_COMPONENTS_BASE_PROPERTIES_EDGE_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_BASE_PROPERTIES_EDGE_H
18 
19 #include "base/geometry/animatable_dimension.h"
20 #include "base/geometry/calc_dimension.h"
21 #include "base/geometry/dimension.h"
22 #include "base/geometry/offset.h"
23 #include "base/geometry/size.h"
24 #include "base/utils/macros.h"
25 #include "base/utils/utils.h"
26 #include "core/pipeline/base/constants.h"
27 
28 namespace OHOS::Ace {
29 
30 // Types of padding and margin. Contains four directions: left, top, right and bottom.
31 class ACE_EXPORT Edge {
32 public:
33     Edge() = default;
Edge(double value)34     explicit Edge(double value) : Edge(value, value, value, value) {}
Edge(const Dimension & value)35     explicit Edge(const Dimension& value) : Edge(value, value, value, value) {}
Edge(const std::string & value)36     explicit Edge(const std::string& value) : Edge(value, value, value, value) {}
Edge(const CalcDimension & value)37     explicit Edge(const CalcDimension& value) : Edge(value, value, value, value) {}
38     Edge(double left, double top, double right, double bottom, DimensionUnit unit = DimensionUnit::PX)
39         : left_(Dimension(left, unit)), top_(Dimension(top, unit)), right_(Dimension(right, unit)),
40           bottom_(Dimension(bottom, unit)) {}
41     Edge(const std::string& left, const std::string& top, const std::string& right, const std::string& bottom,
42         DimensionUnit unit = DimensionUnit::CALC) : left_(CalcDimension(left, unit)), top_(CalcDimension(top, unit)),
43         right_(CalcDimension(right, unit)), bottom_(CalcDimension(bottom, unit)) {}
Edge(const CalcDimension & left,const CalcDimension & top,const CalcDimension & right,const CalcDimension & bottom)44     Edge(const CalcDimension& left, const CalcDimension& top, const CalcDimension& right, const CalcDimension& bottom)
45         : left_(left), top_(top), right_(right), bottom_(bottom) {}
Edge(const Dimension & left,const Dimension & top,const Dimension & right,const Dimension & bottom,const AnimationOption & option)46     Edge(const Dimension& left, const Dimension& top, const Dimension& right, const Dimension& bottom,
47          const AnimationOption& option)
48         : left_(AnimatableDimension(left, option)), top_(AnimatableDimension(top, option)),
49           right_(AnimatableDimension(right, option)), bottom_(AnimatableDimension(bottom, option)) {}
Edge(const CalcDimension & left,const CalcDimension & top,const CalcDimension & right,const CalcDimension & bottom,const AnimationOption & option)50     Edge(const CalcDimension& left, const CalcDimension& top, const CalcDimension& right, const CalcDimension& bottom,
51          const AnimationOption& option)
52         : left_(AnimatableDimension(left, option)), top_(AnimatableDimension(top, option)),
53           right_(AnimatableDimension(right, option)), bottom_(AnimatableDimension(bottom, option)) {}
54 
55     virtual ~Edge() = default;
56 
57     static const Edge NONE;
58 
59     // Parse string to edge, support four formats(value separated by one space):
60     // 1. 1px, edge has same value.
61     // 2. 1px 2px, top and bottom are 1px, left and right are 2px.
62     // 3. 1px 2px 3px, top is 1px, left and right are 2px, bottom is 3px.
63     // 4. 1px 2px 3px 4px, top is 1px, right is 2px, bottom is 3px and left is 4px.
64     static bool FromString(const std::string& value, Edge& edge);
65 
66     bool IsValid() const;
67     bool IsEffective() const;
68     Size GetLayoutSizeInPx(double dipScale) const;
69     Offset GetOffsetInPx(double dipScale) const;
70     double HorizontalInPx(double dipScale) const;
71     double VerticalInPx(double dipScale) const;
72 
Left()73     const AnimatableDimension& Left() const
74     {
75         return left_;
76     }
77 
SetLeft(const AnimatableDimension & left)78     virtual void SetLeft(const AnimatableDimension& left)
79     {
80         left_ = left;
81     }
82 
SetLeft(const CalcDimension & left)83     virtual void SetLeft(const CalcDimension& left)
84     {
85         left_ = AnimatableDimension(left);
86     }
87 
88 
SetLeft(const Dimension & left)89     virtual void SetLeft(const Dimension& left)
90     {
91         left_ = AnimatableDimension(left);
92     }
93 
Top()94     const AnimatableDimension& Top() const
95     {
96         return top_;
97     }
98 
SetTop(const AnimatableDimension & top)99     virtual void SetTop(const AnimatableDimension& top)
100     {
101         top_ = top;
102     }
103 
SetTop(const CalcDimension & top)104     virtual void SetTop(const CalcDimension& top)
105     {
106         top_ = AnimatableDimension(top);
107     }
108 
109 
SetTop(const Dimension & top)110     virtual void SetTop(const Dimension& top)
111     {
112         top_ = AnimatableDimension(top);
113     }
114 
Right()115     const AnimatableDimension& Right() const
116     {
117         return right_;
118     }
119 
SetRight(const AnimatableDimension & right)120     virtual void SetRight(const AnimatableDimension& right)
121     {
122         right_ = right;
123     }
124 
SetRight(const CalcDimension & right)125     virtual void SetRight(const CalcDimension& right)
126     {
127         right_ = AnimatableDimension(right);
128     }
129 
SetRight(const Dimension & right)130     virtual void SetRight(const Dimension& right)
131     {
132         right_ = AnimatableDimension(right);
133     }
134 
Bottom()135     const AnimatableDimension& Bottom() const
136     {
137         return bottom_;
138     }
139 
SetBottom(const AnimatableDimension & bottom)140     virtual void SetBottom(const AnimatableDimension& bottom)
141     {
142         bottom_ = bottom;
143     }
144 
SetBottom(const CalcDimension & bottom)145     virtual void SetBottom(const CalcDimension& bottom)
146     {
147         bottom_ = AnimatableDimension(bottom);
148     }
149 
SetBottom(const Dimension & bottom)150     virtual void SetBottom(const Dimension& bottom)
151     {
152         bottom_ = AnimatableDimension(bottom);
153     }
154 
155     Edge operator+(const Edge& edge) const
156     {
157         return Edge(left_ + edge.left_, top_ + edge.top_, right_ + edge.right_, bottom_ + edge.bottom_);
158     }
159 
160     Edge operator-(const Edge& edge) const
161     {
162         return Edge(left_ - edge.left_, top_ - edge.top_, right_ - edge.right_, bottom_ - edge.bottom_);
163     }
164 
165     Edge operator*(const double factor) const
166     {
167         return Edge(left_ * factor, top_ * factor, right_ * factor, bottom_ * factor);
168     }
169 
170     Edge operator/(const double factor) const
171     {
172         if (NearZero(factor)) {
173             return NONE;
174         }
175         return Edge(left_ / factor, top_ / factor, right_ / factor, bottom_ / factor);
176     }
177 
178     bool operator==(const Edge& edge) const
179     {
180         return (edge.left_ == left_) && (edge.top_ == top_) && (edge.right_ == right_) && (edge.bottom_ == bottom_);
181     }
182 
SetContextAndCallback(const WeakPtr<PipelineBase> & context,const RenderNodeAnimationCallback & callback)183     void SetContextAndCallback(const WeakPtr<PipelineBase>& context, const RenderNodeAnimationCallback& callback)
184     {
185         left_.SetContextAndCallback(context, callback);
186         top_.SetContextAndCallback(context, callback);
187         right_.SetContextAndCallback(context, callback);
188         bottom_.SetContextAndCallback(context, callback);
189     }
190 
191 protected:
192     AnimatableDimension left_;
193     AnimatableDimension top_;
194     AnimatableDimension right_;
195     AnimatableDimension bottom_;
196 };
197 
198 class EdgePx : public Edge {
199 public:
200     EdgePx() = default;
EdgePx(double value)201     explicit EdgePx(double value) : EdgePx(value, value, value, value) {}
EdgePx(const std::string & value)202     explicit EdgePx(const std::string& value) : EdgePx(value, value, value, value) {}
EdgePx(double left,double top,double right,double bottom)203     EdgePx(double left, double top, double right, double bottom) : Edge(left, top, right, bottom) {}
EdgePx(const std::string & left,const std::string & top,const std::string & right,const std::string & bottom)204     EdgePx(const std::string& left, const std::string& top, const std::string& right, const std::string& bottom)
205         : Edge(left, top, right, bottom) {}
206     ~EdgePx() override = default;
207 
LeftPx()208     double LeftPx() const
209     {
210         return left_.Value();
211     }
212 
TopPx()213     double TopPx() const
214     {
215         return top_.Value();
216     }
217 
RightPx()218     double RightPx() const
219     {
220         return right_.Value();
221     }
222 
BottomPx()223     double BottomPx() const
224     {
225         return bottom_.Value();
226     }
227 
SetLeft(const AnimatableDimension & left)228     void SetLeft(const AnimatableDimension& left) override
229     {
230         if (left.Unit() != DimensionUnit::PX && left.Unit() != DimensionUnit::CALC) {
231             return;
232         }
233         left_ = left;
234     }
235 
SetLeft(const Dimension & left)236     void SetLeft(const Dimension& left) override
237     {
238         if (left.Unit() != DimensionUnit::PX) {
239             return;
240         }
241         left_ = AnimatableDimension(left);
242     }
243 
SetLeft(const CalcDimension & left)244     void SetLeft(const CalcDimension& left) override
245     {
246         if (left.Unit() != DimensionUnit::CALC) {
247             return;
248         }
249         left_ = AnimatableDimension(left);
250     }
251 
SetTop(const AnimatableDimension & top)252     void SetTop(const AnimatableDimension& top) override
253     {
254         if (top.Unit() != DimensionUnit::PX && top.Unit() != DimensionUnit::CALC) {
255             return;
256         }
257         top_ = top;
258     }
259 
SetTop(const Dimension & top)260     void SetTop(const Dimension& top) override
261     {
262         if (top.Unit() != DimensionUnit::PX) {
263             return;
264         }
265         top_ = AnimatableDimension(top);
266     }
267 
SetTop(const CalcDimension & top)268     void SetTop(const CalcDimension& top) override
269     {
270         if (top.Unit() != DimensionUnit::CALC) {
271             return;
272         }
273         top_ = AnimatableDimension(top);
274     }
275 
SetRight(const AnimatableDimension & right)276     void SetRight(const AnimatableDimension& right) override
277     {
278         if (right.Unit() != DimensionUnit::PX && right.Unit() != DimensionUnit::CALC) {
279             return;
280         }
281         right_ = right;
282     }
283 
SetRight(const Dimension & right)284     void SetRight(const Dimension& right) override
285     {
286         if (right.Unit() != DimensionUnit::PX) {
287             return;
288         }
289         right_ = AnimatableDimension(right);
290     }
291 
SetRight(const CalcDimension & right)292     void SetRight(const CalcDimension& right) override
293     {
294         if (right.Unit() != DimensionUnit::CALC) {
295             return;
296         }
297         right_ = AnimatableDimension(right);
298     }
299 
SetBottom(const AnimatableDimension & bottom)300     void SetBottom(const AnimatableDimension& bottom) override
301     {
302         if (bottom.Unit() != DimensionUnit::PX && bottom.Unit() != DimensionUnit::CALC) {
303             return;
304         }
305         bottom_ = bottom;
306     }
307 
SetBottom(const Dimension & bottom)308     void SetBottom(const Dimension& bottom) override
309     {
310         if (bottom.Unit() != DimensionUnit::PX) {
311             return;
312         }
313         bottom_ = AnimatableDimension(bottom);
314     }
315 
SetBottom(const CalcDimension & bottom)316     void SetBottom(const CalcDimension& bottom) override
317     {
318         if (bottom.Unit() != DimensionUnit::CALC) {
319             return;
320         }
321         bottom_ = AnimatableDimension(bottom);
322     }
323 
GetLayoutSize()324     Size GetLayoutSize() const
325     {
326         return Size(left_.Value() + right_.Value(), top_.Value() + bottom_.Value());
327     }
328 
GetOffset()329     Offset GetOffset() const
330     {
331         return Offset(left_.Value(), top_.Value());
332     }
333 
334     EdgePx operator+(const EdgePx& edge) const
335     {
336         return EdgePx(LeftPx() + edge.LeftPx(), TopPx() + edge.TopPx(), RightPx() + edge.RightPx(),
337             BottomPx() + edge.BottomPx());
338     }
339 };
340 
341 } // namespace OHOS::Ace
342 
343 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_BASE_PROPERTIES_EDGE_H
344