1 /*
2  * Copyright (c) 2022-2023 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_SVG_PARSE_SVG_NODE_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_SVG_PARSE_SVG_NODE_H
18 
19 #include <vector>
20 
21 #ifndef USE_ROSEN_DRAWING
22 #include "include/core/SkCanvas.h"
23 #include "include/core/SkPath.h"
24 #endif
25 
26 #include "base/memory/ace_type.h"
27 #include "base/utils/noncopyable.h"
28 #include "core/animation/svg_animate.h"
29 #include "core/components/declaration/svg/svg_base_declaration.h"
30 #include "core/components_ng/image_provider/svg_dom_base.h"
31 #include "core/components_ng/render/drawing_forward.h"
32 #ifdef USE_ROSEN_DRAWING
33 #include "core/components_ng/render/drawing.h"
34 #endif
35 #include "core/components_ng/svg/svg_context.h"
36 
37 namespace OHOS::Ace::NG {
38 enum class SvgLengthType {
39     HORIZONTAL,
40     VERTICAL,
41     OTHER,
42 };
43 
44 class SvgContext;
45 class SvgAnimation;
46 
47 // three level inherit class, for example:
48 // 1. SvgMask::SvgQuote::SvgNode
49 // 2. SvgPath::SvgGraphic::SvgNode
50 class SvgNode : public AceType {
51     DECLARE_ACE_TYPE(SvgNode, AceType);
52 
53 public:
54     SvgNode() = default;
55     ~SvgNode() override = default;
56 
57     void InitStyle(const SvgBaseAttribute& attr);
58 
59     // draw entrance function, approve override by second level class.
60     virtual void Draw(RSCanvas& canvas, const Size& viewPort, const std::optional<Color>& color);
61 
62     virtual void SetAttr(const std::string& name, const std::string& value);
63 
ParseAndSetSpecializedAttr(const std::string & name,const std::string & value)64     virtual bool ParseAndSetSpecializedAttr(const std::string& name, const std::string& value)
65     {
66         return false;
67     }
68 
AppendChild(const RefPtr<SvgNode> & child)69     virtual void AppendChild(const RefPtr<SvgNode>& child)
70     {
71         children_.emplace_back(child);
72         OnAppendChild(child);
73     }
74 
InheritAttr(const SvgBaseAttribute & parent)75     virtual void InheritAttr(const SvgBaseAttribute& parent)
76     {
77         attributes_.Inherit(parent);
78     }
79 
InheritUseAttr(const SvgBaseAttribute & parent)80     void InheritUseAttr(const SvgBaseAttribute& parent)
81     {
82         attributes_.InheritFromUse(parent);
83     }
84 
85 #ifndef USE_ROSEN_DRAWING
AsPath(const Size & viewPort)86     virtual SkPath AsPath(const Size& viewPort) const
87 #else
88     virtual RSRecordingPath AsPath(const Size& viewPort) const
89 #endif
90     {
91         return {};
92     }
93 
94     virtual RSPath AsRSPath(const Size& viewPort) const;
95 
AsBounds(const Size & viewPort)96     Rect AsBounds(const Size& viewPort) const
97     {
98 #ifndef USE_ROSEN_DRAWING
99         auto bounds = AsPath(viewPort).getBounds();
100         return { bounds.left(), bounds.top(), bounds.width(), bounds.height() };
101 #else
102         auto bounds = AsPath(viewPort).GetBounds();
103         return { bounds.GetLeft(), bounds.GetTop(), bounds.GetWidth(), bounds.GetHeight() };
104 #endif
105     }
106 
SetContext(const WeakPtr<SvgContext> & svgContext)107     void SetContext(const WeakPtr<SvgContext>& svgContext)
108     {
109         svgContext_ = svgContext;
110     }
111 
SetNodeId(const std::string & value)112     void SetNodeId(const std::string& value)
113     {
114         nodeId_ = value;
115     }
116 
SetSmoothEdge(float value)117     void SetSmoothEdge(float value)
118     {
119         smoothEdge_ = value;
120     }
121 
GetSmoothEdge()122     float GetSmoothEdge() const
123     {
124         return smoothEdge_;
125     }
126 
SetColorFilter(const std::optional<ImageColorFilter> & colorFilter)127     void SetColorFilter(const std::optional<ImageColorFilter>& colorFilter)
128     {
129         colorFilter_ = colorFilter;
130     }
131 
SetEffectFilterArea(const Rect & effectFilterArea)132     void SetEffectFilterArea(const Rect& effectFilterArea)
133     {
134         effectFilterArea_ = effectFilterArea;
135     }
136 
GetEffectFilterArea()137     Rect GetEffectFilterArea() const
138     {
139         return effectFilterArea_;
140     }
141 
GetColorFilter()142     std::optional<ImageColorFilter> GetColorFilter() const
143     {
144         return colorFilter_;
145     }
146 
GetBaseAttributes()147     SvgBaseAttribute GetBaseAttributes() const
148     {
149         return attributes_;
150     }
151 
SetBaseAttributes(const SvgBaseAttribute & attr)152     void SetBaseAttributes(const SvgBaseAttribute& attr)
153     {
154         attributes_ = attr;
155     }
156 
SetImagePath(const std::string & path)157     void SetImagePath(const std::string& path)
158     {
159         imagePath_ = path;
160     }
161 
GetImagePath()162     std::string GetImagePath() const
163     {
164         return imagePath_;
165     }
SetIsRootNode(bool isRoot)166     void SetIsRootNode(bool isRoot)
167     {
168         isRootNode_ = isRoot;
169     }
170 protected:
171     // override as need by derived class
172     // called by function AppendChild
OnAppendChild(const RefPtr<SvgNode> & child)173     virtual void OnAppendChild(const RefPtr<SvgNode>& child) {}
174     // called by function InitStyle
OnInitStyle()175     virtual void OnInitStyle() {}
176     // function override by graphic tag
OnDraw(RSCanvas & canvas,const Size & viewPort,const std::optional<Color> & color)177     virtual void OnDraw(RSCanvas& canvas, const Size& viewPort, const std::optional<Color>& color) {}
178 
179     virtual void OnDrawTraversed(RSCanvas& canvas, const Size& viewPort, const std::optional<Color>& color);
AdjustContentAreaByViewBox(RSCanvas & canvas,const Size & viewPort)180     virtual void AdjustContentAreaByViewBox(RSCanvas& canvas, const Size& viewPort) {}
181     bool OnCanvas(RSCanvas& canvas);
182     void OnClipPath(RSCanvas& canvas, const Size& viewPort);
183     void OnFilter(RSCanvas& canvas, const Size& viewPort);
184     void OnMask(RSCanvas& canvas, const Size& viewPort);
185     void OnTransform(RSCanvas& canvas, const Size& viewPort);
186 
187     double ConvertDimensionToPx(const Dimension& value, const Size& viewPort, SvgLengthType type) const;
188     double ConvertDimensionToPx(const Dimension& value, double baseValue) const;
189 
190     std::optional<Gradient> GetGradient(const std::string& href);
191     const Rect& GetRootViewBox() const;
192     virtual void PrepareAnimation(const RefPtr<SvgAnimation>& animate);
193     // create animation that changes an attribute
194     template<typename T>
195     void AnimateOnAttribute(const RefPtr<SvgAnimation>& animate, const T& originalValue);
196     // animate a transformation attribute
197     void AnimateTransform(const RefPtr<SvgAnimation>& animate, double originalValue);
198     void AnimateFromToTransform(const RefPtr<SvgAnimation>& animate, double originalValue);
199     void AnimateFrameTransform(const RefPtr<SvgAnimation>& animate, double originalValue);
200 
201     // update svg attribute in animation
202     template<typename T>
203     void UpdateAttr(const std::string& name, const T& val);
204     void UpdateAttrHelper(const std::string& name, const std::string& val);
205 
206     // defs gradient animation
InitNoneFlag()207     void InitNoneFlag()
208     {
209         hrefFill_ = false;
210         hrefRender_ = false;
211         passStyle_ = false;
212         inheritStyle_ = false;
213         drawTraversed_ = false;
214     }
215 
216     WeakPtr<SvgContext> svgContext_;
217     std::vector<RefPtr<SvgNode>> children_;
218     std::string nodeId_;
219     std::string transform_;
220     std::map<std::string, std::vector<float>> animateTransform_;
221 
222     SvgBaseAttribute attributes_;
223 
224     std::string hrefClipPath_;
225     std::string hrefMaskId_;
226     std::string hrefFilterId_;
227     std::string imagePath_;
228     uint8_t opacity_ = 0xFF;
229     float smoothEdge_ = 0.0f;
230     std::optional<ImageColorFilter> colorFilter_;
231     Rect effectFilterArea_;
232     float useOffsetX_ = 0.0f;
233     float useOffsetY_ = 0.0f;
234 
235     bool hrefFill_ = true;   // get fill attributes from reference
236     bool hrefRender_ = true; // get render attr (mask, filter, transform, opacity, clip path) from reference
237     bool passStyle_ = true; // pass style attributes to child node, TAGS circle/path/line/... = false
238     bool inheritStyle_ = true;  // inherit style attributes from parent node, TAGS mask/defs/pattern/filter = false
239     bool drawTraversed_ = true; // enable OnDraw, TAGS mask/defs/pattern/filter = false
240     bool isRootNode_ = false;
241 #ifndef USE_ROSEN_DRAWING
242     SkCanvas* skCanvas_ = nullptr;
243 #else
244     RSCanvas* rsCanvas_ = nullptr;
245 #endif
246 
247     ACE_DISALLOW_COPY_AND_MOVE(SvgNode);
248 };
249 
250 } // namespace OHOS::Ace::NG
251 
252 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_SVG_PARSE_SVG_NODE_H