* Copyright (c) 2021-2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "frameworks/bridge/common/utils/utils.h"
#include "frameworks/bridge/js_frontend/engine/common/js_constants.h"
#include "interfaces/native/native_type.h"
namespace OHOS::Ace::Framework {
namespace {
using CustomCurveCreator = RefPtr<Curve> (*)(const std::vector<std::string>&);
const size_t STEPS_PARAMS_SIZE = 2;
const size_t CUBIC_PARAMS_SIZE = 4;
const size_t SPRING_PARAMS_SIZE = 4;
constexpr size_t RESPONSIVE_SPRING_MOTION_PARAMS_SIZE = 3;
constexpr size_t INTERPOLATING_SPRING_PARAMS_SIZE = 4;
static const std::unordered_set<std::string> HORIZON_SET = {
DOM_BACKGROUND_IMAGE_POSITION_LEFT,
DOM_BACKGROUND_IMAGE_POSITION_RIGHT,
};
static const std::unordered_set<std::string> VERTICAL_SET = {
DOM_BACKGROUND_IMAGE_POSITION_TOP,
DOM_BACKGROUND_IMAGE_POSITION_BOTTOM,
};
static const std::unordered_set<std::string> OBJECT_HORIZON_SET = {
DOM_IMAGE_POSITION_LEFT,
DOM_IMAGE_POSITION_RIGHT,
};
static const std::unordered_set<std::string> OBJECT_VERTICAL_SET = {
DOM_IMAGE_POSITION_TOP,
DOM_IMAGE_POSITION_BOTTOM,
};
RefPtr<Curve> StepsCurveCreator(const std::vector<std::string>& params)
{
if (params.empty() || params.size() > STEPS_PARAMS_SIZE) {
return nullptr;
}
auto step = StringUtils::StringToInt(params.front());
if (step <= 0) {
return nullptr;
}
StepsCurvePosition position = StepsCurvePosition::END;
if (params.size() > 1) {
if (params.back() == "start") {
position = StepsCurvePosition::START;
} else if (params.back() == "end") {
position = StepsCurvePosition::END;
} else {
return nullptr;
}
}
return AceType::MakeRefPtr<StepsCurve>(step, position);
}
RefPtr<Curve> CubicCurveCreator(const std::vector<std::string>& params)
{
if (params.size() != CUBIC_PARAMS_SIZE) {
return nullptr;
}
double x1 = StringToDouble(params.at(0));
double y1 = StringToDouble(params.at(1));
double x2 = StringToDouble(params.at(2));
double y2 = StringToDouble(params.at(3));
return AceType::MakeRefPtr<CubicCurve>(x1, y1, x2, y2);
}
RefPtr<Curve> SpringCurveCreator(const std::vector<std::string>& params)
{
if (params.size() != SPRING_PARAMS_SIZE) {
return nullptr;
}
double velocity = StringToDouble(params.at(0));
double mass = StringToDouble(params.at(1));
double stiffness = StringToDouble(params.at(2));
double damping = StringToDouble(params.at(3));
return AceType::MakeRefPtr<SpringCurve>(velocity, mass, stiffness, damping);
}
RefPtr<Curve> InterpolatingSpringCreator(const std::vector<std::string>& params)
{
if (params.size() != INTERPOLATING_SPRING_PARAMS_SIZE) {
return nullptr;
}
double velocity = StringToDouble(params.at(0));
double mass = StringToDouble(params.at(1));
double stiffness = StringToDouble(params.at(2));
double damping = StringToDouble(params.at(3));
return AceType::MakeRefPtr<InterpolatingSpring>(velocity, mass, stiffness, damping);
}
RefPtr<Curve> SpringMotionCreator(const std::vector<std::string>& params)
{
if (params.size() > RESPONSIVE_SPRING_MOTION_PARAMS_SIZE) {
return nullptr;
}
size_t paramSize = params.size();
float response = paramSize > 0 ? StringUtils::StringToFloat(params[0])
: ResponsiveSpringMotion::DEFAULT_SPRING_MOTION_RESPONSE;
float dampingRatio = paramSize > 1 ? StringUtils::StringToFloat(params[1])
: ResponsiveSpringMotion::DEFAULT_SPRING_MOTION_DAMPING_RATIO;
float blendDuration = paramSize > 2 ? StringUtils::StringToFloat(params[2])
: ResponsiveSpringMotion::DEFAULT_SPRING_MOTION_BLEND_DURATION;
return AceType::MakeRefPtr<ResponsiveSpringMotion>(response, dampingRatio, blendDuration);
}
RefPtr<Curve> ResponsiveSpringMotionCreator(const std::vector<std::string>& params)
{
if (params.size() > RESPONSIVE_SPRING_MOTION_PARAMS_SIZE) {
return nullptr;
}
size_t paramSize = params.size();
float response = paramSize > 0 ? StringUtils::StringToFloat(params[0])
: ResponsiveSpringMotion::DEFAULT_RESPONSIVE_SPRING_MOTION_RESPONSE;
float dampingRatio = paramSize > 1 ? StringUtils::StringToFloat(params[1])
: ResponsiveSpringMotion::DEFAULT_RESPONSIVE_SPRING_MOTION_DAMPING_RATIO;
float blendDuration = paramSize > 2 ? StringUtils::StringToFloat(params[2])
: ResponsiveSpringMotion::DEFAULT_RESPONSIVE_SPRING_MOTION_BLEND_DURATION;
return AceType::MakeRefPtr<ResponsiveSpringMotion>(response, dampingRatio, blendDuration);
}
#ifndef FUZZTEST
void SetBgImgPositionX(
const BackgroundImagePositionType type, const double value, BackgroundImagePosition& bgImgPosition)
{
bgImgPosition.SetSizeTypeX(type);
bgImgPosition.SetSizeValueX(value);
}
void SetBgImgPositionY(
const BackgroundImagePositionType type, const double value, BackgroundImagePosition& bgImgPosition)
{
bgImgPosition.SetSizeTypeY(type);
bgImgPosition.SetSizeValueY(value);
}
void SetBgImgPosition(
const BackgroundImagePositionType type, const double value, BackgroundImagePosition& bgImgPosition)
{
SetBgImgPositionX(type, value, bgImgPosition);
SetBgImgPositionY(type, value, bgImgPosition);
}
void GetOffsetValue(std::vector<std::string> offsets, std::string& posX, std::string& posY)
{
if (offsets.size() == 1) {
posX = offsets.front();
if (VERTICAL_SET.find(posX) != VERTICAL_SET.end()) {
posY = offsets.front();
posX = DOM_BACKGROUND_IMAGE_POSITION_CENTER;
} else {
posY = DOM_BACKGROUND_IMAGE_POSITION_CENTER;
}
} else {
posX = offsets.front();
posY = offsets.back();
if (VERTICAL_SET.find(posX) != VERTICAL_SET.end() && HORIZON_SET.find(posY) != HORIZON_SET.end()) {
posY = offsets.front();
posX = offsets.back();
}
}
}
void GetOffsetValueObjectPosition(std::vector<std::string> offsets, std::string& posX, std::string& posY)
{
if (offsets.size() == 1) {
posX = offsets.front();
if (OBJECT_VERTICAL_SET.find(posX) != OBJECT_VERTICAL_SET.end()) {
posY = offsets.front();
posX = DOM_IMAGE_POSITION_CENTER;
} else {
posY = DOM_IMAGE_POSITION_CENTER;
}
} else {
posX = offsets.front();
posY = offsets.back();
if (OBJECT_VERTICAL_SET.find(posX) != OBJECT_VERTICAL_SET.end()
&& OBJECT_HORIZON_SET.find(posY) != OBJECT_HORIZON_SET.end()) {
posY = offsets.front();
posX = offsets.back();
}
}
}
bool BgImgPositionIsValid(const std::string& posX, const std::string& posY)
{
if ((posX == DOM_BACKGROUND_IMAGE_POSITION_CENTER) || (posY == DOM_BACKGROUND_IMAGE_POSITION_CENTER)) {
return true;
}
if (posX.find("px") != std::string::npos || posX.find('%') != std::string::npos ||
HORIZON_SET.find(posX) != HORIZON_SET.end()) {
if (posY.find("px") != std::string::npos || posY.find('%') != std::string::npos ||
VERTICAL_SET.find(posY) != VERTICAL_SET.end()) {
return true;
}
}
return VERTICAL_SET.find(posX) != VERTICAL_SET.end() && HORIZON_SET.find(posY) != HORIZON_SET.end();
}
bool ObjectImgPositionIsValid(const std::string& posX, const std::string& posY)
{
if (posX.find("px") != std::string::npos || posX.find('%') != std::string::npos ||
OBJECT_HORIZON_SET.find(posX) != OBJECT_HORIZON_SET.end() || posX != DOM_IMAGE_POSITION_CENTER) {
if (posY.find("px") != std::string::npos || posY.find('%') != std::string::npos ||
OBJECT_VERTICAL_SET.find(posY) != OBJECT_VERTICAL_SET.end() || posY != DOM_IMAGE_POSITION_CENTER) {
return true;
}
}
return false;
}
void SetBgImgSizeX(BackgroundImageSizeType type, double value, BackgroundImageSize& bgImgSize)
{
bgImgSize.SetSizeTypeX(type);
bgImgSize.SetSizeValueX(value);
}
void SetBgImgSizeY(BackgroundImageSizeType type, double value, BackgroundImageSize& bgImgSize)
{
bgImgSize.SetSizeTypeY(type);
bgImgSize.SetSizeValueY(value);
}
#endif
}
FlexAlign ConvertStrToFlexAlign(const std::string& flexKey)
{
static const LinearMapNode<FlexAlign> flexMap[] = {
{ DOM_ALIGN_ITEMS_BASELINE, FlexAlign::BASELINE },
{ DOM_JUSTIFY_CONTENT_CENTER, FlexAlign::CENTER },
{ DOM_JUSTIFY_CONTENT_END, FlexAlign::FLEX_END },
{ DOM_JUSTIFY_CONTENT_START, FlexAlign::FLEX_START },
{ DOM_JUSTIFY_CONTENT_AROUND, FlexAlign::SPACE_AROUND },
{ DOM_JUSTIFY_CONTENT_BETWEEN, FlexAlign::SPACE_BETWEEN },
{ DOM_JUSTIFY_CONTENT_EVENLY, FlexAlign::SPACE_EVENLY },
{ DOM_ALIGN_ITEMS_STRETCH, FlexAlign::STRETCH },
};
auto index = BinarySearchFindIndex(flexMap, ArraySize(flexMap), flexKey.c_str());
return index < 0 ? FlexAlign::FLEX_START : flexMap[index].value;
}
RefPtr<Curve> CreateBuiltinCurve(const std::string& aniTimFunc)
{
static const LinearMapNode<RefPtr<Curve>> aniTimFuncMap[] = {
{ DOM_ANIMATION_TIMING_FUNCTION_EASE, Curves::EASE },
{ DOM_ANIMATION_TIMING_FUNCTION_EASE_IN, Curves::EASE_IN },
{ DOM_ANIMATION_TIMING_FUNCTION_EASE_IN_OUT, Curves::EASE_IN_OUT },
{ DOM_ANIMATION_TIMING_FUNCTION_EASE_OUT, Curves::EASE_OUT },
{ DOM_ANIMATION_TIMING_FUNCTION_EXTREME_DECELERATION, Curves::EXTREME_DECELERATION },
{ DOM_ANIMATION_TIMING_FUNCTION_FAST_OUT_LINEAR_IN, Curves::FAST_OUT_LINEAR_IN },
{ DOM_ANIMATION_TIMING_FUNCTION_FAST_OUT_SLOW_IN, Curves::FAST_OUT_SLOW_IN },
{ DOM_ANIMATION_TIMING_FUNCTION_FRICTION, Curves::FRICTION },
{ DOM_ANIMATION_TIMING_FUNCTION_LINEAR, Curves::LINEAR },
{ DOM_ANIMATION_TIMING_FUNCTION_LINEAR_OUT_SLOW_IN, Curves::LINEAR_OUT_SLOW_IN },
{ DOM_ANIMATION_TIMING_FUNCTION_RHYTHM, Curves::RHYTHM },
{ DOM_ANIMATION_TIMING_FUNCTION_SHARP, Curves::SHARP },
{ DOM_ANIMATION_TIMING_FUNCTION_SMOOTH, Curves::SMOOTH },
};
auto index = BinarySearchFindIndex(aniTimFuncMap, ArraySize(aniTimFuncMap), aniTimFunc.c_str());
return index < 0 ? nullptr : aniTimFuncMap[index].value;
}
std::string CurveIntToString(int curve)
{
static const LinearEnumMapNode<ArkUI_AnimationCurve, std::string> curveMap[] = {
{ ArkUI_AnimationCurve::ARKUI_CURVE_EASE, DOM_ANIMATION_TIMING_FUNCTION_EASE },
{ ArkUI_AnimationCurve::ARKUI_CURVE_EASE_IN, DOM_ANIMATION_TIMING_FUNCTION_EASE_IN },
{ ArkUI_AnimationCurve::ARKUI_CURVE_EASE_IN_OUT, DOM_ANIMATION_TIMING_FUNCTION_EASE_IN_OUT },
{ ArkUI_AnimationCurve::ARKUI_CURVE_EASE_OUT, DOM_ANIMATION_TIMING_FUNCTION_EASE_OUT},
{ ArkUI_AnimationCurve::ARKUI_CURVE_EXTREME_DECELERATION, DOM_ANIMATION_TIMING_FUNCTION_EXTREME_DECELERATION },
{ ArkUI_AnimationCurve::ARKUI_CURVE_FAST_OUT_LINEAR_IN, DOM_ANIMATION_TIMING_FUNCTION_FAST_OUT_LINEAR_IN },
{ ArkUI_AnimationCurve::ARKUI_CURVE_FAST_OUT_SLOW_IN, DOM_ANIMATION_TIMING_FUNCTION_FAST_OUT_SLOW_IN},
{ ArkUI_AnimationCurve::ARKUI_CURVE_FRICTION, DOM_ANIMATION_TIMING_FUNCTION_FRICTION },
{ ArkUI_AnimationCurve::ARKUI_CURVE_LINEAR, DOM_ANIMATION_TIMING_FUNCTION_LINEAR},
{ ArkUI_AnimationCurve::ARKUI_CURVE_LINEAR_OUT_SLOW_IN, DOM_ANIMATION_TIMING_FUNCTION_LINEAR_OUT_SLOW_IN},
{ ArkUI_AnimationCurve::ARKUI_CURVE_RHYTHM, DOM_ANIMATION_TIMING_FUNCTION_RHYTHM},
{ ArkUI_AnimationCurve::ARKUI_CURVE_SHARP, DOM_ANIMATION_TIMING_FUNCTION_SHARP},
{ ArkUI_AnimationCurve::ARKUI_CURVE_SMOOTH, DOM_ANIMATION_TIMING_FUNCTION_SMOOTH},
};
auto index = BinarySearchFindIndex(curveMap, ArraySize(curveMap), static_cast<ArkUI_AnimationCurve>(curve));
return index < 0 ? DOM_ANIMATION_TIMING_FUNCTION_LINEAR : curveMap[index].value;
}
bool ParseCurveParam(
const std::string& aniTimFunc, std::string& curveName, std::vector<std::string>& paramsVector)
{
if (aniTimFunc.back() != ')') {
return false;
}
std::string::size_type leftEmbracePosition = aniTimFunc.find_last_of('(');
if (leftEmbracePosition == std::string::npos) {
return false;
}
auto aniTimFuncName = aniTimFunc.substr(0, leftEmbracePosition);
auto params = aniTimFunc.substr(leftEmbracePosition + 1, aniTimFunc.length() - leftEmbracePosition - 2);
if (aniTimFuncName.empty() || params.empty()) {
return false;
}
StringUtils::StringSplitter(params, ',', paramsVector);
for (auto& param : paramsVector) {
RemoveHeadTailSpace(param);
}
curveName = std::move(aniTimFuncName);
return true;
}
RefPtr<Curve> CreateCustomCurve(const std::string& aniTimFunc)
{
std::string aniTimFuncName;
std::vector<std::string> paramsVector;
bool result = ParseCurveParam(aniTimFunc, aniTimFuncName, paramsVector);
if (!result) {
return nullptr;
}
static const LinearMapNode<CustomCurveCreator> customCurveMap[] = {
{ DOM_ANIMATION_TIMING_FUNCTION_CUBIC_BEZIER, CubicCurveCreator },
{ DOM_ANIMATION_TIMING_FUNCTION_INTERPOLATING_SPRING, InterpolatingSpringCreator },
{ DOM_ANIMATION_TIMING_FUNCTION_RESPONSIVE_SPRING_MOTION, ResponsiveSpringMotionCreator },
{ DOM_ANIMATION_TIMING_FUNCTION_SPRING, SpringCurveCreator },
{ DOM_ANIMATION_TIMING_FUNCTION_SPRING_MOTION, SpringMotionCreator },
{ DOM_ANIMATION_TIMING_FUNCTION_STEPS, StepsCurveCreator },
};
int64_t index = BinarySearchFindIndex(customCurveMap, ArraySize(customCurveMap), aniTimFuncName.c_str());
if (index < 0) {
return nullptr;
}
return customCurveMap[index].value(paramsVector);
}
RefPtr<Curve> CreateCustomCurveExceptSpring(const std::string& aniTimFunc)
{
std::string aniTimFuncName;
std::vector<std::string> paramsVector;
bool result = ParseCurveParam(aniTimFunc, aniTimFuncName, paramsVector);
if (!result) {
return nullptr;
}
static const LinearMapNode<CustomCurveCreator> customCurveExceptSpringMap[] = {
{ DOM_ANIMATION_TIMING_FUNCTION_CUBIC_BEZIER, CubicCurveCreator },
{ DOM_ANIMATION_TIMING_FUNCTION_SPRING, SpringCurveCreator },
{ DOM_ANIMATION_TIMING_FUNCTION_STEPS, StepsCurveCreator },
};
int64_t index = BinarySearchFindIndex(
customCurveExceptSpringMap, ArraySize(customCurveExceptSpringMap), aniTimFuncName.c_str());
if (index < 0) {
return nullptr;
}
return customCurveExceptSpringMap[index].value(paramsVector);
}
RefPtr<Curve> CreateCurve(const std::function<float(float)>& jsFunc)
{
if (jsFunc) {
return AceType::MakeRefPtr<CustomCurve>(jsFunc);
}
return Curves::EASE_IN_OUT;
}
RefPtr<Curve> CreateCurve(const std::string& aniTimFunc, bool useDefault)
{
auto curve = CreateBuiltinCurve(aniTimFunc);
if (curve) {
return curve;
}
curve = CreateCustomCurve(aniTimFunc);
if (curve) {
return curve;
}
return useDefault? Curves::EASE_IN_OUT : nullptr;
}
RefPtr<Curve> CreateCurve(int curveType, bool useDefault)
{
static const LinearEnumMapNode<int, RefPtr<Curve>> curveMap[] = {
{ static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_LINEAR), Curves::LINEAR },
{ static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_EASE), Curves::EASE },
{ static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_EASE_IN), Curves::EASE_IN },
{ static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_EASE_OUT), Curves::EASE_OUT },
{ static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_EASE_IN_OUT), Curves::EASE_IN_OUT },
{ static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_FAST_OUT_SLOW_IN), Curves::FAST_OUT_SLOW_IN },
{ static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_LINEAR_OUT_SLOW_IN), Curves::LINEAR_OUT_SLOW_IN },
{ static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_FAST_OUT_LINEAR_IN), Curves::FAST_OUT_LINEAR_IN },
{ static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_EXTREME_DECELERATION), Curves::EXTREME_DECELERATION },
{ static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_RHYTHM), Curves::RHYTHM },
{ static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_SHARP), Curves::SHARP },
{ static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_SMOOTH), Curves::SMOOTH },
{ static_cast<int>(ArkUI_AnimationCurve::ARKUI_CURVE_FRICTION), Curves::FRICTION },
};
auto index = BinarySearchFindIndex(curveMap, ArraySize(curveMap), curveType);
RefPtr<Curve> defaultCurve = useDefault? Curves::EASE_IN_OUT : nullptr;
return index < 0 ? defaultCurve : curveMap[index].value;
}
RefPtr<Curve> CreateCurveExceptSpring(
const std::string& aniTimFunc, const std::function<float(float)>& jsFunc)
{
if (jsFunc) {
return AceType::MakeRefPtr<CustomCurve>(jsFunc);
}
auto curve = CreateBuiltinCurve(aniTimFunc);
if (curve) {
return curve;
}
curve = CreateCustomCurveExceptSpring(aniTimFunc);
if (curve) {
return curve;
}
return Curves::EASE_IN_OUT;
}
TransitionType ParseTransitionType(const std::string& transitionType)
{
if (transitionType == "All") {
return TransitionType::ALL;
} else if (transitionType == "Insert") {
return TransitionType::APPEARING;
} else if (transitionType == "Delete") {
return TransitionType::DISAPPEARING;
} else {
return TransitionType::ALL;
}
}
#ifndef FUZZTEST
bool ParseBackgroundImagePosition(const std::string& value, BackgroundImagePosition& backgroundImagePosition)
{
static const LinearMapNode<void (*)(BackgroundImagePosition&)> backGroundPositionOperators[] = {
{ DOM_BACKGROUND_IMAGE_POSITION_BOTTOM,
[](BackgroundImagePosition& backgroundImagePosition) {
SetBgImgPositionY(BackgroundImagePositionType::PERCENT, 100.0, backgroundImagePosition);
} },
{ DOM_BACKGROUND_IMAGE_POSITION_LEFT,
[](BackgroundImagePosition& backgroundImagePosition) {
SetBgImgPositionX(BackgroundImagePositionType::PERCENT, 0.0, backgroundImagePosition);
} },
{ DOM_BACKGROUND_IMAGE_POSITION_RIGHT,
[](BackgroundImagePosition& backgroundImagePosition) {
SetBgImgPositionX(BackgroundImagePositionType::PERCENT, 100.0, backgroundImagePosition);
} },
{ DOM_BACKGROUND_IMAGE_POSITION_TOP,
[](BackgroundImagePosition& backgroundImagePosition) {
SetBgImgPositionY(BackgroundImagePositionType::PERCENT, 0.0, backgroundImagePosition);
} },
};
std::vector<std::string> offsets;
StringUtils::StringSplitter(value, ' ', offsets);
if (!offsets.empty()) {
std::string valueX = "";
std::string valueY = "";
GetOffsetValue(offsets, valueX, valueY);
if (!BgImgPositionIsValid(valueX, valueY)) {
return false;
}
SetBgImgPosition(BackgroundImagePositionType::PERCENT, 50.0, backgroundImagePosition);
if (valueX.find("px") != std::string::npos) {
SetBgImgPositionX(BackgroundImagePositionType::PX, StringToDouble(valueX), backgroundImagePosition);
} else if (valueX.find('%') != std::string::npos) {
SetBgImgPositionX(BackgroundImagePositionType::PERCENT, StringToDouble(valueX), backgroundImagePosition);
} else {
auto operatorIterX = BinarySearchFindIndex(
backGroundPositionOperators, ArraySize(backGroundPositionOperators), valueX.c_str());
if (operatorIterX != -1) {
backGroundPositionOperators[operatorIterX].value(backgroundImagePosition);
}
}
if (valueY.find("px") != std::string::npos) {
SetBgImgPositionY(BackgroundImagePositionType::PX, StringToDouble(valueY), backgroundImagePosition);
} else if (valueY.find('%') != std::string::npos) {
SetBgImgPositionY(BackgroundImagePositionType::PERCENT, StringToDouble(valueY), backgroundImagePosition);
} else {
auto operatorIterY = BinarySearchFindIndex(
backGroundPositionOperators, ArraySize(backGroundPositionOperators), valueY.c_str());
if (operatorIterY != -1) {
backGroundPositionOperators[operatorIterY].value(backgroundImagePosition);
}
}
} else {
SetBgImgPosition(BackgroundImagePositionType::PERCENT, 50.0, backgroundImagePosition);
if (value.find("px") != std::string::npos) {
SetBgImgPositionX(BackgroundImagePositionType::PX, StringToDouble(value), backgroundImagePosition);
} else if (value.find('%') != std::string::npos) {
SetBgImgPositionX(BackgroundImagePositionType::PERCENT, StringToDouble(value), backgroundImagePosition);
} else {
auto operatorIter = BinarySearchFindIndex(
backGroundPositionOperators, ArraySize(backGroundPositionOperators), value.c_str());
if (operatorIter != -1) {
backGroundPositionOperators[operatorIter].value(backgroundImagePosition);
}
}
}
return true;
}
bool ParseBackgroundImageSize(const std::string& value, BackgroundImageSize& bgImgSize)
{
static const LinearMapNode<BackgroundImageSizeType> bgImageSizeType[] = {
{ DOM_BACKGROUND_IMAGE_SIZE_AUTO, BackgroundImageSizeType::AUTO },
{ DOM_BACKGROUND_IMAGE_SIZE_CONTAIN, BackgroundImageSizeType::CONTAIN },
{ DOM_BACKGROUND_IMAGE_SIZE_COVER, BackgroundImageSizeType::COVER },
{ DOM_BACKGROUND_IMAGE_SIZE_FILL, BackgroundImageSizeType::FILL },
};
auto spaceIndex = value.find(' ', 0);
if (spaceIndex != std::string::npos) {
std::string valueX = value.substr(0, spaceIndex);
std::string valueY = value.substr(spaceIndex + 1, value.size() - spaceIndex - 1);
if (valueX.find("px") != std::string::npos) {
SetBgImgSizeX(BackgroundImageSizeType::LENGTH, StringToDouble(valueX), bgImgSize);
} else if (valueX.find('%') != std::string::npos) {
SetBgImgSizeX(BackgroundImageSizeType::PERCENT, StringToDouble(valueX), bgImgSize);
} else {
bgImgSize.SetSizeTypeX(BackgroundImageSizeType::AUTO);
}
if (valueY.find("px") != std::string::npos) {
SetBgImgSizeY(BackgroundImageSizeType::LENGTH, StringToDouble(valueY), bgImgSize);
} else if (valueY.find('%') != std::string::npos) {
SetBgImgSizeY(BackgroundImageSizeType::PERCENT, StringToDouble(valueY), bgImgSize);
} else {
bgImgSize.SetSizeTypeY(BackgroundImageSizeType::AUTO);
}
} else {
auto sizeTypeIter = BinarySearchFindIndex(bgImageSizeType, ArraySize(bgImageSizeType), value.c_str());
if (sizeTypeIter != -1) {
bgImgSize.SetSizeTypeX(bgImageSizeType[sizeTypeIter].value);
bgImgSize.SetSizeTypeY(bgImageSizeType[sizeTypeIter].value);
} else if (value.find("px") != std::string::npos) {
SetBgImgSizeX(BackgroundImageSizeType::LENGTH, StringToDouble(value), bgImgSize);
bgImgSize.SetSizeTypeY(BackgroundImageSizeType::AUTO);
} else if (value.find('%') != std::string::npos) {
SetBgImgSizeX(BackgroundImageSizeType::PERCENT, StringToDouble(value), bgImgSize);
bgImgSize.SetSizeTypeY(BackgroundImageSizeType::AUTO);
} else {
bgImgSize.SetSizeTypeX(BackgroundImageSizeType::AUTO);
bgImgSize.SetSizeTypeY(BackgroundImageSizeType::AUTO);
}
}
return true;
}
#endif
RefPtr<ClipPath> CreateClipPath(const std::string& value)
{
if (value.empty()) {
return nullptr;
}
auto clipPath = ClipPath::CreateShape(value);
GeometryBoxType geometryBoxType = ClipPath::GetGeometryBoxType(value);
if (geometryBoxType != GeometryBoxType::NONE) {
if (!clipPath) {
clipPath = AceType::MakeRefPtr<ClipPath>();
}
}
if (clipPath) {
clipPath->SetGeometryBoxType(geometryBoxType);
}
return clipPath;
}
std::optional<RadialSizeType> ParseRadialGradientSize(const std::string& value)
{
const static std::unordered_map<std::string, RadialSizeType> sizeTypes = {
{ DOM_GRADIENT_SIZE_CLOSEST_CORNER, RadialSizeType::CLOSEST_CORNER },
{ DOM_GRADIENT_SIZE_CLOSEST_SIDE, RadialSizeType::CLOSEST_SIDE },
{ DOM_GRADIENT_SIZE_FARTHEST_CORNER, RadialSizeType::FARTHEST_CORNER },
{ DOM_GRADIENT_SIZE_FARTHEST_SIDE, RadialSizeType::FARTHEST_SIDE },
};
if (!value.empty()) {
auto pos = sizeTypes.find(value);
if (pos != sizeTypes.end()) {
return std::make_optional(pos->second);
}
}
return std::nullopt;
}
TextAlign ConvertStrToTextAlign(const std::string& align)
{
static const LinearMapNode<TextAlign> textAlignTable[] = {
{ DOM_CENTER, TextAlign::CENTER },
{ DOM_END, TextAlign::END },
{ DOM_LEFT, TextAlign::LEFT },
{ DOM_RIGHT, TextAlign::RIGHT },
{ DOM_START, TextAlign::START },
};
auto index = BinarySearchFindIndex(textAlignTable, ArraySize(textAlignTable), align.c_str());
return index < 0 ? TextAlign::CENTER : textAlignTable[index].value;
}
FontStyle ConvertStrToFontStyle(const std::string& fontStyle)
{
return fontStyle == DOM_TEXT_FONT_STYLE_ITALIC ? FontStyle::ITALIC : FontStyle::NORMAL;
}
TextDecoration ConvertStrToTextDecoration(const std::string& textDecoration)
{
static const LinearMapNode<TextDecoration> textDecorationTable[] = {
{ DOM_TEXT_DECORATION_INHERIT, TextDecoration::INHERIT },
{ DOM_TEXT_DECORATION_LINETHROUGH, TextDecoration::LINE_THROUGH },
{ DOM_TEXT_DECORATION_NONE, TextDecoration::NONE },
{ DOM_TEXT_DECORATION_OVERLINE, TextDecoration::OVERLINE },
{ DOM_TEXT_DECORATION_UNDERLINE, TextDecoration::UNDERLINE },
};
auto index = BinarySearchFindIndex(textDecorationTable, ArraySize(textDecorationTable), textDecoration.c_str());
return index < 0 ? TextDecoration::NONE : textDecorationTable[index].value;
}
#ifndef FUZZTEST
ImageObjectPosition ParseImageObjectPosition(const std::string& value)
{
ImageObjectPosition imageObjectPosition;
static const LinearMapNode<void (*)(ImageObjectPosition&)> backGroundPositionOperators[] = {
{ DOM_IMAGE_POSITION_BOTTOM,
[](ImageObjectPosition& imageObjectPosition) {
SetBgImgPositionY(BackgroundImagePositionType::PERCENT, 100.0, imageObjectPosition);
} },
{ DOM_IMAGE_POSITION_LEFT,
[](ImageObjectPosition& imageObjectPosition) {
SetBgImgPositionX(BackgroundImagePositionType::PERCENT, 0.0, imageObjectPosition);
} },
{ DOM_IMAGE_POSITION_RIGHT,
[](ImageObjectPosition& imageObjectPosition) {
SetBgImgPositionX(BackgroundImagePositionType::PERCENT, 100.0, imageObjectPosition);
} },
{ DOM_IMAGE_POSITION_TOP,
[](ImageObjectPosition& imageObjectPosition) {
SetBgImgPositionY(BackgroundImagePositionType::PERCENT, 0.0, imageObjectPosition);
} },
};
std::vector<std::string> offsets;
StringUtils::StringSplitter(value, ' ', offsets);
if (!offsets.empty()) {
std::string valueX = "";
std::string valueY = "";
GetOffsetValueObjectPosition(offsets, valueX, valueY);
SetBgImgPosition(BackgroundImagePositionType::PERCENT, 50.0, imageObjectPosition);
if (ObjectImgPositionIsValid(valueX, valueY)) {
if (valueX.find("px") != std::string::npos) {
SetBgImgPositionX(BackgroundImagePositionType::PX, StringToDouble(valueX), imageObjectPosition);
} else if (valueX.find('%') != std::string::npos) {
SetBgImgPositionX(BackgroundImagePositionType::PERCENT, StringToDouble(valueX), imageObjectPosition);
} else {
auto operatorIterX = BinarySearchFindIndex(
backGroundPositionOperators, ArraySize(backGroundPositionOperators), valueX.c_str());
if (operatorIterX != -1) {
backGroundPositionOperators[operatorIterX].value(imageObjectPosition);
}
}
if (valueY.find("px") != std::string::npos) {
SetBgImgPositionY(BackgroundImagePositionType::PX, StringToDouble(valueY), imageObjectPosition);
} else if (valueY.find('%') != std::string::npos) {
SetBgImgPositionY(BackgroundImagePositionType::PERCENT, StringToDouble(valueY), imageObjectPosition);
} else {
auto operatorIterY = BinarySearchFindIndex(
backGroundPositionOperators, ArraySize(backGroundPositionOperators), valueY.c_str());
if (operatorIterY != -1) {
backGroundPositionOperators[operatorIterY].value(imageObjectPosition);
}
}
}
}
return imageObjectPosition;
}
#endif
}