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