1 /*
2 * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "core/components_ng/svg/parse/svg_fe_color_matrix.h"
17
18 #include "base/utils/utils.h"
19 #include "core/components/declaration/svg/svg_declaration.h"
20 #include "core/components/declaration/svg/svg_fe_colormatrix_declaration.h"
21
22 namespace OHOS::Ace::NG {
23
24 static constexpr float HUE_R = 0.213f;
25 static constexpr float HUE_G = 0.715f;
26 static constexpr float HUE_B = 0.072f;
27
28 static constexpr float LUM_COEFF_R = 0.2126f;
29 static constexpr float LUM_COEFF_G = 0.7152f;
30 static constexpr float LUM_COEFF_B = 0.0722f;
31
DegreesToRadians(float degrees)32 inline float DegreesToRadians(float degrees)
33 {
34 return (degrees) * (M_PI / 180.0f);
35 }
36
37 const std::vector<float> luminanceMatrix_ = {
38 0, 0, 0, 0, 0,
39 0, 0, 0, 0, 0,
40 0, 0, 0, 0, 0,
41 LUM_COEFF_R, LUM_COEFF_G, LUM_COEFF_B, 0, 0
42 };
43
SetRow(float * row,float r,float g,float b)44 static void SetRow(float* row, float r, float g, float b)
45 {
46 row[0] = r;
47 row[1] = g;
48 row[2] = b;
49 }
50
Create()51 RefPtr<SvgNode> SvgFeColorMatrix::Create()
52 {
53 return AceType::MakeRefPtr<SvgFeColorMatrix>();
54 }
55
SvgFeColorMatrix()56 SvgFeColorMatrix::SvgFeColorMatrix() : SvgFe() {}
57
MakeMatrix(const std::string & value)58 void SvgFeColorMatrix::MakeMatrix(const std::string& value)
59 {
60 std::vector<float> matrix;
61 if (!StringUtils::ParseStringToArray(value, matrix)) {
62 return;
63 }
64 // when matrix length not equal 20, then return
65 if (matrix.size() != matrix_.size()) {
66 return;
67 }
68 matrix_ = matrix;
69 }
70
MakeHueRotate(const std::string & value)71 void SvgFeColorMatrix::MakeHueRotate(const std::string& value)
72 {
73 float theta = DegreesToRadians(std::stof(value));
74 const float cosValue = cos(theta);
75 const float sinValue = sin(theta);
76
77 // The source of the formula is this website: https://www.w3.org/TR/SVG11/filters.html#FilterPrimitiveSubRegion
78 matrix_ = {
79 0.213f + cosValue*0.787f + sinValue*-0.213f,
80 0.715f + cosValue*-0.715f + sinValue*-0.715f,
81 0.072f + cosValue*-0.072f + sinValue* 0.928f,
82 0,
83 0,
84
85 0.213f + cosValue*-0.213f + sinValue* 0.143f,
86 0.715f + cosValue* 0.285f + sinValue* 0.140f,
87 0.072f + cosValue*-0.072f + sinValue*-0.283f,
88 0,
89 0,
90
91 0.213f + cosValue*-0.213f + sinValue*-0.787f,
92 0.715f + cosValue*-0.715f + sinValue* 0.715f,
93 0.072f + cosValue* 0.928f + sinValue* 0.072f,
94 0,
95 0,
96
97 0, 0, 0, 1, 0
98 };
99 }
100
MakeSaturate(const std::string & value)101 void SvgFeColorMatrix::MakeSaturate(const std::string& value)
102 {
103 float satValue = std::stof(value);
104
105 const float RValue = HUE_R * (1 - satValue);
106 const float GValue = HUE_G * (1 - satValue);
107 const float BValue = HUE_B * (1 - satValue);
108
109 SetRow(matrix_.data() + 0, RValue + satValue, GValue, BValue);
110 SetRow(matrix_.data() + 5, RValue, GValue + satValue, BValue);
111 SetRow(matrix_.data() + 10, RValue, GValue, BValue + satValue);
112 }
113
MakeLuminanceToAlpha()114 void SvgFeColorMatrix::MakeLuminanceToAlpha()
115 {
116 matrix_ = luminanceMatrix_;
117 }
118
OnInitStyle()119 void SvgFeColorMatrix::OnInitStyle()
120 {
121 auto type = matrixAttr_.type;
122 switch (type) {
123 case SvgFeColorMatrixType::SATURATE:
124 MakeSaturate(matrixAttr_.values);
125 break;
126 case SvgFeColorMatrixType::HUE_ROTATE:
127 MakeHueRotate(matrixAttr_.values);
128 break;
129 case SvgFeColorMatrixType::LUMINACE_TO_ALPHA:
130 MakeLuminanceToAlpha();
131 break;
132 default:
133 MakeMatrix(matrixAttr_.values);
134 break;
135 }
136 }
137
OnAsImageFilter(std::shared_ptr<RSImageFilter> & imageFilter,const SvgColorInterpolationType & srcColor,SvgColorInterpolationType & currentColor,std::unordered_map<std::string,std::shared_ptr<RSImageFilter>> & resultHash) const138 void SvgFeColorMatrix::OnAsImageFilter(std::shared_ptr<RSImageFilter>& imageFilter,
139 const SvgColorInterpolationType& srcColor, SvgColorInterpolationType& currentColor,
140 std::unordered_map<std::string, std::shared_ptr<RSImageFilter>>& resultHash) const
141 {
142 imageFilter = MakeImageFilter(feAttr_.in, imageFilter, resultHash);
143
144 RSColorMatrix colorMatrix;
145 colorMatrix.SetArray(matrix_.data());
146 auto colorFilter = RSRecordingColorFilter::CreateMatrixColorFilter(colorMatrix);
147 CHECK_NULL_VOID(colorFilter);
148
149 imageFilter = RSRecordingImageFilter::CreateColorFilterImageFilter(*colorFilter, imageFilter);
150 ConverImageFilterColor(imageFilter, srcColor, currentColor);
151 RegisterResult(feAttr_.result, imageFilter, resultHash);
152 }
153
ParseAndSetSpecializedAttr(const std::string & name,const std::string & value)154 bool SvgFeColorMatrix::ParseAndSetSpecializedAttr(const std::string& name, const std::string& value)
155 {
156 static const LinearMapNode<void (*)(const std::string&, SvgFeColorMatrixAttribute&)> attrs[] = {
157 { DOM_SVG_FE_TYPE,
158 [](const std::string& type, SvgFeColorMatrixAttribute& attr) {
159 if (type == "saturate") {
160 attr.type = SvgFeColorMatrixType::SATURATE;
161 } else if (type == "hueRotate") {
162 attr.type = SvgFeColorMatrixType::HUE_ROTATE;
163 } else if (type == "luminanceToAlpha") {
164 attr.type = SvgFeColorMatrixType::LUMINACE_TO_ALPHA;
165 }
166 } },
167 { DOM_SVG_FE_VALUES,
168 [](const std::string& val, SvgFeColorMatrixAttribute& attr) {
169 attr.values = val;
170 } },
171 };
172 auto attrIter = BinarySearchFindIndex(attrs, ArraySize(attrs), name.c_str());
173 if (attrIter != -1) {
174 attrs[attrIter].value(value, matrixAttr_);
175 return true;
176 }
177 return SvgFe::ParseAndSetSpecializedAttr(name, value);
178 }
179
180 } // namespace OHOS::Ace::NG
181