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