• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 
16 #include "frameworks/bridge/common/utils/utils.h"
17 
18 #include "frameworks/bridge/js_frontend/engine/common/js_constants.h"
19 #include "interfaces/native/native_type.h"
20 
21 namespace OHOS::Ace::Framework {
22 
23 namespace {
24 
25 using CustomCurveCreator = RefPtr<Curve> (*)(const std::vector<std::string>&);
26 
27 const size_t STEPS_PARAMS_SIZE = 2;
28 const size_t CUBIC_PARAMS_SIZE = 4;
29 const size_t SPRING_PARAMS_SIZE = 4;
30 constexpr size_t RESPONSIVE_SPRING_MOTION_PARAMS_SIZE = 3;
31 constexpr size_t INTERPOLATING_SPRING_PARAMS_SIZE = 4;
32 
33 static const std::unordered_set<std::string> HORIZON_SET = {
34     DOM_BACKGROUND_IMAGE_POSITION_LEFT,
35     DOM_BACKGROUND_IMAGE_POSITION_RIGHT,
36 };
37 static const std::unordered_set<std::string> VERTICAL_SET = {
38     DOM_BACKGROUND_IMAGE_POSITION_TOP,
39     DOM_BACKGROUND_IMAGE_POSITION_BOTTOM,
40 };
41 static const std::unordered_set<std::string> OBJECT_HORIZON_SET = {
42     DOM_IMAGE_POSITION_LEFT,
43     DOM_IMAGE_POSITION_RIGHT,
44 };
45 static const std::unordered_set<std::string> OBJECT_VERTICAL_SET = {
46     DOM_IMAGE_POSITION_TOP,
47     DOM_IMAGE_POSITION_BOTTOM,
48 };
49 
StepsCurveCreator(const std::vector<std::string> & params)50 RefPtr<Curve> StepsCurveCreator(const std::vector<std::string>& params)
51 {
52     if (params.empty() || params.size() > STEPS_PARAMS_SIZE) {
53         return nullptr;
54     }
55     auto step = StringUtils::StringToInt(params.front());
56     if (step <= 0) {
57         return nullptr;
58     }
59     StepsCurvePosition position = StepsCurvePosition::END;
60     if (params.size() > 1) {
61         if (params.back() == "start") {
62             position = StepsCurvePosition::START;
63         } else if (params.back() == "end") {
64             position = StepsCurvePosition::END;
65         } else {
66             return nullptr;
67         }
68     }
69     return AceType::MakeRefPtr<StepsCurve>(step, position);
70 }
71 
CubicCurveCreator(const std::vector<std::string> & params)72 RefPtr<Curve> CubicCurveCreator(const std::vector<std::string>& params)
73 {
74     if (params.size() != CUBIC_PARAMS_SIZE) {
75         return nullptr;
76     }
77     double x1 = StringToDouble(params.at(0));
78     double y1 = StringToDouble(params.at(1));
79     double x2 = StringToDouble(params.at(2));
80     double y2 = StringToDouble(params.at(3));
81     return AceType::MakeRefPtr<CubicCurve>(x1, y1, x2, y2);
82 }
83 
SpringCurveCreator(const std::vector<std::string> & params)84 RefPtr<Curve> SpringCurveCreator(const std::vector<std::string>& params)
85 {
86     if (params.size() != SPRING_PARAMS_SIZE) {
87         return nullptr;
88     }
89     double velocity = StringToDouble(params.at(0));
90     double mass = StringToDouble(params.at(1));
91     double stiffness = StringToDouble(params.at(2));
92     double damping = StringToDouble(params.at(3));
93     return AceType::MakeRefPtr<SpringCurve>(velocity, mass, stiffness, damping);
94 }
95 
InterpolatingSpringCreator(const std::vector<std::string> & params)96 RefPtr<Curve> InterpolatingSpringCreator(const std::vector<std::string>& params)
97 {
98     if (params.size() != INTERPOLATING_SPRING_PARAMS_SIZE) {
99         return nullptr;
100     }
101     double velocity = StringToDouble(params.at(0));
102     double mass = StringToDouble(params.at(1));
103     double stiffness = StringToDouble(params.at(2));
104     double damping = StringToDouble(params.at(3));
105     return AceType::MakeRefPtr<InterpolatingSpring>(velocity, mass, stiffness, damping);
106 }
107 
SpringMotionCreator(const std::vector<std::string> & params)108 RefPtr<Curve> SpringMotionCreator(const std::vector<std::string>& params)
109 {
110     if (params.size() > RESPONSIVE_SPRING_MOTION_PARAMS_SIZE) {
111         return nullptr;
112     }
113     size_t paramSize = params.size();
114     float response = paramSize > 0 ? StringUtils::StringToFloat(params[0])
115                         : ResponsiveSpringMotion::DEFAULT_SPRING_MOTION_RESPONSE;
116     float dampingRatio = paramSize > 1 ? StringUtils::StringToFloat(params[1])
117                             : ResponsiveSpringMotion::DEFAULT_SPRING_MOTION_DAMPING_RATIO;
118     float blendDuration = paramSize > 2 ? StringUtils::StringToFloat(params[2])
119                             : ResponsiveSpringMotion::DEFAULT_SPRING_MOTION_BLEND_DURATION;
120     return AceType::MakeRefPtr<ResponsiveSpringMotion>(response, dampingRatio, blendDuration);
121 }
122 
ResponsiveSpringMotionCreator(const std::vector<std::string> & params)123 RefPtr<Curve> ResponsiveSpringMotionCreator(const std::vector<std::string>& params)
124 {
125     if (params.size() > RESPONSIVE_SPRING_MOTION_PARAMS_SIZE) {
126         return nullptr;
127     }
128     size_t paramSize = params.size();
129     float response = paramSize > 0 ? StringUtils::StringToFloat(params[0])
130                         : ResponsiveSpringMotion::DEFAULT_RESPONSIVE_SPRING_MOTION_RESPONSE;
131     float dampingRatio = paramSize > 1 ? StringUtils::StringToFloat(params[1])
132                             : ResponsiveSpringMotion::DEFAULT_RESPONSIVE_SPRING_MOTION_DAMPING_RATIO;
133     float blendDuration = paramSize > 2 ? StringUtils::StringToFloat(params[2])
134                             : ResponsiveSpringMotion::DEFAULT_RESPONSIVE_SPRING_MOTION_BLEND_DURATION;
135     return AceType::MakeRefPtr<ResponsiveSpringMotion>(response, dampingRatio, blendDuration);
136 }
137 #ifndef FUZZTEST
SetBgImgPositionX(const BackgroundImagePositionType type,const double value,BackgroundImagePosition & bgImgPosition)138 void SetBgImgPositionX(
139     const BackgroundImagePositionType type, const double value, BackgroundImagePosition& bgImgPosition)
140 {
141     bgImgPosition.SetSizeTypeX(type);
142     bgImgPosition.SetSizeValueX(value);
143 }
144 
SetBgImgPositionY(const BackgroundImagePositionType type,const double value,BackgroundImagePosition & bgImgPosition)145 void SetBgImgPositionY(
146     const BackgroundImagePositionType type, const double value, BackgroundImagePosition& bgImgPosition)
147 {
148     bgImgPosition.SetSizeTypeY(type);
149     bgImgPosition.SetSizeValueY(value);
150 }
151 
SetBgImgPosition(const BackgroundImagePositionType type,const double value,BackgroundImagePosition & bgImgPosition)152 void SetBgImgPosition(
153     const BackgroundImagePositionType type, const double value, BackgroundImagePosition& bgImgPosition)
154 {
155     SetBgImgPositionX(type, value, bgImgPosition);
156     SetBgImgPositionY(type, value, bgImgPosition);
157 }
158 
GetOffsetValue(std::vector<std::string> offsets,std::string & posX,std::string & posY)159 void GetOffsetValue(std::vector<std::string> offsets, std::string& posX, std::string& posY)
160 {
161     if (offsets.size() == 1) {
162         posX = offsets.front();
163         if (VERTICAL_SET.find(posX) != VERTICAL_SET.end()) {
164             posY = offsets.front();
165             posX = DOM_BACKGROUND_IMAGE_POSITION_CENTER;
166         } else {
167             posY = DOM_BACKGROUND_IMAGE_POSITION_CENTER;
168         }
169     } else {
170         posX = offsets.front();
171         posY = offsets.back();
172         if (VERTICAL_SET.find(posX) != VERTICAL_SET.end() && HORIZON_SET.find(posY) != HORIZON_SET.end()) {
173             posY = offsets.front();
174             posX = offsets.back();
175         }
176     }
177 }
178 
179 // object-position check msg number
GetOffsetValueObjectPosition(std::vector<std::string> offsets,std::string & posX,std::string & posY)180 void GetOffsetValueObjectPosition(std::vector<std::string> offsets, std::string& posX, std::string& posY)
181 {
182     if (offsets.size() == 1) {
183         posX = offsets.front();
184         if (OBJECT_VERTICAL_SET.find(posX) != OBJECT_VERTICAL_SET.end()) {
185             posY = offsets.front();
186             posX = DOM_IMAGE_POSITION_CENTER;
187         } else {
188             posY = DOM_IMAGE_POSITION_CENTER;
189         }
190     } else {
191         posX = offsets.front();
192         posY = offsets.back();
193         if (OBJECT_VERTICAL_SET.find(posX) != OBJECT_VERTICAL_SET.end()
194             && OBJECT_HORIZON_SET.find(posY) != OBJECT_HORIZON_SET.end()) {
195             posY = offsets.front();
196             posX = offsets.back();
197         }
198     }
199 }
200 
BgImgPositionIsValid(const std::string & posX,const std::string & posY)201 bool BgImgPositionIsValid(const std::string& posX, const std::string& posY)
202 {
203     if ((posX == DOM_BACKGROUND_IMAGE_POSITION_CENTER) || (posY == DOM_BACKGROUND_IMAGE_POSITION_CENTER)) {
204         return true;
205     }
206     // posX and posY are not strictly corresponding to horizontal or vertical, but they must not conflict,
207     // for example both of them are "top" is invalid.
208     if (posX.find("px") != std::string::npos || posX.find('%') != std::string::npos ||
209         HORIZON_SET.find(posX) != HORIZON_SET.end()) {
210         if (posY.find("px") != std::string::npos || posY.find('%') != std::string::npos ||
211             VERTICAL_SET.find(posY) != VERTICAL_SET.end()) {
212             return true;
213         }
214     }
215     return VERTICAL_SET.find(posX) != VERTICAL_SET.end() && HORIZON_SET.find(posY) != HORIZON_SET.end();
216 }
217 
218 // objectPosition
ObjectImgPositionIsValid(const std::string & posX,const std::string & posY)219 bool ObjectImgPositionIsValid(const std::string& posX, const std::string& posY)
220 {
221     if (posX.find("px") != std::string::npos || posX.find('%') != std::string::npos ||
222         OBJECT_HORIZON_SET.find(posX) != OBJECT_HORIZON_SET.end() || posX != DOM_IMAGE_POSITION_CENTER) {
223         if (posY.find("px") != std::string::npos || posY.find('%') != std::string::npos ||
224             OBJECT_VERTICAL_SET.find(posY) != OBJECT_VERTICAL_SET.end() || posY != DOM_IMAGE_POSITION_CENTER) {
225             return true;
226         }
227     }
228     return false;
229 }
230 
SetBgImgSizeX(BackgroundImageSizeType type,double value,BackgroundImageSize & bgImgSize)231 void SetBgImgSizeX(BackgroundImageSizeType type, double value, BackgroundImageSize& bgImgSize)
232 {
233     bgImgSize.SetSizeTypeX(type);
234     bgImgSize.SetSizeValueX(value);
235 }
236 
SetBgImgSizeY(BackgroundImageSizeType type,double value,BackgroundImageSize & bgImgSize)237 void SetBgImgSizeY(BackgroundImageSizeType type, double value, BackgroundImageSize& bgImgSize)
238 {
239     bgImgSize.SetSizeTypeY(type);
240     bgImgSize.SetSizeValueY(value);
241 }
242 #endif
243 } // namespace
244 
CreateBuiltinCurve(const std::string & aniTimFunc)245 RefPtr<Curve> CreateBuiltinCurve(const std::string& aniTimFunc)
246 {
247     // this map should be sorted by key
248     static const LinearMapNode<RefPtr<Curve>> aniTimFuncMap[] = {
249         { DOM_ANIMATION_TIMING_FUNCTION_EASE, Curves::EASE },
250         { DOM_ANIMATION_TIMING_FUNCTION_EASE_IN, Curves::EASE_IN },
251         { DOM_ANIMATION_TIMING_FUNCTION_EASE_IN_OUT, Curves::EASE_IN_OUT },
252         { DOM_ANIMATION_TIMING_FUNCTION_EASE_OUT, Curves::EASE_OUT },
253         { DOM_ANIMATION_TIMING_FUNCTION_EXTREME_DECELERATION, Curves::EXTREME_DECELERATION },
254         { DOM_ANIMATION_TIMING_FUNCTION_FAST_OUT_LINEAR_IN, Curves::FAST_OUT_LINEAR_IN },
255         { DOM_ANIMATION_TIMING_FUNCTION_FAST_OUT_SLOW_IN, Curves::FAST_OUT_SLOW_IN },
256         { DOM_ANIMATION_TIMING_FUNCTION_FRICTION, Curves::FRICTION },
257         { DOM_ANIMATION_TIMING_FUNCTION_LINEAR, Curves::LINEAR },
258         { DOM_ANIMATION_TIMING_FUNCTION_LINEAR_OUT_SLOW_IN, Curves::LINEAR_OUT_SLOW_IN },
259         { DOM_ANIMATION_TIMING_FUNCTION_RHYTHM, Curves::RHYTHM },
260         { DOM_ANIMATION_TIMING_FUNCTION_SHARP, Curves::SHARP },
261         { DOM_ANIMATION_TIMING_FUNCTION_SMOOTH, Curves::SMOOTH },
262     };
263     auto index = BinarySearchFindIndex(aniTimFuncMap, ArraySize(aniTimFuncMap), aniTimFunc.c_str());
264     return index < 0 ? nullptr : aniTimFuncMap[index].value;
265 }
266 
CurveIntToString(int curve)267 std::string CurveIntToString(int curve)
268 {
269     static const LinearEnumMapNode<ArkUI_AnimationCurve, std::string> curveMap[] = {
270         { ArkUI_AnimationCurve::ARKUI_CURVE_EASE, DOM_ANIMATION_TIMING_FUNCTION_EASE },
271         { ArkUI_AnimationCurve::ARKUI_CURVE_EASE_IN, DOM_ANIMATION_TIMING_FUNCTION_EASE_IN },
272         { ArkUI_AnimationCurve::ARKUI_CURVE_EASE_IN_OUT, DOM_ANIMATION_TIMING_FUNCTION_EASE_IN_OUT },
273         { ArkUI_AnimationCurve::ARKUI_CURVE_EASE_OUT, DOM_ANIMATION_TIMING_FUNCTION_EASE_OUT},
274         { ArkUI_AnimationCurve::ARKUI_CURVE_EXTREME_DECELERATION, DOM_ANIMATION_TIMING_FUNCTION_EXTREME_DECELERATION },
275         { ArkUI_AnimationCurve::ARKUI_CURVE_FAST_OUT_LINEAR_IN, DOM_ANIMATION_TIMING_FUNCTION_FAST_OUT_LINEAR_IN },
276         { ArkUI_AnimationCurve::ARKUI_CURVE_FAST_OUT_SLOW_IN, DOM_ANIMATION_TIMING_FUNCTION_FAST_OUT_SLOW_IN},
277         { ArkUI_AnimationCurve::ARKUI_CURVE_FRICTION, DOM_ANIMATION_TIMING_FUNCTION_FRICTION },
278         { ArkUI_AnimationCurve::ARKUI_CURVE_LINEAR, DOM_ANIMATION_TIMING_FUNCTION_LINEAR},
279         { ArkUI_AnimationCurve::ARKUI_CURVE_LINEAR_OUT_SLOW_IN, DOM_ANIMATION_TIMING_FUNCTION_LINEAR_OUT_SLOW_IN},
280         { ArkUI_AnimationCurve::ARKUI_CURVE_RHYTHM, DOM_ANIMATION_TIMING_FUNCTION_RHYTHM},
281         { ArkUI_AnimationCurve::ARKUI_CURVE_SHARP, DOM_ANIMATION_TIMING_FUNCTION_SHARP},
282         { ArkUI_AnimationCurve::ARKUI_CURVE_SMOOTH, DOM_ANIMATION_TIMING_FUNCTION_SMOOTH},
283     };
284     auto index = BinarySearchFindIndex(curveMap, ArraySize(curveMap), static_cast<ArkUI_AnimationCurve>(curve));
285     return index < 0 ? DOM_ANIMATION_TIMING_FUNCTION_LINEAR : curveMap[index].value;
286 }
287 
ParseCurveParam(const std::string & aniTimFunc,std::string & curveName,std::vector<std::string> & paramsVector)288 bool ParseCurveParam(
289     const std::string& aniTimFunc, std::string& curveName, std::vector<std::string>& paramsVector)
290 {
291     if (aniTimFunc.back() != ')') {
292         return false;
293     }
294     std::string::size_type leftEmbracePosition = aniTimFunc.find_last_of('(');
295     if (leftEmbracePosition == std::string::npos) {
296         return false;
297     }
298     auto aniTimFuncName = aniTimFunc.substr(0, leftEmbracePosition);
299     auto params = aniTimFunc.substr(leftEmbracePosition + 1, aniTimFunc.length() - leftEmbracePosition - 2);
300     if (aniTimFuncName.empty() || params.empty()) {
301         return false;
302     }
303     StringUtils::StringSplitter(params, ',', paramsVector);
304     for (auto& param : paramsVector) {
305         RemoveHeadTailSpace(param);
306     }
307     curveName = std::move(aniTimFuncName);
308     return true;
309 }
310 
CreateCustomCurve(const std::string & aniTimFunc)311 RefPtr<Curve> CreateCustomCurve(const std::string& aniTimFunc)
312 {
313     std::string aniTimFuncName;
314     std::vector<std::string> paramsVector;
315     bool result = ParseCurveParam(aniTimFunc, aniTimFuncName, paramsVector);
316     if (!result) {
317         return nullptr;
318     }
319     static const LinearMapNode<CustomCurveCreator> customCurveMap[] = {
320         { DOM_ANIMATION_TIMING_FUNCTION_CUBIC_BEZIER, CubicCurveCreator },
321         { DOM_ANIMATION_TIMING_FUNCTION_INTERPOLATING_SPRING, InterpolatingSpringCreator },
322         { DOM_ANIMATION_TIMING_FUNCTION_RESPONSIVE_SPRING_MOTION, ResponsiveSpringMotionCreator },
323         { DOM_ANIMATION_TIMING_FUNCTION_SPRING, SpringCurveCreator },
324         { DOM_ANIMATION_TIMING_FUNCTION_SPRING_MOTION, SpringMotionCreator },
325         { DOM_ANIMATION_TIMING_FUNCTION_STEPS, StepsCurveCreator },
326     };
327     int64_t index = BinarySearchFindIndex(customCurveMap, ArraySize(customCurveMap), aniTimFuncName.c_str());
328     if (index < 0) {
329         return nullptr;
330     }
331     return customCurveMap[index].value(paramsVector);
332 }
333 
CreateCustomCurveExceptSpring(const std::string & aniTimFunc)334 RefPtr<Curve> CreateCustomCurveExceptSpring(const std::string& aniTimFunc)
335 {
336     std::string aniTimFuncName;
337     std::vector<std::string> paramsVector;
338     bool result = ParseCurveParam(aniTimFunc, aniTimFuncName, paramsVector);
339     if (!result) {
340         return nullptr;
341     }
342     static const LinearMapNode<CustomCurveCreator> customCurveExceptSpringMap[] = {
343         { DOM_ANIMATION_TIMING_FUNCTION_CUBIC_BEZIER, CubicCurveCreator },
344         { DOM_ANIMATION_TIMING_FUNCTION_SPRING, SpringCurveCreator },
345         { DOM_ANIMATION_TIMING_FUNCTION_STEPS, StepsCurveCreator },
346     };
347     int64_t index = BinarySearchFindIndex(
348         customCurveExceptSpringMap, ArraySize(customCurveExceptSpringMap), aniTimFuncName.c_str());
349     if (index < 0) {
350         return nullptr;
351     }
352     return customCurveExceptSpringMap[index].value(paramsVector);
353 }
354 
CreateCurve(const std::function<float (float)> & jsFunc)355 RefPtr<Curve> CreateCurve(const std::function<float(float)>& jsFunc)
356 {
357     if (jsFunc) {
358         return AceType::MakeRefPtr<CustomCurve>(jsFunc);
359     }
360     return Curves::EASE_IN_OUT;
361 }
362 
CreateCurve(const std::string & aniTimFunc,bool useDefault)363 RefPtr<Curve> CreateCurve(const std::string& aniTimFunc, bool useDefault)
364 {
365     auto curve = CreateBuiltinCurve(aniTimFunc);
366     if (curve) {
367         return curve;
368     }
369     curve = CreateCustomCurve(aniTimFunc);
370     if (curve) {
371         return curve;
372     }
373     return useDefault? Curves::EASE_IN_OUT : nullptr;
374 }
375 
CreateCurve(int curveType,bool useDefault)376 RefPtr<Curve> CreateCurve(int curveType, bool useDefault)
377 {
378     static const LinearEnumMapNode<int, RefPtr<Curve>> curveMap[] = {
379         { static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_LINEAR), Curves::LINEAR },
380         { static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_EASE), Curves::EASE },
381         { static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_EASE_IN), Curves::EASE_IN },
382         { static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_EASE_OUT), Curves::EASE_OUT },
383         { static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_EASE_IN_OUT), Curves::EASE_IN_OUT },
384         { static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_FAST_OUT_SLOW_IN), Curves::FAST_OUT_SLOW_IN },
385         { static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_LINEAR_OUT_SLOW_IN), Curves::LINEAR_OUT_SLOW_IN },
386         { static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_FAST_OUT_LINEAR_IN), Curves::FAST_OUT_LINEAR_IN },
387         { static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_EXTREME_DECELERATION), Curves::EXTREME_DECELERATION },
388         { static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_RHYTHM), Curves::RHYTHM },
389         { static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_SHARP), Curves::SHARP },
390         { static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_SMOOTH), Curves::SMOOTH },
391         { static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_FRICTION), Curves::FRICTION },
392     };
393     auto index = BinarySearchFindIndex(curveMap, ArraySize(curveMap), curveType);
394     RefPtr<Curve> defaultCurve = useDefault? Curves::EASE_IN_OUT : nullptr;
395     return index < 0 ? defaultCurve : curveMap[index].value;
396 }
397 
398 // create curve whose duration works. i.e not support spring
CreateCurveExceptSpring(const std::string & aniTimFunc,const std::function<float (float)> & jsFunc)399 RefPtr<Curve> CreateCurveExceptSpring(
400     const std::string& aniTimFunc, const std::function<float(float)>& jsFunc)
401 {
402     if (jsFunc) {
403         return AceType::MakeRefPtr<CustomCurve>(jsFunc);
404     }
405     auto curve = CreateBuiltinCurve(aniTimFunc);
406     if (curve) {
407         return curve;
408     }
409     curve = CreateCustomCurveExceptSpring(aniTimFunc);
410     if (curve) {
411         return curve;
412     }
413     return Curves::EASE_IN_OUT;
414 }
415 
416 // used for declarative only
ParseTransitionType(const std::string & transitionType)417 TransitionType ParseTransitionType(const std::string& transitionType)
418 {
419     if (transitionType == "All") {
420         return TransitionType::ALL;
421     } else if (transitionType == "Insert") {
422         return TransitionType::APPEARING;
423     } else if (transitionType == "Delete") {
424         return TransitionType::DISAPPEARING;
425     } else {
426         return TransitionType::ALL;
427     }
428 }
429 #ifndef FUZZTEST
430 // Support keyword values / percentage/px values. Do not support multiple images and edge offsets values.
ParseBackgroundImagePosition(const std::string & value,BackgroundImagePosition & backgroundImagePosition)431 bool ParseBackgroundImagePosition(const std::string& value, BackgroundImagePosition& backgroundImagePosition)
432 {
433     static const LinearMapNode<void (*)(BackgroundImagePosition&)> backGroundPositionOperators[] = {
434         { DOM_BACKGROUND_IMAGE_POSITION_BOTTOM,
435             [](BackgroundImagePosition& backgroundImagePosition) {
436                 SetBgImgPositionY(BackgroundImagePositionType::PERCENT, 100.0, backgroundImagePosition);
437             } },
438         { DOM_BACKGROUND_IMAGE_POSITION_LEFT,
439             [](BackgroundImagePosition& backgroundImagePosition) {
440                 SetBgImgPositionX(BackgroundImagePositionType::PERCENT, 0.0, backgroundImagePosition);
441             } },
442         { DOM_BACKGROUND_IMAGE_POSITION_RIGHT,
443             [](BackgroundImagePosition& backgroundImagePosition) {
444                 SetBgImgPositionX(BackgroundImagePositionType::PERCENT, 100.0, backgroundImagePosition);
445             } },
446         { DOM_BACKGROUND_IMAGE_POSITION_TOP,
447             [](BackgroundImagePosition& backgroundImagePosition) {
448                 SetBgImgPositionY(BackgroundImagePositionType::PERCENT, 0.0, backgroundImagePosition);
449             } },
450     };
451 
452     std::vector<std::string> offsets;
453     StringUtils::StringSplitter(value, ' ', offsets);
454     if (!offsets.empty()) {
455         std::string valueX = "";
456         std::string valueY = "";
457         GetOffsetValue(offsets, valueX, valueY);
458         if (!BgImgPositionIsValid(valueX, valueY)) {
459             return false;
460         }
461         // The input is valid,so set the default is (center,center),
462         // if the value is different, the default value is overwritten.
463         // the center value is 50%.
464         SetBgImgPosition(BackgroundImagePositionType::PERCENT, 50.0, backgroundImagePosition);
465         if (valueX.find("px") != std::string::npos) {
466             SetBgImgPositionX(BackgroundImagePositionType::PX, StringToDouble(valueX), backgroundImagePosition);
467         } else if (valueX.find('%') != std::string::npos) {
468             SetBgImgPositionX(BackgroundImagePositionType::PERCENT, StringToDouble(valueX), backgroundImagePosition);
469         } else {
470             auto operatorIterX = BinarySearchFindIndex(
471                 backGroundPositionOperators, ArraySize(backGroundPositionOperators), valueX.c_str());
472             if (operatorIterX != -1) {
473                 backGroundPositionOperators[operatorIterX].value(backgroundImagePosition);
474             }
475         }
476         if (valueY.find("px") != std::string::npos) {
477             SetBgImgPositionY(BackgroundImagePositionType::PX, StringToDouble(valueY), backgroundImagePosition);
478         } else if (valueY.find('%') != std::string::npos) {
479             SetBgImgPositionY(BackgroundImagePositionType::PERCENT, StringToDouble(valueY), backgroundImagePosition);
480         } else {
481             auto operatorIterY = BinarySearchFindIndex(
482                 backGroundPositionOperators, ArraySize(backGroundPositionOperators), valueY.c_str());
483             if (operatorIterY != -1) {
484                 backGroundPositionOperators[operatorIterY].value(backgroundImagePosition);
485             }
486         }
487     } else {
488         SetBgImgPosition(BackgroundImagePositionType::PERCENT, 50.0, backgroundImagePosition);
489         if (value.find("px") != std::string::npos) {
490             SetBgImgPositionX(BackgroundImagePositionType::PX, StringToDouble(value), backgroundImagePosition);
491         } else if (value.find('%') != std::string::npos) {
492             SetBgImgPositionX(BackgroundImagePositionType::PERCENT, StringToDouble(value), backgroundImagePosition);
493         } else {
494             auto operatorIter = BinarySearchFindIndex(
495                 backGroundPositionOperators, ArraySize(backGroundPositionOperators), value.c_str());
496             if (operatorIter != -1) {
497                 backGroundPositionOperators[operatorIter].value(backgroundImagePosition);
498             }
499         }
500     }
501     return true;
502 }
503 
ParseBackgroundImageSize(const std::string & value,BackgroundImageSize & bgImgSize)504 bool ParseBackgroundImageSize(const std::string& value, BackgroundImageSize& bgImgSize)
505 {
506     static const LinearMapNode<BackgroundImageSizeType> bgImageSizeType[] = {
507         { DOM_BACKGROUND_IMAGE_SIZE_AUTO, BackgroundImageSizeType::AUTO },
508         { DOM_BACKGROUND_IMAGE_SIZE_CONTAIN, BackgroundImageSizeType::CONTAIN },
509         { DOM_BACKGROUND_IMAGE_SIZE_COVER, BackgroundImageSizeType::COVER },
510         { DOM_BACKGROUND_IMAGE_SIZE_FILL, BackgroundImageSizeType::FILL },
511     };
512     auto spaceIndex = value.find(' ', 0);
513     if (spaceIndex != std::string::npos) {
514         std::string valueX = value.substr(0, spaceIndex);
515         std::string valueY = value.substr(spaceIndex + 1, value.size() - spaceIndex - 1);
516         if (valueX.find("px") != std::string::npos) {
517             SetBgImgSizeX(BackgroundImageSizeType::LENGTH, StringToDouble(valueX), bgImgSize);
518         } else if (valueX.find('%') != std::string::npos) {
519             SetBgImgSizeX(BackgroundImageSizeType::PERCENT, StringToDouble(valueX), bgImgSize);
520         } else {
521             bgImgSize.SetSizeTypeX(BackgroundImageSizeType::AUTO);
522         }
523         if (valueY.find("px") != std::string::npos) {
524             SetBgImgSizeY(BackgroundImageSizeType::LENGTH, StringToDouble(valueY), bgImgSize);
525         } else if (valueY.find('%') != std::string::npos) {
526             SetBgImgSizeY(BackgroundImageSizeType::PERCENT, StringToDouble(valueY), bgImgSize);
527         } else {
528             bgImgSize.SetSizeTypeY(BackgroundImageSizeType::AUTO);
529         }
530     } else {
531         auto sizeTypeIter = BinarySearchFindIndex(bgImageSizeType, ArraySize(bgImageSizeType), value.c_str());
532         if (sizeTypeIter != -1) {
533             bgImgSize.SetSizeTypeX(bgImageSizeType[sizeTypeIter].value);
534             bgImgSize.SetSizeTypeY(bgImageSizeType[sizeTypeIter].value);
535         } else if (value.find("px") != std::string::npos) {
536             SetBgImgSizeX(BackgroundImageSizeType::LENGTH, StringToDouble(value), bgImgSize);
537             bgImgSize.SetSizeTypeY(BackgroundImageSizeType::AUTO);
538         } else if (value.find('%') != std::string::npos) {
539             SetBgImgSizeX(BackgroundImageSizeType::PERCENT, StringToDouble(value), bgImgSize);
540             bgImgSize.SetSizeTypeY(BackgroundImageSizeType::AUTO);
541         } else {
542             bgImgSize.SetSizeTypeX(BackgroundImageSizeType::AUTO);
543             bgImgSize.SetSizeTypeY(BackgroundImageSizeType::AUTO);
544         }
545     }
546     return true;
547 }
548 #endif
CreateClipPath(const std::string & value)549 RefPtr<ClipPath> CreateClipPath(const std::string& value)
550 {
551     if (value.empty()) {
552         return nullptr;
553     }
554     auto clipPath = ClipPath::CreateShape(value);
555     GeometryBoxType geometryBoxType = ClipPath::GetGeometryBoxType(value);
556     if (geometryBoxType != GeometryBoxType::NONE) {
557         if (!clipPath) {
558             clipPath = AceType::MakeRefPtr<ClipPath>();
559         }
560     }
561     if (clipPath) {
562         clipPath->SetGeometryBoxType(geometryBoxType);
563     }
564     return clipPath;
565 }
566 
ParseRadialGradientSize(const std::string & value)567 std::optional<RadialSizeType> ParseRadialGradientSize(const std::string& value)
568 {
569     const static std::unordered_map<std::string, RadialSizeType> sizeTypes = {
570         { DOM_GRADIENT_SIZE_CLOSEST_CORNER, RadialSizeType::CLOSEST_CORNER },
571         { DOM_GRADIENT_SIZE_CLOSEST_SIDE, RadialSizeType::CLOSEST_SIDE },
572         { DOM_GRADIENT_SIZE_FARTHEST_CORNER, RadialSizeType::FARTHEST_CORNER },
573         { DOM_GRADIENT_SIZE_FARTHEST_SIDE, RadialSizeType::FARTHEST_SIDE },
574     };
575     if (!value.empty()) {
576         auto pos = sizeTypes.find(value);
577         if (pos != sizeTypes.end()) {
578             return std::make_optional(pos->second);
579         }
580     }
581     return std::nullopt;
582 }
583 #ifndef FUZZTEST
584 // ObjectPosition
ParseImageObjectPosition(const std::string & value)585 ImageObjectPosition ParseImageObjectPosition(const std::string& value)
586 {
587     ImageObjectPosition imageObjectPosition;
588     static const LinearMapNode<void (*)(ImageObjectPosition&)> backGroundPositionOperators[] = {
589         { DOM_IMAGE_POSITION_BOTTOM,
590             [](ImageObjectPosition& imageObjectPosition) {
591                 SetBgImgPositionY(BackgroundImagePositionType::PERCENT, 100.0, imageObjectPosition);
592             } },
593         { DOM_IMAGE_POSITION_LEFT,
594             [](ImageObjectPosition& imageObjectPosition) {
595                 SetBgImgPositionX(BackgroundImagePositionType::PERCENT, 0.0, imageObjectPosition);
596             } },
597         { DOM_IMAGE_POSITION_RIGHT,
598             [](ImageObjectPosition& imageObjectPosition) {
599                 SetBgImgPositionX(BackgroundImagePositionType::PERCENT, 100.0, imageObjectPosition);
600             } },
601         { DOM_IMAGE_POSITION_TOP,
602             [](ImageObjectPosition& imageObjectPosition) {
603                 SetBgImgPositionY(BackgroundImagePositionType::PERCENT, 0.0, imageObjectPosition);
604             } },
605     };
606 
607     std::vector<std::string> offsets;
608     StringUtils::StringSplitter(value, ' ', offsets);
609     if (!offsets.empty()) {
610         std::string valueX = "";
611         std::string valueY = "";
612         GetOffsetValueObjectPosition(offsets, valueX, valueY);
613         SetBgImgPosition(BackgroundImagePositionType::PERCENT, 50.0, imageObjectPosition);
614         if (ObjectImgPositionIsValid(valueX, valueY)) {
615             if (valueX.find("px") != std::string::npos) {
616                 SetBgImgPositionX(BackgroundImagePositionType::PX, StringToDouble(valueX), imageObjectPosition);
617             } else if (valueX.find('%') != std::string::npos) {
618                 SetBgImgPositionX(BackgroundImagePositionType::PERCENT, StringToDouble(valueX), imageObjectPosition);
619             } else {
620                 auto operatorIterX = BinarySearchFindIndex(
621                     backGroundPositionOperators, ArraySize(backGroundPositionOperators), valueX.c_str());
622                 if (operatorIterX != -1) {
623                     backGroundPositionOperators[operatorIterX].value(imageObjectPosition);
624                 }
625             }
626             if (valueY.find("px") != std::string::npos) {
627                 SetBgImgPositionY(BackgroundImagePositionType::PX, StringToDouble(valueY), imageObjectPosition);
628             } else if (valueY.find('%') != std::string::npos) {
629                 SetBgImgPositionY(BackgroundImagePositionType::PERCENT, StringToDouble(valueY), imageObjectPosition);
630             } else {
631                 auto operatorIterY = BinarySearchFindIndex(
632                     backGroundPositionOperators, ArraySize(backGroundPositionOperators), valueY.c_str());
633                 if (operatorIterY != -1) {
634                     backGroundPositionOperators[operatorIterY].value(imageObjectPosition);
635                 }
636             }
637         }
638     }
639 
640     return imageObjectPosition;
641 }
642 #endif
643 
644 } // namespace OHOS::Ace::Framework