• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_PATTERNS_SHAPE_PATTERN_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SHAPE_PATTERN_H
18 
19 #include <cstddef>
20 #include <optional>
21 
22 #include "base/geometry/ng/rect_t.h"
23 #include "base/log/log_wrapper.h"
24 #include "base/memory/referenced.h"
25 #include "base/utils/noncopyable.h"
26 #include "core/components_ng/pattern/pattern.h"
27 #include "core/components_ng/pattern/shape/shape_container_pattern.h"
28 #include "core/components_ng/pattern/shape/shape_layout_algorithm.h"
29 #include "core/components_ng/pattern/shape/shape_overlay_modifier.h"
30 #include "core/components_ng/pattern/shape/shape_paint_property.h"
31 #include "core/components_ng/pattern/shape/shape_view_box.h"
32 
33 namespace OHOS::Ace::NG {
34 class ShapePattern : public Pattern {
35     DECLARE_ACE_TYPE(ShapePattern, Pattern);
36 
37 public:
38     ShapePattern() = default;
39     ~ShapePattern() override = default;
40 
IsEnableMatchParent()41     bool IsEnableMatchParent() override
42     {
43         return true;
44     }
45 
IsEnableFix()46     bool IsEnableFix() override
47     {
48         return true;
49     }
50 
CreateLayoutAlgorithm()51     RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override
52     {
53         return MakeRefPtr<ShapeLayoutAlgorithm>();
54     }
55 
CreatePaintProperty()56     RefPtr<PaintProperty> CreatePaintProperty() override
57     {
58         return MakeRefPtr<ShapePaintProperty>();
59     }
60 
OnModifyDone()61     void OnModifyDone() override
62     {
63         Pattern::CheckLocalized();
64         auto host = GetHost();
65         CHECK_NULL_VOID(host);
66         auto paintProperty = host->GetPaintProperty<ShapePaintProperty>();
67         CHECK_NULL_VOID(paintProperty);
68         if (paintProperty->HasStrokeMiterLimit()) {
69             auto miterLimit = paintProperty->GetStrokeMiterLimitValue();
70             if (Negative(miterLimit)) {
71                 paintProperty->UpdateStrokeMiterLimit(ShapePaintProperty::STROKE_MITERLIMIT_DEFAULT);
72             } else if (NonNegative(miterLimit) &&
73                 LessNotEqual(miterLimit, ShapePaintProperty::STROKE_MITERLIMIT_MIN)) {
74                 paintProperty->UpdateStrokeMiterLimit(ShapePaintProperty::STROKE_MITERLIMIT_MIN);
75             }
76         }
77     }
78 
79 protected:
GetAncestorPaintProperty()80     RefPtr<ShapePaintProperty> GetAncestorPaintProperty()
81     {
82         auto curFrameNode = GetHost();
83         CHECK_NULL_RETURN(curFrameNode, nullptr);
84         auto childNode = curFrameNode;
85         ShapePaintProperty propertiesFromAncestor;
86         auto parentFrameNode = AceType::DynamicCast<FrameNode>(curFrameNode->GetAncestorNodeOfFrame(false));
87         while (parentFrameNode) {
88             auto parentPaintProperty = parentFrameNode->GetPaintProperty<ShapePaintProperty>();
89             if (parentPaintProperty) {
90                 propertiesFromAncestor.UpdateShapeProperty(parentPaintProperty);
91                 UpdateForeground(parentFrameNode, childNode);
92                 auto pattern = AceType::DynamicCast<ShapeContainerPattern>(parentFrameNode->GetPattern());
93                 if (pattern) {
94                     pattern->AddChildShapeNode(WeakPtr<FrameNode>(childNode));
95                 }
96             }
97             curFrameNode = parentFrameNode;
98             parentFrameNode = AceType::DynamicCast<FrameNode>(curFrameNode->GetAncestorNodeOfFrame(false));
99         }
100         return DynamicCast<ShapePaintProperty>(propertiesFromAncestor.Clone());
101     }
102 
OnForegroundColorUpdate()103     void OnForegroundColorUpdate() override
104     {
105         auto host = GetHost();
106         CHECK_NULL_VOID(host);
107         host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
108     }
109 
UpdateForeground(RefPtr<FrameNode> parentFrameNode,RefPtr<FrameNode> childFrameNode)110     void UpdateForeground(RefPtr<FrameNode> parentFrameNode, RefPtr<FrameNode> childFrameNode)
111     {
112         auto renderContext = parentFrameNode->GetRenderContext();
113         CHECK_NULL_VOID(renderContext);
114         auto childRenderContext = childFrameNode->GetRenderContext();
115         CHECK_NULL_VOID(childRenderContext);
116         if (!childRenderContext->HasForegroundColor() && !childRenderContext->HasForegroundColorStrategy()) {
117             if (renderContext->HasForegroundColor()) {
118                 childRenderContext->UpdateForegroundColor(renderContext->GetForegroundColorValue());
119                 childRenderContext->ResetForegroundColorStrategy();
120                 childRenderContext->UpdateForegroundColorFlag(false);
121             } else if (renderContext->HasForegroundColorStrategy()) {
122                 childRenderContext->UpdateForegroundColorStrategy(renderContext->GetForegroundColorStrategyValue());
123                 childRenderContext->ResetForegroundColor();
124                 childRenderContext->UpdateForegroundColorFlag(false);
125             }
126         } else {
127             if (!childRenderContext->GetForegroundColorFlag().value_or(false)) {
128                 if (renderContext->HasForegroundColor()) {
129                     childRenderContext->UpdateForegroundColor(renderContext->GetForegroundColorValue());
130                     childRenderContext->ResetForegroundColorStrategy();
131                     childRenderContext->UpdateForegroundColorFlag(false);
132                 } else if (renderContext->HasForegroundColorStrategy()) {
133                     childRenderContext->UpdateForegroundColorStrategy(renderContext->GetForegroundColorStrategyValue());
134                     childRenderContext->ResetForegroundColor();
135                     childRenderContext->UpdateForegroundColorFlag(false);
136                 }
137             }
138         }
139     }
140 
UpdatePropertyImpl(const std::string & key,RefPtr<PropertyValueBase> value)141     void UpdatePropertyImpl(const std::string& key, RefPtr<PropertyValueBase> value) override
142     {
143         auto frameNode = GetHost();
144         CHECK_NULL_VOID(frameNode);
145         using Handler = std::function<void(RefPtr<PropertyValueBase>, RefPtr<FrameNode>)>;
146         static const std::unordered_map<std::string, Handler> handlers = {
147             { "ShapeAbstractStroke",
148                 [](RefPtr<PropertyValueBase> value, RefPtr<FrameNode> frameNode) {
149                     if (auto realValue = std::get_if<Color>(&(value->GetValue()))) {
150                         ACE_UPDATE_NODE_PAINT_PROPERTY(ShapePaintProperty, Stroke, *realValue, frameNode);
151                     }
152                 } },
153             { "ShapeAbstractFill",
154                 [](RefPtr<PropertyValueBase> value, RefPtr<FrameNode> frameNode) {
155                     if (auto realValue = std::get_if<Color>(&(value->GetValue()))) {
156                         ACE_UPDATE_NODE_PAINT_PROPERTY(ShapePaintProperty, Fill, *realValue, frameNode);
157                         ACE_UPDATE_NODE_RENDER_CONTEXT(ForegroundColor, *realValue, frameNode);
158                         ACE_UPDATE_NODE_RENDER_CONTEXT(ForegroundColorFlag, true, frameNode);
159                     }
160                 } },
161             { "ShapeAbstractStrokeOpacity",
162                 [](RefPtr<PropertyValueBase> value, RefPtr<FrameNode> frameNode) {
163                     if (auto realValue = std::get_if<double>(&(value->GetValue()))) {
164                         ACE_UPDATE_NODE_PAINT_PROPERTY(
165                             ShapePaintProperty, StrokeOpacity, std::clamp(*realValue, 0.0, 1.0), frameNode);
166                     }
167                 } },
168             { "ShapeAbstractFillOpacity",
169                 [](RefPtr<PropertyValueBase> value, RefPtr<FrameNode> frameNode) {
170                     if (auto realValue = std::get_if<double>(&(value->GetValue()))) {
171                         ACE_UPDATE_NODE_PAINT_PROPERTY(
172                             ShapePaintProperty, FillOpacity, std::clamp(*realValue, 0.0, 1.0), frameNode);
173                     }
174                 } },
175             { "ShapeAbstractStrokeWidth",
176                 [](RefPtr<PropertyValueBase> value, RefPtr<FrameNode> frameNode) {
177                     if (auto realValue = std::get_if<CalcDimension>(&(value->GetValue()))) {
178                         auto strokeWidth = realValue->IsNegative() ? 1.0_vp : *realValue;
179                         ACE_UPDATE_NODE_PAINT_PROPERTY(ShapePaintProperty, StrokeWidth, strokeWidth, frameNode);
180                     }
181                 } },
182             { "ShapeAbstractWidth",
183                 [](RefPtr<PropertyValueBase> value, RefPtr<FrameNode> frameNode) {
184                     if (auto realValue = std::get_if<CalcDimension>(&(value->GetValue()))) {
185                         auto width = *realValue;
186                         if (LessNotEqual(width.Value(), 0.0)) {
187                             width.SetValue(0.0);
188                         }
189                         CHECK_NULL_VOID(frameNode);
190                         auto layoutProperty = frameNode->GetLayoutProperty();
191                         CHECK_NULL_VOID(layoutProperty);
192                         // get previously user defined ideal height
193                         std::optional<CalcLength> height = std::nullopt;
194                         auto&& layoutConstraint = layoutProperty->GetCalcLayoutConstraint();
195                         if (layoutConstraint && layoutConstraint->selfIdealSize) {
196                             height = layoutConstraint->selfIdealSize->Height();
197                         }
198                         layoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(width), height));
199                     }
200                 } },
201             { "ShapeAbstractHeight",
202                 [](RefPtr<PropertyValueBase> value, RefPtr<FrameNode> frameNode) {
203                     if (auto realValue = std::get_if<CalcDimension>(&(value->GetValue()))) {
204                         auto height = *realValue;
205                         if (LessNotEqual(height.Value(), 0.0)) {
206                             height.SetValue(0.0);
207                         }
208                         CHECK_NULL_VOID(frameNode);
209                         auto layoutProperty = frameNode->GetLayoutProperty();
210                         CHECK_NULL_VOID(layoutProperty);
211                         std::optional<CalcLength> width = std::nullopt;
212                         auto&& layoutConstraint = layoutProperty->GetCalcLayoutConstraint();
213                         if (layoutConstraint && layoutConstraint->selfIdealSize) {
214                             width = layoutConstraint->selfIdealSize->Width();
215                         }
216                         layoutProperty->UpdateUserDefinedIdealSize(CalcSize(width, CalcLength(height)));
217                     }
218                 } },
219             { "ShapeAbstractForegroundColor",
220                 [](RefPtr<PropertyValueBase> value, RefPtr<FrameNode> frameNode) {
221                     if (auto realValue = std::get_if<Color>(&(value->GetValue()))) {
222                         if (!ViewStackProcessor::GetInstance()->IsCurrentVisualStateProcess()) {
223                             return;
224                         }
225                         ACE_UPDATE_NODE_PAINT_PROPERTY(ShapePaintProperty, Fill, *realValue, frameNode);
226                         ACE_UPDATE_NODE_RENDER_CONTEXT(ForegroundColor, *realValue, frameNode);
227                         ACE_UPDATE_NODE_RENDER_CONTEXT(ForegroundColorFlag, true, frameNode);
228                     }
229                 } },
230         };
231         auto it = handlers.find(key);
232         if (it != handlers.end()) {
233             it->second(value, frameNode);
234         }
235         if (frameNode->GetRerenderable()) {
236             frameNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
237         }
238     }
239 
240     RefPtr<ShapeOverlayModifier> shapeOverlayModifier_;
241 
242 private:
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,bool skipMeasure,bool skipLayout)243     bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, bool skipMeasure, bool skipLayout) override
244     {
245         return !(skipMeasure || dirty->SkipMeasureContent());
246     }
247     ACE_DISALLOW_COPY_AND_MOVE(ShapePattern);
248 };
249 } // namespace OHOS::Ace::NG
250 
251 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SHAPE_PATTERN_H
252