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