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