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
21namespace OHOS::Ace::Framework {
22
23namespace {
24
25using CustomCurveCreator = RefPtr<Curve> (*)(const std::vector<std::string>&);
26
27const size_t STEPS_PARAMS_SIZE = 2;
28const size_t CUBIC_PARAMS_SIZE = 4;
29const size_t SPRING_PARAMS_SIZE = 4;
30constexpr size_t RESPONSIVE_SPRING_MOTION_PARAMS_SIZE = 3;
31constexpr size_t INTERPOLATING_SPRING_PARAMS_SIZE = 4;
32
33static const std::unordered_set<std::string> HORIZON_SET = {
34    DOM_BACKGROUND_IMAGE_POSITION_LEFT,
35    DOM_BACKGROUND_IMAGE_POSITION_RIGHT,
36};
37static const std::unordered_set<std::string> VERTICAL_SET = {
38    DOM_BACKGROUND_IMAGE_POSITION_TOP,
39    DOM_BACKGROUND_IMAGE_POSITION_BOTTOM,
40};
41static const std::unordered_set<std::string> OBJECT_HORIZON_SET = {
42    DOM_IMAGE_POSITION_LEFT,
43    DOM_IMAGE_POSITION_RIGHT,
44};
45static const std::unordered_set<std::string> OBJECT_VERTICAL_SET = {
46    DOM_IMAGE_POSITION_TOP,
47    DOM_IMAGE_POSITION_BOTTOM,
48};
49
50RefPtr<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
72RefPtr<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
84RefPtr<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
96RefPtr<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
108RefPtr<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
123RefPtr<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
138void SetBgImgPositionX(
139    const BackgroundImagePositionType type, const double value, BackgroundImagePosition& bgImgPosition)
140{
141    bgImgPosition.SetSizeTypeX(type);
142    bgImgPosition.SetSizeValueX(value);
143}
144
145void SetBgImgPositionY(
146    const BackgroundImagePositionType type, const double value, BackgroundImagePosition& bgImgPosition)
147{
148    bgImgPosition.SetSizeTypeY(type);
149    bgImgPosition.SetSizeValueY(value);
150}
151
152void SetBgImgPosition(
153    const BackgroundImagePositionType type, const double value, BackgroundImagePosition& bgImgPosition)
154{
155    SetBgImgPositionX(type, value, bgImgPosition);
156    SetBgImgPositionY(type, value, bgImgPosition);
157}
158
159void 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
180void 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
201bool 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
219bool 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
231void SetBgImgSizeX(BackgroundImageSizeType type, double value, BackgroundImageSize& bgImgSize)
232{
233    bgImgSize.SetSizeTypeX(type);
234    bgImgSize.SetSizeValueX(value);
235}
236
237void SetBgImgSizeY(BackgroundImageSizeType type, double value, BackgroundImageSize& bgImgSize)
238{
239    bgImgSize.SetSizeTypeY(type);
240    bgImgSize.SetSizeValueY(value);
241}
242#endif
243} // namespace
244
245RefPtr<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
267std::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
288bool 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
311RefPtr<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
334RefPtr<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
355RefPtr<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
363RefPtr<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
377RefPtr<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
395TransitionType 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.
409bool 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
482bool 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
527RefPtr<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
545std::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
563ImageObjectPosition 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