diff --git a/Userland/Libraries/LibWeb/CSS/ComputedValues.h b/Userland/Libraries/LibWeb/CSS/ComputedValues.h index 9ee0a456b0..ae62480888 100644 --- a/Userland/Libraries/LibWeb/CSS/ComputedValues.h +++ b/Userland/Libraries/LibWeb/CSS/ComputedValues.h @@ -163,6 +163,21 @@ private: Variant m_value; }; +// https://drafts.fxtf.org/css-masking-1/#typedef-mask-reference +class MaskReference { +public: + // TODO: Support other mask types. + MaskReference(AK::URL const& url) + : m_url(url) + { + } + + AK::URL const& url() const { return m_url; } + +private: + AK::URL m_url; +}; + struct BackgroundLayerData { RefPtr background_image { nullptr }; CSS::BackgroundAttachment attachment { CSS::BackgroundAttachment::Scroll }; @@ -344,6 +359,7 @@ public: Color stop_color() const { return m_noninherited.stop_color; } float stop_opacity() const { return m_noninherited.stop_opacity; } CSS::TextAnchor text_anchor() const { return m_inherited.text_anchor; } + Optional const& mask() const { return m_noninherited.mask; } Vector const& transformations() const { return m_noninherited.transformations; } CSS::TransformOrigin const& transform_origin() const { return m_noninherited.transform_origin; } @@ -488,6 +504,8 @@ protected: CSS::OutlineStyle outline_style { InitialValues::outline_style() }; CSS::Length outline_width { InitialValues::outline_width() }; CSS::TableLayout table_layout { InitialValues::table_layout() }; + + Optional mask; } m_noninherited; }; @@ -605,6 +623,7 @@ public: void set_outline_offset(CSS::Length value) { m_noninherited.outline_offset = value; } void set_outline_style(CSS::OutlineStyle value) { m_noninherited.outline_style = value; } void set_outline_width(CSS::Length value) { m_noninherited.outline_width = value; } + void set_mask(MaskReference value) { m_noninherited.mask = value; } void set_math_shift(CSS::MathShift value) { m_inherited.math_shift = value; } void set_math_style(CSS::MathStyle value) { m_inherited.math_style = value; } diff --git a/Userland/Libraries/LibWeb/CSS/Properties.json b/Userland/Libraries/LibWeb/CSS/Properties.json index cd487ecc97..60fc5fe19c 100644 --- a/Userland/Libraries/LibWeb/CSS/Properties.json +++ b/Userland/Libraries/LibWeb/CSS/Properties.json @@ -1484,6 +1484,19 @@ "unitless-length" ] }, + "mask": { + "affects-layout": false, + "affects-stacking-context": true, + "inherited": false, + "valid-identifiers": [ + "none" + ], + "__comment": "FIXME: This should be a and/or #", + "valid-types": [ + "url" + ], + "initial": "none" + }, "math-depth": { "inherited": true, "initial": "0", diff --git a/Userland/Libraries/LibWeb/Layout/Node.cpp b/Userland/Libraries/LibWeb/Layout/Node.cpp index 9d76e958ca..e6ba0f095e 100644 --- a/Userland/Libraries/LibWeb/Layout/Node.cpp +++ b/Userland/Libraries/LibWeb/Layout/Node.cpp @@ -184,6 +184,16 @@ bool Node::establishes_stacking_context() const if (!computed_values().backdrop_filter().is_none()) return true; + // Element with any of the following properties with value other than none: + // - transform + // - filter + // - backdrop-filter + // - perspective + // - clip-path + // - mask / mask-image / mask-border + if (computed_values().mask().has_value()) + return true; + return computed_values().opacity() < 1.0f; } @@ -755,6 +765,9 @@ void NodeWithStyle::apply_style(const CSS::StyleProperties& computed_style) else if (stroke_width->is_percentage()) computed_values.set_stroke_width(CSS::LengthPercentage { stroke_width->as_percentage().percentage() }); + if (auto mask = computed_style.property(CSS::PropertyID::Mask); mask->is_url()) + computed_values.set_mask(mask->as_url().url()); + if (auto fill_rule = computed_style.fill_rule(); fill_rule.has_value()) computed_values.set_fill_rule(*fill_rule);