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