• 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 "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