xref: /aosp_15_r20/external/skia/modules/svg/include/SkSVGNode.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2016 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #ifndef SkSVGNode_DEFINED
9*c8dee2aaSAndroid Build Coastguard Worker #define SkSVGNode_DEFINED
10*c8dee2aaSAndroid Build Coastguard Worker 
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAPI.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGAttribute.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGAttributeParser.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGTypes.h"
17*c8dee2aaSAndroid Build Coastguard Worker 
18*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
19*c8dee2aaSAndroid Build Coastguard Worker 
20*c8dee2aaSAndroid Build Coastguard Worker class SkMatrix;
21*c8dee2aaSAndroid Build Coastguard Worker class SkPaint;
22*c8dee2aaSAndroid Build Coastguard Worker class SkPath;
23*c8dee2aaSAndroid Build Coastguard Worker class SkSVGNode;
24*c8dee2aaSAndroid Build Coastguard Worker class SkSVGRenderContext;
25*c8dee2aaSAndroid Build Coastguard Worker class SkSVGValue;
26*c8dee2aaSAndroid Build Coastguard Worker 
27*c8dee2aaSAndroid Build Coastguard Worker enum class SkSVGTag {
28*c8dee2aaSAndroid Build Coastguard Worker     kCircle,
29*c8dee2aaSAndroid Build Coastguard Worker     kClipPath,
30*c8dee2aaSAndroid Build Coastguard Worker     kDefs,
31*c8dee2aaSAndroid Build Coastguard Worker     kEllipse,
32*c8dee2aaSAndroid Build Coastguard Worker     kFeBlend,
33*c8dee2aaSAndroid Build Coastguard Worker     kFeColorMatrix,
34*c8dee2aaSAndroid Build Coastguard Worker     kFeComponentTransfer,
35*c8dee2aaSAndroid Build Coastguard Worker     kFeComposite,
36*c8dee2aaSAndroid Build Coastguard Worker     kFeDiffuseLighting,
37*c8dee2aaSAndroid Build Coastguard Worker     kFeDisplacementMap,
38*c8dee2aaSAndroid Build Coastguard Worker     kFeDistantLight,
39*c8dee2aaSAndroid Build Coastguard Worker     kFeFlood,
40*c8dee2aaSAndroid Build Coastguard Worker     kFeFuncA,
41*c8dee2aaSAndroid Build Coastguard Worker     kFeFuncR,
42*c8dee2aaSAndroid Build Coastguard Worker     kFeFuncG,
43*c8dee2aaSAndroid Build Coastguard Worker     kFeFuncB,
44*c8dee2aaSAndroid Build Coastguard Worker     kFeGaussianBlur,
45*c8dee2aaSAndroid Build Coastguard Worker     kFeImage,
46*c8dee2aaSAndroid Build Coastguard Worker     kFeMerge,
47*c8dee2aaSAndroid Build Coastguard Worker     kFeMergeNode,
48*c8dee2aaSAndroid Build Coastguard Worker     kFeMorphology,
49*c8dee2aaSAndroid Build Coastguard Worker     kFeOffset,
50*c8dee2aaSAndroid Build Coastguard Worker     kFePointLight,
51*c8dee2aaSAndroid Build Coastguard Worker     kFeSpecularLighting,
52*c8dee2aaSAndroid Build Coastguard Worker     kFeSpotLight,
53*c8dee2aaSAndroid Build Coastguard Worker     kFeTurbulence,
54*c8dee2aaSAndroid Build Coastguard Worker     kFilter,
55*c8dee2aaSAndroid Build Coastguard Worker     kG,
56*c8dee2aaSAndroid Build Coastguard Worker     kImage,
57*c8dee2aaSAndroid Build Coastguard Worker     kLine,
58*c8dee2aaSAndroid Build Coastguard Worker     kLinearGradient,
59*c8dee2aaSAndroid Build Coastguard Worker     kMask,
60*c8dee2aaSAndroid Build Coastguard Worker     kPath,
61*c8dee2aaSAndroid Build Coastguard Worker     kPattern,
62*c8dee2aaSAndroid Build Coastguard Worker     kPolygon,
63*c8dee2aaSAndroid Build Coastguard Worker     kPolyline,
64*c8dee2aaSAndroid Build Coastguard Worker     kRadialGradient,
65*c8dee2aaSAndroid Build Coastguard Worker     kRect,
66*c8dee2aaSAndroid Build Coastguard Worker     kStop,
67*c8dee2aaSAndroid Build Coastguard Worker     kSvg,
68*c8dee2aaSAndroid Build Coastguard Worker     kText,
69*c8dee2aaSAndroid Build Coastguard Worker     kTextLiteral,
70*c8dee2aaSAndroid Build Coastguard Worker     kTextPath,
71*c8dee2aaSAndroid Build Coastguard Worker     kTSpan,
72*c8dee2aaSAndroid Build Coastguard Worker     kUse
73*c8dee2aaSAndroid Build Coastguard Worker };
74*c8dee2aaSAndroid Build Coastguard Worker 
75*c8dee2aaSAndroid Build Coastguard Worker #define SVG_PRES_ATTR(attr_name, attr_type, attr_inherited)                  \
76*c8dee2aaSAndroid Build Coastguard Worker private:                                                                     \
77*c8dee2aaSAndroid Build Coastguard Worker     bool set##attr_name(SkSVGAttributeParser::ParseResult<                   \
78*c8dee2aaSAndroid Build Coastguard Worker                             SkSVGProperty<attr_type, attr_inherited>>&& pr) {\
79*c8dee2aaSAndroid Build Coastguard Worker         if (pr.isValid()) { this->set##attr_name(std::move(*pr)); }          \
80*c8dee2aaSAndroid Build Coastguard Worker         return pr.isValid();                                                 \
81*c8dee2aaSAndroid Build Coastguard Worker     }                                                                        \
82*c8dee2aaSAndroid Build Coastguard Worker                                                                              \
83*c8dee2aaSAndroid Build Coastguard Worker public:                                                                      \
84*c8dee2aaSAndroid Build Coastguard Worker     const SkSVGProperty<attr_type, attr_inherited>& get##attr_name() const { \
85*c8dee2aaSAndroid Build Coastguard Worker         return fPresentationAttributes.f##attr_name;                         \
86*c8dee2aaSAndroid Build Coastguard Worker     }                                                                        \
87*c8dee2aaSAndroid Build Coastguard Worker     void set##attr_name(const SkSVGProperty<attr_type, attr_inherited>& v) { \
88*c8dee2aaSAndroid Build Coastguard Worker         auto* dest = &fPresentationAttributes.f##attr_name;                  \
89*c8dee2aaSAndroid Build Coastguard Worker         if (!dest->isInheritable() || v.isValue()) {                         \
90*c8dee2aaSAndroid Build Coastguard Worker             /* TODO: If dest is not inheritable, handle v == "inherit" */    \
91*c8dee2aaSAndroid Build Coastguard Worker             *dest = v;                                                       \
92*c8dee2aaSAndroid Build Coastguard Worker         } else {                                                             \
93*c8dee2aaSAndroid Build Coastguard Worker             dest->set(SkSVGPropertyState::kInherit);                         \
94*c8dee2aaSAndroid Build Coastguard Worker         }                                                                    \
95*c8dee2aaSAndroid Build Coastguard Worker     }                                                                        \
96*c8dee2aaSAndroid Build Coastguard Worker     void set##attr_name(SkSVGProperty<attr_type, attr_inherited>&& v) {      \
97*c8dee2aaSAndroid Build Coastguard Worker         auto* dest = &fPresentationAttributes.f##attr_name;                  \
98*c8dee2aaSAndroid Build Coastguard Worker         if (!dest->isInheritable() || v.isValue()) {                         \
99*c8dee2aaSAndroid Build Coastguard Worker             /* TODO: If dest is not inheritable, handle v == "inherit" */    \
100*c8dee2aaSAndroid Build Coastguard Worker             *dest = std::move(v);                                            \
101*c8dee2aaSAndroid Build Coastguard Worker         } else {                                                             \
102*c8dee2aaSAndroid Build Coastguard Worker             dest->set(SkSVGPropertyState::kInherit);                         \
103*c8dee2aaSAndroid Build Coastguard Worker         }                                                                    \
104*c8dee2aaSAndroid Build Coastguard Worker     }
105*c8dee2aaSAndroid Build Coastguard Worker 
106*c8dee2aaSAndroid Build Coastguard Worker class SK_API SkSVGNode : public SkRefCnt {
107*c8dee2aaSAndroid Build Coastguard Worker public:
108*c8dee2aaSAndroid Build Coastguard Worker     ~SkSVGNode() override;
109*c8dee2aaSAndroid Build Coastguard Worker 
tag()110*c8dee2aaSAndroid Build Coastguard Worker     SkSVGTag tag() const { return fTag; }
111*c8dee2aaSAndroid Build Coastguard Worker 
112*c8dee2aaSAndroid Build Coastguard Worker     virtual void appendChild(sk_sp<SkSVGNode>) = 0;
113*c8dee2aaSAndroid Build Coastguard Worker 
114*c8dee2aaSAndroid Build Coastguard Worker     void render(const SkSVGRenderContext&) const;
115*c8dee2aaSAndroid Build Coastguard Worker     bool asPaint(const SkSVGRenderContext&, SkPaint*) const;
116*c8dee2aaSAndroid Build Coastguard Worker     SkPath asPath(const SkSVGRenderContext&) const;
117*c8dee2aaSAndroid Build Coastguard Worker     SkRect objectBoundingBox(const SkSVGRenderContext&) const;
118*c8dee2aaSAndroid Build Coastguard Worker 
119*c8dee2aaSAndroid Build Coastguard Worker     void setAttribute(SkSVGAttribute, const SkSVGValue&);
120*c8dee2aaSAndroid Build Coastguard Worker     bool setAttribute(const char* attributeName, const char* attributeValue);
121*c8dee2aaSAndroid Build Coastguard Worker 
122*c8dee2aaSAndroid Build Coastguard Worker     // TODO: consolidate with existing setAttribute
123*c8dee2aaSAndroid Build Coastguard Worker     virtual bool parseAndSetAttribute(const char* name, const char* value);
124*c8dee2aaSAndroid Build Coastguard Worker 
125*c8dee2aaSAndroid Build Coastguard Worker     // inherited
126*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(ClipRule                 , SkSVGFillRule  , true)
127*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(Color                    , SkSVGColorType , true)
128*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(ColorInterpolation       , SkSVGColorspace, true)
129*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(ColorInterpolationFilters, SkSVGColorspace, true)
130*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(FillRule                 , SkSVGFillRule  , true)
131*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(Fill                     , SkSVGPaint     , true)
132*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(FillOpacity              , SkSVGNumberType, true)
133*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(FontFamily               , SkSVGFontFamily, true)
134*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(FontSize                 , SkSVGFontSize  , true)
135*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(FontStyle                , SkSVGFontStyle , true)
136*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(FontWeight               , SkSVGFontWeight, true)
137*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(Stroke                   , SkSVGPaint     , true)
138*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(StrokeDashArray          , SkSVGDashArray , true)
139*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(StrokeDashOffset         , SkSVGLength    , true)
140*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(StrokeLineCap            , SkSVGLineCap   , true)
141*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(StrokeLineJoin           , SkSVGLineJoin  , true)
142*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(StrokeMiterLimit         , SkSVGNumberType, true)
143*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(StrokeOpacity            , SkSVGNumberType, true)
144*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(StrokeWidth              , SkSVGLength    , true)
145*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(TextAnchor               , SkSVGTextAnchor, true)
146*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(Visibility               , SkSVGVisibility, true)
147*c8dee2aaSAndroid Build Coastguard Worker 
148*c8dee2aaSAndroid Build Coastguard Worker     // not inherited
149*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(ClipPath                 , SkSVGFuncIRI   , false)
150*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(Display                  , SkSVGDisplay   , false)
151*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(Mask                     , SkSVGFuncIRI   , false)
152*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(Filter                   , SkSVGFuncIRI   , false)
153*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(Opacity                  , SkSVGNumberType, false)
154*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(StopColor                , SkSVGColor     , false)
155*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(StopOpacity              , SkSVGNumberType, false)
156*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(FloodColor               , SkSVGColor     , false)
157*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(FloodOpacity             , SkSVGNumberType, false)
158*c8dee2aaSAndroid Build Coastguard Worker     SVG_PRES_ATTR(LightingColor            , SkSVGColor     , false)
159*c8dee2aaSAndroid Build Coastguard Worker 
160*c8dee2aaSAndroid Build Coastguard Worker protected:
161*c8dee2aaSAndroid Build Coastguard Worker     SkSVGNode(SkSVGTag);
162*c8dee2aaSAndroid Build Coastguard Worker 
163*c8dee2aaSAndroid Build Coastguard Worker     static SkMatrix ComputeViewboxMatrix(const SkRect&, const SkRect&, SkSVGPreserveAspectRatio);
164*c8dee2aaSAndroid Build Coastguard Worker 
165*c8dee2aaSAndroid Build Coastguard Worker     // Called before onRender(), to apply local attributes to the context.  Unlike onRender(),
166*c8dee2aaSAndroid Build Coastguard Worker     // onPrepareToRender() bubbles up the inheritance chain: overriders should always call
167*c8dee2aaSAndroid Build Coastguard Worker     // INHERITED::onPrepareToRender(), unless they intend to short-circuit rendering
168*c8dee2aaSAndroid Build Coastguard Worker     // (return false).
169*c8dee2aaSAndroid Build Coastguard Worker     // Implementations are expected to return true if rendering is to continue, or false if
170*c8dee2aaSAndroid Build Coastguard Worker     // the node/subtree rendering is disabled.
171*c8dee2aaSAndroid Build Coastguard Worker     virtual bool onPrepareToRender(SkSVGRenderContext*) const;
172*c8dee2aaSAndroid Build Coastguard Worker 
173*c8dee2aaSAndroid Build Coastguard Worker     virtual void onRender(const SkSVGRenderContext&) const = 0;
174*c8dee2aaSAndroid Build Coastguard Worker 
onAsPaint(const SkSVGRenderContext &,SkPaint *)175*c8dee2aaSAndroid Build Coastguard Worker     virtual bool onAsPaint(const SkSVGRenderContext&, SkPaint*) const { return false; }
176*c8dee2aaSAndroid Build Coastguard Worker 
177*c8dee2aaSAndroid Build Coastguard Worker     virtual SkPath onAsPath(const SkSVGRenderContext&) const = 0;
178*c8dee2aaSAndroid Build Coastguard Worker 
onSetAttribute(SkSVGAttribute,const SkSVGValue &)179*c8dee2aaSAndroid Build Coastguard Worker     virtual void onSetAttribute(SkSVGAttribute, const SkSVGValue&) {}
180*c8dee2aaSAndroid Build Coastguard Worker 
hasChildren()181*c8dee2aaSAndroid Build Coastguard Worker     virtual bool hasChildren() const { return false; }
182*c8dee2aaSAndroid Build Coastguard Worker 
onObjectBoundingBox(const SkSVGRenderContext &)183*c8dee2aaSAndroid Build Coastguard Worker     virtual SkRect onObjectBoundingBox(const SkSVGRenderContext&) const {
184*c8dee2aaSAndroid Build Coastguard Worker         return SkRect::MakeEmpty();
185*c8dee2aaSAndroid Build Coastguard Worker     }
186*c8dee2aaSAndroid Build Coastguard Worker 
187*c8dee2aaSAndroid Build Coastguard Worker private:
188*c8dee2aaSAndroid Build Coastguard Worker     SkSVGTag                    fTag;
189*c8dee2aaSAndroid Build Coastguard Worker 
190*c8dee2aaSAndroid Build Coastguard Worker     // FIXME: this should be sparse
191*c8dee2aaSAndroid Build Coastguard Worker     SkSVGPresentationAttributes fPresentationAttributes;
192*c8dee2aaSAndroid Build Coastguard Worker 
193*c8dee2aaSAndroid Build Coastguard Worker     using INHERITED = SkRefCnt;
194*c8dee2aaSAndroid Build Coastguard Worker };
195*c8dee2aaSAndroid Build Coastguard Worker 
196*c8dee2aaSAndroid Build Coastguard Worker #undef SVG_PRES_ATTR // presentation attributes are only defined for the base class
197*c8dee2aaSAndroid Build Coastguard Worker 
198*c8dee2aaSAndroid Build Coastguard Worker #define _SVG_ATTR_SETTERS(attr_name, attr_type, attr_default, set_cp, set_mv) \
199*c8dee2aaSAndroid Build Coastguard Worker     private:                                                                  \
200*c8dee2aaSAndroid Build Coastguard Worker         bool set##attr_name(                                                  \
201*c8dee2aaSAndroid Build Coastguard Worker                 const SkSVGAttributeParser::ParseResult<attr_type>& pr) {     \
202*c8dee2aaSAndroid Build Coastguard Worker             if (pr.isValid()) { this->set##attr_name(*pr); }                  \
203*c8dee2aaSAndroid Build Coastguard Worker             return pr.isValid();                                              \
204*c8dee2aaSAndroid Build Coastguard Worker         }                                                                     \
205*c8dee2aaSAndroid Build Coastguard Worker         bool set##attr_name(                                                  \
206*c8dee2aaSAndroid Build Coastguard Worker                 SkSVGAttributeParser::ParseResult<attr_type>&& pr) {          \
207*c8dee2aaSAndroid Build Coastguard Worker             if (pr.isValid()) { this->set##attr_name(std::move(*pr)); }       \
208*c8dee2aaSAndroid Build Coastguard Worker             return pr.isValid();                                              \
209*c8dee2aaSAndroid Build Coastguard Worker         }                                                                     \
210*c8dee2aaSAndroid Build Coastguard Worker     public:                                                                   \
211*c8dee2aaSAndroid Build Coastguard Worker         void set##attr_name(const attr_type& a) { set_cp(a); }                \
212*c8dee2aaSAndroid Build Coastguard Worker         void set##attr_name(attr_type&& a) { set_mv(std::move(a)); }
213*c8dee2aaSAndroid Build Coastguard Worker 
214*c8dee2aaSAndroid Build Coastguard Worker #define SVG_ATTR(attr_name, attr_type, attr_default)                        \
215*c8dee2aaSAndroid Build Coastguard Worker     private:                                                                \
216*c8dee2aaSAndroid Build Coastguard Worker         attr_type f##attr_name = attr_default;                              \
217*c8dee2aaSAndroid Build Coastguard Worker     public:                                                                 \
218*c8dee2aaSAndroid Build Coastguard Worker         const attr_type& get##attr_name() const { return f##attr_name; }    \
219*c8dee2aaSAndroid Build Coastguard Worker     _SVG_ATTR_SETTERS(                                                      \
220*c8dee2aaSAndroid Build Coastguard Worker             attr_name, attr_type, attr_default,                             \
221*c8dee2aaSAndroid Build Coastguard Worker             [this](const attr_type& a) { this->f##attr_name = a; },         \
222*c8dee2aaSAndroid Build Coastguard Worker             [this](attr_type&& a) { this->f##attr_name = std::move(a); })
223*c8dee2aaSAndroid Build Coastguard Worker 
224*c8dee2aaSAndroid Build Coastguard Worker #define SVG_OPTIONAL_ATTR(attr_name, attr_type)                                   \
225*c8dee2aaSAndroid Build Coastguard Worker     private:                                                                      \
226*c8dee2aaSAndroid Build Coastguard Worker         SkTLazy<attr_type> f##attr_name;                                          \
227*c8dee2aaSAndroid Build Coastguard Worker     public:                                                                       \
228*c8dee2aaSAndroid Build Coastguard Worker         const SkTLazy<attr_type>& get##attr_name() const { return f##attr_name; } \
229*c8dee2aaSAndroid Build Coastguard Worker     _SVG_ATTR_SETTERS(                                                            \
230*c8dee2aaSAndroid Build Coastguard Worker             attr_name, attr_type, attr_default,                                   \
231*c8dee2aaSAndroid Build Coastguard Worker             [this](const attr_type& a) { this->f##attr_name.set(a); },            \
232*c8dee2aaSAndroid Build Coastguard Worker             [this](attr_type&& a) { this->f##attr_name.set(std::move(a)); })
233*c8dee2aaSAndroid Build Coastguard Worker 
234*c8dee2aaSAndroid Build Coastguard Worker #endif // SkSVGNode_DEFINED
235