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 #include "core/components_ng/render/adapter/rosen_modifier_adapter.h"
16
17 #include "interfaces/inner_api/ace_kit/src/view/draw/modifier_adapter.h"
18 #include "ui/view/draw/content_modifier.h"
19
20 #include "core/animation/native_curve_helper.h"
21 #include "core/components_ng/animation/animatable_arithmetic_proxy.h"
22
23 namespace OHOS::Ace::NG {
24
25 std::unordered_map<int32_t, std::shared_ptr<RSModifier>> g_ModifiersMap;
26 std::mutex g_ModifiersMapLock;
27
ConvertKitContentModifier(const RefPtr<Kit::Modifier> & modifier)28 std::shared_ptr<RSModifier> ConvertKitContentModifier(const RefPtr<Kit::Modifier>& modifier)
29 {
30 auto kitModifier = AceType::DynamicCast<Kit::ContentModifier>(modifier);
31 CHECK_NULL_RETURN(kitModifier, nullptr);
32 return kitModifier->GetRSModifier();
33 }
34
ConvertContentModifier(const RefPtr<Modifier> & modifier)35 std::shared_ptr<RSModifier> ConvertContentModifier(const RefPtr<Modifier>& modifier)
36 {
37 CHECK_NULL_RETURN(modifier, nullptr);
38 std::lock_guard<std::mutex> lock(g_ModifiersMapLock);
39 const auto& iter = g_ModifiersMap.find(modifier->GetId());
40 if (iter != g_ModifiersMap.end()) {
41 return iter->second;
42 }
43 auto modifierAdapter = std::make_shared<ContentModifierAdapter>(modifier);
44 g_ModifiersMap.emplace(modifier->GetId(), modifierAdapter);
45 return modifierAdapter;
46 }
47
ConvertOverlayModifier(const RefPtr<Modifier> & modifier)48 std::shared_ptr<RSModifier> ConvertOverlayModifier(const RefPtr<Modifier>& modifier)
49 {
50 CHECK_NULL_RETURN(modifier, nullptr);
51 std::lock_guard<std::mutex> lock(g_ModifiersMapLock);
52 const auto& iter = g_ModifiersMap.find(modifier->GetId());
53 if (iter != g_ModifiersMap.end()) {
54 return iter->second;
55 }
56 auto modifierAdapter = std::make_shared<OverlayModifierAdapter>(modifier);
57 g_ModifiersMap.emplace(modifier->GetId(), modifierAdapter);
58 return modifierAdapter;
59 }
60
ConvertForegroundModifier(const RefPtr<Modifier> & modifier)61 std::shared_ptr<RSModifier> ConvertForegroundModifier(const RefPtr<Modifier>& modifier)
62 {
63 CHECK_NULL_RETURN(modifier, nullptr);
64 std::lock_guard<std::mutex> lock(g_ModifiersMapLock);
65 const auto& iter = g_ModifiersMap.find(modifier->GetId());
66 if (iter != g_ModifiersMap.end()) {
67 return iter->second;
68 }
69 auto modifierAdapter = std::make_shared<ForegroundModifierAdapter>(modifier);
70 g_ModifiersMap.emplace(modifier->GetId(), modifierAdapter);
71 return modifierAdapter;
72 }
73
RemoveModifier(int32_t modifierId)74 void ModifierAdapter::RemoveModifier(int32_t modifierId)
75 {
76 std::lock_guard<std::mutex> lock(g_ModifiersMapLock);
77 g_ModifiersMap.erase(modifierId);
78 }
79
Draw(RSDrawingContext & context) const80 void ContentModifierAdapter::Draw(RSDrawingContext& context) const
81 {
82 // use dummy deleter avoid delete the SkCanvas by shared_ptr, its owned by context
83 CHECK_NULL_VOID(context.canvas);
84 auto modifier = modifier_.Upgrade();
85 CHECK_NULL_VOID(modifier);
86 DrawingContext context_ = { *context.canvas, context.width, context.height };
87 modifier->Draw(context_);
88 }
89
90 #define CONVERT_PROP(prop, srcType, propType) \
91 if (AceType::InstanceOf<srcType>(prop)) { \
92 auto castProp = AceType::DynamicCast<srcType>(prop); \
93 auto rsProp = std::make_shared<RSProperty<propType>>(castProp->Get()); \
94 castProp->SetUpCallbacks([rsProp]() -> propType { return rsProp->Get(); }, \
95 [rsProp](const propType& value) { rsProp->Set(value); }, \
96 [rsProp]() -> propType { return rsProp->Get(); }); \
97 return rsProp; \
98 }
99
100 #define CONVERT_ANIMATABLE_PROP(prop, srcType, propType) \
101 if (AceType::InstanceOf<srcType>(prop)) { \
102 auto castProp = AceType::DynamicCast<srcType>(prop); \
103 auto rsProp = std::make_shared<RSAnimatableProperty<propType>>(castProp->Get()); \
104 castProp->SetUpCallbacks([rsProp]() -> propType { return rsProp->Get(); }, \
105 [rsProp](const propType& value) { rsProp->Set(value); }, \
106 [rsProp]() -> propType { return rsProp->GetStagingValue(); }); \
107 rsProp->SetUpdateCallback(castProp->GetUpdateCallback()); \
108 return rsProp; \
109 }
110
ConvertToRSProperty(const RefPtr<PropertyBase> & property)111 inline std::shared_ptr<RSPropertyBase> ConvertToRSProperty(const RefPtr<PropertyBase>& property)
112 {
113 // should manually add convert type here
114 CONVERT_PROP(property, PropertyBool, bool);
115 CONVERT_PROP(property, PropertySizeF, SizeF);
116 CONVERT_PROP(property, PropertyOffsetF, OffsetF);
117 CONVERT_PROP(property, PropertyInt, int32_t);
118 CONVERT_PROP(property, PropertyFloat, float);
119 CONVERT_PROP(property, PropertyString, std::string);
120 CONVERT_PROP(property, PropertyColor, Color);
121 CONVERT_PROP(property, PropertyRectF, RectF);
122 CONVERT_PROP(property, PropertyVectorFloat, LinearVector<float>);
123 CONVERT_PROP(property, PropertyCanvasImageModifierWrapper, CanvasImageModifierWrapper);
124 CONVERT_ANIMATABLE_PROP(property, AnimatablePropertyOffsetF, OffsetF);
125 CONVERT_ANIMATABLE_PROP(property, AnimatablePropertyUint8, uint8_t);
126 CONVERT_ANIMATABLE_PROP(property, AnimatablePropertyFloat, float);
127 CONVERT_ANIMATABLE_PROP(property, AnimatablePropertyColor, LinearColor);
128 CONVERT_ANIMATABLE_PROP(property, AnimatablePropertyVectorColor, GradientArithmetic);
129 CONVERT_ANIMATABLE_PROP(property, AnimatablePropertyVectorFloat, LinearVector<float>);
130 CONVERT_ANIMATABLE_PROP(property, AnimatablePropertyVectorLinearVector, LinearVector<LinearColor>);
131 CONVERT_ANIMATABLE_PROP(property, AnimatablePropertySizeF, SizeF);
132
133 if (AceType::InstanceOf<AnimatableArithmeticProperty>(property)) {
134 auto castProp = AceType::DynamicCast<AnimatableArithmeticProperty>(property);
135 if (!castProp && !castProp->Get()) {
136 LOGE("ConvertToRSProperty: Failed converting to RSProperty - AnimatableArithmeticProperty is null");
137 return nullptr;
138 }
139 AnimatableArithmeticProxy proxy(castProp->Get());
140 auto rsProp = std::make_shared<RSAnimatableProperty<AnimatableArithmeticProxy>>(proxy);
141 auto getter = [rsProp]() -> RefPtr<CustomAnimatableArithmetic> { return rsProp->Get().GetObject(); };
142 auto setter = [rsProp](const RefPtr<CustomAnimatableArithmetic>& value) {
143 rsProp->Set(AnimatableArithmeticProxy(value));
144 };
145 castProp->SetUpCallbacks(getter, setter);
146 if (castProp->GetUpdateCallback()) {
147 rsProp->SetUpdateCallback([cb = castProp->GetUpdateCallback()](
148 const AnimatableArithmeticProxy& value) { cb(value.GetObject()); });
149 }
150 return rsProp;
151 }
152
153 return nullptr;
154 }
155
AttachProperties()156 void ContentModifierAdapter::AttachProperties()
157 {
158 auto modifier = modifier_.Upgrade();
159 if (!hasAttached_ && modifier && modifier->GetAttachedProperties().size()) {
160 for (const auto& property : modifier->GetAttachedProperties()) {
161 auto rsProperty = ConvertToRSProperty(property);
162 AttachProperty(rsProperty);
163 }
164 hasAttached_ = true;
165 }
166 }
167
Draw(RSDrawingContext & context) const168 void OverlayModifierAdapter::Draw(RSDrawingContext& context) const
169 {
170 // use dummy deleter avoid delete the SkCanvas by shared_ptr, its owned by context
171 CHECK_NULL_VOID(context.canvas);
172 auto modifier = modifier_.Upgrade();
173 CHECK_NULL_VOID(modifier);
174 DrawingContext context_ = { *context.canvas, context.width, context.height };
175 modifier->Draw(context_);
176 }
177
AttachProperties()178 void OverlayModifierAdapter::AttachProperties()
179 {
180 auto modifier = modifier_.Upgrade();
181 if (!hasAttached_ && modifier && modifier->GetAttachedProperties().size()) {
182 for (const auto& property : modifier->GetAttachedProperties()) {
183 auto rsProperty = ConvertToRSProperty(property);
184 AttachProperty(rsProperty);
185 }
186 hasAttached_ = true;
187 }
188 }
189
Draw(RSDrawingContext & context) const190 void ForegroundModifierAdapter::Draw(RSDrawingContext& context) const
191 {
192 // use dummy deleter avoid delete the SkCanvas by shared_ptr, its owned by context
193 CHECK_NULL_VOID(context.canvas);
194 auto modifier = modifier_.Upgrade();
195 CHECK_NULL_VOID(modifier);
196 DrawingContext context_ = { *context.canvas, context.width, context.height };
197 modifier->Draw(context_);
198 }
199
AttachProperties()200 void ForegroundModifierAdapter::AttachProperties()
201 {
202 auto modifier = modifier_.Upgrade();
203 if (!hasAttached_ && modifier && modifier->GetAttachedProperties().size()) {
204 for (const auto& property : modifier->GetAttachedProperties()) {
205 auto rsProperty = ConvertToRSProperty(property);
206 AttachProperty(rsProperty);
207 }
208 hasAttached_ = true;
209 }
210 }
211
AddProperty(const RefPtr<PropertyBase> & property)212 void RSNodeModifierImpl::AddProperty(const RefPtr<PropertyBase>& property)
213 {
214 if (!attachedProperty_) {
215 auto rsProperty = ConvertToRSProperty(property);
216 AttachProperty(rsProperty);
217 attachedProperty_ = rsProperty;
218 }
219 }
220
221 namespace {
ToAnimationFinishCallbackType(const FinishCallbackType finishCallbackType)222 Rosen::FinishCallbackType ToAnimationFinishCallbackType(const FinishCallbackType finishCallbackType)
223 {
224 if (finishCallbackType == FinishCallbackType::LOGICALLY) {
225 return Rosen::FinishCallbackType::LOGICALLY;
226 } else if (finishCallbackType == FinishCallbackType::REMOVED) {
227 return Rosen::FinishCallbackType::TIME_SENSITIVE;
228 } else {
229 return Rosen::FinishCallbackType::TIME_SENSITIVE;
230 }
231 }
OptionToTimingProtocol(const AnimationOption & option)232 Rosen::RSAnimationTimingProtocol OptionToTimingProtocol(const AnimationOption& option)
233 {
234 Rosen::RSAnimationTimingProtocol timingProtocol;
235 timingProtocol.SetDuration(option.GetDuration());
236 timingProtocol.SetStartDelay(option.GetDelay());
237 timingProtocol.SetSpeed(option.GetTempo());
238 timingProtocol.SetRepeatCount(option.GetIteration());
239 timingProtocol.SetDirection(option.GetAnimationDirection() == AnimationDirection::NORMAL ||
240 option.GetAnimationDirection() == AnimationDirection::ALTERNATE);
241 timingProtocol.SetAutoReverse(option.GetAnimationDirection() == AnimationDirection::ALTERNATE ||
242 option.GetAnimationDirection() == AnimationDirection::ALTERNATE_REVERSE);
243 timingProtocol.SetFillMode(static_cast<Rosen::FillMode>(option.GetFillMode()));
244 timingProtocol.SetFinishCallbackType(ToAnimationFinishCallbackType(option.GetFinishCallbackType()));
245 return timingProtocol;
246 }
247 } // namespace
248
249 // Common template implementation
250 template<typename T, typename S>
AnimateWithVelocity(const AnimationOption & option,T value,T velocity,const FinishCallback & finishCallback)251 void NodeAnimatableProperty<T, S>::AnimateWithVelocity(
252 const AnimationOption& option, T value, T velocity, const FinishCallback& finishCallback)
253 {
254 const auto& timingProtocol = OptionToTimingProtocol(option);
255 auto targetValue = std::make_shared<RSAnimatableProperty<T>>(value);
256 auto initialVelocity = std::make_shared<RSAnimatableProperty<T>>(velocity);
257 auto modifier = std::static_pointer_cast<RSNodeModifierImpl>(GetModifyImpl());
258 if (modifier) {
259 auto property = std::static_pointer_cast<RSAnimatableProperty<T>>(modifier->GetProperty());
260 if (property) {
261 property->AnimateWithInitialVelocity(timingProtocol,
262 NativeCurveHelper::ToNativeCurve(option.GetCurve()),
263 targetValue, initialVelocity, finishCallback, nullptr);
264 }
265 }
266 }
267
268 template<typename T, typename S>
SetThresholdType(ThresholdType type)269 void NodeAnimatableProperty<T, S>::SetThresholdType(ThresholdType type)
270 {
271 auto modifier = std::static_pointer_cast<RSNodeModifierImpl>(GetModifyImpl());
272 CHECK_NULL_VOID(modifier);
273 auto property = std::static_pointer_cast<RSPropertyBase>(modifier->GetProperty());
274 CHECK_NULL_VOID(property);
275 property->SetThresholdType(static_cast<Rosen::ThresholdType>(type));
276 }
277
278 template<typename T, typename S>
SetPropertyUnit(PropertyUnit unit)279 void NodeAnimatableProperty<T, S>::SetPropertyUnit(PropertyUnit unit)
280 {
281 auto modifier = std::static_pointer_cast<RSNodeModifierImpl>(GetModifyImpl());
282 CHECK_NULL_VOID(modifier);
283 auto property = std::static_pointer_cast<RSAnimatableProperty<T>>(modifier->GetProperty());
284 CHECK_NULL_VOID(property);
285 property->SetPropertyUnit(static_cast<Rosen::RSPropertyUnit>(unit));
286 }
287
288 // Explicit template instantiations
289 template class NodeAnimatableProperty<float, AnimatablePropertyFloat>;
290 template class NodeAnimatableProperty<OffsetF, AnimatablePropertyOffsetF>;
291 } // namespace OHOS::Ace::NG
292