LibWeb: Implement <step-position> as an enum

This simplifies parsing and serialization by using the generated
functions
This commit is contained in:
Callum Law 2025-10-10 19:42:28 +13:00 committed by Sam Atkins
parent 4c97b336c3
commit 0e30de82cc
Notes: github-actions[bot] 2025-10-20 10:29:53 +00:00
4 changed files with 36 additions and 53 deletions

View file

@ -715,6 +715,14 @@
"crispedges", "crispedges",
"geometricprecision" "geometricprecision"
], ],
"step-position": [
"jump-start",
"jump-end",
"jump-none",
"jump-both",
"start",
"end"
],
"stroke-linecap": [ "stroke-linecap": [
"butt", "butt",
"square", "square",

View file

@ -2997,32 +2997,25 @@ RefPtr<StyleValue const> Parser::parse_easing_value(TokenStream<ComponentValue>&
return nullptr; return nullptr;
if (comma_separated_arguments.size() == 2) { if (comma_separated_arguments.size() == 2) {
TokenStream identifier_stream { comma_separated_arguments[1] }; if (comma_separated_arguments[1].size() != 1)
auto keyword_value = parse_keyword_value(identifier_stream);
if (!keyword_value)
return nullptr; return nullptr;
switch (keyword_value->to_keyword()) {
case Keyword::JumpStart: auto token = comma_separated_arguments[1][0];
steps.position = EasingStyleValue::Steps::Position::JumpStart;
break; if (!token.is(Token::Type::Ident))
case Keyword::JumpEnd:
steps.position = EasingStyleValue::Steps::Position::JumpEnd;
break;
case Keyword::JumpBoth:
steps.position = EasingStyleValue::Steps::Position::JumpBoth;
break;
case Keyword::JumpNone:
steps.position = EasingStyleValue::Steps::Position::JumpNone;
break;
case Keyword::Start:
steps.position = EasingStyleValue::Steps::Position::Start;
break;
case Keyword::End:
steps.position = EasingStyleValue::Steps::Position::End;
break;
default:
return nullptr; return nullptr;
}
auto keyword = keyword_from_string(token.token().ident());
if (!keyword.has_value())
return nullptr;
auto step_position = keyword_to_step_position(keyword.value());
if (!step_position.has_value())
return nullptr;
steps.position = step_position.value();
} }
// Perform extra validation // Perform extra validation
@ -3030,7 +3023,7 @@ RefPtr<StyleValue const> Parser::parse_easing_value(TokenStream<ComponentValue>&
// If the <step-position> is jump-none, the <integer> must be at least 2, or the function is invalid. // If the <step-position> is jump-none, the <integer> must be at least 2, or the function is invalid.
// Otherwise, the <integer> must be at least 1, or the function is invalid. // Otherwise, the <integer> must be at least 1, or the function is invalid.
if (!intervals->is_calculated()) { if (!intervals->is_calculated()) {
if (steps.position == EasingStyleValue::Steps::Position::JumpNone) { if (steps.position == StepPosition::JumpNone) {
if (intervals->value() <= 1) if (intervals->value() <= 1)
return nullptr; return nullptr;
} else if (intervals->value() <= 0) { } else if (intervals->value() <= 0) {

View file

@ -50,13 +50,13 @@ EasingStyleValue::CubicBezier EasingStyleValue::CubicBezier::ease_in_out()
EasingStyleValue::Steps EasingStyleValue::Steps::step_start() EasingStyleValue::Steps EasingStyleValue::Steps::step_start()
{ {
static Steps steps { 1, Steps::Position::Start }; static Steps steps { 1, StepPosition::Start };
return steps; return steps;
} }
EasingStyleValue::Steps EasingStyleValue::Steps::step_end() EasingStyleValue::Steps EasingStyleValue::Steps::step_end()
{ {
static Steps steps { 1, Steps::Position::End }; static Steps steps { 1, StepPosition::End };
return steps; return steps;
} }
@ -350,7 +350,7 @@ double EasingStyleValue::Steps::evaluate_at(double input_progress, bool before_f
// https://www.w3.org/TR/css-easing-1/#step-easing-algo // https://www.w3.org/TR/css-easing-1/#step-easing-algo
// 1. Calculate the current step as floor(input progress value × steps). // 1. Calculate the current step as floor(input progress value × steps).
auto resolved_number_of_intervals = number_of_intervals.resolved({}).value_or(1); auto resolved_number_of_intervals = number_of_intervals.resolved({}).value_or(1);
resolved_number_of_intervals = max(resolved_number_of_intervals, position == Steps::Position::JumpNone ? 2 : 1); resolved_number_of_intervals = max(resolved_number_of_intervals, position == StepPosition::JumpNone ? 2 : 1);
auto current_step = floor(input_progress * resolved_number_of_intervals); auto current_step = floor(input_progress * resolved_number_of_intervals);
@ -358,7 +358,7 @@ double EasingStyleValue::Steps::evaluate_at(double input_progress, bool before_f
// - jump-start, // - jump-start,
// - jump-both, // - jump-both,
// increment current step by one. // increment current step by one.
if (position == Steps::Position::JumpStart || position == Steps::Position::Start || position == Steps::Position::JumpBoth) if (position == StepPosition::JumpStart || position == StepPosition::Start || position == StepPosition::JumpBoth)
current_step += 1; current_step += 1;
// 3. If both of the following conditions are true: // 3. If both of the following conditions are true:
@ -379,9 +379,9 @@ double EasingStyleValue::Steps::evaluate_at(double input_progress, bool before_f
// jump-none -> steps - 1 // jump-none -> steps - 1
// jump-both -> steps + 1 // jump-both -> steps + 1
auto jumps = resolved_number_of_intervals; auto jumps = resolved_number_of_intervals;
if (position == Steps::Position::JumpNone) { if (position == StepPosition::JumpNone) {
jumps--; jumps--;
} else if (position == Steps::Position::JumpBoth) { } else if (position == StepPosition::JumpBoth) {
jumps++; jumps++;
} }
@ -405,23 +405,14 @@ String EasingStyleValue::Steps::to_string(SerializationMode mode) const
builder.append("steps(1)"sv); builder.append("steps(1)"sv);
} else { } else {
auto position = [&] -> Optional<StringView> { auto position = [&] -> Optional<StringView> {
switch (this->position) { if (first_is_one_of(this->position, StepPosition::JumpEnd, StepPosition::End))
case Steps::Position::JumpStart:
return "jump-start"sv;
case Steps::Position::JumpNone:
return "jump-none"sv;
case Steps::Position::JumpBoth:
return "jump-both"sv;
case Steps::Position::Start:
return "start"sv;
default:
return {}; return {};
} return CSS::to_string(this->position);
}(); }();
auto intervals = number_of_intervals; auto intervals = number_of_intervals;
if (mode == SerializationMode::ResolvedValue) { if (mode == SerializationMode::ResolvedValue) {
auto resolved_value = number_of_intervals.resolved({}).value_or(1); auto resolved_value = number_of_intervals.resolved({}).value_or(1);
intervals = max(resolved_value, this->position == Steps::Position::JumpNone ? 2 : 1); intervals = max(resolved_value, this->position == StepPosition::JumpNone ? 2 : 1);
} }
if (position.has_value()) { if (position.has_value()) {
builder.appendff("steps({}, {})", intervals.to_string(mode), position.value()); builder.appendff("steps({}, {})", intervals.to_string(mode), position.value());

View file

@ -71,20 +71,11 @@ public:
}; };
struct Steps { struct Steps {
enum class Position {
JumpStart,
JumpEnd,
JumpNone,
JumpBoth,
Start,
End,
};
static Steps step_start(); static Steps step_start();
static Steps step_end(); static Steps step_end();
IntegerOrCalculated number_of_intervals { 1 }; IntegerOrCalculated number_of_intervals { 1 };
Position position { Position::End }; StepPosition position { StepPosition::End };
bool operator==(Steps const&) const = default; bool operator==(Steps const&) const = default;