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