mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-09 09:39:39 +00:00
LibWeb: Parse and store filter
property
This shares its implementation with `backdrop-filter`.
This commit is contained in:
parent
ea9abe26e1
commit
29974de852
Notes:
github-actions[bot]
2024-10-26 09:28:54 +00:00
Author: https://github.com/gmta
Commit: 29974de852
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1963
14 changed files with 104 additions and 75 deletions
|
@ -104,6 +104,7 @@ counter-set: none
|
||||||
cx: 0px
|
cx: 0px
|
||||||
cy: 0px
|
cy: 0px
|
||||||
display: block
|
display: block
|
||||||
|
filter: none
|
||||||
flex-basis: auto
|
flex-basis: auto
|
||||||
flex-direction: row
|
flex-direction: row
|
||||||
flex-grow: 0
|
flex-grow: 0
|
||||||
|
@ -120,7 +121,7 @@ grid-row-start: auto
|
||||||
grid-template-areas: none
|
grid-template-areas: none
|
||||||
grid-template-columns: auto
|
grid-template-columns: auto
|
||||||
grid-template-rows: auto
|
grid-template-rows: auto
|
||||||
height: 2074px
|
height: 2091px
|
||||||
inline-size: auto
|
inline-size: auto
|
||||||
inset-block-end: auto
|
inset-block-end: auto
|
||||||
inset-block-start: auto
|
inset-block-start: auto
|
||||||
|
|
|
@ -11,12 +11,12 @@
|
||||||
#include <AK/Optional.h>
|
#include <AK/Optional.h>
|
||||||
#include <LibGfx/FontCascadeList.h>
|
#include <LibGfx/FontCascadeList.h>
|
||||||
#include <LibGfx/ScalingMode.h>
|
#include <LibGfx/ScalingMode.h>
|
||||||
#include <LibWeb/CSS/BackdropFilter.h>
|
|
||||||
#include <LibWeb/CSS/CalculatedOr.h>
|
#include <LibWeb/CSS/CalculatedOr.h>
|
||||||
#include <LibWeb/CSS/Clip.h>
|
#include <LibWeb/CSS/Clip.h>
|
||||||
#include <LibWeb/CSS/ColumnCount.h>
|
#include <LibWeb/CSS/ColumnCount.h>
|
||||||
#include <LibWeb/CSS/CountersSet.h>
|
#include <LibWeb/CSS/CountersSet.h>
|
||||||
#include <LibWeb/CSS/Display.h>
|
#include <LibWeb/CSS/Display.h>
|
||||||
|
#include <LibWeb/CSS/Filter.h>
|
||||||
#include <LibWeb/CSS/GridTrackPlacement.h>
|
#include <LibWeb/CSS/GridTrackPlacement.h>
|
||||||
#include <LibWeb/CSS/GridTrackSize.h>
|
#include <LibWeb/CSS/GridTrackSize.h>
|
||||||
#include <LibWeb/CSS/LengthBox.h>
|
#include <LibWeb/CSS/LengthBox.h>
|
||||||
|
@ -55,7 +55,7 @@ struct QuotesData {
|
||||||
Vector<Array<FlyString, 2>> strings {};
|
Vector<Array<FlyString, 2>> strings {};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ResolvedBackdropFilter {
|
struct ResolvedFilter {
|
||||||
struct Blur {
|
struct Blur {
|
||||||
float radius;
|
float radius;
|
||||||
};
|
};
|
||||||
|
@ -64,19 +64,19 @@ struct ResolvedBackdropFilter {
|
||||||
double offset_x;
|
double offset_x;
|
||||||
double offset_y;
|
double offset_y;
|
||||||
double radius;
|
double radius;
|
||||||
Color color;
|
Gfx::Color color;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HueRotate {
|
struct HueRotate {
|
||||||
float angle_degrees;
|
float angle_degrees;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ColorOperation {
|
struct Color {
|
||||||
Filter::Color::Operation operation;
|
FilterOperation::Color::Type type;
|
||||||
float amount;
|
float amount;
|
||||||
};
|
};
|
||||||
|
|
||||||
using FilterFunction = Variant<Blur, DropShadow, HueRotate, ColorOperation>;
|
using FilterFunction = Variant<Blur, DropShadow, HueRotate, Color>;
|
||||||
|
|
||||||
bool is_none() const { return filters.size() == 0; }
|
bool is_none() const { return filters.size() == 0; }
|
||||||
|
|
||||||
|
@ -121,7 +121,8 @@ public:
|
||||||
static CSS::Display display() { return CSS::Display { CSS::DisplayOutside::Inline, CSS::DisplayInside::Flow }; }
|
static CSS::Display display() { return CSS::Display { CSS::DisplayOutside::Inline, CSS::DisplayInside::Flow }; }
|
||||||
static Color color() { return Color::Black; }
|
static Color color() { return Color::Black; }
|
||||||
static Color stop_color() { return Color::Black; }
|
static Color stop_color() { return Color::Black; }
|
||||||
static CSS::ResolvedBackdropFilter backdrop_filter() { return ResolvedBackdropFilter { .filters = {} }; }
|
static CSS::ResolvedFilter backdrop_filter() { return ResolvedFilter { .filters = {} }; }
|
||||||
|
static CSS::ResolvedFilter filter() { return ResolvedFilter { .filters = {} }; }
|
||||||
static Color background_color() { return Color::Transparent; }
|
static Color background_color() { return Color::Transparent; }
|
||||||
static CSS::ListStyleType list_style_type() { return CSS::ListStyleType::Disc; }
|
static CSS::ListStyleType list_style_type() { return CSS::ListStyleType::Disc; }
|
||||||
static CSS::ListStylePosition list_style_position() { return CSS::ListStylePosition::Outside; }
|
static CSS::ListStylePosition list_style_position() { return CSS::ListStylePosition::Outside; }
|
||||||
|
@ -409,7 +410,8 @@ public:
|
||||||
CSS::JustifyContent justify_content() const { return m_noninherited.justify_content; }
|
CSS::JustifyContent justify_content() const { return m_noninherited.justify_content; }
|
||||||
CSS::JustifySelf justify_self() const { return m_noninherited.justify_self; }
|
CSS::JustifySelf justify_self() const { return m_noninherited.justify_self; }
|
||||||
CSS::JustifyItems justify_items() const { return m_noninherited.justify_items; }
|
CSS::JustifyItems justify_items() const { return m_noninherited.justify_items; }
|
||||||
CSS::ResolvedBackdropFilter const& backdrop_filter() const { return m_noninherited.backdrop_filter; }
|
CSS::ResolvedFilter const& backdrop_filter() const { return m_noninherited.backdrop_filter; }
|
||||||
|
CSS::ResolvedFilter const& filter() const { return m_noninherited.filter; }
|
||||||
Vector<ShadowData> const& box_shadow() const { return m_noninherited.box_shadow; }
|
Vector<ShadowData> const& box_shadow() const { return m_noninherited.box_shadow; }
|
||||||
CSS::BoxSizing box_sizing() const { return m_noninherited.box_sizing; }
|
CSS::BoxSizing box_sizing() const { return m_noninherited.box_sizing; }
|
||||||
CSS::Size const& width() const { return m_noninherited.width; }
|
CSS::Size const& width() const { return m_noninherited.width; }
|
||||||
|
@ -601,7 +603,8 @@ protected:
|
||||||
CSS::LengthBox inset { InitialValues::inset() };
|
CSS::LengthBox inset { InitialValues::inset() };
|
||||||
CSS::LengthBox margin { InitialValues::margin() };
|
CSS::LengthBox margin { InitialValues::margin() };
|
||||||
CSS::LengthBox padding { InitialValues::padding() };
|
CSS::LengthBox padding { InitialValues::padding() };
|
||||||
CSS::ResolvedBackdropFilter backdrop_filter { InitialValues::backdrop_filter() };
|
CSS::ResolvedFilter backdrop_filter { InitialValues::backdrop_filter() };
|
||||||
|
CSS::ResolvedFilter filter { InitialValues::filter() };
|
||||||
BorderData border_left;
|
BorderData border_left;
|
||||||
BorderData border_top;
|
BorderData border_top;
|
||||||
BorderData border_right;
|
BorderData border_right;
|
||||||
|
@ -746,7 +749,8 @@ public:
|
||||||
void set_list_style_type(CSS::ListStyleType value) { m_inherited.list_style_type = value; }
|
void set_list_style_type(CSS::ListStyleType value) { m_inherited.list_style_type = value; }
|
||||||
void set_list_style_position(CSS::ListStylePosition value) { m_inherited.list_style_position = value; }
|
void set_list_style_position(CSS::ListStylePosition value) { m_inherited.list_style_position = value; }
|
||||||
void set_display(CSS::Display value) { m_noninherited.display = value; }
|
void set_display(CSS::Display value) { m_noninherited.display = value; }
|
||||||
void set_backdrop_filter(CSS::ResolvedBackdropFilter backdrop_filter) { m_noninherited.backdrop_filter = move(backdrop_filter); }
|
void set_backdrop_filter(CSS::ResolvedFilter backdrop_filter) { m_noninherited.backdrop_filter = move(backdrop_filter); }
|
||||||
|
void set_filter(CSS::ResolvedFilter filter) { m_noninherited.filter = move(filter); }
|
||||||
void set_border_bottom_left_radius(CSS::BorderRadiusData value) { m_noninherited.border_bottom_left_radius = move(value); }
|
void set_border_bottom_left_radius(CSS::BorderRadiusData value) { m_noninherited.border_bottom_left_radius = move(value); }
|
||||||
void set_border_bottom_right_radius(CSS::BorderRadiusData value) { m_noninherited.border_bottom_right_radius = move(value); }
|
void set_border_bottom_right_radius(CSS::BorderRadiusData value) { m_noninherited.border_bottom_right_radius = move(value); }
|
||||||
void set_border_top_left_radius(CSS::BorderRadiusData value) { m_noninherited.border_top_left_radius = move(value); }
|
void set_border_top_left_radius(CSS::BorderRadiusData value) { m_noninherited.border_top_left_radius = move(value); }
|
||||||
|
|
|
@ -12,15 +12,15 @@
|
||||||
|
|
||||||
namespace Web::CSS {
|
namespace Web::CSS {
|
||||||
|
|
||||||
class BackdropFilter {
|
class Filter {
|
||||||
public:
|
public:
|
||||||
BackdropFilter() = default;
|
Filter() = default;
|
||||||
BackdropFilter(FilterValueListStyleValue const& filter_value_list)
|
Filter(FilterValueListStyleValue const& filter_value_list)
|
||||||
: m_filter_value_list { filter_value_list } {};
|
: m_filter_value_list { filter_value_list } {};
|
||||||
|
|
||||||
static inline BackdropFilter make_none()
|
static Filter make_none()
|
||||||
{
|
{
|
||||||
return BackdropFilter {};
|
return Filter {};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has_filters() const { return m_filter_value_list; }
|
bool has_filters() const { return m_filter_value_list; }
|
|
@ -5156,7 +5156,7 @@ RefPtr<CSSStyleValue> Parser::parse_filter_value_list_value(TokenStream<Componen
|
||||||
|
|
||||||
auto filter_token_to_operation = [&](auto filter) {
|
auto filter_token_to_operation = [&](auto filter) {
|
||||||
VERIFY(to_underlying(filter) < to_underlying(FilterToken::Blur));
|
VERIFY(to_underlying(filter) < to_underlying(FilterToken::Blur));
|
||||||
return static_cast<Filter::Color::Operation>(filter);
|
return static_cast<FilterOperation::Color::Type>(filter);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto parse_number_percentage = [&](auto& token) -> Optional<NumberPercentage> {
|
auto parse_number_percentage = [&](auto& token) -> Optional<NumberPercentage> {
|
||||||
|
@ -5205,13 +5205,13 @@ RefPtr<CSSStyleValue> Parser::parse_filter_value_list_value(TokenStream<Componen
|
||||||
if (filter_token == FilterToken::Blur) {
|
if (filter_token == FilterToken::Blur) {
|
||||||
// blur( <length>? )
|
// blur( <length>? )
|
||||||
if (!tokens.has_next_token())
|
if (!tokens.has_next_token())
|
||||||
return Filter::Blur {};
|
return FilterOperation::Blur {};
|
||||||
auto blur_radius = parse_length(tokens);
|
auto blur_radius = parse_length(tokens);
|
||||||
tokens.discard_whitespace();
|
tokens.discard_whitespace();
|
||||||
if (!blur_radius.has_value())
|
if (!blur_radius.has_value())
|
||||||
return {};
|
return {};
|
||||||
// FIXME: Support calculated radius
|
// FIXME: Support calculated radius
|
||||||
return if_no_more_tokens_return(Filter::Blur { blur_radius->value() });
|
return if_no_more_tokens_return(FilterOperation::Blur { blur_radius->value() });
|
||||||
} else if (filter_token == FilterToken::DropShadow) {
|
} else if (filter_token == FilterToken::DropShadow) {
|
||||||
if (!tokens.has_next_token())
|
if (!tokens.has_next_token())
|
||||||
return {};
|
return {};
|
||||||
|
@ -5240,17 +5240,17 @@ RefPtr<CSSStyleValue> Parser::parse_filter_value_list_value(TokenStream<Componen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// FIXME: Support calculated offsets and radius
|
// FIXME: Support calculated offsets and radius
|
||||||
return if_no_more_tokens_return(Filter::DropShadow { x_offset->value(), y_offset->value(), maybe_radius.map([](auto& it) { return it.value(); }), maybe_color->to_color({}) });
|
return if_no_more_tokens_return(FilterOperation::DropShadow { x_offset->value(), y_offset->value(), maybe_radius.map([](auto& it) { return it.value(); }), maybe_color->to_color({}) });
|
||||||
} else if (filter_token == FilterToken::HueRotate) {
|
} else if (filter_token == FilterToken::HueRotate) {
|
||||||
// hue-rotate( [ <angle> | <zero> ]? )
|
// hue-rotate( [ <angle> | <zero> ]? )
|
||||||
if (!tokens.has_next_token())
|
if (!tokens.has_next_token())
|
||||||
return Filter::HueRotate {};
|
return FilterOperation::HueRotate {};
|
||||||
auto& token = tokens.consume_a_token();
|
auto& token = tokens.consume_a_token();
|
||||||
if (token.is(Token::Type::Number)) {
|
if (token.is(Token::Type::Number)) {
|
||||||
// hue-rotate(0)
|
// hue-rotate(0)
|
||||||
auto number = token.token().number();
|
auto number = token.token().number();
|
||||||
if (number.is_integer() && number.integer_value() == 0)
|
if (number.is_integer() && number.integer_value() == 0)
|
||||||
return if_no_more_tokens_return(Filter::HueRotate { Filter::HueRotate::Zero {} });
|
return if_no_more_tokens_return(FilterOperation::HueRotate { FilterOperation::HueRotate::Zero {} });
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
if (!token.is(Token::Type::Dimension))
|
if (!token.is(Token::Type::Dimension))
|
||||||
|
@ -5261,7 +5261,7 @@ RefPtr<CSSStyleValue> Parser::parse_filter_value_list_value(TokenStream<Componen
|
||||||
if (!angle_unit.has_value())
|
if (!angle_unit.has_value())
|
||||||
return {};
|
return {};
|
||||||
Angle angle { angle_value, angle_unit.release_value() };
|
Angle angle { angle_value, angle_unit.release_value() };
|
||||||
return if_no_more_tokens_return(Filter::HueRotate { angle });
|
return if_no_more_tokens_return(FilterOperation::HueRotate { angle });
|
||||||
} else {
|
} else {
|
||||||
// Simple filters:
|
// Simple filters:
|
||||||
// brightness( <number-percentage>? )
|
// brightness( <number-percentage>? )
|
||||||
|
@ -5272,11 +5272,11 @@ RefPtr<CSSStyleValue> Parser::parse_filter_value_list_value(TokenStream<Componen
|
||||||
// sepia( <number-percentage>? )
|
// sepia( <number-percentage>? )
|
||||||
// saturate( <number-percentage>? )
|
// saturate( <number-percentage>? )
|
||||||
if (!tokens.has_next_token())
|
if (!tokens.has_next_token())
|
||||||
return Filter::Color { filter_token_to_operation(filter_token) };
|
return FilterOperation::Color { filter_token_to_operation(filter_token) };
|
||||||
auto amount = parse_number_percentage(tokens.consume_a_token());
|
auto amount = parse_number_percentage(tokens.consume_a_token());
|
||||||
if (!amount.has_value())
|
if (!amount.has_value())
|
||||||
return {};
|
return {};
|
||||||
return if_no_more_tokens_return(Filter::Color { filter_token_to_operation(filter_token), *amount });
|
return if_no_more_tokens_return(FilterOperation::Color { filter_token_to_operation(filter_token), *amount });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -7860,6 +7860,7 @@ Parser::ParseErrorOr<NonnullRefPtr<CSSStyleValue>> Parser::parse_css_value(Prope
|
||||||
return parsed_value.release_nonnull();
|
return parsed_value.release_nonnull();
|
||||||
return ParseError::SyntaxError;
|
return ParseError::SyntaxError;
|
||||||
case PropertyID::BackdropFilter:
|
case PropertyID::BackdropFilter:
|
||||||
|
case PropertyID::Filter:
|
||||||
if (auto parsed_value = parse_filter_value_list_value(tokens); parsed_value && !tokens.has_next_token())
|
if (auto parsed_value = parse_filter_value_list_value(tokens); parsed_value && !tokens.has_next_token())
|
||||||
return parsed_value.release_nonnull();
|
return parsed_value.release_nonnull();
|
||||||
return ParseError::SyntaxError;
|
return ParseError::SyntaxError;
|
||||||
|
|
|
@ -1065,6 +1065,16 @@
|
||||||
"fill-rule"
|
"fill-rule"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"filter": {
|
||||||
|
"affects-layout": false,
|
||||||
|
"animation-type": "custom",
|
||||||
|
"inherited": false,
|
||||||
|
"initial": "none",
|
||||||
|
"__comment": "FIXME: List `filter-value-list` as a valid-type once it's generically supported.",
|
||||||
|
"valid-identifiers": [
|
||||||
|
"none"
|
||||||
|
]
|
||||||
|
},
|
||||||
"flex": {
|
"flex": {
|
||||||
"inherited": false,
|
"inherited": false,
|
||||||
"initial": "0 1 auto",
|
"initial": "0 1 auto",
|
||||||
|
|
|
@ -613,12 +613,20 @@ Optional<CSS::Appearance> StyleProperties::appearance() const
|
||||||
return appearance;
|
return appearance;
|
||||||
}
|
}
|
||||||
|
|
||||||
CSS::BackdropFilter StyleProperties::backdrop_filter() const
|
CSS::Filter StyleProperties::backdrop_filter() const
|
||||||
{
|
{
|
||||||
auto value = property(CSS::PropertyID::BackdropFilter);
|
auto value = property(CSS::PropertyID::BackdropFilter);
|
||||||
if (value->is_filter_value_list())
|
if (value->is_filter_value_list())
|
||||||
return BackdropFilter(value->as_filter_value_list());
|
return Filter(value->as_filter_value_list());
|
||||||
return BackdropFilter::make_none();
|
return Filter::make_none();
|
||||||
|
}
|
||||||
|
|
||||||
|
CSS::Filter StyleProperties::filter() const
|
||||||
|
{
|
||||||
|
auto value = property(CSS::PropertyID::Filter);
|
||||||
|
if (value->is_filter_value_list())
|
||||||
|
return Filter(value->as_filter_value_list());
|
||||||
|
return Filter::make_none();
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<CSS::Positioning> StyleProperties::position() const
|
Optional<CSS::Positioning> StyleProperties::position() const
|
||||||
|
|
|
@ -137,7 +137,8 @@ public:
|
||||||
Optional<CSS::AlignItems> align_items() const;
|
Optional<CSS::AlignItems> align_items() const;
|
||||||
Optional<CSS::AlignSelf> align_self() const;
|
Optional<CSS::AlignSelf> align_self() const;
|
||||||
Optional<CSS::Appearance> appearance() const;
|
Optional<CSS::Appearance> appearance() const;
|
||||||
CSS::BackdropFilter backdrop_filter() const;
|
CSS::Filter backdrop_filter() const;
|
||||||
|
CSS::Filter filter() const;
|
||||||
float opacity() const;
|
float opacity() const;
|
||||||
Optional<CSS::Visibility> visibility() const;
|
Optional<CSS::Visibility> visibility() const;
|
||||||
Optional<CSS::ImageRendering> image_rendering() const;
|
Optional<CSS::ImageRendering> image_rendering() const;
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
namespace Web::CSS {
|
namespace Web::CSS {
|
||||||
|
|
||||||
float Filter::Blur::resolved_radius(Layout::Node const& node) const
|
float FilterOperation::Blur::resolved_radius(Layout::Node const& node) const
|
||||||
{
|
{
|
||||||
// Default value when omitted is 0px.
|
// Default value when omitted is 0px.
|
||||||
auto sigma = 0;
|
auto sigma = 0;
|
||||||
|
@ -23,7 +23,7 @@ float Filter::Blur::resolved_radius(Layout::Node const& node) const
|
||||||
return sigma * 2;
|
return sigma * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
float Filter::HueRotate::angle_degrees() const
|
float FilterOperation::HueRotate::angle_degrees() const
|
||||||
{
|
{
|
||||||
// Default value when omitted is 0deg.
|
// Default value when omitted is 0deg.
|
||||||
if (!angle.has_value())
|
if (!angle.has_value())
|
||||||
|
@ -31,7 +31,7 @@ float Filter::HueRotate::angle_degrees() const
|
||||||
return angle->visit([&](Angle const& a) { return a.to_degrees(); }, [&](auto) { return 0.0; });
|
return angle->visit([&](Angle const& a) { return a.to_degrees(); }, [&](auto) { return 0.0; });
|
||||||
}
|
}
|
||||||
|
|
||||||
float Filter::Color::resolved_amount() const
|
float FilterOperation::Color::resolved_amount() const
|
||||||
{
|
{
|
||||||
if (amount.has_value()) {
|
if (amount.has_value()) {
|
||||||
if (amount->is_percentage())
|
if (amount->is_percentage())
|
||||||
|
@ -50,12 +50,12 @@ String FilterValueListStyleValue::to_string() const
|
||||||
if (!first)
|
if (!first)
|
||||||
builder.append(' ');
|
builder.append(' ');
|
||||||
filter_function.visit(
|
filter_function.visit(
|
||||||
[&](Filter::Blur const& blur) {
|
[&](FilterOperation::Blur const& blur) {
|
||||||
builder.append("blur("sv);
|
builder.append("blur("sv);
|
||||||
if (blur.radius.has_value())
|
if (blur.radius.has_value())
|
||||||
builder.append(blur.radius->to_string());
|
builder.append(blur.radius->to_string());
|
||||||
},
|
},
|
||||||
[&](Filter::DropShadow const& drop_shadow) {
|
[&](FilterOperation::DropShadow const& drop_shadow) {
|
||||||
builder.appendff("drop-shadow({} {}"sv,
|
builder.appendff("drop-shadow({} {}"sv,
|
||||||
drop_shadow.offset_x, drop_shadow.offset_y);
|
drop_shadow.offset_x, drop_shadow.offset_y);
|
||||||
if (drop_shadow.radius.has_value())
|
if (drop_shadow.radius.has_value())
|
||||||
|
@ -65,7 +65,7 @@ String FilterValueListStyleValue::to_string() const
|
||||||
serialize_a_srgb_value(builder, *drop_shadow.color);
|
serialize_a_srgb_value(builder, *drop_shadow.color);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[&](Filter::HueRotate const& hue_rotate) {
|
[&](FilterOperation::HueRotate const& hue_rotate) {
|
||||||
builder.append("hue-rotate("sv);
|
builder.append("hue-rotate("sv);
|
||||||
if (hue_rotate.angle.has_value()) {
|
if (hue_rotate.angle.has_value()) {
|
||||||
hue_rotate.angle->visit(
|
hue_rotate.angle->visit(
|
||||||
|
@ -77,23 +77,23 @@ String FilterValueListStyleValue::to_string() const
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[&](Filter::Color const& color) {
|
[&](FilterOperation::Color const& color) {
|
||||||
builder.appendff("{}(",
|
builder.appendff("{}(",
|
||||||
[&] {
|
[&] {
|
||||||
switch (color.operation) {
|
switch (color.operation) {
|
||||||
case Filter::Color::Operation::Brightness:
|
case FilterOperation::Color::Type::Brightness:
|
||||||
return "brightness"sv;
|
return "brightness"sv;
|
||||||
case Filter::Color::Operation::Contrast:
|
case FilterOperation::Color::Type::Contrast:
|
||||||
return "contrast"sv;
|
return "contrast"sv;
|
||||||
case Filter::Color::Operation::Grayscale:
|
case FilterOperation::Color::Type::Grayscale:
|
||||||
return "grayscale"sv;
|
return "grayscale"sv;
|
||||||
case Filter::Color::Operation::Invert:
|
case FilterOperation::Color::Type::Invert:
|
||||||
return "invert"sv;
|
return "invert"sv;
|
||||||
case Filter::Color::Operation::Opacity:
|
case FilterOperation::Color::Type::Opacity:
|
||||||
return "opacity"sv;
|
return "opacity"sv;
|
||||||
case Filter::Color::Operation::Saturate:
|
case FilterOperation::Color::Type::Saturate:
|
||||||
return "saturate"sv;
|
return "saturate"sv;
|
||||||
case Filter::Color::Operation::Sepia:
|
case FilterOperation::Color::Type::Sepia:
|
||||||
return "sepia"sv;
|
return "sepia"sv;
|
||||||
default:
|
default:
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
namespace Web::CSS {
|
namespace Web::CSS {
|
||||||
|
|
||||||
namespace Filter {
|
namespace FilterOperation {
|
||||||
|
|
||||||
struct Blur {
|
struct Blur {
|
||||||
Optional<Length> radius {};
|
Optional<Length> radius {};
|
||||||
|
@ -43,7 +43,7 @@ struct HueRotate {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Color {
|
struct Color {
|
||||||
enum class Operation {
|
enum class Type {
|
||||||
Brightness,
|
Brightness,
|
||||||
Contrast,
|
Contrast,
|
||||||
Grayscale,
|
Grayscale,
|
||||||
|
@ -59,7 +59,7 @@ struct Color {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
using FilterFunction = Variant<Filter::Blur, Filter::DropShadow, Filter::HueRotate, Filter::Color>;
|
using FilterFunction = Variant<FilterOperation::Blur, FilterOperation::DropShadow, FilterOperation::HueRotate, FilterOperation::Color>;
|
||||||
|
|
||||||
class FilterValueListStyleValue final : public StyleValueWithDefaultOperators<FilterValueListStyleValue> {
|
class FilterValueListStyleValue final : public StyleValueWithDefaultOperators<FilterValueListStyleValue> {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -512,34 +512,38 @@ void NodeWithStyle::apply_style(const CSS::StyleProperties& computed_style)
|
||||||
computed_values.set_order(computed_style.order());
|
computed_values.set_order(computed_style.order());
|
||||||
computed_values.set_clip(computed_style.clip());
|
computed_values.set_clip(computed_style.clip());
|
||||||
|
|
||||||
if (computed_style.backdrop_filter().has_filters()) {
|
auto resolve_filter = [this](CSS::Filter const& computed_filter) -> CSS::ResolvedFilter {
|
||||||
CSS::ResolvedBackdropFilter resolved_backdrop_filter;
|
CSS::ResolvedFilter resolved_filter;
|
||||||
for (auto& filter : computed_style.backdrop_filter().filters()) {
|
for (auto const& filter : computed_filter.filters()) {
|
||||||
filter.visit(
|
filter.visit(
|
||||||
[&](CSS::Filter::Blur const& blur) {
|
[&](CSS::FilterOperation::Blur const& blur) {
|
||||||
resolved_backdrop_filter.filters.append(CSS::ResolvedBackdropFilter::Blur {
|
resolved_filter.filters.append(CSS::ResolvedFilter::Blur {
|
||||||
.radius = blur.resolved_radius(*this) });
|
.radius = blur.resolved_radius(*this) });
|
||||||
},
|
},
|
||||||
[&](CSS::Filter::DropShadow const& drop_shadow) {
|
[&](CSS::FilterOperation::DropShadow const& drop_shadow) {
|
||||||
// The default value for omitted values is missing length values set to 0
|
// The default value for omitted values is missing length values set to 0
|
||||||
// and the missing used color is taken from the color property.
|
// and the missing used color is taken from the color property.
|
||||||
resolved_backdrop_filter.filters.append(CSS::ResolvedBackdropFilter::DropShadow {
|
resolved_filter.filters.append(CSS::ResolvedFilter::DropShadow {
|
||||||
.offset_x = drop_shadow.offset_x.to_px(*this).to_double(),
|
.offset_x = drop_shadow.offset_x.to_px(*this).to_double(),
|
||||||
.offset_y = drop_shadow.offset_y.to_px(*this).to_double(),
|
.offset_y = drop_shadow.offset_y.to_px(*this).to_double(),
|
||||||
.radius = drop_shadow.radius.has_value() ? drop_shadow.radius->to_px(*this).to_double() : 0.0,
|
.radius = drop_shadow.radius.has_value() ? drop_shadow.radius->to_px(*this).to_double() : 0.0,
|
||||||
.color = drop_shadow.color.has_value() ? *drop_shadow.color : this->computed_values().color() });
|
.color = drop_shadow.color.has_value() ? *drop_shadow.color : this->computed_values().color() });
|
||||||
},
|
},
|
||||||
[&](CSS::Filter::Color const& color_operation) {
|
[&](CSS::FilterOperation::Color const& color_operation) {
|
||||||
resolved_backdrop_filter.filters.append(CSS::ResolvedBackdropFilter::ColorOperation {
|
resolved_filter.filters.append(CSS::ResolvedFilter::Color {
|
||||||
.operation = color_operation.operation,
|
.type = color_operation.operation,
|
||||||
.amount = color_operation.resolved_amount() });
|
.amount = color_operation.resolved_amount() });
|
||||||
},
|
},
|
||||||
[&](CSS::Filter::HueRotate const& hue_rotate) {
|
[&](CSS::FilterOperation::HueRotate const& hue_rotate) {
|
||||||
resolved_backdrop_filter.filters.append(CSS::ResolvedBackdropFilter::HueRotate { .angle_degrees = hue_rotate.angle_degrees() });
|
resolved_filter.filters.append(CSS::ResolvedFilter::HueRotate { .angle_degrees = hue_rotate.angle_degrees() });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
computed_values.set_backdrop_filter(resolved_backdrop_filter);
|
return resolved_filter;
|
||||||
}
|
};
|
||||||
|
if (computed_style.backdrop_filter().has_filters())
|
||||||
|
computed_values.set_backdrop_filter(resolve_filter(computed_style.backdrop_filter()));
|
||||||
|
if (computed_style.filter().has_filters())
|
||||||
|
computed_values.set_filter(resolve_filter(computed_style.filter()));
|
||||||
|
|
||||||
auto justify_content = computed_style.justify_content();
|
auto justify_content = computed_style.justify_content();
|
||||||
if (justify_content.has_value())
|
if (justify_content.has_value())
|
||||||
|
|
|
@ -285,7 +285,7 @@ struct DrawLine {
|
||||||
struct ApplyBackdropFilter {
|
struct ApplyBackdropFilter {
|
||||||
Gfx::IntRect backdrop_region;
|
Gfx::IntRect backdrop_region;
|
||||||
BorderRadiiData border_radii_data;
|
BorderRadiiData border_radii_data;
|
||||||
CSS::ResolvedBackdropFilter backdrop_filter;
|
CSS::ResolvedFilter backdrop_filter;
|
||||||
|
|
||||||
[[nodiscard]] Gfx::IntRect bounding_rect() const { return backdrop_region; }
|
[[nodiscard]] Gfx::IntRect bounding_rect() const { return backdrop_region; }
|
||||||
|
|
||||||
|
|
|
@ -964,18 +964,18 @@ void DisplayListPlayerSkia::apply_backdrop_filter(ApplyBackdropFilter const& com
|
||||||
for (auto const& filter_function : command.backdrop_filter.filters) {
|
for (auto const& filter_function : command.backdrop_filter.filters) {
|
||||||
// See: https://drafts.fxtf.org/filter-effects-1/#supported-filter-functions
|
// See: https://drafts.fxtf.org/filter-effects-1/#supported-filter-functions
|
||||||
filter_function.visit(
|
filter_function.visit(
|
||||||
[&](CSS::ResolvedBackdropFilter::Blur const& blur_filter) {
|
[&](CSS::ResolvedFilter::Blur const& blur_filter) {
|
||||||
auto blur_image_filter = SkImageFilters::Blur(blur_filter.radius, blur_filter.radius, nullptr);
|
auto blur_image_filter = SkImageFilters::Blur(blur_filter.radius, blur_filter.radius, nullptr);
|
||||||
canvas.saveLayer(SkCanvas::SaveLayerRec(nullptr, nullptr, blur_image_filter.get(), 0));
|
canvas.saveLayer(SkCanvas::SaveLayerRec(nullptr, nullptr, blur_image_filter.get(), 0));
|
||||||
canvas.restore();
|
canvas.restore();
|
||||||
},
|
},
|
||||||
[&](CSS::ResolvedBackdropFilter::ColorOperation const& color) {
|
[&](CSS::ResolvedFilter::Color const& color) {
|
||||||
auto amount = clamp(color.amount, 0.0f, 1.0f);
|
auto amount = clamp(color.amount, 0.0f, 1.0f);
|
||||||
|
|
||||||
// Matrices are taken from https://drafts.fxtf.org/filter-effects-1/#FilterPrimitiveRepresentation
|
// Matrices are taken from https://drafts.fxtf.org/filter-effects-1/#FilterPrimitiveRepresentation
|
||||||
sk_sp<SkColorFilter> color_filter;
|
sk_sp<SkColorFilter> color_filter;
|
||||||
switch (color.operation) {
|
switch (color.type) {
|
||||||
case CSS::Filter::Color::Operation::Grayscale: {
|
case CSS::FilterOperation::Color::Type::Grayscale: {
|
||||||
float matrix[20] = {
|
float matrix[20] = {
|
||||||
0.2126f + 0.7874f * (1 - amount), 0.7152f - 0.7152f * (1 - amount), 0.0722f - 0.0722f * (1 - amount), 0, 0,
|
0.2126f + 0.7874f * (1 - amount), 0.7152f - 0.7152f * (1 - amount), 0.0722f - 0.0722f * (1 - amount), 0, 0,
|
||||||
0.2126f - 0.2126f * (1 - amount), 0.7152f + 0.2848f * (1 - amount), 0.0722f - 0.0722f * (1 - amount), 0, 0,
|
0.2126f - 0.2126f * (1 - amount), 0.7152f + 0.2848f * (1 - amount), 0.0722f - 0.0722f * (1 - amount), 0, 0,
|
||||||
|
@ -985,7 +985,7 @@ void DisplayListPlayerSkia::apply_backdrop_filter(ApplyBackdropFilter const& com
|
||||||
color_filter = SkColorFilters::Matrix(matrix);
|
color_filter = SkColorFilters::Matrix(matrix);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CSS::Filter::Color::Operation::Brightness: {
|
case CSS::FilterOperation::Color::Type::Brightness: {
|
||||||
float matrix[20] = {
|
float matrix[20] = {
|
||||||
amount, 0, 0, 0, 0,
|
amount, 0, 0, 0, 0,
|
||||||
0, amount, 0, 0, 0,
|
0, amount, 0, 0, 0,
|
||||||
|
@ -995,7 +995,7 @@ void DisplayListPlayerSkia::apply_backdrop_filter(ApplyBackdropFilter const& com
|
||||||
color_filter = SkColorFilters::Matrix(matrix);
|
color_filter = SkColorFilters::Matrix(matrix);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CSS::Filter::Color::Operation::Contrast: {
|
case CSS::FilterOperation::Color::Type::Contrast: {
|
||||||
float intercept = -(0.5f * amount) + 0.5f;
|
float intercept = -(0.5f * amount) + 0.5f;
|
||||||
float matrix[20] = {
|
float matrix[20] = {
|
||||||
amount, 0, 0, 0, intercept,
|
amount, 0, 0, 0, intercept,
|
||||||
|
@ -1006,7 +1006,7 @@ void DisplayListPlayerSkia::apply_backdrop_filter(ApplyBackdropFilter const& com
|
||||||
color_filter = SkColorFilters::Matrix(matrix);
|
color_filter = SkColorFilters::Matrix(matrix);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CSS::Filter::Color::Operation::Invert: {
|
case CSS::FilterOperation::Color::Type::Invert: {
|
||||||
float matrix[20] = {
|
float matrix[20] = {
|
||||||
1 - 2 * amount, 0, 0, 0, amount,
|
1 - 2 * amount, 0, 0, 0, amount,
|
||||||
0, 1 - 2 * amount, 0, 0, amount,
|
0, 1 - 2 * amount, 0, 0, amount,
|
||||||
|
@ -1016,7 +1016,7 @@ void DisplayListPlayerSkia::apply_backdrop_filter(ApplyBackdropFilter const& com
|
||||||
color_filter = SkColorFilters::Matrix(matrix);
|
color_filter = SkColorFilters::Matrix(matrix);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CSS::Filter::Color::Operation::Opacity: {
|
case CSS::FilterOperation::Color::Type::Opacity: {
|
||||||
float matrix[20] = {
|
float matrix[20] = {
|
||||||
1, 0, 0, 0, 0,
|
1, 0, 0, 0, 0,
|
||||||
0, 1, 0, 0, 0,
|
0, 1, 0, 0, 0,
|
||||||
|
@ -1026,7 +1026,7 @@ void DisplayListPlayerSkia::apply_backdrop_filter(ApplyBackdropFilter const& com
|
||||||
color_filter = SkColorFilters::Matrix(matrix);
|
color_filter = SkColorFilters::Matrix(matrix);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CSS::Filter::Color::Operation::Sepia: {
|
case CSS::FilterOperation::Color::Type::Sepia: {
|
||||||
float matrix[20] = {
|
float matrix[20] = {
|
||||||
0.393f + 0.607f * (1 - amount), 0.769f - 0.769f * (1 - amount), 0.189f - 0.189f * (1 - amount), 0, 0,
|
0.393f + 0.607f * (1 - amount), 0.769f - 0.769f * (1 - amount), 0.189f - 0.189f * (1 - amount), 0, 0,
|
||||||
0.349f - 0.349f * (1 - amount), 0.686f + 0.314f * (1 - amount), 0.168f - 0.168f * (1 - amount), 0, 0,
|
0.349f - 0.349f * (1 - amount), 0.686f + 0.314f * (1 - amount), 0.168f - 0.168f * (1 - amount), 0, 0,
|
||||||
|
@ -1036,7 +1036,7 @@ void DisplayListPlayerSkia::apply_backdrop_filter(ApplyBackdropFilter const& com
|
||||||
color_filter = SkColorFilters::Matrix(matrix);
|
color_filter = SkColorFilters::Matrix(matrix);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CSS::Filter::Color::Operation::Saturate: {
|
case CSS::FilterOperation::Color::Type::Saturate: {
|
||||||
float matrix[20] = {
|
float matrix[20] = {
|
||||||
0.213f + 0.787f * amount, 0.715f - 0.715f * amount, 0.072f - 0.072f * amount, 0, 0,
|
0.213f + 0.787f * amount, 0.715f - 0.715f * amount, 0.072f - 0.072f * amount, 0, 0,
|
||||||
0.213f - 0.213f * amount, 0.715f + 0.285f * amount, 0.072f - 0.072f * amount, 0, 0,
|
0.213f - 0.213f * amount, 0.715f + 0.285f * amount, 0.072f - 0.072f * amount, 0, 0,
|
||||||
|
@ -1054,7 +1054,7 @@ void DisplayListPlayerSkia::apply_backdrop_filter(ApplyBackdropFilter const& com
|
||||||
canvas.saveLayer(SkCanvas::SaveLayerRec(nullptr, nullptr, image_filter.get(), 0));
|
canvas.saveLayer(SkCanvas::SaveLayerRec(nullptr, nullptr, image_filter.get(), 0));
|
||||||
canvas.restore();
|
canvas.restore();
|
||||||
},
|
},
|
||||||
[&](CSS::ResolvedBackdropFilter::HueRotate const& hue_rotate) {
|
[&](CSS::ResolvedFilter::HueRotate const& hue_rotate) {
|
||||||
float radians = AK::to_radians(hue_rotate.angle_degrees);
|
float radians = AK::to_radians(hue_rotate.angle_degrees);
|
||||||
|
|
||||||
auto cosA = cos(radians);
|
auto cosA = cos(radians);
|
||||||
|
@ -1082,7 +1082,7 @@ void DisplayListPlayerSkia::apply_backdrop_filter(ApplyBackdropFilter const& com
|
||||||
canvas.saveLayer(SkCanvas::SaveLayerRec(nullptr, nullptr, image_filter.get(), 0));
|
canvas.saveLayer(SkCanvas::SaveLayerRec(nullptr, nullptr, image_filter.get(), 0));
|
||||||
canvas.restore();
|
canvas.restore();
|
||||||
},
|
},
|
||||||
[&](CSS::ResolvedBackdropFilter::DropShadow const&) {
|
[&](CSS::ResolvedFilter::DropShadow const&) {
|
||||||
dbgln("TODO: Implement drop-shadow() filter function!");
|
dbgln("TODO: Implement drop-shadow() filter function!");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -299,7 +299,7 @@ void DisplayListRecorder::pop_stacking_context()
|
||||||
append(PopStackingContext {});
|
append(PopStackingContext {});
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayListRecorder::apply_backdrop_filter(Gfx::IntRect const& backdrop_region, BorderRadiiData const& border_radii_data, CSS::ResolvedBackdropFilter const& backdrop_filter)
|
void DisplayListRecorder::apply_backdrop_filter(Gfx::IntRect const& backdrop_region, BorderRadiiData const& border_radii_data, CSS::ResolvedFilter const& backdrop_filter)
|
||||||
{
|
{
|
||||||
if (backdrop_region.is_empty())
|
if (backdrop_region.is_empty())
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -124,7 +124,7 @@ public:
|
||||||
void add_rounded_rect_clip(CornerRadii corner_radii, Gfx::IntRect border_rect, CornerClip corner_clip);
|
void add_rounded_rect_clip(CornerRadii corner_radii, Gfx::IntRect border_rect, CornerClip corner_clip);
|
||||||
void add_mask(RefPtr<DisplayList> display_list, Gfx::IntRect rect);
|
void add_mask(RefPtr<DisplayList> display_list, Gfx::IntRect rect);
|
||||||
|
|
||||||
void apply_backdrop_filter(Gfx::IntRect const& backdrop_region, BorderRadiiData const& border_radii_data, CSS::ResolvedBackdropFilter const& backdrop_filter);
|
void apply_backdrop_filter(Gfx::IntRect const& backdrop_region, BorderRadiiData const& border_radii_data, CSS::ResolvedFilter const& backdrop_filter);
|
||||||
|
|
||||||
void paint_outer_box_shadow_params(PaintBoxShadowParams params);
|
void paint_outer_box_shadow_params(PaintBoxShadowParams params);
|
||||||
void paint_inner_box_shadow_params(PaintBoxShadowParams params);
|
void paint_inner_box_shadow_params(PaintBoxShadowParams params);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue