mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-02 22:30:31 +00:00
LibWeb: Add SVGFilterElement
This commit is contained in:
parent
aeef179668
commit
63b451cb46
Notes:
github-actions[bot]
2025-02-22 09:15:28 +00:00
Author: https://github.com/gmta
Commit: 63b451cb46
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3657
10 changed files with 176 additions and 0 deletions
|
@ -748,6 +748,7 @@ set(SOURCES
|
||||||
SVG/SVGPathElement.cpp
|
SVG/SVGPathElement.cpp
|
||||||
SVG/SVGCircleElement.cpp
|
SVG/SVGCircleElement.cpp
|
||||||
SVG/SVGEllipseElement.cpp
|
SVG/SVGEllipseElement.cpp
|
||||||
|
SVG/SVGFilterElement.cpp
|
||||||
SVG/SVGForeignObjectElement.cpp
|
SVG/SVGForeignObjectElement.cpp
|
||||||
SVG/SVGLength.cpp
|
SVG/SVGLength.cpp
|
||||||
SVG/SVGLineElement.cpp
|
SVG/SVGLineElement.cpp
|
||||||
|
|
|
@ -91,6 +91,7 @@
|
||||||
#include <LibWeb/SVG/SVGDefsElement.h>
|
#include <LibWeb/SVG/SVGDefsElement.h>
|
||||||
#include <LibWeb/SVG/SVGDescElement.h>
|
#include <LibWeb/SVG/SVGDescElement.h>
|
||||||
#include <LibWeb/SVG/SVGEllipseElement.h>
|
#include <LibWeb/SVG/SVGEllipseElement.h>
|
||||||
|
#include <LibWeb/SVG/SVGFilterElement.h>
|
||||||
#include <LibWeb/SVG/SVGForeignObjectElement.h>
|
#include <LibWeb/SVG/SVGForeignObjectElement.h>
|
||||||
#include <LibWeb/SVG/SVGGElement.h>
|
#include <LibWeb/SVG/SVGGElement.h>
|
||||||
#include <LibWeb/SVG/SVGImageElement.h>
|
#include <LibWeb/SVG/SVGImageElement.h>
|
||||||
|
@ -460,6 +461,8 @@ static GC::Ref<SVG::SVGElement> create_svg_element(JS::Realm& realm, Document& d
|
||||||
return realm.create<SVG::SVGDescElement>(document, move(qualified_name));
|
return realm.create<SVG::SVGDescElement>(document, move(qualified_name));
|
||||||
if (local_name == SVG::TagNames::ellipse)
|
if (local_name == SVG::TagNames::ellipse)
|
||||||
return realm.create<SVG::SVGEllipseElement>(document, move(qualified_name));
|
return realm.create<SVG::SVGEllipseElement>(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))
|
if (local_name.equals_ignoring_ascii_case(SVG::TagNames::foreignObject))
|
||||||
return realm.create<SVG::SVGForeignObjectElement>(document, move(qualified_name));
|
return realm.create<SVG::SVGForeignObjectElement>(document, move(qualified_name));
|
||||||
if (local_name == SVG::TagNames::line)
|
if (local_name == SVG::TagNames::line)
|
||||||
|
|
|
@ -804,6 +804,7 @@ class SVGDefsElement;
|
||||||
class SVGDescElement;
|
class SVGDescElement;
|
||||||
class SVGElement;
|
class SVGElement;
|
||||||
class SVGEllipseElement;
|
class SVGEllipseElement;
|
||||||
|
class SVGFilterElement;
|
||||||
class SVGForeignObjectElement;
|
class SVGForeignObjectElement;
|
||||||
class SVGGeometryElement;
|
class SVGGeometryElement;
|
||||||
class SVGGraphicsElement;
|
class SVGGraphicsElement;
|
||||||
|
|
102
Libraries/LibWeb/SVG/SVGFilterElement.cpp
Normal file
102
Libraries/LibWeb/SVG/SVGFilterElement.cpp
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025, Jelle Raaijmakers <jelle@ladybird.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <LibWeb/Bindings/SVGFilterElementPrototype.h>
|
||||||
|
#include <LibWeb/CSS/Parser/Parser.h>
|
||||||
|
#include <LibWeb/SVG/SVGFilterElement.h>
|
||||||
|
|
||||||
|
namespace Web::SVG {
|
||||||
|
|
||||||
|
GC_DEFINE_ALLOCATOR(SVGFilterElement);
|
||||||
|
|
||||||
|
SVGFilterElement::SVGFilterElement(DOM::Document& document, DOM::QualifiedName qualified_name)
|
||||||
|
: SVGElement(document, qualified_name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SVGFilterElement::initialize(JS::Realm& realm)
|
||||||
|
{
|
||||||
|
Base::initialize(realm);
|
||||||
|
WEB_SET_PROTOTYPE_FOR_INTERFACE(SVGFilterElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SVGFilterElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
||||||
|
{
|
||||||
|
Base::apply_presentational_hints(cascaded_properties);
|
||||||
|
auto parsing_context = CSS::Parser::ParsingParams { document(), CSS::Parser::ParsingMode::SVGPresentationAttribute };
|
||||||
|
|
||||||
|
auto x_attribute = attribute(AttributeNames::x);
|
||||||
|
if (auto x_value = parse_css_value(parsing_context, x_attribute.value_or(String {}), CSS::PropertyID::X))
|
||||||
|
cascaded_properties->set_property_from_presentational_hint(CSS::PropertyID::X, x_value.release_nonnull());
|
||||||
|
|
||||||
|
auto y_attribute = attribute(AttributeNames::y);
|
||||||
|
if (auto y_value = parse_css_value(parsing_context, y_attribute.value_or(String {}), CSS::PropertyID::Y))
|
||||||
|
cascaded_properties->set_property_from_presentational_hint(CSS::PropertyID::Y, y_value.release_nonnull());
|
||||||
|
|
||||||
|
auto width_attribute = attribute(AttributeNames::width);
|
||||||
|
if (auto width_value = parse_css_value(parsing_context, width_attribute.value_or(String {}), CSS::PropertyID::Width))
|
||||||
|
cascaded_properties->set_property_from_presentational_hint(CSS::PropertyID::Width, width_value.release_nonnull());
|
||||||
|
|
||||||
|
auto height_attribute = attribute(AttributeNames::height);
|
||||||
|
if (auto height_value = parse_css_value(parsing_context, height_attribute.value_or(String {}), CSS::PropertyID::Height))
|
||||||
|
cascaded_properties->set_property_from_presentational_hint(CSS::PropertyID::Height, height_value.release_nonnull());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SVGFilterElement::is_presentational_hint(FlyString const& name) const
|
||||||
|
{
|
||||||
|
if (Base::is_presentational_hint(name))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return name.is_one_of(AttributeNames::x, AttributeNames::y, AttributeNames::width, AttributeNames::height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SVGFilterElement::attribute_changed(FlyString const& name, Optional<String> const& old_value, Optional<String> const& value, Optional<FlyString> const& namespace_)
|
||||||
|
{
|
||||||
|
Base::attribute_changed(name, old_value, value, namespace_);
|
||||||
|
|
||||||
|
if (name == AttributeNames::filterUnits)
|
||||||
|
m_filter_units = AttributeParser::parse_units(value.value_or({}));
|
||||||
|
else if (name == AttributeNames::primitiveUnits)
|
||||||
|
m_primitive_units = AttributeParser::parse_units(value.value_or({}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://drafts.fxtf.org/filter-effects/#element-attrdef-filter-filterunits
|
||||||
|
GC::Ref<SVGAnimatedEnumeration> SVGFilterElement::filter_units() const
|
||||||
|
{
|
||||||
|
return SVGAnimatedEnumeration::create(realm(), to_underlying(m_filter_units.value_or(SVGUnits::ObjectBoundingBox)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://drafts.fxtf.org/filter-effects/#element-attrdef-filter-primitiveunits
|
||||||
|
GC::Ref<SVGAnimatedEnumeration> SVGFilterElement::primitive_units() const
|
||||||
|
{
|
||||||
|
return SVGAnimatedEnumeration::create(realm(), to_underlying(m_primitive_units.value_or(SVGUnits::UserSpaceOnUse)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://drafts.fxtf.org/filter-effects/#element-attrdef-filter-x
|
||||||
|
GC::Ref<SVGAnimatedLength> SVGFilterElement::x() const
|
||||||
|
{
|
||||||
|
return svg_animated_length_for_property(CSS::PropertyID::X);
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://drafts.fxtf.org/filter-effects/#element-attrdef-filter-y
|
||||||
|
GC::Ref<SVGAnimatedLength> SVGFilterElement::y() const
|
||||||
|
{
|
||||||
|
return svg_animated_length_for_property(CSS::PropertyID::Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://drafts.fxtf.org/filter-effects/#element-attrdef-filter-width
|
||||||
|
GC::Ref<SVGAnimatedLength> SVGFilterElement::width() const
|
||||||
|
{
|
||||||
|
return svg_animated_length_for_property(CSS::PropertyID::Width);
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://drafts.fxtf.org/filter-effects/#element-attrdef-filter-height
|
||||||
|
GC::Ref<SVGAnimatedLength> SVGFilterElement::height() const
|
||||||
|
{
|
||||||
|
return svg_animated_length_for_property(CSS::PropertyID::Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
49
Libraries/LibWeb/SVG/SVGFilterElement.h
Normal file
49
Libraries/LibWeb/SVG/SVGFilterElement.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025, Jelle Raaijmakers <jelle@ladybird.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <LibWeb/SVG/AttributeParser.h>
|
||||||
|
#include <LibWeb/SVG/SVGAnimatedEnumeration.h>
|
||||||
|
#include <LibWeb/SVG/SVGAnimatedLength.h>
|
||||||
|
#include <LibWeb/SVG/SVGElement.h>
|
||||||
|
#include <LibWeb/SVG/SVGURIReference.h>
|
||||||
|
|
||||||
|
namespace Web::SVG {
|
||||||
|
|
||||||
|
// https://drafts.fxtf.org/filter-effects/#elementdef-filter
|
||||||
|
class SVGFilterElement final
|
||||||
|
: public SVGElement
|
||||||
|
, public SVGURIReferenceMixin<SupportsXLinkHref::No> {
|
||||||
|
WEB_PLATFORM_OBJECT(SVGFilterElement, SVGElement);
|
||||||
|
GC_DECLARE_ALLOCATOR(SVGFilterElement);
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~SVGFilterElement() override = default;
|
||||||
|
|
||||||
|
// ^DOM::Element
|
||||||
|
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
||||||
|
virtual bool is_presentational_hint(AK::FlyString const&) const override;
|
||||||
|
|
||||||
|
virtual void attribute_changed(FlyString const& name, Optional<String> const& old_value, Optional<String> const& value, Optional<FlyString> const& namespace_) override;
|
||||||
|
|
||||||
|
GC::Ref<SVGAnimatedEnumeration> filter_units() const;
|
||||||
|
GC::Ref<SVGAnimatedEnumeration> primitive_units() const;
|
||||||
|
GC::Ref<SVGAnimatedLength> x() const;
|
||||||
|
GC::Ref<SVGAnimatedLength> y() const;
|
||||||
|
GC::Ref<SVGAnimatedLength> width() const;
|
||||||
|
GC::Ref<SVGAnimatedLength> height() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
SVGFilterElement(DOM::Document&, DOM::QualifiedName);
|
||||||
|
|
||||||
|
virtual void initialize(JS::Realm&) override;
|
||||||
|
|
||||||
|
Optional<SVGUnits> m_filter_units {};
|
||||||
|
Optional<SVGUnits> m_primitive_units {};
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
16
Libraries/LibWeb/SVG/SVGFilterElement.idl
Normal file
16
Libraries/LibWeb/SVG/SVGFilterElement.idl
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#import <SVG/SVGAnimatedEnumeration.idl>
|
||||||
|
#import <SVG/SVGAnimatedLength.idl>
|
||||||
|
#import <SVG/SVGURIReference.idl>
|
||||||
|
|
||||||
|
// https://drafts.fxtf.org/filter-effects/#InterfaceSVGFilterElement
|
||||||
|
[Exposed=Window]
|
||||||
|
interface SVGFilterElement : SVGElement {
|
||||||
|
readonly attribute SVGAnimatedEnumeration filterUnits;
|
||||||
|
readonly attribute SVGAnimatedEnumeration primitiveUnits;
|
||||||
|
readonly attribute SVGAnimatedLength x;
|
||||||
|
readonly attribute SVGAnimatedLength y;
|
||||||
|
readonly attribute SVGAnimatedLength width;
|
||||||
|
readonly attribute SVGAnimatedLength height;
|
||||||
|
};
|
||||||
|
|
||||||
|
SVGFilterElement includes SVGURIReference;
|
|
@ -17,6 +17,7 @@ namespace Web::SVG::TagNames {
|
||||||
__ENUMERATE_SVG_TAG(defs) \
|
__ENUMERATE_SVG_TAG(defs) \
|
||||||
__ENUMERATE_SVG_TAG(desc) \
|
__ENUMERATE_SVG_TAG(desc) \
|
||||||
__ENUMERATE_SVG_TAG(ellipse) \
|
__ENUMERATE_SVG_TAG(ellipse) \
|
||||||
|
__ENUMERATE_SVG_TAG(filter) \
|
||||||
__ENUMERATE_SVG_TAG(foreignObject) \
|
__ENUMERATE_SVG_TAG(foreignObject) \
|
||||||
__ENUMERATE_SVG_TAG(g) \
|
__ENUMERATE_SVG_TAG(g) \
|
||||||
__ENUMERATE_SVG_TAG(image) \
|
__ENUMERATE_SVG_TAG(image) \
|
||||||
|
|
|
@ -319,6 +319,7 @@ libweb_js_bindings(SVG/SVGGraphicsElement)
|
||||||
libweb_js_bindings(SVG/SVGImageElement)
|
libweb_js_bindings(SVG/SVGImageElement)
|
||||||
libweb_js_bindings(SVG/SVGCircleElement)
|
libweb_js_bindings(SVG/SVGCircleElement)
|
||||||
libweb_js_bindings(SVG/SVGEllipseElement)
|
libweb_js_bindings(SVG/SVGEllipseElement)
|
||||||
|
libweb_js_bindings(SVG/SVGFilterElement)
|
||||||
libweb_js_bindings(SVG/SVGForeignObjectElement)
|
libweb_js_bindings(SVG/SVGForeignObjectElement)
|
||||||
libweb_js_bindings(SVG/SVGLength)
|
libweb_js_bindings(SVG/SVGLength)
|
||||||
libweb_js_bindings(SVG/SVGLineElement)
|
libweb_js_bindings(SVG/SVGLineElement)
|
||||||
|
|
|
@ -312,6 +312,7 @@ standard_idl_files = [
|
||||||
"//Userland/Libraries/LibWeb/SVG/SVGDescElement.idl",
|
"//Userland/Libraries/LibWeb/SVG/SVGDescElement.idl",
|
||||||
"//Userland/Libraries/LibWeb/SVG/SVGElement.idl",
|
"//Userland/Libraries/LibWeb/SVG/SVGElement.idl",
|
||||||
"//Userland/Libraries/LibWeb/SVG/SVGEllipseElement.idl",
|
"//Userland/Libraries/LibWeb/SVG/SVGEllipseElement.idl",
|
||||||
|
"//Userland/Libraries/LibWeb/SVG/SVGFilterElement.idl",
|
||||||
"//Userland/Libraries/LibWeb/SVG/SVGForeignObjectElement.idl",
|
"//Userland/Libraries/LibWeb/SVG/SVGForeignObjectElement.idl",
|
||||||
"//Userland/Libraries/LibWeb/SVG/SVGGElement.idl",
|
"//Userland/Libraries/LibWeb/SVG/SVGGElement.idl",
|
||||||
"//Userland/Libraries/LibWeb/SVG/SVGGeometryElement.idl",
|
"//Userland/Libraries/LibWeb/SVG/SVGGeometryElement.idl",
|
||||||
|
|
|
@ -321,6 +321,7 @@ SVGDefsElement
|
||||||
SVGDescElement
|
SVGDescElement
|
||||||
SVGElement
|
SVGElement
|
||||||
SVGEllipseElement
|
SVGEllipseElement
|
||||||
|
SVGFilterElement
|
||||||
SVGForeignObjectElement
|
SVGForeignObjectElement
|
||||||
SVGGElement
|
SVGGElement
|
||||||
SVGGeometryElement
|
SVGGeometryElement
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue