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 LOGE("ConvertToRSProperty failed!");
154 return nullptr;
155 }
156
AttachProperties()157 void ContentModifierAdapter::AttachProperties()
158 {
159 auto modifier = modifier_.Upgrade();
160 if (!hasAttached_ && modifier && modifier->GetAttachedProperties().size()) {
161 for (const auto& property : modifier->GetAttachedProperties()) {
162 auto rsProperty = ConvertToRSProperty(property);
163 AttachProperty(rsProperty);
164 }
165 hasAttached_ = true;
166 }
167 }
168
Draw(RSDrawingContext & context) const169 void OverlayModifierAdapter::Draw(RSDrawingContext& context) const
170 {
171 // use dummy deleter avoid delete the SkCanvas by shared_ptr, its owned by context
172 CHECK_NULL_VOID(context.canvas);
173 auto modifier = modifier_.Upgrade();
174 CHECK_NULL_VOID(modifier);
175 DrawingContext context_ = { *context.canvas, context.width, context.height };
176 modifier->Draw(context_);
177 }
178
AttachProperties()179 void OverlayModifierAdapter::AttachProperties()
180 {
181 auto modifier = modifier_.Upgrade();
182 if (!hasAttached_ && modifier && modifier->GetAttachedProperties().size()) {
183 for (const auto& property : modifier->GetAttachedProperties()) {
184 auto rsProperty = ConvertToRSProperty(property);
185 AttachProperty(rsProperty);
186 }
187 hasAttached_ = true;
188 }
189 }
190
Draw(RSDrawingContext & context) const191 void ForegroundModifierAdapter::Draw(RSDrawingContext& context) const
192 {
193 // use dummy deleter avoid delete the SkCanvas by shared_ptr, its owned by context
194 CHECK_NULL_VOID(context.canvas);
195 auto modifier = modifier_.Upgrade();
196 CHECK_NULL_VOID(modifier);
197 DrawingContext context_ = { *context.canvas, context.width, context.height };
198 modifier->Draw(context_);
199 }
200
AttachProperties()201 void ForegroundModifierAdapter::AttachProperties()
202 {
203 auto modifier = modifier_.Upgrade();
204 if (!hasAttached_ && modifier && modifier->GetAttachedProperties().size()) {
205 for (const auto& property : modifier->GetAttachedProperties()) {
206 auto rsProperty = ConvertToRSProperty(property);
207 AttachProperty(rsProperty);
208 }
209 hasAttached_ = true;
210 }
211 }
212
AddProperty(const RefPtr<PropertyBase> & property)213 void RSNodeModifierImpl::AddProperty(const RefPtr<PropertyBase>& property)
214 {
215 if (!attachedProperty_) {
216 auto rsProperty = ConvertToRSProperty(property);
217 AttachProperty(rsProperty);
218 attachedProperty_ = rsProperty;
219 }
220 }
221
222 namespace {
ToAnimationFinishCallbackType(const FinishCallbackType finishCallbackType)223 Rosen::FinishCallbackType ToAnimationFinishCallbackType(const FinishCallbackType finishCallbackType)
224 {
225 if (finishCallbackType == FinishCallbackType::LOGICALLY) {
226 return Rosen::FinishCallbackType::LOGICALLY;
227 } else if (finishCallbackType == FinishCallbackType::REMOVED) {
228 return Rosen::FinishCallbackType::TIME_SENSITIVE;
229 } else {
230 return Rosen::FinishCallbackType::TIME_SENSITIVE;
231 }
232 }
OptionToTimingProtocol(const AnimationOption & option)233 Rosen::RSAnimationTimingProtocol OptionToTimingProtocol(const AnimationOption& option)
234 {
235 Rosen::RSAnimationTimingProtocol timingProtocol;
236 timingProtocol.SetDuration(option.GetDuration());
237 timingProtocol.SetStartDelay(option.GetDelay());
238 timingProtocol.SetSpeed(option.GetTempo());
239 timingProtocol.SetRepeatCount(option.GetIteration());
240 timingProtocol.SetDirection(option.GetAnimationDirection() == AnimationDirection::NORMAL ||
241 option.GetAnimationDirection() == AnimationDirection::ALTERNATE);
242 timingProtocol.SetAutoReverse(option.GetAnimationDirection() == AnimationDirection::ALTERNATE ||
243 option.GetAnimationDirection() == AnimationDirection::ALTERNATE_REVERSE);
244 timingProtocol.SetFillMode(static_cast<Rosen::FillMode>(option.GetFillMode()));
245 timingProtocol.SetFinishCallbackType(ToAnimationFinishCallbackType(option.GetFinishCallbackType()));
246 return timingProtocol;
247 }
248 } // namespace
249
250 template<>
AnimateWithVelocity(const AnimationOption & option,float value,float velocity,const FinishCallback & finishCallback)251 void NodeAnimatableProperty<float, AnimatablePropertyFloat>::AnimateWithVelocity(
252 const AnimationOption& option, float value, float velocity, const FinishCallback& finishCallback)
253 {
254 const auto& timingProtocol = OptionToTimingProtocol(option);
255 auto targetValue = std::make_shared<RSAnimatableProperty<float>>(value);
256 auto initialVelocity = std::make_shared<RSAnimatableProperty<float>>(velocity);
257 auto modify = std::static_pointer_cast<RSNodeModifierImpl>(GetModifyImpl());
258 if (modify) {
259 auto property = std::static_pointer_cast<RSAnimatableProperty<float>>(modify->GetProperty());
260 if (property) {
261 property->AnimateWithInitialVelocity(timingProtocol, NativeCurveHelper::ToNativeCurve(option.GetCurve()),
262 targetValue, initialVelocity, finishCallback, nullptr);
263 }
264 }
265 }
266
267 template<>
SetThresholdType(ThresholdType type)268 void NodeAnimatableProperty<float, AnimatablePropertyFloat>::SetThresholdType(ThresholdType type)
269 {
270 auto modify = std::static_pointer_cast<RSNodeModifierImpl>(GetModifyImpl());
271 CHECK_NULL_VOID(modify);
272 auto property = std::static_pointer_cast<RSPropertyBase>(modify->GetProperty());
273 CHECK_NULL_VOID(property);
274 property->SetThresholdType(static_cast<Rosen::ThresholdType>(type));
275 }
276
277 template<>
SetPropertyUnit(PropertyUnit unit)278 void NodeAnimatableProperty<float, AnimatablePropertyFloat>::SetPropertyUnit(PropertyUnit unit)
279 {
280 auto modify = std::static_pointer_cast<RSNodeModifierImpl>(GetModifyImpl());
281 CHECK_NULL_VOID(modify);
282 auto property = std::static_pointer_cast<RSAnimatableProperty<float>>(modify->GetProperty());
283 CHECK_NULL_VOID(property);
284 property->SetPropertyUnit(static_cast<Rosen::RSPropertyUnit>(unit));
285 }
286 } // namespace OHOS::Ace::NG
287