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