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