| /* |
| * Copyright 2016 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef SkSVGNode_DEFINED |
| #define SkSVGNode_DEFINED |
| |
| #include "include/core/SkRefCnt.h" |
| #include "modules/svg/include/SkSVGAttribute.h" |
| #include "modules/svg/include/SkSVGAttributeParser.h" |
| |
| class SkCanvas; |
| class SkMatrix; |
| class SkPaint; |
| class SkPath; |
| class SkSVGLengthContext; |
| class SkSVGRenderContext; |
| class SkSVGValue; |
| |
| enum class SkSVGTag { |
| kCircle, |
| kClipPath, |
| kDefs, |
| kEllipse, |
| kFeBlend, |
| kFeColorMatrix, |
| kFeComposite, |
| kFeDiffuseLighting, |
| kFeDisplacementMap, |
| kFeDistantLight, |
| kFeFlood, |
| kFeGaussianBlur, |
| kFeImage, |
| kFeMorphology, |
| kFeOffset, |
| kFePointLight, |
| kFeSpecularLighting, |
| kFeSpotLight, |
| kFeTurbulence, |
| kFilter, |
| kG, |
| kImage, |
| kLine, |
| kLinearGradient, |
| kMask, |
| kPath, |
| kPattern, |
| kPolygon, |
| kPolyline, |
| kRadialGradient, |
| kRect, |
| kStop, |
| kSvg, |
| kText, |
| kTextLiteral, |
| kTextPath, |
| kTSpan, |
| kUse |
| }; |
| |
| #define SVG_PRES_ATTR(attr_name, attr_type, attr_inherited) \ |
| private: \ |
| bool set##attr_name(SkSVGAttributeParser::ParseResult< \ |
| SkSVGProperty<attr_type, attr_inherited>>&& pr) {\ |
| if (pr.isValid()) { this->set##attr_name(std::move(*pr)); } \ |
| return pr.isValid(); \ |
| } \ |
| \ |
| public: \ |
| const SkSVGProperty<attr_type, attr_inherited>& get##attr_name() const { \ |
| return fPresentationAttributes.f##attr_name; \ |
| } \ |
| void set##attr_name(const SkSVGProperty<attr_type, attr_inherited>& v) { \ |
| auto* dest = &fPresentationAttributes.f##attr_name; \ |
| if (!dest->isInheritable() || v.isValue()) { \ |
| /* TODO: If dest is not inheritable, handle v == "inherit" */ \ |
| *dest = v; \ |
| } else { \ |
| dest->set(SkSVGPropertyState::kInherit); \ |
| } \ |
| } \ |
| void set##attr_name(SkSVGProperty<attr_type, attr_inherited>&& v) { \ |
| auto* dest = &fPresentationAttributes.f##attr_name; \ |
| if (!dest->isInheritable() || v.isValue()) { \ |
| /* TODO: If dest is not inheritable, handle v == "inherit" */ \ |
| *dest = std::move(v); \ |
| } else { \ |
| dest->set(SkSVGPropertyState::kInherit); \ |
| } \ |
| } |
| |
| class SkSVGNode : public SkRefCnt { |
| public: |
| ~SkSVGNode() override; |
| |
| SkSVGTag tag() const { return fTag; } |
| |
| virtual void appendChild(sk_sp<SkSVGNode>) = 0; |
| |
| void render(const SkSVGRenderContext&) const; |
| bool asPaint(const SkSVGRenderContext&, SkPaint*) const; |
| SkPath asPath(const SkSVGRenderContext&) const; |
| SkRect objectBoundingBox(const SkSVGRenderContext&) const; |
| |
| void setAttribute(SkSVGAttribute, const SkSVGValue&); |
| bool setAttribute(const char* attributeName, const char* attributeValue); |
| |
| // TODO: consolidate with existing setAttribute |
| virtual bool parseAndSetAttribute(const char* name, const char* value); |
| |
| // inherited |
| SVG_PRES_ATTR(ClipRule , SkSVGFillRule , true) |
| SVG_PRES_ATTR(Color , SkSVGColorType , true) |
| SVG_PRES_ATTR(ColorInterpolation , SkSVGColorspace, true) |
| SVG_PRES_ATTR(ColorInterpolationFilters, SkSVGColorspace, true) |
| SVG_PRES_ATTR(FillRule , SkSVGFillRule , true) |
| SVG_PRES_ATTR(Fill , SkSVGPaint , true) |
| SVG_PRES_ATTR(FillOpacity , SkSVGNumberType, true) |
| SVG_PRES_ATTR(FontFamily , SkSVGFontFamily, true) |
| SVG_PRES_ATTR(FontSize , SkSVGFontSize , true) |
| SVG_PRES_ATTR(FontStyle , SkSVGFontStyle , true) |
| SVG_PRES_ATTR(FontWeight , SkSVGFontWeight, true) |
| SVG_PRES_ATTR(Stroke , SkSVGPaint , true) |
| SVG_PRES_ATTR(StrokeDashArray , SkSVGDashArray , true) |
| SVG_PRES_ATTR(StrokeDashOffset , SkSVGLength , true) |
| SVG_PRES_ATTR(StrokeLineCap , SkSVGLineCap , true) |
| SVG_PRES_ATTR(StrokeLineJoin , SkSVGLineJoin , true) |
| SVG_PRES_ATTR(StrokeMiterLimit , SkSVGNumberType, true) |
| SVG_PRES_ATTR(StrokeOpacity , SkSVGNumberType, true) |
| SVG_PRES_ATTR(StrokeWidth , SkSVGLength , true) |
| SVG_PRES_ATTR(TextAnchor , SkSVGTextAnchor, true) |
| SVG_PRES_ATTR(Visibility , SkSVGVisibility, true) |
| |
| // not inherited |
| SVG_PRES_ATTR(ClipPath , SkSVGFuncIRI , false) |
| SVG_PRES_ATTR(Display , SkSVGDisplay , false) |
| SVG_PRES_ATTR(Mask , SkSVGFuncIRI , false) |
| SVG_PRES_ATTR(Filter , SkSVGFuncIRI , false) |
| SVG_PRES_ATTR(Opacity , SkSVGNumberType, false) |
| SVG_PRES_ATTR(StopColor , SkSVGColor , false) |
| SVG_PRES_ATTR(StopOpacity , SkSVGNumberType, false) |
| SVG_PRES_ATTR(FloodColor , SkSVGColor , false) |
| SVG_PRES_ATTR(FloodOpacity , SkSVGNumberType, false) |
| SVG_PRES_ATTR(LightingColor , SkSVGColor , false) |
| |
| protected: |
| SkSVGNode(SkSVGTag); |
| |
| static SkMatrix ComputeViewboxMatrix(const SkRect&, const SkRect&, SkSVGPreserveAspectRatio); |
| |
| // Called before onRender(), to apply local attributes to the context. Unlike onRender(), |
| // onPrepareToRender() bubbles up the inheritance chain: overriders should always call |
| // INHERITED::onPrepareToRender(), unless they intend to short-circuit rendering |
| // (return false). |
| // Implementations are expected to return true if rendering is to continue, or false if |
| // the node/subtree rendering is disabled. |
| virtual bool onPrepareToRender(SkSVGRenderContext*) const; |
| |
| virtual void onRender(const SkSVGRenderContext&) const = 0; |
| |
| virtual bool onAsPaint(const SkSVGRenderContext&, SkPaint*) const { return false; } |
| |
| virtual SkPath onAsPath(const SkSVGRenderContext&) const = 0; |
| |
| virtual void onSetAttribute(SkSVGAttribute, const SkSVGValue&) {} |
| |
| virtual bool hasChildren() const { return false; } |
| |
| virtual SkRect onObjectBoundingBox(const SkSVGRenderContext&) const { |
| return SkRect::MakeEmpty(); |
| } |
| |
| private: |
| SkSVGTag fTag; |
| |
| // FIXME: this should be sparse |
| SkSVGPresentationAttributes fPresentationAttributes; |
| |
| using INHERITED = SkRefCnt; |
| }; |
| |
| #undef SVG_PRES_ATTR // presentation attributes are only defined for the base class |
| |
| #define _SVG_ATTR_SETTERS(attr_name, attr_type, attr_default, set_cp, set_mv) \ |
| private: \ |
| bool set##attr_name( \ |
| const SkSVGAttributeParser::ParseResult<attr_type>& pr) { \ |
| if (pr.isValid()) { this->set##attr_name(*pr); } \ |
| return pr.isValid(); \ |
| } \ |
| bool set##attr_name( \ |
| SkSVGAttributeParser::ParseResult<attr_type>&& pr) { \ |
| if (pr.isValid()) { this->set##attr_name(std::move(*pr)); } \ |
| return pr.isValid(); \ |
| } \ |
| public: \ |
| void set##attr_name(const attr_type& a) { set_cp(a); } \ |
| void set##attr_name(attr_type&& a) { set_mv(std::move(a)); } |
| |
| #define SVG_ATTR(attr_name, attr_type, attr_default) \ |
| private: \ |
| attr_type f##attr_name = attr_default; \ |
| public: \ |
| const attr_type& get##attr_name() const { return f##attr_name; } \ |
| _SVG_ATTR_SETTERS( \ |
| attr_name, attr_type, attr_default, \ |
| [this](const attr_type& a) { this->f##attr_name = a; }, \ |
| [this](attr_type&& a) { this->f##attr_name = std::move(a); }) |
| |
| #define SVG_OPTIONAL_ATTR(attr_name, attr_type) \ |
| private: \ |
| SkTLazy<attr_type> f##attr_name; \ |
| public: \ |
| const SkTLazy<attr_type>& get##attr_name() const { return f##attr_name; } \ |
| _SVG_ATTR_SETTERS( \ |
| attr_name, attr_type, attr_default, \ |
| [this](const attr_type& a) { this->f##attr_name.set(a); }, \ |
| [this](attr_type&& a) { this->f##attr_name.set(std::move(a)); }) |
| |
| #endif // SkSVGNode_DEFINED |