• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2024 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 #include "core/components_ng/pattern/shape/shape_container_pattern.h"
17 
18 #include "core/components_ng/base/view_stack_processor.h"
19 #include "core/components_ng/pattern/shape/shape_container_paint_method.h"
20 
21 namespace OHOS::Ace::NG {
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,bool skipMeasure,bool skipLayout)22 bool ShapeContainerPattern::OnDirtyLayoutWrapperSwap(
23     const RefPtr<LayoutWrapper>& dirty, bool skipMeasure, bool skipLayout)
24 {
25     if (skipMeasure || dirty->SkipMeasureContent() || isShapeContainerInit_) {
26         return false;
27     }
28     ViewPortTransform();
29     return true;
30 }
31 
ViewPortTransform()32 void ShapeContainerPattern::ViewPortTransform()
33 {
34     auto curFrameNode = GetHost();
35     auto renderContext = curFrameNode->GetRenderContext();
36     auto geoNode = curFrameNode->GetGeometryNode();
37     CHECK_NULL_VOID(geoNode);
38     auto contentSize = geoNode->GetContentSize();
39     auto paintProperty = curFrameNode->GetPaintProperty<ShapeContainerPaintProperty>();
40     if (paintProperty->HasShapeViewBox() && paintProperty->GetShapeViewBoxValue().IsValid()) {
41         double portWidth = paintProperty->GetShapeViewBoxValue().Width().ConvertToPx();
42         double portHeight = paintProperty->GetShapeViewBoxValue().Height().ConvertToPx();
43         double portLeft = paintProperty->GetShapeViewBoxValue().Left().ConvertToPx();
44         double portTop = paintProperty->GetShapeViewBoxValue().Top().ConvertToPx();
45         if (contentSize.IsPositive() && GreatNotEqual(portWidth, 0.0) && GreatNotEqual(portHeight, 0.0)) {
46             double scale = std::min(contentSize.Width() / portWidth, contentSize.Height() / portHeight);
47             double tx = contentSize.Width() * 0.5 - (portWidth * 0.5 + portLeft) * scale;
48             double ty = contentSize.Height() * 0.5 - (portHeight * 0.5 + portTop) * scale;
49             for (const auto& child : curFrameNode->GetChildren()) {
50                 auto node = AceType::DynamicCast<FrameNode>(child);
51                 CHECK_NULL_VOID(node);
52                 auto context = node->GetRenderContext();
53                 CHECK_NULL_VOID(context);
54                 context->UpdateTransformCenter(DimensionOffset(Offset(0.0, 0.0)));
55                 context->OnTransformTranslateUpdate({ tx, ty, 0 });
56                 context->OnTransformScaleUpdate({ scale, scale });
57 
58                 if (context->HasOffset()) {
59                     auto currentOffset = context->GetOffset();
60                     auto newOffset = OffsetT(Dimension(currentOffset->GetX() * scale),
61                         Dimension(currentOffset->GetY() * scale));
62                     context->UpdateOffset(newOffset);
63                     context->OnOffsetUpdate(newOffset);
64                     node->MarkModifyDone();
65                 }
66             }
67         }
68     }
69     isShapeContainerInit_ = true;
70 }
71 
OnModifyDone()72 void ShapeContainerPattern::OnModifyDone()
73 {
74     auto host = GetHost();
75     CHECK_NULL_VOID(host);
76     auto paintProperty = host->GetPaintProperty<ShapeContainerPaintProperty>();
77     CHECK_NULL_VOID(paintProperty);
78     if (paintProperty->HasStrokeMiterLimit()) {
79         auto miterLimit = paintProperty->GetStrokeMiterLimitValue();
80         if (Negative(miterLimit)) {
81             paintProperty->UpdateStrokeMiterLimit(ShapePaintProperty::STROKE_MITERLIMIT_DEFAULT);
82         } else if (NonNegative(miterLimit) &&
83             LessNotEqual(miterLimit, ShapePaintProperty::STROKE_MITERLIMIT_MIN)) {
84             paintProperty->UpdateStrokeMiterLimit(ShapePaintProperty::STROKE_MITERLIMIT_MIN);
85         }
86     }
87 
88     Pattern::OnModifyDone();
89     for (auto childNode : ChildNodes_) {
90         auto child = childNode.Upgrade();
91         if (!child) {
92             continue;
93         }
94         child->MarkNeedRenderOnly();
95     }
96     ChildNodes_.clear();
97 }
98 
OnAttachToFrameNode()99 void ShapeContainerPattern::OnAttachToFrameNode()
100 {
101     auto host = GetHost();
102     CHECK_NULL_VOID(host);
103     host->GetLayoutProperty()->UpdateAlignment(Alignment::TOP_LEFT);
104     host->GetRenderContext()->SetClipToFrame(true);
105 }
106 
CreateNodePaintMethod()107 RefPtr<NodePaintMethod> ShapeContainerPattern::CreateNodePaintMethod()
108 {
109     if (!shapeContainerModifier_) {
110         shapeContainerModifier_ = MakeRefPtr<ShapeContainerModifier>();
111     }
112     return MakeRefPtr<ShapeContainerPaintMethod>(shapeContainerModifier_);
113 }
114 
UpdatePropertyImpl(const std::string & key,RefPtr<PropertyValueBase> value)115 void ShapeContainerPattern::UpdatePropertyImpl(const std::string& key, RefPtr<PropertyValueBase> value)
116 {
117     auto frameNode = GetHost();
118     CHECK_NULL_VOID(frameNode);
119     using Handler = std::function<void(RefPtr<PropertyValueBase>, RefPtr<FrameNode>)>;
120     static const std::unordered_map<std::string, Handler> handlers = {
121         { "ShapeStroke",
122             [](RefPtr<PropertyValueBase> value, RefPtr<FrameNode> frameNode) {
123                 if (auto realValue = std::get_if<Color>(&(value->GetValue()))) {
124                     ACE_UPDATE_NODE_PAINT_PROPERTY(ShapePaintProperty, Stroke, *realValue, frameNode);
125                 }
126             } },
127         { "ShapeDashOffset",
128             [](RefPtr<PropertyValueBase> value, RefPtr<FrameNode> frameNode) {
129                 if (auto realValue = std::get_if<CalcDimension>(&(value->GetValue()))) {
130                     ACE_UPDATE_NODE_PAINT_PROPERTY(ShapePaintProperty, StrokeDashOffset, *realValue, frameNode);
131                 }
132             } },
133         { "ShapeMiterLimit",
134             [](RefPtr<PropertyValueBase> value, RefPtr<FrameNode> frameNode) {
135                 if (auto realValue = std::get_if<double>(&(value->GetValue()))) {
136                     ACE_UPDATE_NODE_PAINT_PROPERTY(ShapePaintProperty, StrokeMiterLimit, *realValue, frameNode);
137                 }
138             } },
139         { "ShapeFill",
140             [](RefPtr<PropertyValueBase> value, RefPtr<FrameNode> frameNode) {
141                 if (auto realValue = std::get_if<Color>(&(value->GetValue()))) {
142                     ACE_UPDATE_NODE_PAINT_PROPERTY(ShapePaintProperty, Fill, *realValue, frameNode);
143                     ACE_UPDATE_NODE_RENDER_CONTEXT(ForegroundColor, *realValue, frameNode);
144                     ACE_UPDATE_NODE_RENDER_CONTEXT(ForegroundColorFlag, true, frameNode);
145                 }
146             } },
147         { "ShapeStrokeOpacity",
148             [](RefPtr<PropertyValueBase> value, RefPtr<FrameNode> frameNode) {
149                 if (auto realValue = std::get_if<double>(&(value->GetValue()))) {
150                     ACE_UPDATE_NODE_PAINT_PROPERTY(
151                         ShapePaintProperty, StrokeOpacity, std::clamp(*realValue, 0.0, 1.0), frameNode);
152                 }
153             } },
154         { "ShapeFillOpacity",
155             [](RefPtr<PropertyValueBase> value, RefPtr<FrameNode> frameNode) {
156                 if (auto realValue = std::get_if<double>(&(value->GetValue()))) {
157                     ACE_UPDATE_NODE_PAINT_PROPERTY(
158                         ShapePaintProperty, FillOpacity, std::clamp(*realValue, 0.0, 1.0), frameNode);
159                 }
160             } },
161         { "ShapeStrokeWidth",
162             [](RefPtr<PropertyValueBase> value, RefPtr<FrameNode> frameNode) {
163                 if (auto realValue = std::get_if<CalcDimension>(&(value->GetValue()))) {
164                     auto strokeWidth = realValue->IsNegative() ? 1.0_vp : *realValue;
165                     ACE_UPDATE_NODE_PAINT_PROPERTY(ShapePaintProperty, StrokeWidth, strokeWidth, frameNode);
166                 }
167             } },
168     };
169     auto it = handlers.find(key);
170     if (it != handlers.end()) {
171         it->second(value, frameNode);
172     }
173     if (frameNode->GetRerenderable()) {
174         for (auto childNode : ChildNodes_) {
175             auto child = childNode.Upgrade();
176             if (!child) {
177                 continue;
178             }
179             child->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
180         }
181     }
182 }
183 } // namespace OHOS::Ace::NG
184