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 "modules/svg/include/SkSVGFeColorMatrix.h"
9
10 #include "include/core/SkColorFilter.h"
11 #include "include/core/SkScalar.h"
12 #include "include/effects/SkImageFilters.h"
13 #include "include/private/SkColorData.h"
14 #include "include/private/base/SkAssert.h"
15 #include "modules/svg/include/SkSVGAttributeParser.h"
16 #include "modules/svg/include/SkSVGFilterContext.h"
17
18 #include <tuple>
19
20 class SkImageFilter;
21 class SkSVGRenderContext;
22
parseAndSetAttribute(const char * name,const char * value)23 bool SkSVGFeColorMatrix::parseAndSetAttribute(const char* name, const char* value) {
24 return INHERITED::parseAndSetAttribute(name, value) ||
25 this->setType(
26 SkSVGAttributeParser::parse<SkSVGFeColorMatrixType>("type", name, value)) ||
27 this->setValues(
28 SkSVGAttributeParser::parse<SkSVGFeColorMatrixValues>("values", name, value));
29 }
30
makeMatrixForType() const31 SkColorMatrix SkSVGFeColorMatrix::makeMatrixForType() const {
32 if (fValues.empty() && fType != SkSVGFeColorMatrixType::kLuminanceToAlpha) {
33 return SkColorMatrix();
34 }
35
36 switch (fType) {
37 case SkSVGFeColorMatrixType::kMatrix: {
38 if (fValues.size() < 20) {
39 return SkColorMatrix();
40 }
41 SkColorMatrix m;
42 m.setRowMajor(fValues.data());
43 return m;
44 }
45 case SkSVGFeColorMatrixType::kSaturate:
46 return MakeSaturate(!fValues.empty() ? fValues[0] : 1);
47 case SkSVGFeColorMatrixType::kHueRotate:
48 return MakeHueRotate(!fValues.empty() ? fValues[0] : 0);
49 case SkSVGFeColorMatrixType::kLuminanceToAlpha:
50 return MakeLuminanceToAlpha();
51 }
52
53 SkUNREACHABLE;
54 }
55
MakeSaturate(SkSVGNumberType s)56 SkColorMatrix SkSVGFeColorMatrix::MakeSaturate(SkSVGNumberType s) {
57 SkColorMatrix m;
58 m.setSaturation(s);
59 return m;
60 }
61
MakeHueRotate(SkSVGNumberType degrees)62 SkColorMatrix SkSVGFeColorMatrix::MakeHueRotate(SkSVGNumberType degrees) {
63 const SkScalar theta = SkDegreesToRadians(degrees);
64 const SkSVGNumberType c = SkScalarCos(theta);
65 const SkSVGNumberType s = SkScalarSin(theta);
66 return SkColorMatrix(
67 0.213f + c* 0.787f + s*-0.213f,
68 0.715f + c*-0.715f + s*-0.715f,
69 0.072f + c*-0.072f + s* 0.928f,
70 0,
71 0,
72
73 0.213f + c*-0.213f + s* 0.143f,
74 0.715f + c* 0.285f + s* 0.140f,
75 0.072f + c*-0.072f + s*-0.283f,
76 0,
77 0,
78
79 0.213f + c*-0.213f + s*-0.787f,
80 0.715f + c*-0.715f + s* 0.715f,
81 0.072f + c* 0.928f + s* 0.072f,
82 0,
83 0,
84
85 0,0,0,1,0
86 );
87 }
88
MakeLuminanceToAlpha()89 SkColorMatrix SkSVGFeColorMatrix::MakeLuminanceToAlpha() {
90 return SkColorMatrix(
91 0, 0, 0, 0, 0,
92 0, 0, 0, 0, 0,
93 0, 0, 0, 0, 0,
94 SK_LUM_COEFF_R, SK_LUM_COEFF_G, SK_LUM_COEFF_B, 0, 0
95 );
96 }
97
onMakeImageFilter(const SkSVGRenderContext & ctx,const SkSVGFilterContext & fctx) const98 sk_sp<SkImageFilter> SkSVGFeColorMatrix::onMakeImageFilter(const SkSVGRenderContext& ctx,
99 const SkSVGFilterContext& fctx) const {
100 return SkImageFilters::ColorFilter(
101 SkColorFilters::Matrix(makeMatrixForType()),
102 fctx.resolveInput(ctx, this->getIn(), this->resolveColorspace(ctx, fctx)),
103 this->resolveFilterSubregion(ctx, fctx));
104 }
105
parse(SkSVGFeColorMatrixType * type)106 template <> bool SkSVGAttributeParser::parse(SkSVGFeColorMatrixType* type) {
107 static constexpr std::tuple<const char*, SkSVGFeColorMatrixType> gTypeMap[] = {
108 {"matrix", SkSVGFeColorMatrixType::kMatrix},
109 {"saturate", SkSVGFeColorMatrixType::kSaturate},
110 {"hueRotate", SkSVGFeColorMatrixType::kHueRotate},
111 {"luminanceToAlpha", SkSVGFeColorMatrixType::kLuminanceToAlpha},
112 };
113
114 return this->parseEnumMap(gTypeMap, type) && this->parseEOSToken();
115 }
116