LibWeb/SVG: Add FEFloodElement

This commit is contained in:
Lucien Fiorini 2025-07-06 21:48:55 +02:00 committed by Sam Atkins
commit d3684a36b0
Notes: github-actions[bot] 2025-07-09 17:08:44 +00:00
22 changed files with 189 additions and 18 deletions

View file

@ -823,6 +823,7 @@ set(SOURCES
SVG/SVGDescElement.cpp
SVG/SVGElement.cpp
SVG/SVGEllipseElement.cpp
SVG/SVGFEFloodElement.cpp
SVG/SVGFilterElement.cpp
SVG/SVGForeignObjectElement.cpp
SVG/SVGGElement.cpp

View file

@ -443,6 +443,22 @@ ClipRule ComputedProperties::clip_rule() const
return keyword_to_fill_rule(value.to_keyword()).release_value();
}
Color ComputedProperties::flood_color(Layout::NodeWithStyle const& node) const
{
auto const& value = property(PropertyID::FloodColor);
if (value.has_color()) {
return value.to_color(node, { .length_resolution_context = Length::ResolutionContext::for_layout_node(node) });
}
return InitialValues::flood_color();
}
float ComputedProperties::flood_opacity() const
{
auto const& value = property(PropertyID::FloodOpacity);
return resolve_opacity_value(value);
}
FlexDirection ComputedProperties::flex_direction() const
{
auto const& value = property(PropertyID::FlexDirection);

View file

@ -194,6 +194,8 @@ public:
float stroke_opacity() const;
FillRule fill_rule() const;
ClipRule clip_rule() const;
Color flood_color(Layout::NodeWithStyle const&) const;
float flood_opacity() const;
Gfx::FontCascadeList const& computed_font_list() const
{

View file

@ -152,6 +152,8 @@ public:
static float fill_opacity() { return 1.0f; }
static CSS::FillRule fill_rule() { return CSS::FillRule::Nonzero; }
static CSS::ClipRule clip_rule() { return CSS::ClipRule::Nonzero; }
static Color flood_color() { return Color::Black; }
static float flood_opacity() { return 1.0f; }
static CSS::LengthPercentage stroke_dashoffset() { return CSS::Length::make_px(0); }
static CSS::StrokeLinecap stroke_linecap() { return CSS::StrokeLinecap::Butt; }
static CSS::StrokeLinejoin stroke_linejoin() { return CSS::StrokeLinejoin::Miter; }
@ -554,6 +556,8 @@ public:
CSS::MaskType mask_type() const { return m_noninherited.mask_type; }
Optional<ClipPathReference> const& clip_path() const { return m_noninherited.clip_path; }
CSS::ClipRule clip_rule() const { return m_inherited.clip_rule; }
Color flood_color() const { return m_noninherited.flood_color; }
float flood_opacity() const { return m_noninherited.flood_opacity; }
LengthPercentage const& cx() const { return m_noninherited.cx; }
LengthPercentage const& cy() const { return m_noninherited.cy; }
@ -796,6 +800,9 @@ protected:
Vector<CounterData, 0> counter_increment;
Vector<CounterData, 0> counter_reset;
Vector<CounterData, 0> counter_set;
Color flood_color { InitialValues::flood_color() };
float flood_opacity { InitialValues::flood_opacity() };
} m_noninherited;
};
@ -982,6 +989,8 @@ public:
void set_mask_image(CSS::AbstractImageStyleValue const& value) { m_noninherited.mask_image = value; }
void set_clip_path(ClipPathReference value) { m_noninherited.clip_path = move(value); }
void set_clip_rule(CSS::ClipRule value) { m_inherited.clip_rule = value; }
void set_flood_color(Color value) { m_noninherited.flood_color = value; }
void set_flood_opacity(float value) { m_noninherited.flood_opacity = value; }
void set_cx(LengthPercentage cx) { m_noninherited.cx = move(cx); }
void set_cy(LengthPercentage cy) { m_noninherited.cy = move(cy); }

View file

