| /* |
| * 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<SkSVGFeColorMatrixType>("type", name, value)) || |
| this->setValues( |
| SkSVGAttributeParser::parse<SkSVGFeColorMatrixValues>("values", name, value)); |
| } |
| |
| SkColorMatrix SkSVGFeColorMatrix::makeMatrixForType() const { |
| if (fValues.empty() && fType != SkSVGFeColorMatrixType::kLuminanceToAlpha) { |
| return SkColorMatrix(); |
| } |
| |
| switch (fType) { |
| case SkSVGFeColorMatrixType::kMatrix: { |
| if (fValues.size() < 20) { |
| return SkColorMatrix(); |
| } |
| SkColorMatrix m; |
| m.setRowMajor(this->fValues.begin()); |
| return m; |
| } |
| case SkSVGFeColorMatrixType::kSaturate: |
| return MakeSaturate(!fValues.empty() ? fValues[0] : 1); |
| case SkSVGFeColorMatrixType::kHueRotate: |
| return MakeHueRotate(!fValues.empty() ? 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<SkImageFilter> 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->size() >= 20) { |
| break; |
| } |
| values->push_back(value); |
| } |
| |
| return this->parseEOSToken(); |
| } |
| |
| template <> bool SkSVGAttributeParser::parse(SkSVGFeColorMatrixType* type) { |
| static constexpr std::tuple<const char*, SkSVGFeColorMatrixType> gTypeMap[] = { |
| {"matrix", SkSVGFeColorMatrixType::kMatrix}, |
| {"saturate", SkSVGFeColorMatrixType::kSaturate}, |
| {"hueRotate", SkSVGFeColorMatrixType::kHueRotate}, |
| {"luminanceToAlpha", SkSVGFeColorMatrixType::kLuminanceToAlpha}, |
| }; |
| |
| return this->parseEnumMap(gTypeMap, type) && this->parseEOSToken(); |
| } |