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