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