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 
376 // create curve whose duration works. i.e not support spring
CreateCurveExceptSpring(const std::string & aniTimFunc,const std::function<float (float)> & jsFunc)377 RefPtr<Curve> CreateCurveExceptSpring(
378     const std::string& aniTimFunc, const std::function<float(float)>& jsFunc)
379 {
380     if (jsFunc) {
381         return AceType::MakeRefPtr<CustomCurve>(jsFunc);
382     }
383     auto curve = CreateBuiltinCurve(aniTimFunc);
384     if (curve) {
385         return curve;
386     }
387     curve = CreateCustomCurveExceptSpring(aniTimFunc);
388     if (curve) {
389         return curve;
390     }
391     return Curves::EASE_IN_OUT;
392 }
393 
394 // used for declarative only
ParseTransitionType(const std::string & transitionType)395 TransitionType ParseTransitionType(const std::string& transitionType)
396 {
397     if (transitionType == "All") {
398         return TransitionType::ALL;
399     } else if (transitionType == "Insert") {
400         return TransitionType::APPEARING;
401     } else if (transitionType == "Delete") {
402         return TransitionType::DISAPPEARING;
403     } else {
404         return TransitionType::ALL;
405     }
406 }
407 #ifndef FUZZTEST
408 // Support keyword values / percentage/px values. Do not support multiple images and edge offsets values.
ParseBackgroundImagePosition(const std::string & value,BackgroundImagePosition & backgroundImagePosition)409 bool ParseBackgroundImagePosition(const std::string& value, BackgroundImagePosition& backgroundImagePosition)
410 {
411     static const LinearMapNode<void (*)(BackgroundImagePosition&)> backGroundPositionOperators[] = {
412         { DOM_BACKGROUND_IMAGE_POSITION_BOTTOM,
413             [](BackgroundImagePosition& backgroundImagePosition) {
414                 SetBgImgPositionY(BackgroundImagePositionType::PERCENT, 100.0, backgroundImagePosition);
415             } },
416         { DOM_BACKGROUND_IMAGE_POSITION_LEFT,
417             [](BackgroundImagePosition& backgroundImagePosition) {
418                 SetBgImgPositionX(BackgroundImagePositionType::PERCENT, 0.0, backgroundImagePosition);
419             } },
420         { DOM_BACKGROUND_IMAGE_POSITION_RIGHT,
421             [](BackgroundImagePosition& backgroundImagePosition) {
422                 SetBgImgPositionX(BackgroundImagePositionType::PERCENT, 100.0, backgroundImagePosition);
423             } },
424         { DOM_BACKGROUND_IMAGE_POSITION_TOP,
425             [](BackgroundImagePosition& backgroundImagePosition) {
426                 SetBgImgPositionY(BackgroundImagePositionType::PERCENT, 0.0, backgroundImagePosition);
427             } },
428     };
429 
430     std::vector<std::string> offsets;
431     StringUtils::StringSplitter(value, ' ', offsets);
432     if (!offsets.empty()) {
433         std::string valueX = "";
434         std::string valueY = "";
435         GetOffsetValue(offsets, valueX, valueY);
436         if (!BgImgPositionIsValid(valueX, valueY)) {
437             return false;
438         }
439         // The input is valid,so set the default is (center,center),
440         // if the value is different, the default value is overwritten.
441         // the center value is 50%.
442         SetBgImgPosition(BackgroundImagePositionType::PERCENT, 50.0, backgroundImagePosition);
443         if (valueX.find("px") != std::string::npos) {
444             SetBgImgPositionX(BackgroundImagePositionType::PX, StringToDouble(valueX), backgroundImagePosition);
445         } else if (valueX.find('%') != std::string::npos) {
446             SetBgImgPositionX(BackgroundImagePositionType::PERCENT, StringToDouble(valueX), backgroundImagePosition);
447         } else {
448             auto operatorIterX = BinarySearchFindIndex(
449                 backGroundPositionOperators, ArraySize(backGroundPositionOperators), valueX.c_str());
450             if (operatorIterX != -1) {
451                 backGroundPositionOperators[operatorIterX].value(backgroundImagePosition);
452             }
453         }
454         if (valueY.find("px") != std::string::npos) {
455             SetBgImgPositionY(BackgroundImagePositionType::PX, StringToDouble(valueY), backgroundImagePosition);
456         } else if (valueY.find('%') != std::string::npos) {
457             SetBgImgPositionY(BackgroundImagePositionType::PERCENT, StringToDouble(valueY), backgroundImagePosition);
458         } else {
459             auto operatorIterY = BinarySearchFindIndex(
460                 backGroundPositionOperators, ArraySize(backGroundPositionOperators), valueY.c_str());
461             if (operatorIterY != -1) {
462                 backGroundPositionOperators[operatorIterY].value(backgroundImagePosition);
463             }
464         }
465     } else {
466         SetBgImgPosition(BackgroundImagePositionType::PERCENT, 50.0, backgroundImagePosition);
467         if (value.find("px") != std::string::npos) {
468             SetBgImgPositionX(BackgroundImagePositionType::PX, StringToDouble(value), backgroundImagePosition);
469         } else if (value.find('%') != std::string::npos) {
470             SetBgImgPositionX(BackgroundImagePositionType::PERCENT, StringToDouble(value), backgroundImagePosition);
471         } else {
472             auto operatorIter = BinarySearchFindIndex(
473                 backGroundPositionOperators, ArraySize(backGroundPositionOperators), value.c_str());
474             if (operatorIter != -1) {
475                 backGroundPositionOperators[operatorIter].value(backgroundImagePosition);
476             }
477         }
478     }
479     return true;
480 }
481 
ParseBackgroundImageSize(const std::string & value,BackgroundImageSize & bgImgSize)482 bool ParseBackgroundImageSize(const std::string& value, BackgroundImageSize& bgImgSize)
483 {
484     static const LinearMapNode<BackgroundImageSizeType> bgImageSizeType[] = {
485         { DOM_BACKGROUND_IMAGE_SIZE_AUTO, BackgroundImageSizeType::AUTO },
486         { DOM_BACKGROUND_IMAGE_SIZE_CONTAIN, BackgroundImageSizeType::CONTAIN },
487         { DOM_BACKGROUND_IMAGE_SIZE_COVER, BackgroundImageSizeType::COVER },
488         { DOM_BACKGROUND_IMAGE_SIZE_FILL, BackgroundImageSizeType::FILL },
489     };
490     auto spaceIndex = value.find(' ', 0);
491     if (spaceIndex != std::string::npos) {
492         std::string valueX = value.substr(0, spaceIndex);
493         std::string valueY = value.substr(spaceIndex + 1, value.size() - spaceIndex - 1);
494         if (valueX.find("px") != std::string::npos) {
495             SetBgImgSizeX(BackgroundImageSizeType::LENGTH, StringToDouble(valueX), bgImgSize);
496         } else if (valueX.find('%') != std::string::npos) {
497             SetBgImgSizeX(BackgroundImageSizeType::PERCENT, StringToDouble(valueX), bgImgSize);
498         } else {
499             bgImgSize.SetSizeTypeX(BackgroundImageSizeType::AUTO);
500         }
501         if (valueY.find("px") != std::string::npos) {
502             SetBgImgSizeY(BackgroundImageSizeType::LENGTH, StringToDouble(valueY), bgImgSize);
503         } else if (valueY.find('%') != std::string::npos) {
504             SetBgImgSizeY(BackgroundImageSizeType::PERCENT, StringToDouble(valueY), bgImgSize);
505         } else {
506             bgImgSize.SetSizeTypeY(BackgroundImageSizeType::AUTO);
507         }
508     } else {
509         auto sizeTypeIter = BinarySearchFindIndex(bgImageSizeType, ArraySize(bgImageSizeType), value.c_str());
510         if (sizeTypeIter != -1) {
511             bgImgSize.SetSizeTypeX(bgImageSizeType[sizeTypeIter].value);
512             bgImgSize.SetSizeTypeY(bgImageSizeType[sizeTypeIter].value);
513         } else if (value.find("px") != std::string::npos) {
514             SetBgImgSizeX(BackgroundImageSizeType::LENGTH, StringToDouble(value), bgImgSize);
515             bgImgSize.SetSizeTypeY(BackgroundImageSizeType::AUTO);
516         } else if (value.find('%') != std::string::npos) {
517             SetBgImgSizeX(BackgroundImageSizeType::PERCENT, StringToDouble(value), bgImgSize);
518             bgImgSize.SetSizeTypeY(BackgroundImageSizeType::AUTO);
519         } else {
520             bgImgSize.SetSizeTypeX(BackgroundImageSizeType::AUTO);
521             bgImgSize.SetSizeTypeY(BackgroundImageSizeType::AUTO);
522         }
523     }
524     return true;
525 }
526 #endif
CreateClipPath(const std::string & value)527 RefPtr<ClipPath> CreateClipPath(const std::string& value)
528 {
529     if (value.empty()) {
530         return nullptr;
531     }
532     auto clipPath = ClipPath::CreateShape(value);
533     GeometryBoxType geometryBoxType = ClipPath::GetGeometryBoxType(value);
534     if (geometryBoxType != GeometryBoxType::NONE) {
535         if (!clipPath) {
536             clipPath = AceType::MakeRefPtr<ClipPath>();
537         }
538     }
539     if (clipPath) {
540         clipPath->SetGeometryBoxType(geometryBoxType);
541     }
542     return clipPath;
543 }
544 
ParseRadialGradientSize(const std::string & value)545 std::optional<RadialSizeType> ParseRadialGradientSize(const std::string& value)
546 {
547     const static std::unordered_map<std::string, RadialSizeType> sizeTypes = {
548         { DOM_GRADIENT_SIZE_CLOSEST_CORNER, RadialSizeType::CLOSEST_CORNER },
549         { DOM_GRADIENT_SIZE_CLOSEST_SIDE, RadialSizeType::CLOSEST_SIDE },
550         { DOM_GRADIENT_SIZE_FARTHEST_CORNER, RadialSizeType::FARTHEST_CORNER },
551         { DOM_GRADIENT_SIZE_FARTHEST_SIDE, RadialSizeType::FARTHEST_SIDE },
552     };
553     if (!value.empty()) {
554         auto pos = sizeTypes.find(value);
555         if (pos != sizeTypes.end()) {
556             return std::make_optional(pos->second);
557         }
558     }
559     return std::nullopt;
560 }
561 #ifndef FUZZTEST
562 // ObjectPosition
ParseImageObjectPosition(const std::string & value)563 ImageObjectPosition ParseImageObjectPosition(const std::string& value)
564 {
565     ImageObjectPosition imageObjectPosition;
566     static const LinearMapNode<void (*)(ImageObjectPosition&)> backGroundPositionOperators[] = {
567         { DOM_IMAGE_POSITION_BOTTOM,
568             [](ImageObjectPosition& imageObjectPosition) {
569                 SetBgImgPositionY(BackgroundImagePositionType::PERCENT, 100.0, imageObjectPosition);
570             } },
571         { DOM_IMAGE_POSITION_LEFT,
572             [](ImageObjectPosition& imageObjectPosition) {
573                 SetBgImgPositionX(BackgroundImagePositionType::PERCENT, 0.0, imageObjectPosition);
574             } },
575         { DOM_IMAGE_POSITION_RIGHT,
576             [](ImageObjectPosition& imageObjectPosition) {
577                 SetBgImgPositionX(BackgroundImagePositionType::PERCENT, 100.0, imageObjectPosition);
578             } },
579         { DOM_IMAGE_POSITION_TOP,
580             [](ImageObjectPosition& imageObjectPosition) {
581                 SetBgImgPositionY(BackgroundImagePositionType::PERCENT, 0.0, imageObjectPosition);
582             } },
583     };
584 
585     std::vector<std::string> offsets;
586     StringUtils::StringSplitter(value, ' ', offsets);
587     if (!offsets.empty()) {
588         std::string valueX = "";
589         std::string valueY = "";
590         GetOffsetValueObjectPosition(offsets, valueX, valueY);
591         SetBgImgPosition(BackgroundImagePositionType::PERCENT, 50.0, imageObjectPosition);
592         if (ObjectImgPositionIsValid(valueX, valueY)) {
593             if (valueX.find("px") != std::string::npos) {
594                 SetBgImgPositionX(BackgroundImagePositionType::PX, StringToDouble(valueX), imageObjectPosition);
595             } else if (valueX.find('%') != std::string::npos) {
596                 SetBgImgPositionX(BackgroundImagePositionType::PERCENT, StringToDouble(valueX), imageObjectPosition);
597             } else {
598                 auto operatorIterX = BinarySearchFindIndex(
599                     backGroundPositionOperators, ArraySize(backGroundPositionOperators), valueX.c_str());
600                 if (operatorIterX != -1) {
601                     backGroundPositionOperators[operatorIterX].value(imageObjectPosition);
602                 }
603             }
604             if (valueY.find("px") != std::string::npos) {
605                 SetBgImgPositionY(BackgroundImagePositionType::PX, StringToDouble(valueY), imageObjectPosition);
606             } else if (valueY.find('%') != std::string::npos) {
607                 SetBgImgPositionY(BackgroundImagePositionType::PERCENT, StringToDouble(valueY), imageObjectPosition);
608             } else {
609                 auto operatorIterY = BinarySearchFindIndex(
610                     backGroundPositionOperators, ArraySize(backGroundPositionOperators), valueY.c_str());
611                 if (operatorIterY != -1) {
612                     backGroundPositionOperators[operatorIterY].value(imageObjectPosition);
613                 }
614             }
615         }
616     }
617 
618     return imageObjectPosition;
619 }
620 #endif
621 
622 } // namespace OHOS::Ace::Framework