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
CreateCurve(int curveType,bool useDefault)376 RefPtr<Curve> CreateCurve(int curveType, bool useDefault)
377 {
378 static const LinearEnumMapNode<int, RefPtr<Curve>> curveMap[] = {
379 { static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_LINEAR), Curves::LINEAR },
380 { static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_EASE), Curves::EASE },
381 { static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_EASE_IN), Curves::EASE_IN },
382 { static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_EASE_OUT), Curves::EASE_OUT },
383 { static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_EASE_IN_OUT), Curves::EASE_IN_OUT },
384 { static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_FAST_OUT_SLOW_IN), Curves::FAST_OUT_SLOW_IN },
385 { static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_LINEAR_OUT_SLOW_IN), Curves::LINEAR_OUT_SLOW_IN },
386 { static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_FAST_OUT_LINEAR_IN), Curves::FAST_OUT_LINEAR_IN },
387 { static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_EXTREME_DECELERATION), Curves::EXTREME_DECELERATION },
388 { static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_RHYTHM), Curves::RHYTHM },
389 { static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_SHARP), Curves::SHARP },
390 { static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_SMOOTH), Curves::SMOOTH },
391 { static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_FRICTION), Curves::FRICTION },
392 };
393 auto index = BinarySearchFindIndex(curveMap, ArraySize(curveMap), curveType);
394 RefPtr<Curve> defaultCurve = useDefault? Curves::EASE_IN_OUT : nullptr;
395 return index < 0 ? defaultCurve : curveMap[index].value;
396 }
397
398 // create curve whose duration works. i.e not support spring
CreateCurveExceptSpring(const std::string & aniTimFunc,const std::function<float (float)> & jsFunc)399 RefPtr<Curve> CreateCurveExceptSpring(
400 const std::string& aniTimFunc, const std::function<float(float)>& jsFunc)
401 {
402 if (jsFunc) {
403 return AceType::MakeRefPtr<CustomCurve>(jsFunc);
404 }
405 auto curve = CreateBuiltinCurve(aniTimFunc);
406 if (curve) {
407 return curve;
408 }
409 curve = CreateCustomCurveExceptSpring(aniTimFunc);
410 if (curve) {
411 return curve;
412 }
413 return Curves::EASE_IN_OUT;
414 }
415
416 // used for declarative only
ParseTransitionType(const std::string & transitionType)417 TransitionType ParseTransitionType(const std::string& transitionType)
418 {
419 if (transitionType == "All") {
420 return TransitionType::ALL;
421 } else if (transitionType == "Insert") {
422 return TransitionType::APPEARING;
423 } else if (transitionType == "Delete") {
424 return TransitionType::DISAPPEARING;
425 } else {
426 return TransitionType::ALL;
427 }
428 }
429 #ifndef FUZZTEST
430 // Support keyword values / percentage/px values. Do not support multiple images and edge offsets values.
ParseBackgroundImagePosition(const std::string & value,BackgroundImagePosition & backgroundImagePosition)431 bool ParseBackgroundImagePosition(const std::string& value, BackgroundImagePosition& backgroundImagePosition)
432 {
433 static const LinearMapNode<void (*)(BackgroundImagePosition&)> backGroundPositionOperators[] = {
434 { DOM_BACKGROUND_IMAGE_POSITION_BOTTOM,
435 [](BackgroundImagePosition& backgroundImagePosition) {
436 SetBgImgPositionY(BackgroundImagePositionType::PERCENT, 100.0, backgroundImagePosition);
437 } },
438 { DOM_BACKGROUND_IMAGE_POSITION_LEFT,
439 [](BackgroundImagePosition& backgroundImagePosition) {
440 SetBgImgPositionX(BackgroundImagePositionType::PERCENT, 0.0, backgroundImagePosition);
441 } },
442 { DOM_BACKGROUND_IMAGE_POSITION_RIGHT,
443 [](BackgroundImagePosition& backgroundImagePosition) {
444 SetBgImgPositionX(BackgroundImagePositionType::PERCENT, 100.0, backgroundImagePosition);
445 } },
446 { DOM_BACKGROUND_IMAGE_POSITION_TOP,
447 [](BackgroundImagePosition& backgroundImagePosition) {
448 SetBgImgPositionY(BackgroundImagePositionType::PERCENT, 0.0, backgroundImagePosition);
449 } },
450 };
451
452 std::vector<std::string> offsets;
453 StringUtils::StringSplitter(value, ' ', offsets);
454 if (!offsets.empty()) {
455 std::string valueX = "";
456 std::string valueY = "";
457 GetOffsetValue(offsets, valueX, valueY);
458 if (!BgImgPositionIsValid(valueX, valueY)) {
459 return false;
460 }
461 // The input is valid,so set the default is (center,center),
462 // if the value is different, the default value is overwritten.
463 // the center value is 50%.
464 SetBgImgPosition(BackgroundImagePositionType::PERCENT, 50.0, backgroundImagePosition);
465 if (valueX.find("px") != std::string::npos) {
466 SetBgImgPositionX(BackgroundImagePositionType::PX, StringToDouble(valueX), backgroundImagePosition);
467 } else if (valueX.find('%') != std::string::npos) {
468 SetBgImgPositionX(BackgroundImagePositionType::PERCENT, StringToDouble(valueX), backgroundImagePosition);
469 } else {
470 auto operatorIterX = BinarySearchFindIndex(
471 backGroundPositionOperators, ArraySize(backGroundPositionOperators), valueX.c_str());
472 if (operatorIterX != -1) {
473 backGroundPositionOperators[operatorIterX].value(backgroundImagePosition);
474 }
475 }
476 if (valueY.find("px") != std::string::npos) {
477 SetBgImgPositionY(BackgroundImagePositionType::PX, StringToDouble(valueY), backgroundImagePosition);
478 } else if (valueY.find('%') != std::string::npos) {
479 SetBgImgPositionY(BackgroundImagePositionType::PERCENT, StringToDouble(valueY), backgroundImagePosition);
480 } else {
481 auto operatorIterY = BinarySearchFindIndex(
482 backGroundPositionOperators, ArraySize(backGroundPositionOperators), valueY.c_str());
483 if (operatorIterY != -1) {
484 backGroundPositionOperators[operatorIterY].value(backgroundImagePosition);
485 }
486 }
487 } else {
488 SetBgImgPosition(BackgroundImagePositionType::PERCENT, 50.0, backgroundImagePosition);
489 if (value.find("px") != std::string::npos) {
490 SetBgImgPositionX(BackgroundImagePositionType::PX, StringToDouble(value), backgroundImagePosition);
491 } else if (value.find('%') != std::string::npos) {
492 SetBgImgPositionX(BackgroundImagePositionType::PERCENT, StringToDouble(value), backgroundImagePosition);
493 } else {
494 auto operatorIter = BinarySearchFindIndex(
495 backGroundPositionOperators, ArraySize(backGroundPositionOperators), value.c_str());
496 if (operatorIter != -1) {
497 backGroundPositionOperators[operatorIter].value(backgroundImagePosition);
498 }
499 }
500 }
501 return true;
502 }
503
ParseBackgroundImageSize(const std::string & value,BackgroundImageSize & bgImgSize)504 bool ParseBackgroundImageSize(const std::string& value, BackgroundImageSize& bgImgSize)
505 {
506 static const LinearMapNode<BackgroundImageSizeType> bgImageSizeType[] = {
507 { DOM_BACKGROUND_IMAGE_SIZE_AUTO, BackgroundImageSizeType::AUTO },
508 { DOM_BACKGROUND_IMAGE_SIZE_CONTAIN, BackgroundImageSizeType::CONTAIN },
509 { DOM_BACKGROUND_IMAGE_SIZE_COVER, BackgroundImageSizeType::COVER },
510 { DOM_BACKGROUND_IMAGE_SIZE_FILL, BackgroundImageSizeType::FILL },
511 };
512 auto spaceIndex = value.find(' ', 0);
513 if (spaceIndex != std::string::npos) {
514 std::string valueX = value.substr(0, spaceIndex);
515 std::string valueY = value.substr(spaceIndex + 1, value.size() - spaceIndex - 1);
516 if (valueX.find("px") != std::string::npos) {
517 SetBgImgSizeX(BackgroundImageSizeType::LENGTH, StringToDouble(valueX), bgImgSize);
518 } else if (valueX.find('%') != std::string::npos) {
519 SetBgImgSizeX(BackgroundImageSizeType::PERCENT, StringToDouble(valueX), bgImgSize);
520 } else {
521 bgImgSize.SetSizeTypeX(BackgroundImageSizeType::AUTO);
522 }
523 if (valueY.find("px") != std::string::npos) {
524 SetBgImgSizeY(BackgroundImageSizeType::LENGTH, StringToDouble(valueY), bgImgSize);
525 } else if (valueY.find('%') != std::string::npos) {
526 SetBgImgSizeY(BackgroundImageSizeType::PERCENT, StringToDouble(valueY), bgImgSize);
527 } else {
528 bgImgSize.SetSizeTypeY(BackgroundImageSizeType::AUTO);
529 }
530 } else {
531 auto sizeTypeIter = BinarySearchFindIndex(bgImageSizeType, ArraySize(bgImageSizeType), value.c_str());
532 if (sizeTypeIter != -1) {
533 bgImgSize.SetSizeTypeX(bgImageSizeType[sizeTypeIter].value);
534 bgImgSize.SetSizeTypeY(bgImageSizeType[sizeTypeIter].value);
535 } else if (value.find("px") != std::string::npos) {
536 SetBgImgSizeX(BackgroundImageSizeType::LENGTH, StringToDouble(value), bgImgSize);
537 bgImgSize.SetSizeTypeY(BackgroundImageSizeType::AUTO);
538 } else if (value.find('%') != std::string::npos) {
539 SetBgImgSizeX(BackgroundImageSizeType::PERCENT, StringToDouble(value), bgImgSize);
540 bgImgSize.SetSizeTypeY(BackgroundImageSizeType::AUTO);
541 } else {
542 bgImgSize.SetSizeTypeX(BackgroundImageSizeType::AUTO);
543 bgImgSize.SetSizeTypeY(BackgroundImageSizeType::AUTO);
544 }
545 }
546 return true;
547 }
548 #endif
CreateClipPath(const std::string & value)549 RefPtr<ClipPath> CreateClipPath(const std::string& value)
550 {
551 if (value.empty()) {
552 return nullptr;
553 }
554 auto clipPath = ClipPath::CreateShape(value);
555 GeometryBoxType geometryBoxType = ClipPath::GetGeometryBoxType(value);
556 if (geometryBoxType != GeometryBoxType::NONE) {
557 if (!clipPath) {
558 clipPath = AceType::MakeRefPtr<ClipPath>();
559 }
560 }
561 if (clipPath) {
562 clipPath->SetGeometryBoxType(geometryBoxType);
563 }
564 return clipPath;
565 }
566
ParseRadialGradientSize(const std::string & value)567 std::optional<RadialSizeType> ParseRadialGradientSize(const std::string& value)
568 {
569 const static std::unordered_map<std::string, RadialSizeType> sizeTypes = {
570 { DOM_GRADIENT_SIZE_CLOSEST_CORNER, RadialSizeType::CLOSEST_CORNER },
571 { DOM_GRADIENT_SIZE_CLOSEST_SIDE, RadialSizeType::CLOSEST_SIDE },
572 { DOM_GRADIENT_SIZE_FARTHEST_CORNER, RadialSizeType::FARTHEST_CORNER },
573 { DOM_GRADIENT_SIZE_FARTHEST_SIDE, RadialSizeType::FARTHEST_SIDE },
574 };
575 if (!value.empty()) {
576 auto pos = sizeTypes.find(value);
577 if (pos != sizeTypes.end()) {
578 return std::make_optional(pos->second);
579 }
580 }
581 return std::nullopt;
582 }
583 #ifndef FUZZTEST
584 // ObjectPosition
ParseImageObjectPosition(const std::string & value)585 ImageObjectPosition ParseImageObjectPosition(const std::string& value)
586 {
587 ImageObjectPosition imageObjectPosition;
588 static const LinearMapNode<void (*)(ImageObjectPosition&)> backGroundPositionOperators[] = {
589 { DOM_IMAGE_POSITION_BOTTOM,
590 [](ImageObjectPosition& imageObjectPosition) {
591 SetBgImgPositionY(BackgroundImagePositionType::PERCENT, 100.0, imageObjectPosition);
592 } },
593 { DOM_IMAGE_POSITION_LEFT,
594 [](ImageObjectPosition& imageObjectPosition) {
595 SetBgImgPositionX(BackgroundImagePositionType::PERCENT, 0.0, imageObjectPosition);
596 } },
597 { DOM_IMAGE_POSITION_RIGHT,
598 [](ImageObjectPosition& imageObjectPosition) {
599 SetBgImgPositionX(BackgroundImagePositionType::PERCENT, 100.0, imageObjectPosition);
600 } },
601 { DOM_IMAGE_POSITION_TOP,
602 [](ImageObjectPosition& imageObjectPosition) {
603 SetBgImgPositionY(BackgroundImagePositionType::PERCENT, 0.0, imageObjectPosition);
604 } },
605 };
606
607 std::vector<std::string> offsets;
608 StringUtils::StringSplitter(value, ' ', offsets);
609 if (!offsets.empty()) {
610 std::string valueX = "";
611 std::string valueY = "";
612 GetOffsetValueObjectPosition(offsets, valueX, valueY);
613 SetBgImgPosition(BackgroundImagePositionType::PERCENT, 50.0, imageObjectPosition);
614 if (ObjectImgPositionIsValid(valueX, valueY)) {
615 if (valueX.find("px") != std::string::npos) {
616 SetBgImgPositionX(BackgroundImagePositionType::PX, StringToDouble(valueX), imageObjectPosition);
617 } else if (valueX.find('%') != std::string::npos) {
618 SetBgImgPositionX(BackgroundImagePositionType::PERCENT, StringToDouble(valueX), imageObjectPosition);
619 } else {
620 auto operatorIterX = BinarySearchFindIndex(
621 backGroundPositionOperators, ArraySize(backGroundPositionOperators), valueX.c_str());
622 if (operatorIterX != -1) {
623 backGroundPositionOperators[operatorIterX].value(imageObjectPosition);
624 }
625 }
626 if (valueY.find("px") != std::string::npos) {
627 SetBgImgPositionY(BackgroundImagePositionType::PX, StringToDouble(valueY), imageObjectPosition);
628 } else if (valueY.find('%') != std::string::npos) {
629 SetBgImgPositionY(BackgroundImagePositionType::PERCENT, StringToDouble(valueY), imageObjectPosition);
630 } else {
631 auto operatorIterY = BinarySearchFindIndex(
632 backGroundPositionOperators, ArraySize(backGroundPositionOperators), valueY.c_str());
633 if (operatorIterY != -1) {
634 backGroundPositionOperators[operatorIterY].value(imageObjectPosition);
635 }
636 }
637 }
638 }
639
640 return imageObjectPosition;
641 }
642 #endif
643
644 } // namespace OHOS::Ace::Framework