/* * Copyright 2020 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "include/core/SkColorFilter.h" #include "include/effects/SkImageFilters.h" #include "include/private/SkColorData.h" #include "modules/svg/include/SkSVGAttributeParser.h" #include "modules/svg/include/SkSVGFeColorMatrix.h" #include "modules/svg/include/SkSVGFilterContext.h" #include "modules/svg/include/SkSVGRenderContext.h" #include "modules/svg/include/SkSVGValue.h" bool SkSVGFeColorMatrix::parseAndSetAttribute(const char* name, const char* value) { return INHERITED::parseAndSetAttribute(name, value) || this->setType( SkSVGAttributeParser::parse("type", name, value)) || this->setValues( SkSVGAttributeParser::parse("values", name, value)); } SkColorMatrix SkSVGFeColorMatrix::makeMatrixForType() const { if (fValues.empty() && fType != SkSVGFeColorMatrixType::kLuminanceToAlpha) { return SkColorMatrix(); } switch (fType) { case SkSVGFeColorMatrixType::kMatrix: { if (fValues.count() < 20) { return SkColorMatrix(); } SkColorMatrix m; m.setRowMajor(this->fValues.begin()); return m; } case SkSVGFeColorMatrixType::kSaturate: return MakeSaturate(fValues.count() > 0 ? fValues[0] : 1); case SkSVGFeColorMatrixType::kHueRotate: return MakeHueRotate(fValues.count() > 0 ? fValues[0] : 0); case SkSVGFeColorMatrixType::kLuminanceToAlpha: return MakeLuminanceToAlpha(); } SkUNREACHABLE; } SkColorMatrix SkSVGFeColorMatrix::MakeSaturate(SkSVGNumberType s) { SkColorMatrix m; m.setSaturation(s); return m; } SkColorMatrix SkSVGFeColorMatrix::MakeHueRotate(SkSVGNumberType degrees) { const SkScalar theta = SkDegreesToRadians(degrees); const SkSVGNumberType c = SkScalarCos(theta); const SkSVGNumberType s = SkScalarSin(theta); return SkColorMatrix( 0.213f + c* 0.787f + s*-0.213f, 0.715f + c*-0.715f + s*-0.715f, 0.072f + c*-0.072f + s* 0.928f, 0, 0, 0.213f + c*-0.213f + s* 0.143f, 0.715f + c* 0.285f + s* 0.140f, 0.072f + c*-0.072f + s*-0.283f, 0, 0, 0.213f + c*-0.213f + s*-0.787f, 0.715f + c*-0.715f + s* 0.715f, 0.072f + c* 0.928f + s* 0.072f, 0, 0, 0,0,0,1,0 ); } SkColorMatrix SkSVGFeColorMatrix::MakeLuminanceToAlpha() { return SkColorMatrix( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, SK_LUM_COEFF_R, SK_LUM_COEFF_G, SK_LUM_COEFF_B, 0, 0 ); } sk_sp SkSVGFeColorMatrix::onMakeImageFilter(const SkSVGRenderContext& ctx, const SkSVGFilterContext& fctx) const { return SkImageFilters::ColorFilter( SkColorFilters::Matrix(makeMatrixForType()), fctx.resolveInput(ctx, this->getIn(), this->resolveColorspace(ctx, fctx)), this->resolveFilterSubregion(ctx, fctx)); } template <> bool SkSVGAttributeParser::parse(SkSVGFeColorMatrixValues* values) { SkSVGNumberType value; if (!this->parse(&value)) { return false; } values->push_back(value); while (true) { if (!this->parse(&value) || values->count() >= 20) { break; } values->push_back(value); } return this->parseEOSToken(); } template <> bool SkSVGAttributeParser::parse(SkSVGFeColorMatrixType* type) { static constexpr std::tuple gTypeMap[] = { {"matrix", SkSVGFeColorMatrixType::kMatrix}, {"saturate", SkSVGFeColorMatrixType::kSaturate}, {"hueRotate", SkSVGFeColorMatrixType::kHueRotate}, {"luminanceToAlpha", SkSVGFeColorMatrixType::kLuminanceToAlpha}, }; return this->parseEnumMap(gTypeMap, type) && this->parseEOSToken(); }