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_composite.h"
17 
18 #include "include/effects/SkImageFilters.h"
19 
20 #include "base/utils/utils.h"
21 #include "core/components/common/properties/blend_mode.h"
22 
23 namespace OHOS::Ace::NG {
24 namespace {
ConvertStrToSvgFeInType(const std::string & val,SvgFeInType & type)25 bool ConvertStrToSvgFeInType(const std::string& val, SvgFeInType& type)
26 {
27     static const LinearMapNode<SvgFeInType> IN_TABLE[] = {
28         { "BackgroundAlpha", SvgFeInType::BACKGROUND_ALPHA },
29         { "BackgroundImage", SvgFeInType::BACKGROUND_IMAGE },
30         { "FillPaint", SvgFeInType::FILL_PAINT },
31         { "SourceAlpha", SvgFeInType::SOURCE_ALPHA },
32         { "SourceGraphic", SvgFeInType::SOURCE_GRAPHIC },
33         { "StrokePaint", SvgFeInType::STROKE_PAINT },
34     };
35     int64_t inIndex = BinarySearchFindIndex(IN_TABLE, ArraySize(IN_TABLE), val.c_str());
36     if (inIndex != -1) {
37         type = IN_TABLE[inIndex].value;
38         return true;
39     }
40     return false;
41 }
42 
ConvertStrToSvgFeOperatorType(const std::string & val,SvgFeOperatorType & type)43 bool ConvertStrToSvgFeOperatorType(const std::string& val, SvgFeOperatorType& type)
44 {
45     static const LinearMapNode<SvgFeOperatorType> FE_OPERATOR_TABLE[] = {
46         { "arithmetic", SvgFeOperatorType::FE_ARITHMETIC },
47         { "atop", SvgFeOperatorType::FE_ATOP },
48         { "in", SvgFeOperatorType::FE_IN },
49         { "lighter", SvgFeOperatorType::FE_LIGHTER },
50         { "out", SvgFeOperatorType::FE_OUT },
51         { "over", SvgFeOperatorType::FE_OVER },
52         { "xor", SvgFeOperatorType::FE_XOR },
53     };
54     int64_t inIndex = BinarySearchFindIndex(FE_OPERATOR_TABLE, ArraySize(FE_OPERATOR_TABLE), val.c_str());
55     if (inIndex != -1) {
56         type = FE_OPERATOR_TABLE[inIndex].value;
57         return true;
58     }
59     return false;
60 }
61 }
62 
Create()63 RefPtr<SvgNode> SvgFeComposite::Create()
64 {
65     return AceType::MakeRefPtr<SvgFeComposite>();
66 }
67 
SvgFeComposite()68 SvgFeComposite::SvgFeComposite() : SvgFe() {}
69 
BlendModeForOperator(SvgFeOperatorType op) const70 RSBlendMode SvgFeComposite::BlendModeForOperator(SvgFeOperatorType op) const
71 {
72     switch (op) {
73         case SvgFeOperatorType::FE_ATOP:
74             return RSBlendMode::SRC_ATOP;
75         case SvgFeOperatorType::FE_IN:
76             return RSBlendMode::SRC_IN;
77         case SvgFeOperatorType::FE_LIGHTER:
78             return RSBlendMode::LIGHTEN;
79         case SvgFeOperatorType::FE_OUT:
80             return RSBlendMode::SRC_OUT;
81         case SvgFeOperatorType::FE_OVER:
82             return RSBlendMode::SRC_OVER;
83         case SvgFeOperatorType::FE_XOR:
84             return RSBlendMode::XOR;
85         case SvgFeOperatorType::FE_ARITHMETIC:
86             return RSBlendMode::SRC_OVER;
87         default:
88             return RSBlendMode::SRC_IN;
89     };
90 }
91 
OnAsImageFilter(std::shared_ptr<RSImageFilter> & imageFilter,const SvgColorInterpolationType & srcColor,SvgColorInterpolationType & currentColor,std::unordered_map<std::string,std::shared_ptr<RSImageFilter>> & resultHash) const92 void SvgFeComposite::OnAsImageFilter(std::shared_ptr<RSImageFilter>& imageFilter,
93     const SvgColorInterpolationType& srcColor, SvgColorInterpolationType& currentColor,
94     std::unordered_map<std::string, std::shared_ptr<RSImageFilter>>& resultHash) const
95 {
96     auto mode = feCompositeAttr_.operatorType;
97     auto foreImageFilter = MakeImageFilter(feAttr_.in, imageFilter, resultHash);
98     auto backImageFilter = MakeImageFilter(feCompositeAttr_.in2, imageFilter, resultHash);
99     ConverImageFilterColor(foreImageFilter, srcColor, currentColor);
100     ConverImageFilterColor(backImageFilter, srcColor, currentColor);
101     if (mode != SvgFeOperatorType::FE_ARITHMETIC) {
102         imageFilter = RSRecordingImageFilter::CreateBlendImageFilter(
103             BlendModeForOperator(mode), backImageFilter, foreImageFilter);
104         ConverImageFilterColor(imageFilter, srcColor, currentColor);
105         return;
106     }
107     std::vector<RSScalar> coefficients = { feCompositeAttr_.k1, feCompositeAttr_.k2, feCompositeAttr_.k3,
108         feCompositeAttr_.k4 };
109     imageFilter =
110         RSRecordingImageFilter::CreateArithmeticImageFilter(coefficients, true, backImageFilter, foreImageFilter);
111     ConverImageFilterColor(imageFilter, srcColor, currentColor);
112     RegisterResult(feAttr_.result, imageFilter, resultHash);
113 }
114 
ParseAndSetSpecializedAttr(const std::string & name,const std::string & value)115 bool SvgFeComposite::ParseAndSetSpecializedAttr(const std::string& name, const std::string& value)
116 {
117     static const LinearMapNode<void (*)(const std::string&, SvgFeCompositeAttribute&)> attrs[] = {
118         { DOM_SVG_FE_IN2,
119             [](const std::string& val, SvgFeCompositeAttribute& attribute) {
120                 SvgFeInType type = SvgFeInType::PRIMITIVE;
121                 bool res = ConvertStrToSvgFeInType(val, type);
122                 if (res) {
123                     attribute.in2.in = type;
124                 } else {
125                     attribute.in2.id = val;
126                 }
127             } },
128         { DOM_SVG_FE_K1,
129             [](const std::string& val, SvgFeCompositeAttribute& attr) {
130                 attr.k1 = SvgAttributesParser::ParseDouble(val);
131             } },
132         { DOM_SVG_FE_K2,
133             [](const std::string& val, SvgFeCompositeAttribute& attr) {
134                 attr.k2 = SvgAttributesParser::ParseDouble(val);
135             } },
136         { DOM_SVG_FE_K3,
137             [](const std::string& val, SvgFeCompositeAttribute& attr) {
138                 attr.k3 = SvgAttributesParser::ParseDouble(val);
139             } },
140         { DOM_SVG_FE_K4,
141             [](const std::string& val, SvgFeCompositeAttribute& attr) {
142                 attr.k4 = SvgAttributesParser::ParseDouble(val);
143             } },
144         { DOM_SVG_FE_OPERATOR_TYPE,
145             [](const std::string& val, SvgFeCompositeAttribute& attr) {
146                 SvgFeOperatorType type = SvgFeOperatorType::FE_OVER;
147                 bool res = ConvertStrToSvgFeOperatorType(val, type);
148                 if (res) {
149                     attr.operatorType = type;
150                 }
151             } },
152     };
153     auto attrIter = BinarySearchFindIndex(attrs, ArraySize(attrs), name.c_str());
154     if (attrIter != -1) {
155         attrs[attrIter].value(value, feCompositeAttr_);
156         return true;
157     }
158     return SvgFe::ParseAndSetSpecializedAttr(name, value);
159 }
160 
161 } // namespace OHOS::Ace::NG
162