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 "frameworks/core/components_ng/svg/parse/svg_fe.h"
17
18 #include "include/core/SkColorFilter.h"
19 #include "include/effects/SkColorMatrix.h"
20 #include "include/effects/SkImageFilters.h"
21
22 #include "base/utils/utils.h"
23
24 namespace OHOS::Ace::NG {
25 namespace {
26 static const LinearMapNode<void (*)(const std::string&, SvgFeCommonAttribute&)> FE_ATTRS[] = {
27 { DOM_SVG_FE_COLOR_INTERPOLATION_FILTERS,
__anon17f12f840202() 28 [](const std::string& val, SvgFeCommonAttribute& attr) {
29 static const LinearMapNode<SvgColorInterpolationType> COLOR_INTERPOLATION_TYPE_TABLE[] = {
30 { "auto", SvgColorInterpolationType::AUTO },
31 { "linearRGB", SvgColorInterpolationType::LINEAR_RGB },
32 { "sRGB", SvgColorInterpolationType::SRGB },
33 };
34 int64_t inIndex = BinarySearchFindIndex(
35 COLOR_INTERPOLATION_TYPE_TABLE, ArraySize(COLOR_INTERPOLATION_TYPE_TABLE), val.c_str());
36 if (inIndex != -1) {
37 attr.colorInterpolationType = COLOR_INTERPOLATION_TYPE_TABLE[inIndex].value;
38 }
39 } },
40 { DOM_SVG_HEIGHT,
__anon17f12f840302() 41 [](const std::string& val, SvgFeCommonAttribute& attr) {
42 attr.height = SvgAttributesParser::ParseDimension(val);
43 } },
44 { DOM_SVG_FE_IN,
__anon17f12f840402() 45 [](const std::string& val, SvgFeCommonAttribute& attr) {
46 static const LinearMapNode<SvgFeInType> IN_TABLE[] = {
47 { "BackgroundAlpha", SvgFeInType::BACKGROUND_ALPHA },
48 { "BackgroundImage", SvgFeInType::BACKGROUND_IMAGE },
49 { "FillPaint", SvgFeInType::FILL_PAINT },
50 { "SourceAlpha", SvgFeInType::SOURCE_ALPHA },
51 { "SourceGraphic", SvgFeInType::SOURCE_GRAPHIC },
52 { "StrokePaint", SvgFeInType::STROKE_PAINT },
53 };
54 int64_t inIndex = BinarySearchFindIndex(IN_TABLE, ArraySize(IN_TABLE), val.c_str());
55 if (inIndex != -1) {
56 attr.in.in = IN_TABLE[inIndex].value;
57 } else {
58 attr.in.id = val;
59 }
60 } },
61 { DOM_SVG_FE_RESULT,
__anon17f12f840502() 62 [](const std::string& val, SvgFeCommonAttribute& attr) {
63 attr.result = val;
64 } },
65 { DOM_SVG_WIDTH,
__anon17f12f840602() 66 [](const std::string& val, SvgFeCommonAttribute& attr) {
67 attr.width = SvgAttributesParser::ParseDimension(val);
68 } },
69 { DOM_SVG_X,
__anon17f12f840702() 70 [](const std::string& val, SvgFeCommonAttribute& attr) {
71 attr.x = SvgAttributesParser::ParseDimension(val);
72 } },
73 { DOM_SVG_Y,
__anon17f12f840802() 74 [](const std::string& val, SvgFeCommonAttribute& attr) {
75 attr.y = SvgAttributesParser::ParseDimension(val);
76 } },
77 };
78 }
79
InitFilterColor(const SvgFeCommonAttribute & fe,SvgColorInterpolationType & currentColor)80 void InitFilterColor(const SvgFeCommonAttribute& fe, SvgColorInterpolationType& currentColor)
81 {
82 if (fe.in.in == SvgFeInType::SOURCE_GRAPHIC) {
83 currentColor = SvgColorInterpolationType::SRGB;
84 } else {
85 currentColor = fe.colorInterpolationType;
86 }
87 }
88
OnInitStyle()89 void SvgFe::OnInitStyle() {}
90
RegisterResult(const std::string & id,std::shared_ptr<RSImageFilter> & imageFilter,std::unordered_map<std::string,std::shared_ptr<RSImageFilter>> & resultHash) const91 void SvgFe::RegisterResult(const std::string& id, std::shared_ptr<RSImageFilter>& imageFilter,
92 std::unordered_map<std::string, std::shared_ptr<RSImageFilter>>& resultHash) const
93 {
94 if (!id.empty()) {
95 resultHash[id] = imageFilter;
96 }
97 }
98
SvgFe()99 SvgFe::SvgFe() : SvgNode()
100 {
101 InitNoneFlag();
102 }
103
GetImageFilter(std::shared_ptr<RSImageFilter> & imageFilter,SvgColorInterpolationType & currentColor,std::unordered_map<std::string,std::shared_ptr<RSImageFilter>> & resultHash,const Rect & effectFilterArea)104 void SvgFe::GetImageFilter(std::shared_ptr<RSImageFilter>& imageFilter, SvgColorInterpolationType& currentColor,
105 std::unordered_map<std::string, std::shared_ptr<RSImageFilter>>& resultHash,
106 const Rect& effectFilterArea)
107 {
108 SvgColorInterpolationType srcColor = currentColor;
109 OnInitStyle();
110 InitFilterColor(feAttr_, currentColor);
111 Rect effectFeArea = effectFilterArea;
112 if (feAttr_.x.Unit() != DimensionUnit::PERCENT) {
113 effectFeArea.SetLeft(feAttr_.x.Value());
114 }
115 if (feAttr_.y.Unit() != DimensionUnit::PERCENT) {
116 effectFeArea.SetTop(feAttr_.y.Value());
117 }
118 effectFeArea.SetWidth(feAttr_.width.ConvertToPxWithSize(effectFilterArea.Width()));
119 effectFeArea.SetHeight(feAttr_.height.ConvertToPxWithSize(effectFilterArea.Height()));
120 effectFilterArea_ = effectFilterArea.IntersectRect(effectFeArea);
121 OnAsImageFilter(imageFilter, srcColor, currentColor, resultHash);
122 currentColor = srcColor;
123 }
124
ConverImageFilterColor(std::shared_ptr<RSImageFilter> & imageFilter,const SvgColorInterpolationType & srcColor,const SvgColorInterpolationType & dst)125 void SvgFe::ConverImageFilterColor(std::shared_ptr<RSImageFilter>& imageFilter,
126 const SvgColorInterpolationType& srcColor, const SvgColorInterpolationType& dst)
127 {
128 if (dst == SvgColorInterpolationType::LINEAR_RGB && srcColor == SvgColorInterpolationType::SRGB) {
129 auto colorFilter = RSRecordingColorFilter::CreateSrgbGammaToLinear();
130 CHECK_NULL_VOID(colorFilter);
131 imageFilter = RSRecordingImageFilter::CreateColorFilterImageFilter(*colorFilter, imageFilter);
132 } else if (dst == SvgColorInterpolationType::SRGB && srcColor == SvgColorInterpolationType::LINEAR_RGB) {
133 auto colorFilter = RSRecordingColorFilter::CreateLinearToSrgbGamma();
134 CHECK_NULL_VOID(colorFilter);
135 imageFilter = RSRecordingImageFilter::CreateColorFilterImageFilter(*colorFilter, imageFilter);
136 }
137 }
138
MakeImageFilter(const SvgFeIn & in,std::shared_ptr<RSImageFilter> & imageFilter,std::unordered_map<std::string,std::shared_ptr<RSImageFilter>> & resultHash)139 std::shared_ptr<RSImageFilter> SvgFe::MakeImageFilter(const SvgFeIn& in, std::shared_ptr<RSImageFilter>& imageFilter,
140 std::unordered_map<std::string, std::shared_ptr<RSImageFilter>>& resultHash)
141 {
142 switch (in.in) {
143 case SvgFeInType::SOURCE_GRAPHIC:
144 return nullptr;
145 case SvgFeInType::SOURCE_ALPHA: {
146 RSColorMatrix m;
147 m.SetScale(0, 0, 0, 1.0f);
148 auto colorFilter = RSRecordingColorFilter::CreateMatrixColorFilter(m);
149 CHECK_NULL_RETURN(colorFilter, nullptr);
150 return RSRecordingImageFilter::CreateColorFilterImageFilter(*colorFilter, nullptr);
151 }
152 case SvgFeInType::BACKGROUND_IMAGE:
153 break;
154 case SvgFeInType::BACKGROUND_ALPHA:
155 break;
156 case SvgFeInType::FILL_PAINT:
157 break;
158 case SvgFeInType::STROKE_PAINT:
159 break;
160 case SvgFeInType::PRIMITIVE:
161 if (!in.id.empty()) {
162 auto it = resultHash.find(in.id);
163 if (it != resultHash.end()) {
164 return it->second;
165 }
166 }
167 break;
168 default:
169 break;
170 }
171 return imageFilter;
172 }
173
ParseAndSetSpecializedAttr(const std::string & name,const std::string & value)174 bool SvgFe::ParseAndSetSpecializedAttr(const std::string& name, const std::string& value)
175 {
176 std::string key = name;
177 StringUtils::TransformStrCase(key, StringUtils::TEXT_CASE_LOWERCASE);
178 auto attrIter = BinarySearchFindIndex(FE_ATTRS, ArraySize(FE_ATTRS), key.c_str());
179 if (attrIter != -1) {
180 FE_ATTRS[attrIter].value(value, feAttr_);
181 return true;
182 }
183 return false;
184 }
185
186 } // namespace OHOS::Ace::NG
187