xref: /aosp_15_r20/external/skia/modules/svg/src/SkSVGFeColorMatrix.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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