1 /*
2  * Copyright (c) 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_blend.h"
17 
18 #include "base/utils/utils.h"
19 
20 namespace OHOS::Ace::NG {
21 
Create()22 RefPtr<SvgNode> SvgFeBlend::Create()
23 {
24     return AceType::MakeRefPtr<SvgFeBlend>();
25 }
26 
SvgFeBlend()27 SvgFeBlend::SvgFeBlend() : SvgFe() {}
28 
GetBlendMode(SvgFeBlendMode mode) const29 RSBlendMode SvgFeBlend::GetBlendMode(SvgFeBlendMode mode) const
30 {
31     switch (mode) {
32         case SvgFeBlendMode::NORMAL:
33             return RSBlendMode::SRC_OVER;
34         case SvgFeBlendMode::MULTIPLY:
35             return RSBlendMode::MULTIPLY;
36         case SvgFeBlendMode::SCREEN:
37             return RSBlendMode::SCREEN;
38         case SvgFeBlendMode::DARKEN:
39             return RSBlendMode::DARKEN;
40         case SvgFeBlendMode::LIGHTEN:
41             return RSBlendMode::LIGHTEN;
42         default:
43             return RSBlendMode::SRC_OVER;
44     };
45 }
46 
OnAsImageFilter(std::shared_ptr<RSImageFilter> & imageFilter,const SvgColorInterpolationType & srcColor,SvgColorInterpolationType & currentColor,std::unordered_map<std::string,std::shared_ptr<RSImageFilter>> & resultHash) const47 void SvgFeBlend::OnAsImageFilter(std::shared_ptr<RSImageFilter>& imageFilter,
48     const SvgColorInterpolationType& srcColor, SvgColorInterpolationType& currentColor,
49     std::unordered_map<std::string, std::shared_ptr<RSImageFilter>>& resultHash) const
50 {
51     auto blendMode = feBlendAttr_.blendMode;
52 
53     auto backImageFilter = MakeImageFilter(feBlendAttr_.in2, imageFilter, resultHash);
54     auto foreImageFilter = MakeImageFilter(feAttr_.in, imageFilter, resultHash);
55     ConverImageFilterColor(foreImageFilter, srcColor, currentColor);
56     ConverImageFilterColor(backImageFilter, srcColor, currentColor);
57 
58     imageFilter =
59         RSRecordingImageFilter::CreateBlendImageFilter(GetBlendMode(blendMode), backImageFilter, foreImageFilter);
60     ConverImageFilterColor(imageFilter, srcColor, currentColor);
61     RegisterResult(feAttr_.result, imageFilter, resultHash);
62 }
63 
ParseAndSetSpecializedAttr(const std::string & name,const std::string & value)64 bool SvgFeBlend::ParseAndSetSpecializedAttr(const std::string& name, const std::string& value)
65 {
66     static const LinearMapNode<void (*)(const std::string&, SvgFeBlendAttribute&)> attrs[] = {
67         { DOM_SVG_FE_IN2,
68             [](const std::string& val, SvgFeBlendAttribute& attr) {
69                 static const LinearMapNode<SvgFeInType> IN_TABLE[] = {
70                     { "BackgroundAlpha", SvgFeInType::BACKGROUND_ALPHA },
71                     { "BackgroundImage", SvgFeInType::BACKGROUND_IMAGE },
72                     { "FillPaint", SvgFeInType::FILL_PAINT },
73                     { "SourceAlpha", SvgFeInType::SOURCE_ALPHA },
74                     { "SourceGraphic", SvgFeInType::SOURCE_GRAPHIC },
75                     { "StrokePaint", SvgFeInType::STROKE_PAINT },
76                 };
77                 int64_t inIndex = BinarySearchFindIndex(IN_TABLE, ArraySize(IN_TABLE), val.c_str());
78                 if (inIndex != -1) {
79                     attr.in2.in = IN_TABLE[inIndex].value;
80                 } else {
81                     attr.in2.id = val;
82                 }
83             } },
84         { DOM_SVG_FE_MODE,
85             [](const std::string& val, SvgFeBlendAttribute& attr) {
86                 static const LinearMapNode<SvgFeBlendMode> EDGE_MODE_TABLE[] = {
87                     { "darken", SvgFeBlendMode::DARKEN },
88                     { "lighten", SvgFeBlendMode::LIGHTEN },
89                     { "multiply", SvgFeBlendMode::MULTIPLY },
90                     { "normal", SvgFeBlendMode::NORMAL },
91                     { "screen", SvgFeBlendMode::SCREEN }
92                 };
93                 int64_t inIndex = BinarySearchFindIndex(EDGE_MODE_TABLE, ArraySize(EDGE_MODE_TABLE), val.c_str());
94                 if (inIndex != -1) {
95                     attr.blendMode = EDGE_MODE_TABLE[inIndex].value;
96                 }
97             } },
98     };
99     std::string key = name;
100     StringUtils::TransformStrCase(key, StringUtils::TEXT_CASE_LOWERCASE);
101     auto attrIter = BinarySearchFindIndex(attrs, ArraySize(attrs), key.c_str());
102     if (attrIter != -1) {
103         attrs[attrIter].value(value, feBlendAttr_);
104         return true;
105     }
106     return SvgFe::ParseAndSetSpecializedAttr(name, value);
107 }
108 
109 } // namespace OHOS::Ace::NG
110