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