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