@ -1537,6 +1537,24 @@
"float"
]
},
"flood-color": {
"affects-layout": false,
"animation-type": "by-computed-value",
"inherited": false,
"initial": "black",
"valid-types": [
"color"
]
},
"flood-opacity": {
"affects-layout": false,
"animation-type": "by-computed-value",
"inherited": false,
"initial": "1",
"valid-types": [
"number [0,1]"
]
},
"font": {
"inherited": true,
"initial": "normal medium serif",

View file

@ -91,6 +91,7 @@
#include <LibWeb/SVG/SVGDefsElement.h>
#include <LibWeb/SVG/SVGDescElement.h>
#include <LibWeb/SVG/SVGEllipseElement.h>
#include <LibWeb/SVG/SVGFEFloodElement.h>
#include <LibWeb/SVG/SVGFilterElement.h>
#include <LibWeb/SVG/SVGForeignObjectElement.h>
#include <LibWeb/SVG/SVGGElement.h>
@ -461,6 +462,8 @@ static GC::Ref<SVG::SVGElement> create_svg_element(JS::Realm& realm, Document& d
return realm.create<SVG::SVGDescElement>(document, move(qualified_name));
if (local_name == SVG::TagNames::ellipse)
return realm.create<SVG::SVGEllipseElement>(document, move(qualified_name));
if (local_name == SVG::TagNames::feFlood)
return realm.create<SVG::SVGFEFloodElement>(document, move(qualified_name));
if (local_name == SVG::TagNames::filter)
return realm.create<SVG::SVGFilterElement>(document, move(qualified_name));
if (local_name.equals_ignoring_ascii_case(SVG::TagNames::foreignObject))

View file

@ -967,6 +967,7 @@ class SVGDefsElement;
class SVGDescElement;
class SVGElement;
class SVGEllipseElement;
class SVGFEFloodElement;
class SVGFilterElement;
class SVGForeignObjectElement;
class SVGGeometryElement;

View file

@ -61,6 +61,9 @@ static ReadonlySpan<NamedPropertyID> attribute_style_properties()
NamedPropertyID(CSS::PropertyID::Display),
NamedPropertyID(CSS::PropertyID::FillOpacity),
NamedPropertyID(CSS::PropertyID::FillRule),
NamedPropertyID(CSS::PropertyID::Filter),
NamedPropertyID(CSS::PropertyID::FloodColor),
NamedPropertyID(CSS::PropertyID::FloodOpacity),
NamedPropertyID(CSS::PropertyID::FontFamily),
NamedPropertyID(CSS::PropertyID::FontSize),
NamedPropertyID(CSS::PropertyID::FontStyle),

View file

@ -29,6 +29,8 @@ public:
bool should_include_in_accessibility_tree() const;
virtual Optional<ARIA::Role> default_role() const override;
GC::Ref<SVGAnimatedLength> svg_animated_length_for_property(CSS::PropertyID) const;
virtual bool is_presentational_hint(FlyString const&) const override;
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
@ -47,8 +49,6 @@ protected:
void update_use_elements_that_reference_this();
void remove_from_use_element_that_reference_this();
GC::Ref<SVGAnimatedLength> svg_animated_length_for_property(CSS::PropertyID) const;
private:
// ^HTML::GlobalEventHandlers
virtual GC::Ptr<DOM::EventTarget> global_event_handlers_to_event_target(FlyString const&) override { return *this; }

View file

@ -0,0 +1,54 @@
/*
* Copyright (c) 2025, Lucien Fiorini <lucienfiorini@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/SVGFEFloodElementPrototype.h>
#include <LibWeb/CSS/ComputedProperties.h>
#include <LibWeb/CSS/Parser/Parser.h>
#include <LibWeb/Layout/Node.h>
#include <LibWeb/Layout/SVGGraphicsBox.h>
#include <LibWeb/SVG/SVGFEFloodElement.h>
namespace Web::SVG {
GC_DEFINE_ALLOCATOR(SVGFEFloodElement);
SVGFEFloodElement::SVGFEFloodElement(DOM::Document& document, DOM::QualifiedName qualified_name)
: SVGElement(document, qualified_name)
{
}
void SVGFEFloodElement::initialize(JS::Realm& realm)
{
Base::initialize(realm);
WEB_SET_PROTOTYPE_FOR_INTERFACE(SVGFEFloodElement);
}
void SVGFEFloodElement::visit_edges(Cell::Visitor& visitor)
{
Base::visit_edges(visitor);
SVGFilterPrimitiveStandardAttributes::visit_edges(visitor);
}
GC::Ptr<Layout::Node> SVGFEFloodElement::create_layout_node(GC::Ref<CSS::ComputedProperties> style)
{
return heap().allocate<Layout::SVGBox>(document(), *this, move(style));
}
// https://www.w3.org/TR/filter-effects-1/#FloodColorProperty
Gfx::Color SVGFEFloodElement::flood_color() const
{
// FIXME: Find a way to get the Gfx::Color of the flood_color property
// without having a layout node.
return Color::Black;
}
// https://www.w3.org/TR/filter-effects-1/#FloodOpacityProperty
float SVGFEFloodElement::flood_opacity() const
{
return computed_properties()->flood_opacity();
}
}

View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2025, Lucien Fiorini <lucienfiorini@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/SVG/SVGAnimatedLength.h>
#include <LibWeb/SVG/SVGElement.h>
#include <LibWeb/SVG/SVGFilterPrimitiveStandardAttributes.h>
namespace Web::SVG {
class SVGFEFloodElement final
: public SVGElement
, public SVGFilterPrimitiveStandardAttributes<SVGFEFloodElement> {
WEB_PLATFORM_OBJECT(SVGFEFloodElement, SVGElement);
GC_DECLARE_ALLOCATOR(SVGFEFloodElement);
public:
virtual ~SVGFEFloodElement() override = default;
virtual GC::Ptr<Layout::Node> create_layout_node(GC::Ref<CSS::ComputedProperties>) override;
Gfx::Color flood_color() const;
float flood_opacity() const;
private:
SVGFEFloodElement(DOM::Document&, DOM::QualifiedName);
virtual void initialize(JS::Realm&) override;
virtual void visit_edges(Cell::Visitor&) override;
};
}

View file

@ -0,0 +1,8 @@
#import <SVG/SVGFilterPrimitiveStandardAttributes.idl>
// https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEFloodElement
[Exposed=Window]
interface SVGFEFloodElement : SVGElement {
};
SVGFEFloodElement includes SVGFilterPrimitiveStandardAttributes;

View file

@ -17,6 +17,7 @@ namespace Web::SVG::TagNames {
__ENUMERATE_SVG_TAG(defs) \
__ENUMERATE_SVG_TAG(desc) \
__ENUMERATE_SVG_TAG(ellipse) \
__ENUMERATE_SVG_TAG(feFlood) \
__ENUMERATE_SVG_TAG(filter) \
__ENUMERATE_SVG_TAG(foreignObject) \
__ENUMERATE_SVG_TAG(g) \

View file

@ -340,6 +340,7 @@ libweb_js_bindings(SVG/SVGGraphicsElement)
libweb_js_bindings(SVG/SVGImageElement)
libweb_js_bindings(SVG/SVGCircleElement)
libweb_js_bindings(SVG/SVGEllipseElement)
libweb_js_bindings(SVG/SVGFEFloodElement)
libweb_js_bindings(SVG/SVGFilterElement)
libweb_js_bindings(SVG/SVGForeignObjectElement)
libweb_js_bindings(SVG/SVGLength)