• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 
16 #include "frameworks/bridge/js_frontend/engine/common/base_animation_bridge.h"
17 
18 #include <functional>
19 #include <unordered_map>
20 #include <utility>
21 
22 #include "base/json/json_util.h"
23 #include "base/utils/linear_map.h"
24 #include "base/utils/string_utils.h"
25 #include "base/utils/utils.h"
26 #include "core/animation/keyframe_animation.h"
27 #include "frameworks/bridge/common/dom/dom_type.h"
28 #include "frameworks/bridge/common/utils/transform_convertor.h"
29 #include "frameworks/bridge/common/utils/utils.h"
30 
31 namespace OHOS::Ace::Framework {
32 namespace {
33 
34 constexpr int32_t MIN_SIZE = 2;
35 constexpr Dimension HALF = 0.5_pct;
36 constexpr Dimension FULL = 1.0_pct;
37 constexpr Dimension ZERO = 0.0_pct;
38 
JsParseAnimationFramesInternal(const std::unique_ptr<JsonValue> & argsPtrAnimation,std::unordered_map<std::string,std::string> & animationFrames)39 void JsParseAnimationFramesInternal(
40     const std::unique_ptr<JsonValue>& argsPtrAnimation, std::unordered_map<std::string, std::string>& animationFrames)
41 {
42     if (!argsPtrAnimation || argsPtrAnimation->IsNull()) {
43         return;
44     }
45 
46     for (auto i = 0; i < argsPtrAnimation->GetArraySize(); i++) {
47         auto item = argsPtrAnimation->GetArrayItem(i);
48         if (!item || item->IsNull()) {
49             continue;
50         }
51         auto key = item->GetKey();
52         auto value = item->IsString() ? item->GetString() : item->ToString();
53 
54         if (!key.empty() && !value.empty()) {
55             // in js api offset in range in [0, 1], but keyframe time range in range [0, 100]
56             if (key == DOM_ANIMATION_OFFSET) {
57                 auto time = StringUtils::StringToDouble(value);
58                 value = std::to_string(time * 100.0);
59             }
60             animationFrames[key] = value;
61         }
62     }
63 }
64 
JsParseIterations(const std::unique_ptr<JsonValue> & argsPtrIterations)65 int32_t JsParseIterations(const std::unique_ptr<JsonValue>& argsPtrIterations)
66 {
67     if (!argsPtrIterations) {
68         return 0;
69     }
70     int32_t iterations = 0;
71     if (argsPtrIterations->IsString()) {
72         std::string iterationsString = argsPtrIterations->GetString();
73         if (iterationsString == BaseAnimationBridgeUtils::ITERATIONS_INFINITY) {
74             iterations = ANIMATION_REPEAT_INFINITE;
75         } else {
76             iterations = StringToInt(iterationsString);
77         }
78     } else if (argsPtrIterations->IsNumber()) {
79         iterations = argsPtrIterations->GetInt();
80     } else {
81         iterations = 1;
82     }
83     return iterations;
84 }
85 
JsParseDoubleParams(const std::unique_ptr<JsonValue> & argsPtrDuration,const std::unique_ptr<JsonValue> & argsPtrDelay,std::unordered_map<std::string,double> & animationDoubleParams)86 void JsParseDoubleParams(const std::unique_ptr<JsonValue>& argsPtrDuration,
87     const std::unique_ptr<JsonValue>& argsPtrDelay, std::unordered_map<std::string, double>& animationDoubleParams)
88 {
89     if (argsPtrDelay) {
90         double delay = 0.0;
91         if (argsPtrDelay->IsString()) {
92             delay = StringToDouble(argsPtrDelay->GetString());
93         } else {
94             delay = argsPtrDelay->GetDouble();
95         }
96         animationDoubleParams[DOM_ANIMATION_DELAY_API] = delay;
97     }
98     if (argsPtrDuration) {
99         double duration = 0.0;
100         if (argsPtrDuration->IsString()) {
101             duration = StringToDouble(argsPtrDuration->GetString());
102         } else {
103             duration = argsPtrDuration->GetDouble();
104         }
105         animationDoubleParams[DOM_ANIMATION_DURATION_API] = duration;
106     }
107 }
108 
109 } // namespace
110 
HandleTransformOrigin(const std::vector<std::unordered_map<std::string,std::string>> & animationFrames)111 std::vector<Dimension> BaseAnimationBridgeUtils::HandleTransformOrigin(
112     const std::vector<std::unordered_map<std::string, std::string>>& animationFrames)
113 {
114     std::string transformOrigin;
115     if (animationFrames.size() >= MIN_SIZE) {
116         auto iterFrom = animationFrames.front().find(DOM_TRANSFORM_ORIGIN);
117         if (iterFrom != animationFrames.front().end()) {
118             transformOrigin = iterFrom->second;
119         }
120         if (transformOrigin.empty()) {
121             auto iterTo = animationFrames.back().find(DOM_TRANSFORM_ORIGIN);
122             if (iterTo != animationFrames.back().end()) {
123                 transformOrigin = iterTo->second;
124             }
125         }
126     }
127 
128     std::vector<Dimension> transformOriginValue;
129     if (transformOrigin.empty()) {
130         return transformOriginValue;
131     }
132 
133     static const LinearMapNode<std::vector<Dimension>> transformOriginMap[] = {
134         { DOM_TRANSFORM_ORIGIN_CENTER_BOTTOM, { HALF, FULL } },
135         { DOM_TRANSFORM_ORIGIN_CENTER_CENTER, { HALF, HALF } },
136         { DOM_TRANSFORM_ORIGIN_CENTER_TOP, { HALF, ZERO } },
137         { DOM_TRANSFORM_ORIGIN_LEFT_BOTTOM, { ZERO, FULL } },
138         { DOM_TRANSFORM_ORIGIN_LEFT_CENTER, { ZERO, HALF } },
139         { DOM_TRANSFORM_ORIGIN_LEFT_TOP, { ZERO, ZERO } },
140         { DOM_TRANSFORM_ORIGIN_RIGHT_BOTTOM, { FULL, FULL } },
141         { DOM_TRANSFORM_ORIGIN_RIGHT_CENTER, { FULL, HALF } },
142         { DOM_TRANSFORM_ORIGIN_RIGHT_TOP, { FULL, ZERO } },
143     };
144 
145     int64_t idx = BinarySearchFindIndex(transformOriginMap, ArraySize(transformOriginMap), transformOrigin.c_str());
146     if (idx < 0) {
147         auto pos = transformOrigin.find(' ', 0);
148         if (pos != std::string::npos) {
149             transformOriginValue.emplace_back(StringToDimension(transformOrigin.substr(0, pos)));
150             transformOriginValue.emplace_back(StringToDimension(transformOrigin.substr(pos + 1)));
151         }
152     } else {
153         transformOriginValue = transformOriginMap[idx].value;
154     }
155     return transformOriginValue;
156 }
157 
SetTweenComponentParams(const RefPtr<Curve> & curve,const std::vector<std::unordered_map<std::string,std::string>> & animationFrames,RefPtr<TweenComponent> & tweenComponent,TweenOption & tweenOption)158 void BaseAnimationBridgeUtils::SetTweenComponentParams(const RefPtr<Curve>& curve,
159     const std::vector<std::unordered_map<std::string, std::string>>& animationFrames,
160     RefPtr<TweenComponent>& tweenComponent, TweenOption& tweenOption)
161 {
162     tweenComponent->SetCustomTweenOption(tweenOption);
163     tweenComponent->SetCustomAnimationOperation(AnimationOperation::NONE);
164 }
165 
JsParseAnimationFrames(const std::string & content,std::vector<std::unordered_map<std::string,std::string>> & animationFrames)166 void BaseAnimationBridgeUtils::JsParseAnimationFrames(
167     const std::string& content, std::vector<std::unordered_map<std::string, std::string>>& animationFrames)
168 {
169     auto argsPtr = JsonUtil::ParseJsonString(content);
170     if (!argsPtr) {
171         return;
172     }
173     auto argsPtrItem = argsPtr->GetArrayItem(0);
174     if (!argsPtrItem) {
175         return;
176     }
177     // Parse the arguments to each item in the frame
178     auto size = argsPtrItem->GetArraySize();
179     for (int32_t idx = 0; idx < size; ++idx) {
180         auto argsPtrAnimation = argsPtrItem->GetArrayItem(idx);
181         if (!argsPtrAnimation) {
182             continue;
183         }
184         std::unordered_map<std::string, std::string> animationFrame;
185         JsParseAnimationFramesInternal(argsPtrAnimation, animationFrame);
186         if (idx == 0) {
187             animationFrame[DOM_ANIMATION_OFFSET] = ANIMATION_FROM;
188         } else if (idx == size - 1) {
189             animationFrame[DOM_ANIMATION_OFFSET] = ANIMATION_TO;
190         }
191         animationFrames.emplace_back(animationFrame);
192     }
193 }
194 
JsParseAnimationOptions(const std::string & content,int32_t & iterations,std::unordered_map<std::string,double> & animationDoubleOptions,std::unordered_map<std::string,std::string> & animationStringOptions)195 void BaseAnimationBridgeUtils::JsParseAnimationOptions(const std::string& content, int32_t& iterations,
196     std::unordered_map<std::string, double>& animationDoubleOptions,
197     std::unordered_map<std::string, std::string>& animationStringOptions)
198 {
199     auto argsPtr = JsonUtil::ParseJsonString(content);
200     if (!argsPtr) {
201         return;
202     }
203 
204     auto argsPtrItem = argsPtr->GetArrayItem(1);
205     if (!argsPtrItem) {
206         return;
207     }
208 
209     auto argsPtrItemIterations = argsPtrItem->GetValue(DOM_ANIMATION_ITERATIONS);
210     auto argsPtrItemDelay = argsPtrItem->GetValue(DOM_ANIMATION_DELAY_API);
211     auto argsPtrItemDuration = argsPtrItem->GetValue(DOM_ANIMATION_DURATION_API);
212     auto argsPtrItemEasing = argsPtrItem->GetValue(DOM_ANIMATION_EASING);
213     auto argsPtrItemFill = argsPtrItem->GetValue(DOM_ANIMATION_FILL);
214     auto argsPtrItemDirection = argsPtrItem->GetValue(DOM_ANIMATION_DIRECTION_API);
215 
216     iterations = JsParseIterations(argsPtrItemIterations);
217     JsParseDoubleParams(argsPtrItemDuration, argsPtrItemDelay, animationDoubleOptions);
218     if (argsPtrItemEasing) {
219         animationStringOptions[DOM_ANIMATION_EASING] = argsPtrItemEasing->GetString();
220     }
221     if (argsPtrItemFill) {
222         animationStringOptions[DOM_ANIMATION_FILL] = argsPtrItemFill->GetString();
223     }
224     if (argsPtrItemDirection) {
225         animationStringOptions[DOM_ANIMATION_DIRECTION_API] = argsPtrItemDirection->GetString();
226     }
227 }
228 
JsParseAnimatorParams(const std::string & content,int32_t & iterations,std::unordered_map<std::string,double> & animationDoubleParams,std::unordered_map<std::string,std::string> & animationStringParams)229 void BaseAnimationBridgeUtils::JsParseAnimatorParams(const std::string& content, int32_t& iterations,
230     std::unordered_map<std::string, double>& animationDoubleParams,
231     std::unordered_map<std::string, std::string>& animationStringParams)
232 {
233     auto argsPtr = JsonUtil::ParseJsonString(content);
234     if (!argsPtr) {
235         return;
236     }
237 
238     auto argsPtrIterations = argsPtr->GetValue(DOM_ANIMATION_ITERATIONS);
239     auto argsPtrDelay = argsPtr->GetValue(DOM_ANIMATION_DELAY_API);
240     auto argsPtrDuration = argsPtr->GetValue(DOM_ANIMATION_DURATION_API);
241     auto argsPtrEasing = argsPtr->GetValue(DOM_ANIMATION_EASING);
242     auto argsPtrFill = argsPtr->GetValue(DOM_ANIMATION_FILL);
243     auto argsPtrFrom = argsPtr->GetValue(DOM_ANIMATION_BEGIN);
244     auto argsPtrTo = argsPtr->GetValue(DOM_ANIMATION_END);
245     auto argsPtrDirection = argsPtr->GetValue(DOM_ANIMATION_DIRECTION_API);
246 
247     iterations = JsParseIterations(argsPtrIterations);
248     JsParseDoubleParams(argsPtrDuration, argsPtrDelay, animationDoubleParams);
249     if (argsPtrEasing) {
250         animationStringParams[DOM_ANIMATION_EASING] = argsPtrEasing->GetString();
251     }
252     if (argsPtrFill) {
253         animationStringParams[DOM_ANIMATION_FILL] = argsPtrFill->GetString();
254     }
255     if (argsPtrDirection) {
256         animationStringParams[DOM_ANIMATION_DIRECTION_API] = argsPtrDirection->GetString();
257     }
258     if (argsPtrFrom) {
259         double from = 0.0;
260         from = argsPtrFrom->GetDouble();
261         animationDoubleParams[DOM_ANIMATION_BEGIN] = from;
262     }
263     if (argsPtrTo) {
264         double to = 1.0;
265         to = argsPtrTo->GetDouble();
266         animationDoubleParams[DOM_ANIMATION_END] = to;
267     }
268 }
269 } // namespace OHOS::Ace::Framework
270