mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 14:27:35 +00:00
LibWeb: Add interpolation for shadow values
This commit is contained in:
parent
3c21dd4d2b
commit
ae321b2cdf
1 changed files with 65 additions and 0 deletions
|
@ -760,6 +760,8 @@ static ErrorOr<void> cascade_custom_properties(DOM::Element& element, Optional<C
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ErrorOr<NonnullRefPtr<StyleValue const>> interpolate_value(DOM::Element& element, StyleValue const& from, StyleValue const& to, float delta);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static T interpolate_raw(T from, T to, float delta)
|
static T interpolate_raw(T from, T to, float delta)
|
||||||
{
|
{
|
||||||
|
@ -1076,6 +1078,67 @@ static Color interpolate_color(Color from, Color to, float delta)
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ErrorOr<NonnullRefPtr<StyleValue const>> interpolate_box_shadow(DOM::Element& element, StyleValue const& from, StyleValue const& to, float delta)
|
||||||
|
{
|
||||||
|
// https://drafts.csswg.org/css-backgrounds/#box-shadow
|
||||||
|
// Animation type: by computed value, treating none as a zero-item list and appending blank shadows
|
||||||
|
// (transparent 0 0 0 0) with a corresponding inset keyword as needed to match the longer list if
|
||||||
|
// the shorter list is otherwise compatible with the longer one
|
||||||
|
|
||||||
|
static constexpr auto process_list = [](StyleValue const& value) {
|
||||||
|
StyleValueVector shadows;
|
||||||
|
if (value.is_value_list()) {
|
||||||
|
for (auto const& element : value.as_value_list().values()) {
|
||||||
|
if (element->is_shadow())
|
||||||
|
shadows.append(element);
|
||||||
|
}
|
||||||
|
} else if (value.is_shadow()) {
|
||||||
|
shadows.append(value);
|
||||||
|
} else if (!value.is_identifier() || value.as_identifier().id() != ValueID::None) {
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
}
|
||||||
|
return shadows;
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr auto extend_list_if_necessary = [](StyleValueVector& values, StyleValueVector const& other) {
|
||||||
|
values.ensure_capacity(other.size());
|
||||||
|
for (size_t i = values.size(); i < other.size(); i++) {
|
||||||
|
values.unchecked_append(ShadowStyleValue::create(
|
||||||
|
Color::Transparent,
|
||||||
|
LengthStyleValue::create(Length::make_px(0)),
|
||||||
|
LengthStyleValue::create(Length::make_px(0)),
|
||||||
|
LengthStyleValue::create(Length::make_px(0)),
|
||||||
|
LengthStyleValue::create(Length::make_px(0)),
|
||||||
|
other[i]->as_shadow().placement()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
StyleValueVector from_shadows = process_list(from);
|
||||||
|
StyleValueVector to_shadows = process_list(to);
|
||||||
|
|
||||||
|
extend_list_if_necessary(from_shadows, to_shadows);
|
||||||
|
extend_list_if_necessary(to_shadows, from_shadows);
|
||||||
|
|
||||||
|
VERIFY(from_shadows.size() == to_shadows.size());
|
||||||
|
StyleValueVector result_shadows;
|
||||||
|
result_shadows.ensure_capacity(from_shadows.size());
|
||||||
|
|
||||||
|
for (size_t i = 0; i < from_shadows.size(); i++) {
|
||||||
|
auto const& from_shadow = from_shadows[i]->as_shadow();
|
||||||
|
auto const& to_shadow = to_shadows[i]->as_shadow();
|
||||||
|
auto result_shadow = ShadowStyleValue::create(
|
||||||
|
interpolate_color(from_shadow.color(), to_shadow.color(), delta),
|
||||||
|
TRY(interpolate_value(element, from_shadow.offset_x(), to_shadow.offset_x(), delta)),
|
||||||
|
TRY(interpolate_value(element, from_shadow.offset_y(), to_shadow.offset_y(), delta)),
|
||||||
|
TRY(interpolate_value(element, from_shadow.blur_radius(), to_shadow.blur_radius(), delta)),
|
||||||
|
TRY(interpolate_value(element, from_shadow.spread_distance(), to_shadow.spread_distance(), delta)),
|
||||||
|
delta >= 0.5f ? to_shadow.placement() : from_shadow.placement());
|
||||||
|
result_shadows.unchecked_append(result_shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
return StyleValueList::create(move(result_shadows), StyleValueList::Separator::Comma);
|
||||||
|
}
|
||||||
|
|
||||||
static ErrorOr<NonnullRefPtr<StyleValue const>> interpolate_value(DOM::Element& element, StyleValue const& from, StyleValue const& to, float delta)
|
static ErrorOr<NonnullRefPtr<StyleValue const>> interpolate_value(DOM::Element& element, StyleValue const& from, StyleValue const& to, float delta)
|
||||||
{
|
{
|
||||||
if (from.type() != to.type())
|
if (from.type() != to.type())
|
||||||
|
@ -1161,6 +1224,8 @@ static ErrorOr<ValueComparingNonnullRefPtr<StyleValue const>> interpolate_proper
|
||||||
case AnimationType::Custom: {
|
case AnimationType::Custom: {
|
||||||
if (property_id == PropertyID::Transform)
|
if (property_id == PropertyID::Transform)
|
||||||
return interpolate_transform(element, from, to, delta);
|
return interpolate_transform(element, from, to, delta);
|
||||||
|
if (property_id == PropertyID::BoxShadow)
|
||||||
|
return interpolate_box_shadow(element, from, to, delta);
|
||||||
|
|
||||||
// FIXME: Handle all custom animatable properties
|
// FIXME: Handle all custom animatable properties
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue