• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "include/effects/SkImageFilters.h"
9 #include "modules/svg/include/SkSVGAttributeParser.h"
10 #include "modules/svg/include/SkSVGFe.h"
11 #include "modules/svg/include/SkSVGFilterContext.h"
12 #include "modules/svg/include/SkSVGRenderContext.h"
13 
makeImageFilter(const SkSVGRenderContext & ctx,const SkSVGFilterContext & fctx) const14 sk_sp<SkImageFilter> SkSVGFe::makeImageFilter(const SkSVGRenderContext& ctx,
15                                               const SkSVGFilterContext& fctx) const {
16     return this->onMakeImageFilter(ctx, fctx);
17 }
18 
resolveBoundaries(const SkSVGRenderContext & ctx,const SkSVGFilterContext & fctx) const19 SkRect SkSVGFe::resolveBoundaries(const SkSVGRenderContext& ctx,
20                                   const SkSVGFilterContext& fctx) const {
21     const auto x = fX.isValid() ? *fX : SkSVGLength(0, SkSVGLength::Unit::kPercentage);
22     const auto y = fY.isValid() ? *fY : SkSVGLength(0, SkSVGLength::Unit::kPercentage);
23     const auto w = fWidth.isValid() ? *fWidth : SkSVGLength(100, SkSVGLength::Unit::kPercentage);
24     const auto h = fHeight.isValid() ? *fHeight : SkSVGLength(100, SkSVGLength::Unit::kPercentage);
25 
26     return ctx.resolveOBBRect(x, y, w, h, fctx.primitiveUnits());
27 }
28 
AnyIsStandardInput(const SkSVGFilterContext & fctx,const std::vector<SkSVGFeInputType> & inputs)29 static bool AnyIsStandardInput(const SkSVGFilterContext& fctx,
30                                const std::vector<SkSVGFeInputType>& inputs) {
31     for (const auto& in : inputs) {
32         switch (in.type()) {
33             case SkSVGFeInputType::Type::kFilterPrimitiveReference:
34                 break;
35             case SkSVGFeInputType::Type::kSourceGraphic:
36             case SkSVGFeInputType::Type::kSourceAlpha:
37             case SkSVGFeInputType::Type::kBackgroundImage:
38             case SkSVGFeInputType::Type::kBackgroundAlpha:
39             case SkSVGFeInputType::Type::kFillPaint:
40             case SkSVGFeInputType::Type::kStrokePaint:
41                 return true;
42             case SkSVGFeInputType::Type::kUnspecified:
43                 // Unspecified means previous result (which may be SourceGraphic).
44                 if (fctx.previousResultIsSourceGraphic()) {
45                     return true;
46                 }
47                 break;
48         }
49     }
50 
51     return false;
52 }
53 
resolveFilterSubregion(const SkSVGRenderContext & ctx,const SkSVGFilterContext & fctx) const54 SkRect SkSVGFe::resolveFilterSubregion(const SkSVGRenderContext& ctx,
55                                        const SkSVGFilterContext& fctx) const {
56     // From https://www.w3.org/TR/SVG11/filters.html#FilterPrimitiveSubRegion,
57     // the default filter effect subregion is equal to the union of the subregions defined
58     // for all "referenced nodes" (filter effect inputs). If there are no inputs, the
59     // default subregion is equal to the filter effects region
60     // (https://www.w3.org/TR/SVG11/filters.html#FilterEffectsRegion).
61     const std::vector<SkSVGFeInputType> inputs = this->getInputs();
62     SkRect defaultSubregion;
63     if (inputs.empty() || AnyIsStandardInput(fctx, inputs)) {
64         defaultSubregion = fctx.filterEffectsRegion();
65     } else {
66         defaultSubregion = fctx.filterPrimitiveSubregion(inputs[0]);
67         for (size_t i = 1; i < inputs.size(); i++) {
68             defaultSubregion.join(fctx.filterPrimitiveSubregion(inputs[i]));
69         }
70     }
71 
72     // Next resolve the rect specified by the x, y, width, height attributes on this filter effect.
73     // If those attributes were given, they override the corresponding attribute of the default
74     // filter effect subregion calculated above.
75     const SkRect boundaries = this->resolveBoundaries(ctx, fctx);
76 
77     // Compute and return the fully resolved subregion.
78     return SkRect::MakeXYWH(fX.isValid() ? boundaries.fLeft : defaultSubregion.fLeft,
79                             fY.isValid() ? boundaries.fTop : defaultSubregion.fTop,
80                             fWidth.isValid() ? boundaries.width() : defaultSubregion.width(),
81                             fHeight.isValid() ? boundaries.height() : defaultSubregion.height());
82 }
83 
resolveColorspace(const SkSVGRenderContext & ctx,const SkSVGFilterContext &) const84 SkSVGColorspace SkSVGFe::resolveColorspace(const SkSVGRenderContext& ctx,
85                                            const SkSVGFilterContext&) const {
86     constexpr SkSVGColorspace kDefaultCS = SkSVGColorspace::kSRGB;
87     const SkSVGColorspace cs = *ctx.presentationContext().fInherited.fColorInterpolationFilters;
88     return cs == SkSVGColorspace::kAuto ? kDefaultCS : cs;
89 }
90 
applyProperties(SkSVGRenderContext * ctx) const91 void SkSVGFe::applyProperties(SkSVGRenderContext* ctx) const { this->onPrepareToRender(ctx); }
92 
parseAndSetAttribute(const char * name,const char * value)93 bool SkSVGFe::parseAndSetAttribute(const char* name, const char* value) {
94     return INHERITED::parseAndSetAttribute(name, value) ||
95            this->setIn(SkSVGAttributeParser::parse<SkSVGFeInputType>("in", name, value)) ||
96            this->setResult(SkSVGAttributeParser::parse<SkSVGStringType>("result", name, value)) ||
97            this->setX(SkSVGAttributeParser::parse<SkSVGLength>("x", name, value)) ||
98            this->setY(SkSVGAttributeParser::parse<SkSVGLength>("y", name, value)) ||
99            this->setWidth(SkSVGAttributeParser::parse<SkSVGLength>("width", name, value)) ||
100            this->setHeight(SkSVGAttributeParser::parse<SkSVGLength>("height", name, value));
101 }
102 
parse(SkSVGFeInputType * type)103 template <> bool SkSVGAttributeParser::parse(SkSVGFeInputType* type) {
104     static constexpr std::tuple<const char*, SkSVGFeInputType::Type> gTypeMap[] = {
105             {"SourceGraphic", SkSVGFeInputType::Type::kSourceGraphic},
106             {"SourceAlpha", SkSVGFeInputType::Type::kSourceAlpha},
107             {"BackgroundImage", SkSVGFeInputType::Type::kBackgroundImage},
108             {"BackgroundAlpha", SkSVGFeInputType::Type::kBackgroundAlpha},
109             {"FillPaint", SkSVGFeInputType::Type::kFillPaint},
110             {"StrokePaint", SkSVGFeInputType::Type::kStrokePaint},
111     };
112 
113     SkSVGStringType resultId;
114     SkSVGFeInputType::Type t;
115     bool parsedValue = false;
116     if (this->parseEnumMap(gTypeMap, &t)) {
117         *type = SkSVGFeInputType(t);
118         parsedValue = true;
119     } else if (parse(&resultId)) {
120         *type = SkSVGFeInputType(resultId);
121         parsedValue = true;
122     }
123 
124     return parsedValue && this->parseEOSToken();
125 }
126