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