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/SkSVGFeMorphology.h" 11#include "modules/svg/include/SkSVGFilterContext.h" 12#include "modules/svg/include/SkSVGRenderContext.h" 13#include "modules/svg/include/SkSVGValue.h" 14 15bool SkSVGFeMorphology::parseAndSetAttribute(const char* name, const char* value) { 16 return INHERITED::parseAndSetAttribute(name, value) || 17 this->setOperator(SkSVGAttributeParser::parse<SkSVGFeMorphology::Operator>( 18 "operator", name, value)) || 19 this->setRadius(SkSVGAttributeParser::parse<SkSVGFeMorphology::Radius>( 20 "radius", name, value)); 21} 22 23sk_sp<SkImageFilter> SkSVGFeMorphology::onMakeImageFilter(const SkSVGRenderContext& ctx, 24 const SkSVGFilterContext& fctx) const { 25 const SkRect cropRect = this->resolveFilterSubregion(ctx, fctx); 26 const SkSVGColorspace colorspace = this->resolveColorspace(ctx, fctx); 27 sk_sp<SkImageFilter> input = fctx.resolveInput(ctx, this->getIn(), colorspace); 28 29 const auto r = SkV2{fRadius.fX, fRadius.fY} 30 * ctx.transformForCurrentOBB(fctx.primitiveUnits()).scale; 31 switch (fOperator) { 32 case Operator::kErode: 33 return SkImageFilters::Erode(r.x, r.y, input, cropRect); 34 case Operator::kDilate: 35 return SkImageFilters::Dilate(r.x, r.y, input, cropRect); 36 } 37 38 SkUNREACHABLE; 39} 40 41template <> 42bool SkSVGAttributeParser::parse<SkSVGFeMorphology::Operator>(SkSVGFeMorphology::Operator* op) { 43 static constexpr std::tuple<const char*, SkSVGFeMorphology::Operator> gMap[] = { 44 { "dilate", SkSVGFeMorphology::Operator::kDilate }, 45 { "erode" , SkSVGFeMorphology::Operator::kErode }, 46 }; 47 48 return this->parseEnumMap(gMap, op) && this->parseEOSToken(); 49} 50 51template <> 52bool SkSVGAttributeParser::parse<SkSVGFeMorphology::Radius>(SkSVGFeMorphology::Radius* radius) { 53 std::vector<SkSVGNumberType> values; 54 if (!this->parse(&values)) { 55 return false; 56 } 57 58 radius->fX = values[0]; 59 radius->fY = values.size() > 1 ? values[1] : values[0]; 60 return true; 61} 62