LibWeb: Parse transition style values

This commit is contained in:
Matthew Olsson 2024-02-19 19:01:34 -07:00 committed by Andreas Kling
parent 911088278d
commit 5dce559ed8
Notes: sideshowbarker 2024-07-16 19:42:24 +09:00
8 changed files with 171 additions and 1 deletions

View file

@ -126,6 +126,7 @@ set(SOURCES
CSS/StyleValues/ShorthandStyleValue.cpp
CSS/StyleValues/StyleValueList.cpp
CSS/StyleValues/TransformationStyleValue.cpp
CSS/StyleValues/TransitionStyleValue.cpp
CSS/StyleValues/UnresolvedStyleValue.cpp
CSS/Supports.cpp
CSS/SyntaxHighlighter/SyntaxHighlighter.cpp

View file

@ -6,6 +6,7 @@
* Copyright (c) 2022, MacDue <macdue@dueutil.tech>
* Copyright (c) 2024, Shannon Booth <shannon@serenityos.org>
* Copyright (c) 2024, Tommy van der Vorst <tommy@pixelspark.nl>
* Copyright (c) 2024, Matthew Olsson <mattco@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -73,6 +74,7 @@
#include <LibWeb/CSS/StyleValues/StyleValueList.h>
#include <LibWeb/CSS/StyleValues/TimeStyleValue.h>
#include <LibWeb/CSS/StyleValues/TransformationStyleValue.h>
#include <LibWeb/CSS/StyleValues/TransitionStyleValue.h>
#include <LibWeb/CSS/StyleValues/URLStyleValue.h>
#include <LibWeb/CSS/StyleValues/UnresolvedStyleValue.h>
#include <LibWeb/CSS/StyleValues/UnsetStyleValue.h>
@ -5334,6 +5336,76 @@ RefPtr<StyleValue> Parser::parse_transform_origin_value(TokenStream<ComponentVal
return nullptr;
}
RefPtr<StyleValue> Parser::parse_transition_value(TokenStream<ComponentValue>& tokens)
{
if (contains_single_none_ident(tokens)) {
tokens.next_token(); // none
return IdentifierStyleValue::create(ValueID::None);
}
Vector<TransitionStyleValue::Transition> transitions;
auto transaction = tokens.begin_transaction();
while (tokens.has_next_token()) {
TransitionStyleValue::Transition transition;
auto time_value_count = 0;
while (tokens.has_next_token() && !tokens.peek_token().is(Token::Type::Comma)) {
if (auto time = parse_time(tokens); time.has_value()) {
switch (time_value_count) {
case 0:
transition.duration = time.release_value().value();
break;
case 1:
transition.delay = time.release_value().value();
break;
default:
dbgln_if(CSS_PARSER_DEBUG, "Transition property has more than two time values");
return {};
}
time_value_count++;
continue;
}
if (tokens.peek_token().is(Token::Type::Ident)) {
if (transition.property_name) {
dbgln_if(CSS_PARSER_DEBUG, "Transition property has multiple property identifiers");
return {};
}
auto ident = tokens.next_token().token().ident();
if (auto property = property_id_from_string(ident); property.has_value())
transition.property_name = CustomIdentStyleValue::create(ident);
}
if (auto easing = parse_easing_value(tokens)) {
if (transition.easing) {
dbgln_if(CSS_PARSER_DEBUG, "Transition property has multiple easing values");
return {};
}
transition.easing = easing->as_easing();
}
}
if (!transition.property_name)
transition.property_name = CustomIdentStyleValue::create("all"_fly_string);
if (!transition.easing)
transition.easing = EasingStyleValue::create(EasingFunction::Ease, {});
transitions.append(move(transition));
if (!tokens.peek_token().is(Token::Type::Comma))
break;
tokens.next_token();
}
transaction.commit();
return TransitionStyleValue::create(move(transitions));
}
RefPtr<StyleValue> Parser::parse_as_css_value(PropertyID property_id)
{
auto component_values = parse_a_list_of_component_values(m_token_stream);
@ -6262,7 +6334,11 @@ Parser::ParseErrorOr<NonnullRefPtr<StyleValue>> Parser::parse_css_value(Property
case PropertyID::TransformOrigin:
if (auto parsed_value = parse_transform_origin_value(tokens); parsed_value && !tokens.has_next_token())
return parsed_value.release_nonnull();
return ParseError ::SyntaxError;
return ParseError::SyntaxError;
case PropertyID::Transition:
if (auto parsed_value = parse_transition_value(tokens); parsed_value && !tokens.has_next_token())
return parsed_value.release_nonnull();
return ParseError::SyntaxError;
default:
break;
}

View file

@ -271,6 +271,7 @@ private:
RefPtr<StyleValue> parse_easing_value(TokenStream<ComponentValue>&);
RefPtr<StyleValue> parse_transform_value(TokenStream<ComponentValue>&);
RefPtr<StyleValue> parse_transform_origin_value(TokenStream<ComponentValue>&);
RefPtr<StyleValue> parse_transition_value(TokenStream<ComponentValue>&);
RefPtr<StyleValue> parse_grid_track_size_list(TokenStream<ComponentValue>&, bool allow_separate_line_name_blocks = false);
RefPtr<StyleValue> parse_grid_auto_track_sizes(TokenStream<ComponentValue>&);
RefPtr<GridAutoFlowStyleValue> parse_grid_auto_flow_value(TokenStream<ComponentValue>&);

View file

@ -52,6 +52,7 @@
#include <LibWeb/CSS/StyleValues/StyleValueList.h>
#include <LibWeb/CSS/StyleValues/TimeStyleValue.h>
#include <LibWeb/CSS/StyleValues/TransformationStyleValue.h>
#include <LibWeb/CSS/StyleValues/TransitionStyleValue.h>
#include <LibWeb/CSS/StyleValues/URLStyleValue.h>
#include <LibWeb/CSS/StyleValues/UnresolvedStyleValue.h>
#include <LibWeb/CSS/StyleValues/UnsetStyleValue.h>

View file

@ -123,6 +123,7 @@ using StyleValueVector = Vector<ValueComparingNonnullRefPtr<StyleValue const>>;
__ENUMERATE_STYLE_VALUE_TYPE(String, string) \
__ENUMERATE_STYLE_VALUE_TYPE(Time, time) \
__ENUMERATE_STYLE_VALUE_TYPE(Transformation, transformation) \
__ENUMERATE_STYLE_VALUE_TYPE(Transition, transition) \
__ENUMERATE_STYLE_VALUE_TYPE(Unresolved, unresolved) \
__ENUMERATE_STYLE_VALUE_TYPE(Unset, unset) \
__ENUMERATE_STYLE_VALUE_TYPE(URL, url) \

View file

@ -0,0 +1,39 @@
/*
* Copyright (c) 2024, Matthew Olsson <mattco@serenityos.org>.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/CSS/PropertyID.h>
#include <LibWeb/CSS/StyleValues/TransitionStyleValue.h>
namespace Web::CSS {
String TransitionStyleValue::to_string() const
{
StringBuilder builder;
bool first = true;
for (auto const& transition : m_transitions) {
if (!first)
builder.append(", "sv);
first = false;
builder.appendff("{} {} {} {}", transition.property_name->to_string(), transition.duration, transition.easing->to_string(), transition.delay);
}
return MUST(builder.to_string());
}
bool TransitionStyleValue::properties_equal(TransitionStyleValue const& other) const
{
if (m_transitions.size() != other.m_transitions.size())
return false;
for (size_t i = 0; i < m_transitions.size(); i++) {
if (m_transitions[i] != other.m_transitions[i])
return false;
}
return true;
}
}

View file

@ -0,0 +1,50 @@
/*
* Copyright (c) 2024, Matthew Olsson <mattco@serenityos.org>.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/CSS/StyleValue.h>
#include <LibWeb/CSS/StyleValues/CustomIdentStyleValue.h>
#include <LibWeb/CSS/StyleValues/EasingStyleValue.h>
#include <LibWeb/CSS/Time.h>
namespace Web::CSS {
class TransitionStyleValue final : public StyleValueWithDefaultOperators<TransitionStyleValue> {
public:
struct Transition {
ValueComparingRefPtr<CustomIdentStyleValue> property_name;
CSS::Time duration { CSS::Time::make_seconds(0.0) };
CSS::Time delay { CSS::Time::make_seconds(0.0) };
ValueComparingRefPtr<EasingStyleValue> easing;
bool operator==(Transition const&) const = default;
};
static ValueComparingNonnullRefPtr<TransitionStyleValue> create(Vector<Transition> transitions)
{
return adopt_ref(*new (nothrow) TransitionStyleValue(move(transitions)));
}
virtual ~TransitionStyleValue() override = default;
auto const& transitions() const { return m_transitions; }
virtual String to_string() const override;
bool properties_equal(TransitionStyleValue const& other) const;
private:
explicit TransitionStyleValue(Vector<Transition> transitions)
: StyleValueWithDefaultOperators(Type::Transition)
, m_transitions(move(transitions))
{
}
Vector<Transition> m_transitions;
};
}

View file

@ -191,6 +191,7 @@ class TimePercentage;
class TimeStyleValue;
class Transformation;
class TransformationStyleValue;
class TransitionStyleValue;
class URLStyleValue;
class UnresolvedStyleValue;
class UnsetStyleValue;