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 "core/animation/animation_util.h"
17
18 #include "bridge/common/dom/dom_node.h"
19 #include "bridge/common/utils/utils.h"
20
21 namespace OHOS::Ace {
22 namespace {
23
24 template<class T>
ParseFunctionValue(const std::string & line,const std::string & key,std::function<T (const std::string &)> parser)25 T ParseFunctionValue(const std::string& line, const std::string& key, std::function<T(const std::string&)> parser)
26 {
27 std::vector<std::string> strs;
28 StringUtils::SplitStr(line, " ", strs, true);
29 for (const auto& str : strs) {
30 if (str.empty()) {
31 continue;
32 }
33 auto leftIndex = str.find('(');
34 auto rightIndex = str.find(')');
35 if (leftIndex == std::string::npos || rightIndex == std::string::npos) {
36 continue;
37 }
38 if (leftIndex + 1 >= rightIndex) {
39 continue;
40 }
41 if (str.substr(0, leftIndex) != key) {
42 continue;
43 }
44
45 auto valueStr = str.substr(leftIndex + 1, rightIndex - leftIndex - 1);
46 return parser(valueStr);
47 }
48 return T {};
49 }
50
GetTransformTypeValue(const std::unique_ptr<JsonValue> & transformJson)51 std::string GetTransformTypeValue(const std::unique_ptr<JsonValue>& transformJson)
52 {
53 if (transformJson->IsNull()) {
54 LOGE("transformJson is null");
55 return "";
56 }
57 std::string jsonValue = transformJson->GetString();
58 if (jsonValue.empty()) {
59 double jsonDouble = transformJson->GetDouble();
60 return std::to_string(jsonDouble);
61 }
62 return jsonValue;
63 }
64
GetTransformType(const std::unique_ptr<JsonValue> & transformJson)65 std::string GetTransformType(const std::unique_ptr<JsonValue>& transformJson)
66 {
67 if (transformJson->IsNull()) {
68 LOGE("transformJson is null");
69 return "";
70 }
71 return transformJson->GetKey();
72 }
73
74 } // namespace
75
ParseAnimationStyle(const std::vector<std::unordered_map<std::string,std::string>> & animationKeyframes,const RefPtr<Declaration> & declaration,const RefPtr<ThemeConstants> themeConstants)76 void AnimationUtil::ParseAnimationStyle(
77 const std::vector<std::unordered_map<std::string, std::string>>& animationKeyframes,
78 const RefPtr<Declaration>& declaration, const RefPtr<ThemeConstants> themeConstants)
79 {
80 if (declaration) {
81 isRightToLeft = declaration->IsRightToLeft();
82 }
83 themeConstants_ = themeConstants;
84
85 Clear();
86
87 for (const auto& animationNameKeyframe : animationKeyframes) {
88 auto animationName = animationNameKeyframe.find(DOM_ANIMATION_NAME);
89 if (animationName != animationNameKeyframe.end()) {
90 animationName_ = animationName->second;
91 if (declaration) {
92 auto& animationStyle =
93 declaration->MaybeResetStyle<CommonAnimationStyle>(StyleTag::COMMON_ANIMATION_STYLE);
94 if (animationStyle.IsValid()) {
95 animationStyle.animationOperation = AnimationOperation::PLAY;
96 }
97 }
98 continue;
99 }
100
101 // time from keyframe; offset from js api
102 auto pos = animationNameKeyframe.find(DOM_ANIMATION_NAME_TIME);
103 if (pos == animationNameKeyframe.end()) {
104 pos = animationNameKeyframe.find(DOM_ANIMATION_OFFSET);
105 }
106 if (pos == animationNameKeyframe.end()) {
107 continue;
108 }
109 auto timeStr = pos->second;
110 if (timeStr.empty()) {
111 continue;
112 }
113
114 for (const auto& [keyStyle, value] : animationNameKeyframe) {
115 if (keyStyle == DOM_ANIMATION_NAME_TIME || keyStyle == DOM_ANIMATION_OFFSET) {
116 continue;
117 }
118 KeyframesAddKeyFrame(keyStyle, value, timeStr);
119 }
120 }
121 if (!shadowKeyframes_.empty()) {
122 for (auto&& [key, shadow] : shadowKeyframes_) {
123 double time = StringUtils::StringToDouble(key) / 100.0;
124 AddAnimatable(shadow, time, AnimatableType::PROPERTY_BOX_SHADOW);
125 }
126 }
127 }
128
KeyframesAddKeyFrame(const std::string & keyStyle,const std::string & value,const std::string & timeStr)129 void AnimationUtil::KeyframesAddKeyFrame(
130 const std::string& keyStyle, const std::string& value, const std::string& timeStr)
131 {
132 static const std::unordered_map<std::string,
133 void (*)(const std::string&, const double&, const std::string&, AnimationUtil&)>
134 keyFrameAddMap = {
135 { DOM_BACKGROUND_COLOR,
136 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
137 LOGD("DOM_BACKGROUND_COLOR:%{public}s time:%{public}lf", value.c_str(), time);
138 util.AddAnimatable(util.ParseColor(value), time, AnimatableType::PROPERTY_BG_COLOR);
139 } },
140 { DOM_BACKGROUND_IMAGE_SIZE,
141 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
142 BackgroundImageSize backgroundImageSize;
143 if (!Framework::ParseBackgroundImageSize(value, backgroundImageSize)) {
144 LOGW("ParseBackgroundImageSize failed.");
145 return;
146 }
147 util.AddAnimatable(backgroundImageSize, time, AnimatableType::PROPERTY_BACKGROUND_SIZE);
148 } },
149 { DOM_BACKGROUND_IMAGE_POSITION,
150 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
151 BackgroundImagePosition backgroundImagePosition;
152 if (!Framework::ParseBackgroundImagePosition(value, backgroundImagePosition)) {
153 LOGW("ParseBackgroundImagePosition failed.");
154 return;
155 }
156 util.AddAnimatable(backgroundImagePosition, time, AnimatableType::PROPERTY_BACKGROUND_POSITION);
157 } },
158 { DOM_WIDTH,
159 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
160 LOGE("DOM_WIDTH:%{public}s time:%{public}lf", value.c_str(), time);
161 util.AddAnimatable(util.ParseDimension(value), time, AnimatableType::PROPERTY_WIDTH);
162 } },
163 { DOM_HEIGHT,
164 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
165 LOGD("DOM_HEIGHT:%{public}s time:%{public}lf", value.c_str(), time);
166 util.AddAnimatable(util.ParseDimension(value), time, AnimatableType::PROPERTY_HEIGHT);
167 } },
168 { DOM_OPACITY,
169 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
170 LOGD("DOM_OPACITY:%{public}s time:%{public}lf", value.c_str(), time);
171 util.AddAnimatable<float>(util.ParseDouble(value), time, AnimatableType::PROPERTY_OPACITY);
172 } },
173 // margin
174 { DOM_MARGIN_LEFT,
175 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
176 util.AddAnimatable(
177 util.ParseDimension(value), time, AnimatableType::PROPERTY_MARGIN_LEFT);
178 } },
179 { DOM_MARGIN_RIGHT,
180 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
181 util.AddAnimatable(
182 util.ParseDimension(value), time, AnimatableType::PROPERTY_MARGIN_RIGHT);
183 } },
184 { DOM_MARGIN_TOP,
185 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
186 util.AddAnimatable(
187 util.ParseDimension(value), time, AnimatableType::PROPERTY_MARGIN_TOP);
188 } },
189 { DOM_MARGIN_BOTTOM,
190 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
191 util.AddAnimatable(
192 util.ParseDimension(value), time, AnimatableType::PROPERTY_MARGIN_BOTTOM);
193 } },
194 { DOM_MARGIN_START,
195 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
196 if (util.isRightToLeft) {
197 util.AddAnimatable(
198 util.ParseDimension(value), time, AnimatableType::PROPERTY_MARGIN_RIGHT);
199 } else {
200 util.AddAnimatable(
201 util.ParseDimension(value), time, AnimatableType::PROPERTY_MARGIN_LEFT);
202 }
203 } },
204 { DOM_MARGIN_END,
205 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
206 if (util.isRightToLeft) {
207 util.AddAnimatable(
208 util.ParseDimension(value), time, AnimatableType::PROPERTY_MARGIN_LEFT);
209 } else {
210 util.AddAnimatable(
211 util.ParseDimension(value), time, AnimatableType::PROPERTY_MARGIN_RIGHT);
212 }
213 } },
214 { DOM_MARGIN,
215 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
216 auto margin = util.ParseDimension(value);
217 util.AddAnimatable(margin, time, AnimatableType::PROPERTY_MARGIN_LEFT);
218 util.AddAnimatable(margin, time, AnimatableType::PROPERTY_MARGIN_TOP);
219 util.AddAnimatable(margin, time, AnimatableType::PROPERTY_MARGIN_RIGHT);
220 util.AddAnimatable(margin, time, AnimatableType::PROPERTY_MARGIN_BOTTOM);
221 } },
222 // padding
223 { DOM_PADDING_LEFT,
224 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
225 util.AddAnimatable(
226 util.ParseDimension(value), time, AnimatableType::PROPERTY_PADDING_LEFT);
227 } },
228 { DOM_PADDING_RIGHT,
229 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
230 util.AddAnimatable(
231 util.ParseDimension(value), time, AnimatableType::PROPERTY_PADDING_RIGHT);
232 } },
233 { DOM_PADDING_TOP,
234 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
235 util.AddAnimatable(
236 util.ParseDimension(value), time, AnimatableType::PROPERTY_PADDING_TOP);
237 } },
238 { DOM_PADDING_BOTTOM,
239 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
240 util.AddAnimatable(
241 util.ParseDimension(value), time, AnimatableType::PROPERTY_PADDING_BOTTOM);
242 } },
243 { DOM_PADDING_START,
244 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
245 auto padding = util.ParseDimension(value);
246 if (util.isRightToLeft) {
247 util.AddAnimatable(padding, time, AnimatableType::PROPERTY_PADDING_RIGHT);
248 } else {
249 util.AddAnimatable(padding, time, AnimatableType::PROPERTY_PADDING_LEFT);
250 }
251 } },
252 { DOM_PADDING_END,
253 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
254 auto padding = util.ParseDimension(value);
255 if (util.isRightToLeft) {
256 util.AddAnimatable(padding, time, AnimatableType::PROPERTY_PADDING_LEFT);
257 } else {
258 util.AddAnimatable(padding, time, AnimatableType::PROPERTY_PADDING_RIGHT);
259 }
260 } },
261 { DOM_PADDING,
262 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
263 auto padding = util.ParseDimension(value);
264 util.AddAnimatable(padding, time, AnimatableType::PROPERTY_PADDING_LEFT);
265 util.AddAnimatable(padding, time, AnimatableType::PROPERTY_PADDING_TOP);
266 util.AddAnimatable(padding, time, AnimatableType::PROPERTY_PADDING_RIGHT);
267 util.AddAnimatable(padding, time, AnimatableType::PROPERTY_PADDING_BOTTOM);
268 } },
269 // border
270 { DOM_BORDER_LEFT_WIDTH,
271 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
272 util.AddAnimatable<float>(
273 util.ParseDouble(value), time, AnimatableType::PROPERTY_BORDER_LEFT_WIDTH);
274 } },
275 { DOM_BORDER_RIGHT_WIDTH,
276 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
277 util.AddAnimatable<float>(
278 util.ParseDouble(value), time, AnimatableType::PROPERTY_BORDER_RIGHT_WIDTH);
279 } },
280 { DOM_BORDER_TOP_WIDTH,
281 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
282 util.AddAnimatable<float>(
283 util.ParseDouble(value), time, AnimatableType::PROPERTY_BORDER_TOP_WIDTH);
284 } },
285 { DOM_BORDER_BOTTOM_WIDTH,
286 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
287 util.AddAnimatable<float>(
288 util.ParseDouble(value), time, AnimatableType::PROPERTY_BORDER_BOTTOM_WIDTH);
289 } },
290 { DOM_BORDER_WIDTH,
291 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
292 auto borderWidth = util.ParseDouble(value);
293 util.AddAnimatable<float>(borderWidth, time, AnimatableType::PROPERTY_BORDER_LEFT_WIDTH);
294 util.AddAnimatable<float>(borderWidth, time, AnimatableType::PROPERTY_BORDER_RIGHT_WIDTH);
295 util.AddAnimatable<float>(borderWidth, time, AnimatableType::PROPERTY_BORDER_TOP_WIDTH);
296 util.AddAnimatable<float>(borderWidth, time, AnimatableType::PROPERTY_BORDER_BOTTOM_WIDTH);
297 } },
298 { DOM_BORDER_RADIUS,
299 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
300 auto radius = util.ParseDouble(value);
301 util.AddAnimatable<float>(radius, time, AnimatableType::PROPERTY_BORDER_TOP_LEFT_RADIUS);
302 util.AddAnimatable<float>(radius, time, AnimatableType::PROPERTY_BORDER_TOP_RIGHT_RADIUS);
303 util.AddAnimatable<float>(radius, time, AnimatableType::PROPERTY_BORDER_BOTTOM_LEFT_RADIUS);
304 util.AddAnimatable<float>(radius, time, AnimatableType::PROPERTY_BORDER_BOTTOM_RIGHT_RADIUS);
305 } },
306 { DOM_BORDER_TOP_LEFT_RADIUS,
307 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
308 auto radius = util.ParseDouble(value);
309 util.AddAnimatable<float>(radius, time, AnimatableType::PROPERTY_BORDER_TOP_LEFT_RADIUS);
310 } },
311 { DOM_BORDER_TOP_RIGHT_RADIUS,
312 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
313 auto radius = util.ParseDouble(value);
314 util.AddAnimatable<float>(radius, time, AnimatableType::PROPERTY_BORDER_TOP_RIGHT_RADIUS);
315 } },
316 { DOM_BORDER_BOTTOM_LEFT_RADIUS,
317 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
318 auto radius = util.ParseDouble(value);
319 util.AddAnimatable<float>(radius, time, AnimatableType::PROPERTY_BORDER_BOTTOM_LEFT_RADIUS);
320 } },
321 { DOM_BORDER_BOTTOM_RIGHT_RADIUS,
322 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
323 auto radius = util.ParseDouble(value);
324 util.AddAnimatable<float>(radius, time, AnimatableType::PROPERTY_BORDER_BOTTOM_RIGHT_RADIUS);
325 } },
326 { DOM_BORDER_LEFT_COLOR,
327 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
328 auto color = util.ParseColor(value);
329 util.AddAnimatable<Color>(color, time, AnimatableType::PROPERTY_BORDER_LEFT_COLOR);
330 } },
331 { DOM_BORDER_RIGHT_COLOR,
332 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
333 auto color = util.ParseColor(value);
334 util.AddAnimatable<Color>(color, time, AnimatableType::PROPERTY_BORDER_RIGHT_COLOR);
335 } },
336 { DOM_BORDER_TOP_COLOR,
337 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
338 auto color = util.ParseColor(value);
339 util.AddAnimatable<Color>(color, time, AnimatableType::PROPERTY_BORDER_TOP_COLOR);
340 } },
341 { DOM_BORDER_BOTTOM_COLOR,
342 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
343 auto color = util.ParseColor(value);
344 util.AddAnimatable<Color>(color, time, AnimatableType::PROPERTY_BORDER_BOTTOM_COLOR);
345 } },
346 { DOM_BORDER_COLOR,
347 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
348 auto color = util.ParseColor(value);
349 util.AddAnimatable<Color>(color, time, AnimatableType::PROPERTY_BORDER_LEFT_COLOR);
350 util.AddAnimatable<Color>(color, time, AnimatableType::PROPERTY_BORDER_TOP_COLOR);
351 util.AddAnimatable<Color>(color, time, AnimatableType::PROPERTY_BORDER_RIGHT_COLOR);
352 util.AddAnimatable<Color>(color, time, AnimatableType::PROPERTY_BORDER_BOTTOM_COLOR);
353 } },
354 { DOM_BORDER_LEFT_STYLE,
355 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
356 auto borderStyle = Framework::ConvertStrToBorderStyle(value);
357 util.AddAnimatable<BorderStyle>(borderStyle, time, AnimatableType::PROPERTY_BORDER_LEFT_STYLE);
358 } },
359 { DOM_BORDER_RIGHT_STYLE,
360 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
361 auto borderStyle = Framework::ConvertStrToBorderStyle(value);
362 util.AddAnimatable<BorderStyle>(borderStyle, time, AnimatableType::PROPERTY_BORDER_RIGHT_STYLE);
363 } },
364 { DOM_BORDER_TOP_STYLE,
365 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
366 auto borderStyle = Framework::ConvertStrToBorderStyle(value);
367 util.AddAnimatable<BorderStyle>(borderStyle, time, AnimatableType::PROPERTY_BORDER_TOP_STYLE);
368 } },
369 { DOM_BORDER_BOTTOM_STYLE,
370 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
371 auto borderStyle = Framework::ConvertStrToBorderStyle(value);
372 util.AddAnimatable<BorderStyle>(borderStyle, time, AnimatableType::PROPERTY_BORDER_BOTTOM_STYLE);
373 } },
374 { DOM_BORDER_STYLE,
375 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
376 auto borderStyle = Framework::ConvertStrToBorderStyle(value);
377 util.AddAnimatable<BorderStyle>(borderStyle, time, AnimatableType::PROPERTY_BORDER_LEFT_STYLE);
378 util.AddAnimatable<BorderStyle>(borderStyle, time, AnimatableType::PROPERTY_BORDER_TOP_STYLE);
379 util.AddAnimatable<BorderStyle>(borderStyle, time, AnimatableType::PROPERTY_BORDER_RIGHT_STYLE);
380 util.AddAnimatable<BorderStyle>(borderStyle, time, AnimatableType::PROPERTY_BORDER_BOTTOM_STYLE);
381 } },
382 { DOM_FILTER,
383 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
384 auto radius = ParseFunctionValue<Dimension>(value, DOM_BLUR, Framework::StringToDimension);
385 if (GreatOrEqual(radius.Value(), 0.0)) {
386 util.AddAnimatable<float>(
387 static_cast<float>(radius.Value()), time, AnimatableType::PROPERTY_FILTER_BLUR);
388 }
389 } },
390 { DOM_BACKDROP_FILTER,
391 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
392 auto radius = ParseFunctionValue<Dimension>(value, DOM_BLUR, Framework::StringToDimension);
393 if (GreatOrEqual(radius.Value(), 0.0)) {
394 util.AddAnimatable<float>(
395 static_cast<float>(radius.Value()), time, AnimatableType::PROPERTY_BACKDROP_FILTER_BLUR);
396 }
397 } },
398 { DOM_WINDOW_FILTER,
399 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
400 std::vector<std::string> offsets;
401 StringUtils::StringSplitter(value, ' ', offsets);
402 // property animation only support progress
403 if (!offsets.empty()) {
404 auto progress =
405 ParseFunctionValue<Dimension>(offsets[0], DOM_BLUR, Framework::StringToDimension);
406 if (progress.Unit() == DimensionUnit::PERCENT) {
407 if (GreatOrEqual(progress.Value(), 0.0) && LessOrEqual(progress.Value(), 1.0)) {
408 util.AddAnimatable<float>(static_cast<float>(progress.Value()), time,
409 AnimatableType::PROPERTY_WINDOW_FILTER_BLUR);
410 }
411 }
412 }
413 } },
414 // BoxShadow
415 { DOM_BOX_SHADOW_H,
416 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
417 auto& shadow = util.shadowKeyframes_[timeStr];
418 shadow.SetOffsetX(util.ParseDouble(value));
419 } },
420 { DOM_BOX_SHADOW_V,
421 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
422 auto& shadow = util.shadowKeyframes_[timeStr];
423 shadow.SetOffsetY(util.ParseDouble(value));
424 } },
425 { DOM_BOX_SHADOW_BLUR,
426 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
427 auto& shadow = util.shadowKeyframes_[timeStr];
428 shadow.SetBlurRadius(util.ParseDouble(value));
429 } },
430 { DOM_BOX_SHADOW_SPREAD,
431 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
432 auto& shadow = util.shadowKeyframes_[timeStr];
433 shadow.SetSpreadRadius(util.ParseDouble(value));
434 } },
435 { DOM_BOX_SHADOW_COLOR,
436 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
437 auto& shadow = util.shadowKeyframes_[timeStr];
438 shadow.SetColor(util.ParseColor(value));
439 } },
440 // position
441 { DOM_POSITION_LEFT,
442 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
443 util.AddAnimatable(
444 util.ParseDimension(value), time, AnimatableType::PROPERTY_POSITION_LEFT);
445 } },
446 { DOM_POSITION_TOP,
447 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
448 util.AddAnimatable(
449 util.ParseDimension(value), time, AnimatableType::PROPERTY_POSITION_TOP);
450 } },
451 { DOM_POSITION_RIGHT,
452 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
453 util.AddAnimatable(
454 util.ParseDimension(value), time, AnimatableType::PROPERTY_POSITION_RIGHT);
455 } },
456 { DOM_POSITION_BOTTOM,
457 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
458 util.AddAnimatable(
459 util.ParseDimension(value), time, AnimatableType::PROPERTY_POSITION_BOTTOM);
460 } },
461 { DOM_TRANSFORM,
462 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
463 std::unique_ptr<JsonValue> transformJson = JsonUtil::ParseJsonString(value);
464 if (transformJson->GetArraySize() == 0) {
465 // when empty should insert an identity matrix.
466 util.transformConvertor_.InsertIdentityKeyframe(time);
467 }
468 for (int32_t index = 0; index < transformJson->GetArraySize(); ++index) {
469 std::string typeKey = GetTransformType(transformJson->GetArrayItem(index));
470 std::string typeValue = GetTransformTypeValue(transformJson->GetArrayItem(index));
471 if ((!typeKey.empty()) && (!typeValue.empty())) {
472 util.transformConvertor_.Convert(typeKey, typeValue, time);
473 }
474 }
475 } },
476 };
477 auto pos = keyFrameAddMap.find(keyStyle);
478 if (pos != keyFrameAddMap.end()) {
479 double time = StringUtils::StringToDouble(timeStr) / 100.0;
480 pos->second(value, time, timeStr, *this);
481 }
482 }
483
484 template<class T>
AddAnimatable(const T & value,double time,AnimatableType type)485 void AnimationUtil::AddAnimatable(const T& value, double time, AnimatableType type)
486 {
487 auto animatable = AceType::MakeRefPtr<AnimatableData<T>>(value);
488 animatable->SetTimePoint(time);
489 if (propAnimationMap_.find(type) == propAnimationMap_.end()) {
490 propAnimationMap_[type] = AceType::MakeRefPtr<PropertyAnimation>(type);
491 }
492 propAnimationMap_[type]->AddAnimatable(animatable);
493 }
494
GetThemeConstants() const495 RefPtr<ThemeConstants> AnimationUtil::GetThemeConstants() const
496 {
497 return themeConstants_;
498 }
499
ParseColor(const std::string & value,uint32_t maskAlpha) const500 Color AnimationUtil::ParseColor(const std::string& value, uint32_t maskAlpha) const
501 {
502 auto&& noRefFunc = [&value, maskAlpha = maskAlpha]() { return Color::FromString(value, maskAlpha); };
503 auto&& idRefFunc = [constants = themeConstants_](uint32_t refId) { return constants->GetColor(refId); };
504 if (!themeConstants_) {
505 noRefFunc();
506 }
507 return ParseThemeReference<Color>(value, noRefFunc, idRefFunc, Color::TRANSPARENT);
508 }
509
ParseDouble(const std::string & value) const510 double AnimationUtil::ParseDouble(const std::string& value) const
511 {
512 auto&& noRefFunc = [&value]() { return StringUtils::StringToDouble(value); };
513 auto&& idRefFunc = [constants = themeConstants_](uint32_t refId) { return constants->GetDouble(refId); };
514 if (!themeConstants_) {
515 noRefFunc();
516 }
517 return ParseThemeReference<double>(value, noRefFunc, idRefFunc, 0.0);
518 }
519
ParseDimension(const std::string & value) const520 Dimension AnimationUtil::ParseDimension(const std::string& value) const
521 {
522 auto&& noRefFunc = [&value]() { return StringUtils::StringToDimension(value); };
523 auto&& idRefFunc = [constants = themeConstants_](uint32_t refId) { return constants->GetDimension(refId); };
524 if (!themeConstants_) {
525 noRefFunc();
526 }
527 return ParseThemeReference<Dimension>(value, noRefFunc, idRefFunc, Dimension());
528 }
529
530 } // namespace OHOS::Ace
531