1 /*
2 * Copyright (c) 2022-2023 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 #include "core/components_ng/render/adapter/rosen_modifier_adapter.h"
16
17 #include <mutex>
18 #include <unordered_map>
19
20 #include "base/utils/utils.h"
21 #include "core/components_ng/animation/animatable_arithmetic_proxy.h"
22 #include "core/components_ng/render/modifier_adapter.h"
23
24 namespace OHOS::Ace::NG {
25
26 std::unordered_map<int32_t, std::shared_ptr<RSModifier>> g_ModifiersMap;
27 std::mutex g_ModifiersMapLock;
28
ConvertContentModifier(const RefPtr<Modifier> & modifier)29 std::shared_ptr<RSModifier> ConvertContentModifier(const RefPtr<Modifier>& modifier)
30 {
31 CHECK_NULL_RETURN(modifier, nullptr);
32 std::lock_guard<std::mutex> lock(g_ModifiersMapLock);
33 const auto& iter = g_ModifiersMap.find(modifier->GetId());
34 if (iter != g_ModifiersMap.end()) {
35 return iter->second;
36 }
37 auto modifierAdapter = std::make_shared<ContentModifierAdapter>(modifier);
38 g_ModifiersMap.emplace(modifier->GetId(), modifierAdapter);
39 return modifierAdapter;
40 }
41
ConvertOverlayModifier(const RefPtr<Modifier> & modifier)42 std::shared_ptr<RSModifier> ConvertOverlayModifier(const RefPtr<Modifier>& modifier)
43 {
44 CHECK_NULL_RETURN(modifier, nullptr);
45 std::lock_guard<std::mutex> lock(g_ModifiersMapLock);
46 const auto& iter = g_ModifiersMap.find(modifier->GetId());
47 if (iter != g_ModifiersMap.end()) {
48 return iter->second;
49 }
50 auto modifierAdapter = std::make_shared<OverlayModifierAdapter>(modifier);
51 g_ModifiersMap.emplace(modifier->GetId(), modifierAdapter);
52 return modifierAdapter;
53 }
54
RemoveModifier(int32_t modifierId)55 void ModifierAdapter::RemoveModifier(int32_t modifierId)
56 {
57 std::lock_guard<std::mutex> lock(g_ModifiersMapLock);
58 g_ModifiersMap.erase(modifierId);
59 }
60
Draw(RSDrawingContext & context) const61 void ContentModifierAdapter::Draw(RSDrawingContext& context) const
62 {
63 // use dummy deleter avoid delete the SkCanvas by shared_ptr, its owned by context
64 #ifndef USE_ROSEN_DRAWING
65 std::shared_ptr<SkCanvas> skCanvas { context.canvas, [](SkCanvas*) {} };
66 RSCanvas canvas(&skCanvas);
67 #else
68 CHECK_NULL_VOID_NOLOG(context.canvas);
69 #endif
70 auto modifier = modifier_.Upgrade();
71 CHECK_NULL_VOID_NOLOG(modifier);
72 #ifndef USE_ROSEN_DRAWING
73 DrawingContext context_ = { canvas, context.width, context.height };
74 #else
75 DrawingContext context_ = { *context.canvas, context.width, context.height };
76 #endif
77 modifier->onDraw(context_);
78 }
79
80 #define CONVERT_PROP(prop, srcType, propType) \
81 if (AceType::InstanceOf<srcType>(prop)) { \
82 auto castProp = AceType::DynamicCast<srcType>(prop); \
83 auto rsProp = std::make_shared<RSProperty<propType>>(castProp->Get()); \
84 castProp->SetUpCallbacks([rsProp]() -> propType { return rsProp->Get(); }, \
85 [rsProp](const propType& value) { rsProp->Set(value); }); \
86 return rsProp; \
87 }
88
89 #define CONVERT_ANIMATABLE_PROP(prop, srcType, propType) \
90 if (AceType::InstanceOf<srcType>(prop)) { \
91 auto castProp = AceType::DynamicCast<srcType>(prop); \
92 auto rsProp = std::make_shared<RSAnimatableProperty<propType>>(castProp->Get()); \
93 castProp->SetUpCallbacks([rsProp]() -> propType { return rsProp->Get(); }, \
94 [rsProp](const propType& value) { rsProp->Set(value); }, \
95 [rsProp]() -> propType { return rsProp->GetStagingValue(); }); \
96 rsProp->SetUpdateCallback(castProp->GetUpdateCallback()); \
97 return rsProp; \
98 }
99
ConvertToRSProperty(const RefPtr<PropertyBase> & property)100 inline std::shared_ptr<RSPropertyBase> ConvertToRSProperty(const RefPtr<PropertyBase>& property)
101 {
102 // should manually add convert type here
103 CONVERT_PROP(property, PropertyBool, bool);
104 CONVERT_PROP(property, PropertySizeF, SizeF);
105 CONVERT_PROP(property, PropertyOffsetF, OffsetF);
106 CONVERT_PROP(property, PropertyInt, int32_t);
107 CONVERT_PROP(property, PropertyFloat, float);
108 CONVERT_PROP(property, PropertyString, std::string);
109 CONVERT_PROP(property, PropertyColor, Color);
110 CONVERT_PROP(property, PropertyRectF, RectF);
111 CONVERT_ANIMATABLE_PROP(property, AnimatablePropertyOffsetF, OffsetF);
112 CONVERT_ANIMATABLE_PROP(property, AnimatablePropertyUint8, uint8_t);
113 CONVERT_ANIMATABLE_PROP(property, AnimatablePropertyFloat, float);
114 CONVERT_ANIMATABLE_PROP(property, AnimatablePropertyColor, LinearColor);
115 CONVERT_ANIMATABLE_PROP(property, AnimatablePropertyVectorColor, GradientArithmetic);
116 CONVERT_ANIMATABLE_PROP(property, AnimatablePropertyVectorFloat, LinearVector<float>);
117 CONVERT_ANIMATABLE_PROP(property, AnimatablePropertySizeF, SizeF);
118
119 if (AceType::InstanceOf<AnimatableArithmeticProperty>(property)) {
120 auto castProp = AceType::DynamicCast<AnimatableArithmeticProperty>(property);
121 if (!castProp && !castProp->Get()) {
122 LOGE("ConvertToRSProperty: Failed converting to RSProperty - AnimatableArithmeticProperty is null");
123 return nullptr;
124 }
125 AnimatableArithmeticProxy proxy(castProp->Get());
126 auto rsProp = std::make_shared<RSAnimatableProperty<AnimatableArithmeticProxy>>(proxy);
127 auto getter = [rsProp]() -> RefPtr<CustomAnimatableArithmetic> { return rsProp->Get().GetObject(); };
128 auto setter = [rsProp](const RefPtr<CustomAnimatableArithmetic>& value) {
129 rsProp->Set(AnimatableArithmeticProxy(value));
130 };
131 castProp->SetUpCallbacks(getter, setter);
132 rsProp->SetUpdateCallback(
133 [cb = castProp->GetUpdateCallback()](const AnimatableArithmeticProxy& value) { cb(value.GetObject()); });
134 return rsProp;
135 }
136
137 LOGE("ConvertToRSProperty failed!");
138 return nullptr;
139 }
140
AttachProperties()141 void ContentModifierAdapter::AttachProperties()
142 {
143 auto modifier = modifier_.Upgrade();
144 if (!attachedProperties_.size() && modifier) {
145 for (const auto& property : modifier->GetAttachedProperties()) {
146 auto rsProperty = ConvertToRSProperty(property);
147 AttachProperty(rsProperty);
148 attachedProperties_.emplace_back(rsProperty);
149 }
150 }
151 }
152
Draw(RSDrawingContext & context) const153 void OverlayModifierAdapter::Draw(RSDrawingContext& context) const
154 {
155 // use dummy deleter avoid delete the SkCanvas by shared_ptr, its owned by context
156 #ifndef USE_ROSEN_DRAWING
157 std::shared_ptr<SkCanvas> skCanvas { context.canvas, [](SkCanvas*) {} };
158 RSCanvas canvas(&skCanvas);
159 #else
160 CHECK_NULL_VOID_NOLOG(context.canvas);
161 #endif
162 auto modifier = modifier_.Upgrade();
163 CHECK_NULL_VOID_NOLOG(modifier);
164 #ifndef USE_ROSEN_DRAWING
165 DrawingContext context_ = { canvas, context.width, context.height };
166 #else
167 DrawingContext context_ = { *context.canvas, context.width, context.height };
168 #endif
169 modifier->onDraw(context_);
170 }
171
AttachProperties()172 void OverlayModifierAdapter::AttachProperties()
173 {
174 auto modifier = modifier_.Upgrade();
175 if (attachedProperties_.empty() && modifier) {
176 for (const auto& property : modifier->GetAttachedProperties()) {
177 auto rsProperty = ConvertToRSProperty(property);
178 AttachProperty(rsProperty);
179 attachedProperties_.emplace_back(rsProperty);
180 }
181 }
182 }
183
AddProperty(const RefPtr<PropertyBase> & property)184 void RSNodeModifierImpl::AddProperty(const RefPtr<PropertyBase>& property)
185 {
186 if (!attachedProperty_) {
187 auto rsProperty = ConvertToRSProperty(property);
188 AttachProperty(rsProperty);
189 attachedProperty_ = rsProperty;
190 }
191 }
192 } // namespace OHOS::Ace::NG
193