1 /*
2  * Copyright (c) 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_NG_PATTERN_SHAPE_RECT_PAINT_PROPERTY_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_SHAPE_RECT_PAINT_PROPERTY_H
18 
19 #include <vector>
20 #include "base/geometry/dimension.h"
21 #include "base/geometry/ng/radius.h"
22 #include "base/log/log_wrapper.h"
23 #include "core/components_ng/base/inspector_filter.h"
24 #include "core/components_ng/layout/layout_property.h"
25 #include "core/components_ng/pattern/shape/shape_paint_property.h"
26 #include "core/components_ng/property/property.h"
27 #include "core/components_ng/render/paint_property.h"
28 
29 namespace OHOS::Ace::NG {
30 namespace {
31 // Dimension(0) will update radius, but Dimension(-1) will not.
32 const Dimension DEFAULT_RADIUS_VALUE(0, DimensionUnit::PX);
33 const Dimension DEFAULT_RADIUS_INVALID(-1, DimensionUnit::PX);
34 } // namespace
35 class ACE_EXPORT RectPaintProperty : public ShapePaintProperty {
36     DECLARE_ACE_TYPE(RectPaintProperty, ShapePaintProperty);
37 
38 public:
39     RectPaintProperty() = default;
40     ~RectPaintProperty() override = default;
Clone()41     RefPtr<PaintProperty> Clone() const override
42     {
43         auto value = MakeRefPtr<RectPaintProperty>();
44         value->PaintProperty::UpdatePaintProperty(DynamicCast<PaintProperty>(this));
45         value->propTopLeftRadius_ = CloneTopLeftRadius();
46         value->propTopRightRadius_ = CloneTopRightRadius();
47         value->propBottomLeftRadius_ = CloneBottomLeftRadius();
48         value->propBottomRightRadius_ = CloneBottomRightRadius();
49         value->propFill_ = CloneFill();
50         value->propFillOpacity_ = CloneFillOpacity();
51         value->propStroke_ = CloneStroke();
52         value->propStrokeWidth_ = CloneStrokeWidth();
53         value->propStrokeOpacity_ = CloneStrokeOpacity();
54         value->propStrokeDashArray_ = CloneStrokeDashArray();
55         value->propStrokeDashOffset_ = CloneStrokeDashOffset();
56         value->propStrokeLineCap_ = CloneStrokeLineCap();
57         value->propStrokeLineJoin_ = CloneStrokeLineJoin();
58         value->propStrokeMiterLimit_ = CloneStrokeMiterLimit();
59         value->propAntiAlias_ = CloneAntiAlias();
60         value->SetContentOffset(contentOffset_);
61         value->SetContentSize(contentSize_);
62         return value;
63     }
64 
Reset()65     void Reset() override
66     {
67         ShapePaintProperty::Reset();
68         ResetBottomLeftRadius();
69         ResetBottomRightRadius();
70         ResetTopLeftRadius();
71         ResetTopRightRadius();
72     }
73 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter)74     void ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const override
75     {
76         ShapePaintProperty::ToJsonValue(json, filter);
77         /* no fixed attr below, just return */
78         if (filter.IsFastFilter()) {
79             return;
80         }
81         if (!propTopLeftRadius_.has_value() || !propTopRightRadius_.has_value() || !propBottomLeftRadius_.has_value() ||
82             !propBottomRightRadius_.has_value()) {
83             return;
84         }
85         std::vector<std::vector<double>> radiusArray(4);
86         radiusArray[0] = { propTopLeftRadius_.value().GetX().ConvertToPx(),
87             propTopLeftRadius_.value().GetY().ConvertToPx() };
88         radiusArray[1] = { propTopRightRadius_.value().GetX().ConvertToPx(),
89             propTopRightRadius_.value().GetY().ConvertToPx() };
90         radiusArray[2] = { propBottomRightRadius_.value().GetX().ConvertToPx(),
91             propBottomRightRadius_.value().GetY().ConvertToPx() };
92         radiusArray[3] = { propBottomLeftRadius_.value().GetX().ConvertToPx(),
93             propBottomLeftRadius_.value().GetY().ConvertToPx() };
94         json->PutExtAttr("radius", radiusArray.data(), filter);
95         if (radiusArray[0][0] == radiusArray[1][0] &&
96             radiusArray[0][0] == radiusArray[2][0] &&
97             radiusArray[0][0] == radiusArray[3][0]) {
98             json->PutExtAttr("radiusWidth", radiusArray[0][0], filter);
99         } else {
100             json->PutExtAttr("radiusWidth", 0, filter);
101         }
102         if (radiusArray[0][1] == radiusArray[1][1] &&
103             radiusArray[0][1] == radiusArray[2][1] &&
104             radiusArray[0][1] == radiusArray[3][1]) {
105             json->PutExtAttr("radiusHeight", radiusArray[0][1], filter);
106         } else {
107             json->PutExtAttr("radiusHeight", 0, filter);
108         }
109     }
110 
GetTopLeftRadius()111     const std::optional<Radius>& GetTopLeftRadius()
112     {
113         return propTopLeftRadius_;
114     }
HasTopLeftRadius()115     bool HasTopLeftRadius() const
116     {
117         return propTopLeftRadius_.has_value();
118     }
GetTopLeftRadiusValue()119     const Radius& GetTopLeftRadiusValue() const
120     {
121         return propTopLeftRadius_.value();
122     }
CloneTopLeftRadius()123     const std::optional<Radius>& CloneTopLeftRadius() const
124     {
125         return propTopLeftRadius_;
126     }
ResetTopLeftRadius()127     void ResetTopLeftRadius()
128     {
129         return propTopLeftRadius_.reset();
130     }
131 
UpdateTopLeftRadius(const Radius & value)132     void UpdateTopLeftRadius(const Radius& value)
133     {
134         UpdateRadius(propTopLeftRadius_, value);
135     }
136 
GetTopRightRadius()137     const std::optional<Radius>& GetTopRightRadius()
138     {
139         return propTopRightRadius_;
140     }
HasTopRightRadius()141     bool HasTopRightRadius() const
142     {
143         return propTopRightRadius_.has_value();
144     }
GetTopRightRadiusValue()145     const Radius& GetTopRightRadiusValue() const
146     {
147         return propTopRightRadius_.value();
148     }
CloneTopRightRadius()149     const std::optional<Radius>& CloneTopRightRadius() const
150     {
151         return propTopRightRadius_;
152     }
ResetTopRightRadius()153     void ResetTopRightRadius()
154     {
155         return propTopRightRadius_.reset();
156     }
157 
UpdateTopRightRadius(const Radius & value)158     void UpdateTopRightRadius(const Radius& value)
159     {
160         UpdateRadius(propTopRightRadius_, value);
161     }
162 
GetBottomRightRadius()163     const std::optional<Radius>& GetBottomRightRadius()
164     {
165         return propBottomRightRadius_;
166     }
HasBottomRightRadius()167     bool HasBottomRightRadius() const
168     {
169         return propBottomRightRadius_.has_value();
170     }
GetBottomRightRadiusValue()171     const Radius& GetBottomRightRadiusValue() const
172     {
173         return propBottomRightRadius_.value();
174     }
CloneBottomRightRadius()175     const std::optional<Radius>& CloneBottomRightRadius() const
176     {
177         return propBottomRightRadius_;
178     }
ResetBottomRightRadius()179     void ResetBottomRightRadius()
180     {
181         return propBottomRightRadius_.reset();
182     }
183 
UpdateBottomRightRadius(const Radius & value)184     void UpdateBottomRightRadius(const Radius& value)
185     {
186         UpdateRadius(propBottomRightRadius_, value);
187     }
188 
GetBottomLeftRadius()189     const std::optional<Radius>& GetBottomLeftRadius()
190     {
191         return propBottomLeftRadius_;
192     }
HasBottomLeftRadius()193     bool HasBottomLeftRadius() const
194     {
195         return propBottomLeftRadius_.has_value();
196     }
GetBottomLeftRadiusValue()197     const Radius& GetBottomLeftRadiusValue() const
198     {
199         return propBottomLeftRadius_.value();
200     }
CloneBottomLeftRadius()201     const std::optional<Radius>& CloneBottomLeftRadius() const
202     {
203         return propBottomLeftRadius_;
204     }
ResetBottomLeftRadius()205     void ResetBottomLeftRadius()
206     {
207         return propBottomLeftRadius_.reset();
208     }
UpdateBottomLeftRadius(const Radius & value)209     void UpdateBottomLeftRadius(const Radius& value)
210     {
211         UpdateRadius(propBottomLeftRadius_, value);
212     }
213 
UpdateRadius(std::optional<Radius> & radiusOpt,const Radius & value)214     void UpdateRadius(std ::optional<Radius>& radiusOpt, const Radius& value)
215     {
216         // Dimension(0) is a valid value in radius.
217         if (!value.GetX().IsNonNegative() && !value.GetY().IsNonNegative()) {
218             return;
219         }
220         bool update = false;
221         if (!radiusOpt.has_value()) {
222             radiusOpt = value; // value
223             update = true;
224         } else {
225             if (value.GetX().IsNonNegative() && !NearEqual(radiusOpt.value_or(Radius()).GetX(), value.GetX())) {
226                 radiusOpt->SetX(value.GetX());
227                 update = true;
228             }
229             if (value.GetY().IsNonNegative() && !NearEqual(radiusOpt.value_or(Radius()).GetY(), value.GetY())) {
230                 radiusOpt->SetY(value.GetY());
231                 update = true;
232             }
233         }
234         if (update) {
235             UpdatePropertyChangeFlag(PROPERTY_UPDATE_RENDER);
236         }
237     }
238 
GetContentOffset()239     OffsetF GetContentOffset()
240     {
241         return contentOffset_;
242     }
243 
GetContentSize()244     SizeF GetContentSize()
245     {
246         return contentSize_;
247     }
248 
SetContentOffset(const OffsetF & contentOffset)249     void SetContentOffset(const OffsetF& contentOffset)
250     {
251         contentOffset_.SetX(contentOffset.GetX());
252         contentOffset_.SetY(contentOffset.GetY());
253     }
254 
SetContentSize(const SizeF & contentSize)255     void SetContentSize(const SizeF& contentSize)
256     {
257         contentSize_.SetSizeT(contentSize);
258     }
259 
260 private:
261     std::optional<Radius> propTopLeftRadius_;
262     std::optional<Radius> propTopRightRadius_;
263     std::optional<Radius> propBottomLeftRadius_;
264     std::optional<Radius> propBottomRightRadius_;
265     SizeF contentSize_;
266     OffsetF contentOffset_;
267 
268     ACE_DISALLOW_COPY_AND_MOVE(RectPaintProperty);
269 };
270 
271 } // namespace OHOS::Ace::NG
272 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_SHAPE_RECT_PAINT_PROPERTY_H
273