2023-07-06 02:29:36 +03:30
|
|
|
|
/*
|
2024-10-04 13:19:50 +02:00
|
|
|
|
* Copyright (c) 2018-2020, Andreas Kling <andreas@ladybird.org>
|
2023-07-06 02:29:36 +03:30
|
|
|
|
* Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
|
|
|
|
|
|
* Copyright (c) 2021-2023, Sam Atkins <atkinssj@serenityos.org>
|
|
|
|
|
|
* Copyright (c) 2022-2023, MacDue <macdue@dueutil.tech>
|
|
|
|
|
|
* Copyright (c) 2023, Ali Mohammad Pur <mpfard@serenityos.org>
|
|
|
|
|
|
*
|
|
|
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include "EasingStyleValue.h"
|
2024-06-14 21:50:25 -07:00
|
|
|
|
#include <AK/BinarySearch.h>
|
2023-07-06 02:29:36 +03:30
|
|
|
|
#include <AK/StringBuilder.h>
|
2025-06-17 09:46:51 +01:00
|
|
|
|
#include <LibWeb/CSS/StyleValues/IntegerStyleValue.h>
|
2025-10-09 23:40:46 +13:00
|
|
|
|
#include <LibWeb/CSS/StyleValues/NumberStyleValue.h>
|
2023-07-06 02:29:36 +03:30
|
|
|
|
|
|
|
|
|
|
namespace Web::CSS {
|
|
|
|
|
|
|
2024-11-03 14:56:16 +11:00
|
|
|
|
// https://drafts.csswg.org/css-easing/#linear-easing-function-serializing
|
2025-10-09 23:40:46 +13:00
|
|
|
|
String EasingStyleValue::Linear::to_string(SerializationMode mode) const
|
2024-11-03 10:36:44 +11:00
|
|
|
|
{
|
2024-11-03 14:56:16 +11:00
|
|
|
|
// To serialize a linear() function:
|
|
|
|
|
|
// 1. Let s be the string "linear(".
|
2024-11-03 10:36:44 +11:00
|
|
|
|
StringBuilder builder;
|
2024-11-03 14:56:16 +11:00
|
|
|
|
builder.append("linear("sv);
|
|
|
|
|
|
|
|
|
|
|
|
// 2. Serialize each control point of the function,
|
|
|
|
|
|
// concatenate the results using the separator ", ",
|
|
|
|
|
|
// and append the result to s.
|
|
|
|
|
|
bool first = true;
|
|
|
|
|
|
for (auto stop : stops) {
|
|
|
|
|
|
if (first) {
|
2024-11-03 10:36:44 +11:00
|
|
|
|
first = false;
|
2024-11-03 14:56:16 +11:00
|
|
|
|
} else {
|
|
|
|
|
|
builder.append(", "sv);
|
2024-11-03 10:36:44 +11:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-11-03 14:56:16 +11:00
|
|
|
|
// To serialize a linear() control point:
|
|
|
|
|
|
// 1. Let s be the serialization, as a <number>, of the control point’s output progress value.
|
2025-10-09 23:40:46 +13:00
|
|
|
|
builder.appendff(stop.output->to_string(mode));
|
2024-11-03 14:56:16 +11:00
|
|
|
|
|
|
|
|
|
|
// 2. If the control point originally lacked an input progress value, return s.
|
|
|
|
|
|
// 3. Otherwise, append " " (U+0020 SPACE) to s,
|
|
|
|
|
|
// then serialize the control point’s input progress value as a <percentage> and append it to s.
|
2025-10-09 23:40:46 +13:00
|
|
|
|
if (stop.input) {
|
|
|
|
|
|
builder.appendff(" {}", stop.input->to_string(mode));
|
2024-11-03 14:56:16 +11:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 4. Return s.
|
2024-11-03 10:36:44 +11:00
|
|
|
|
}
|
2024-11-03 14:56:16 +11:00
|
|
|
|
|
|
|
|
|
|
// 4. Append ")" to s, and return it.
|
|
|
|
|
|
builder.append(')');
|
2024-11-03 10:36:44 +11:00
|
|
|
|
return MUST(builder.to_string());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-11-18 19:41:33 +04:00
|
|
|
|
// https://drafts.csswg.org/css-easing/#bezier-serialization
|
2025-06-17 22:51:54 +01:00
|
|
|
|
String EasingStyleValue::CubicBezier::to_string(SerializationMode mode) const
|
2024-11-03 10:36:44 +11:00
|
|
|
|
{
|
2025-10-11 23:34:35 +13:00
|
|
|
|
return MUST(String::formatted("cubic-bezier({}, {}, {}, {})", x1->to_string(mode), y1->to_string(mode), x2->to_string(mode), y2->to_string(mode)));
|
2024-11-03 10:36:44 +11:00
|
|
|
|
}
|
2024-06-14 21:50:25 -07:00
|
|
|
|
|
2024-11-18 19:41:33 +04:00
|
|
|
|
// https://drafts.csswg.org/css-easing/#steps-serialization
|
2025-06-17 09:46:51 +01:00
|
|
|
|
String EasingStyleValue::Steps::to_string(SerializationMode mode) const
|
2024-11-03 10:36:44 +11:00
|
|
|
|
{
|
2025-10-11 23:34:35 +13:00
|
|
|
|
auto position = [&] -> Optional<StringView> {
|
|
|
|
|
|
if (first_is_one_of(this->position, StepPosition::JumpEnd, StepPosition::End))
|
|
|
|
|
|
return {};
|
|
|
|
|
|
return CSS::to_string(this->position);
|
|
|
|
|
|
}();
|
|
|
|
|
|
|
|
|
|
|
|
if (position.has_value()) {
|
|
|
|
|
|
return MUST(String::formatted("steps({}, {})", number_of_intervals->to_string(mode), position.value()));
|
2024-11-03 10:36:44 +11:00
|
|
|
|
}
|
2025-10-11 23:34:35 +13:00
|
|
|
|
|
|
|
|
|
|
return MUST(String::formatted("steps({})", number_of_intervals->to_string(mode)));
|
2024-11-03 10:36:44 +11:00
|
|
|
|
}
|
2024-06-14 21:50:25 -07:00
|
|
|
|
|
2025-06-17 09:46:51 +01:00
|
|
|
|
String EasingStyleValue::Function::to_string(SerializationMode mode) const
|
2023-07-06 02:29:36 +03:30
|
|
|
|
{
|
2024-11-03 10:36:44 +11:00
|
|
|
|
return visit(
|
|
|
|
|
|
[&](auto const& curve) {
|
2025-06-17 09:46:51 +01:00
|
|
|
|
return curve.to_string(mode);
|
2024-06-14 21:27:23 -07:00
|
|
|
|
});
|
2023-07-06 02:29:36 +03:30
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-06 17:09:22 +13:00
|
|
|
|
ValueComparingNonnullRefPtr<StyleValue const> EasingStyleValue::absolutized(ComputationContext const& computation_context, PropertyComputationDependencies& property_computation_dependencies) const
|
2025-10-09 23:40:46 +13:00
|
|
|
|
{
|
|
|
|
|
|
auto const& absolutized_function = m_function.visit(
|
|
|
|
|
|
[&](Linear const& linear) -> Function {
|
|
|
|
|
|
Vector<Linear::Stop> absolutized_stops;
|
|
|
|
|
|
|
|
|
|
|
|
for (auto stop : linear.stops) {
|
|
|
|
|
|
RefPtr<StyleValue const> absolutized_input;
|
|
|
|
|
|
|
|
|
|
|
|
if (stop.input)
|
2025-10-06 17:09:22 +13:00
|
|
|
|
absolutized_input = stop.input->absolutized(computation_context, property_computation_dependencies);
|
2025-10-09 23:40:46 +13:00
|
|
|
|
|
2025-10-06 17:09:22 +13:00
|
|
|
|
absolutized_stops.append({ stop.output->absolutized(computation_context, property_computation_dependencies), absolutized_input });
|
2025-10-09 23:40:46 +13:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return Linear { absolutized_stops };
|
|
|
|
|
|
},
|
|
|
|
|
|
[&](CubicBezier const& cubic_bezier) -> Function {
|
2025-10-11 15:09:11 +13:00
|
|
|
|
return CubicBezier {
|
2025-10-06 17:09:22 +13:00
|
|
|
|
cubic_bezier.x1->absolutized(computation_context, property_computation_dependencies),
|
|
|
|
|
|
cubic_bezier.y1->absolutized(computation_context, property_computation_dependencies),
|
|
|
|
|
|
cubic_bezier.x2->absolutized(computation_context, property_computation_dependencies),
|
|
|
|
|
|
cubic_bezier.y2->absolutized(computation_context, property_computation_dependencies)
|
2025-10-11 15:09:11 +13:00
|
|
|
|
};
|
2025-10-09 23:40:46 +13:00
|
|
|
|
},
|
|
|
|
|
|
[&](Steps const& steps) -> Function {
|
2025-10-11 15:09:11 +13:00
|
|
|
|
return Steps {
|
2025-10-06 17:09:22 +13:00
|
|
|
|
steps.number_of_intervals->absolutized(computation_context, property_computation_dependencies),
|
2025-10-11 15:09:11 +13:00
|
|
|
|
steps.position
|
|
|
|
|
|
};
|
2025-10-09 23:40:46 +13:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return EasingStyleValue::create(absolutized_function);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-07-06 02:29:36 +03:30
|
|
|
|
}
|