Skip to content

Commit db321cb

Browse files
committed
LibWeb: Add SVGComponentTransferFunctionElement
This will be the base for <feFuncR>, <feFuncG>, <feFuncB> and <feFuncA>.
1 parent 03a8de5 commit db321cb

File tree

10 files changed

+262
-0
lines changed

10 files changed

+262
-0
lines changed

Libraries/LibWeb/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -907,6 +907,7 @@ set(SOURCES
907907
SVG/SVGAnimationElement.cpp
908908
SVG/SVGCircleElement.cpp
909909
SVG/SVGClipPathElement.cpp
910+
SVG/SVGComponentTransferFunctionElement.cpp
910911
SVG/SVGDecodedImageData.cpp
911912
SVG/SVGDefsElement.cpp
912913
SVG/SVGDescElement.cpp

Libraries/LibWeb/Forward.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,6 +1098,7 @@ class SVGAnimatedRect;
10981098
class SVGAnimationElement;
10991099
class SVGCircleElement;
11001100
class SVGClipPathElement;
1101+
class SVGComponentTransferFunctionElement;
11011102
class SVGDecodedImageData;
11021103
class SVGDefsElement;
11031104
class SVGDescElement;

Libraries/LibWeb/SVG/AttributeNames.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright (c) 2021-2023, Andreas Kling <andreas@ladybird.org>
3+
* Copyright (c) 2025, Jelle Raaijmakers <jelle@ladybird.org>
34
*
45
* SPDX-License-Identifier: BSD-2-Clause
56
*/
@@ -11,6 +12,7 @@
1112
namespace Web::SVG::AttributeNames {
1213

1314
#define ENUMERATE_SVG_ATTRIBUTES \
15+
__ENUMERATE_SVG_ATTRIBUTE(amplitude, "amplitude") \
1416
__ENUMERATE_SVG_ATTRIBUTE(attributeName, "attributeName") \
1517
__ENUMERATE_SVG_ATTRIBUTE(attributeType, "attributeType") \
1618
__ENUMERATE_SVG_ATTRIBUTE(baseFrequency, "baseFrequency") \
@@ -28,6 +30,7 @@ namespace Web::SVG::AttributeNames {
2830
__ENUMERATE_SVG_ATTRIBUTE(dy, "dy") \
2931
__ENUMERATE_SVG_ATTRIBUTE(edgeMode, "edgeMode") \
3032
__ENUMERATE_SVG_ATTRIBUTE(fill, "fill") \
33+
__ENUMERATE_SVG_ATTRIBUTE(exponent, "exponent") \
3134
__ENUMERATE_SVG_ATTRIBUTE(filterUnits, "filterUnits") \
3235
__ENUMERATE_SVG_ATTRIBUTE(fr, "fr") \
3336
__ENUMERATE_SVG_ATTRIBUTE(fx, "fx") \
@@ -39,6 +42,7 @@ namespace Web::SVG::AttributeNames {
3942
__ENUMERATE_SVG_ATTRIBUTE(href, "href") \
4043
__ENUMERATE_SVG_ATTRIBUTE(in, "in") \
4144
__ENUMERATE_SVG_ATTRIBUTE(in2, "in2") \
45+
__ENUMERATE_SVG_ATTRIBUTE(intercept, "intercept") \
4246
__ENUMERATE_SVG_ATTRIBUTE(kernelMatrix, "kernelMatrix") \
4347
__ENUMERATE_SVG_ATTRIBUTE(kernelUnitLength, "kernelUnitLength") \
4448
__ENUMERATE_SVG_ATTRIBUTE(k1, "k1") \
@@ -81,6 +85,7 @@ namespace Web::SVG::AttributeNames {
8185
__ENUMERATE_SVG_ATTRIBUTE(result, "result") \
8286
__ENUMERATE_SVG_ATTRIBUTE(rx, "rx") \
8387
__ENUMERATE_SVG_ATTRIBUTE(ry, "ry") \
88+
__ENUMERATE_SVG_ATTRIBUTE(slope, "slope") \
8489
__ENUMERATE_SVG_ATTRIBUTE(specularConstant, "specularConstant") \
8590
__ENUMERATE_SVG_ATTRIBUTE(specularExponent, "specularExponent") \
8691
__ENUMERATE_SVG_ATTRIBUTE(spreadMethod, "spreadMethod") \

Libraries/LibWeb/SVG/AttributeParser.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,27 @@ Optional<SpreadMethod> AttributeParser::parse_spread_method(StringView input)
560560
return {};
561561
}
562562

563+
// https://drafts.fxtf.org/filter-effects-1/#element-attrdef-fecomponenttransfer-tablevalues
564+
Vector<float> AttributeParser::parse_table_values(StringView input)
565+
{
566+
Vector<float> table_values;
567+
568+
AttributeParser parser { input };
569+
while (!parser.done()) {
570+
parser.parse_whitespace();
571+
auto table_value = parser.parse_nonnegative_number();
572+
if (table_value.is_error())
573+
return {};
574+
575+
table_values.append(table_value.release_value());
576+
parser.parse_whitespace();
577+
if (parser.match(','))
578+
parser.consume();
579+
}
580+
581+
return table_values;
582+
}
583+
563584
// https://drafts.csswg.org/css-transforms/#svg-syntax
564585
Optional<Vector<Transform>> AttributeParser::parse_transform()
565586
{

Libraries/LibWeb/SVG/AttributeParser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ class WEB_API AttributeParser final {
148148
static Optional<PreserveAspectRatio> parse_preserve_aspect_ratio(StringView input);
149149
static Optional<SVGUnits> parse_units(StringView input);
150150
static Optional<SpreadMethod> parse_spread_method(StringView input);
151+
static Vector<float> parse_table_values(StringView);
151152
static Optional<ViewBox> parse_viewbox(StringView input);
152153

153154
private:
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/*
2+
* Copyright (c) 2025, Jelle Raaijmakers <jelle@ladybird.org>
3+
*
4+
* SPDX-License-Identifier: BSD-2-Clause
5+
*/
6+
7+
#include <LibWeb/Bindings/SVGComponentTransferFunctionElementPrototype.h>
8+
#include <LibWeb/SVG/AttributeNames.h>
9+
#include <LibWeb/SVG/AttributeParser.h>
10+
#include <LibWeb/SVG/SVGComponentTransferFunctionElement.h>
11+
#include <LibWeb/SVG/SVGNumber.h>
12+
#include <LibWeb/SVG/SVGNumberList.h>
13+
14+
namespace Web::SVG {
15+
16+
SVGComponentTransferFunctionElement::SVGComponentTransferFunctionElement(DOM::Document& document, DOM::QualifiedName qualified_name)
17+
: SVGElement(document, move(qualified_name))
18+
{
19+
}
20+
21+
// https://drafts.fxtf.org/filter-effects-1/#element-attrdef-fecomponenttransfer-type
22+
static SVGComponentTransferFunctionElement::Type parse_type(Optional<String> const& value)
23+
{
24+
if (value == "identity"sv)
25+
return SVGComponentTransferFunctionElement::Type::Identity;
26+
if (value == "table"sv)
27+
return SVGComponentTransferFunctionElement::Type::Table;
28+
if (value == "discrete"sv)
29+
return SVGComponentTransferFunctionElement::Type::Discrete;
30+
if (value == "linear"sv)
31+
return SVGComponentTransferFunctionElement::Type::Linear;
32+
if (value == "gamma"sv)
33+
return SVGComponentTransferFunctionElement::Type::Gamma;
34+
35+
return SVGComponentTransferFunctionElement::Type::Unknown;
36+
}
37+
38+
void SVGComponentTransferFunctionElement::attribute_changed(FlyString const& name, Optional<String> const& old_value,
39+
Optional<String> const& value, Optional<FlyString> const& namespace_)
40+
{
41+
Base::attribute_changed(name, old_value, value, namespace_);
42+
43+
// FIXME: Support reflection instead of invalidating the enumeration.
44+
if (name == AttributeNames::type)
45+
m_type = {};
46+
47+
// FIXME: Support reflection instead of invalidating the list.
48+
if (name == AttributeNames::tableValues)
49+
m_table_values = {};
50+
}
51+
52+
void SVGComponentTransferFunctionElement::initialize(JS::Realm& realm)
53+
{
54+
WEB_SET_PROTOTYPE_FOR_INTERFACE(SVGComponentTransferFunctionElement);
55+
Base::initialize(realm);
56+
}
57+
58+
void SVGComponentTransferFunctionElement::visit_edges(Visitor& visitor)
59+
{
60+
Base::visit_edges(visitor);
61+
visitor.visit(m_type);
62+
visitor.visit(m_table_values);
63+
visitor.visit(m_slope);
64+
visitor.visit(m_intercept);
65+
visitor.visit(m_amplitude);
66+
visitor.visit(m_exponent);
67+
visitor.visit(m_offset);
68+
}
69+
70+
// https://www.w3.org/TR/filter-effects-1/#dom-svgcomponenttransferfunctionelement-type
71+
// https://drafts.fxtf.org/filter-effects-1/#element-attrdef-fecomponenttransfer-type
72+
GC::Ref<SVGAnimatedEnumeration> SVGComponentTransferFunctionElement::type()
73+
{
74+
if (!m_type)
75+
m_type = SVGAnimatedEnumeration::create(realm(), to_underlying(type_from_attribute()));
76+
return *m_type;
77+
}
78+
79+
// https://www.w3.org/TR/filter-effects-1/#dom-svgcomponenttransferfunctionelement-tablevalues
80+
// https://drafts.fxtf.org/filter-effects-1/#element-attrdef-fecomponenttransfer-tablevalues
81+
GC::Ref<SVGAnimatedNumberList> SVGComponentTransferFunctionElement::table_values()
82+
{
83+
if (!m_table_values) {
84+
auto numbers = AttributeParser::parse_table_values(get_attribute_value(AttributeNames::tableValues));
85+
86+
Vector<GC::Ref<SVGNumber>> items;
87+
items.ensure_capacity(numbers.size());
88+
for (auto number : numbers)
89+
items.unchecked_append(SVGNumber::create(realm(), number, SVGNumber::ReadOnly::Yes));
90+
91+
auto number_list = SVGNumberList::create(realm(), move(items), ReadOnlyList::Yes);
92+
m_table_values = SVGAnimatedNumberList::create(realm(), number_list);
93+
}
94+
return *m_table_values;
95+
}
96+
97+
// https://www.w3.org/TR/filter-effects-1/#dom-svgcomponenttransferfunctionelement-slope
98+
// https://drafts.fxtf.org/filter-effects-1/#element-attrdef-fecomponenttransfer-slope
99+
GC::Ref<SVGAnimatedNumber> SVGComponentTransferFunctionElement::slope()
100+
{
101+
if (!m_slope)
102+
m_slope = SVGAnimatedNumber::create(realm(), *this, DOM::QualifiedName { AttributeNames::slope, {}, {} }, 1.f);
103+
return *m_slope;
104+
}
105+
106+
// https://www.w3.org/TR/filter-effects-1/#dom-svgcomponenttransferfunctionelement-intercept
107+
// https://drafts.fxtf.org/filter-effects-1/#element-attrdef-fecomponenttransfer-intercept
108+
GC::Ref<SVGAnimatedNumber> SVGComponentTransferFunctionElement::intercept()
109+
{
110+
if (!m_intercept)
111+
m_intercept = SVGAnimatedNumber::create(realm(), *this, DOM::QualifiedName { AttributeNames::intercept, {}, {} }, 0.f);
112+
return *m_intercept;
113+
}
114+
115+
// https://www.w3.org/TR/filter-effects-1/#dom-svgcomponenttransferfunctionelement-amplitude
116+
// https://drafts.fxtf.org/filter-effects-1/#element-attrdef-fecomponenttransfer-amplitude
117+
GC::Ref<SVGAnimatedNumber> SVGComponentTransferFunctionElement::amplitude()
118+
{
119+
if (!m_amplitude)
120+
m_amplitude = SVGAnimatedNumber::create(realm(), *this, DOM::QualifiedName { AttributeNames::amplitude, {}, {} }, 1.f);
121+
return *m_amplitude;
122+
}
123+
124+
// https://www.w3.org/TR/filter-effects-1/#dom-svgcomponenttransferfunctionelement-exponent
125+
// https://drafts.fxtf.org/filter-effects-1/#element-attrdef-fecomponenttransfer-exponent
126+
GC::Ref<SVGAnimatedNumber> SVGComponentTransferFunctionElement::exponent()
127+
{
128+
if (!m_exponent)
129+
m_exponent = SVGAnimatedNumber::create(realm(), *this, DOM::QualifiedName { AttributeNames::exponent, {}, {} }, 1.f);
130+
return *m_exponent;
131+
}
132+
133+
// https://www.w3.org/TR/filter-effects-1/#dom-svgcomponenttransferfunctionelement-offset
134+
// https://drafts.fxtf.org/filter-effects-1/#element-attrdef-fecomponenttransfer-offset
135+
GC::Ref<SVGAnimatedNumber> SVGComponentTransferFunctionElement::offset()
136+
{
137+
if (!m_offset)
138+
m_offset = SVGAnimatedNumber::create(realm(), *this, DOM::QualifiedName { AttributeNames::offset, {}, {} }, 0.f);
139+
return *m_offset;
140+
}
141+
142+
SVGComponentTransferFunctionElement::Type SVGComponentTransferFunctionElement::type_from_attribute() const
143+
{
144+
return parse_type(get_attribute_value(AttributeNames::type));
145+
}
146+
147+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright (c) 2025, Jelle Raaijmakers <jelle@ladybird.org>
3+
*
4+
* SPDX-License-Identifier: BSD-2-Clause
5+
*/
6+
7+
#pragma once
8+
9+
#include <LibWeb/SVG/SVGAnimatedEnumeration.h>
10+
#include <LibWeb/SVG/SVGAnimatedNumber.h>
11+
#include <LibWeb/SVG/SVGAnimatedNumberList.h>
12+
#include <LibWeb/SVG/SVGElement.h>
13+
14+
namespace Web::SVG {
15+
16+
// https://www.w3.org/TR/filter-effects-1/#InterfaceSVGComponentTransferFunctionElement
17+
class SVGComponentTransferFunctionElement
18+
: public SVGElement {
19+
WEB_PLATFORM_OBJECT(SVGComponentTransferFunctionElement, SVGElement);
20+
21+
public:
22+
enum class Type : u8 {
23+
Unknown = 0,
24+
Identity = 1,
25+
Table = 2,
26+
Discrete = 3,
27+
Linear = 4,
28+
Gamma = 5,
29+
};
30+
31+
virtual ~SVGComponentTransferFunctionElement() override = default;
32+
33+
virtual void attribute_changed(FlyString const& name, Optional<String> const& old_value, Optional<String> const& value, Optional<FlyString> const& namespace_) override;
34+
35+
GC::Ref<SVGAnimatedEnumeration> type();
36+
GC::Ref<SVGAnimatedNumberList> table_values();
37+
GC::Ref<SVGAnimatedNumber> slope();
38+
GC::Ref<SVGAnimatedNumber> intercept();
39+
GC::Ref<SVGAnimatedNumber> amplitude();
40+
GC::Ref<SVGAnimatedNumber> exponent();
41+
GC::Ref<SVGAnimatedNumber> offset();
42+
43+
protected:
44+
SVGComponentTransferFunctionElement(DOM::Document&, DOM::QualifiedName);
45+
46+
virtual void initialize(JS::Realm&) override;
47+
48+
private:
49+
virtual void visit_edges(Cell::Visitor&) override;
50+
51+
Type type_from_attribute() const;
52+
53+
GC::Ptr<SVGAnimatedEnumeration> m_type;
54+
GC::Ptr<SVGAnimatedNumberList> m_table_values;
55+
GC::Ptr<SVGAnimatedNumber> m_slope;
56+
GC::Ptr<SVGAnimatedNumber> m_intercept;
57+
GC::Ptr<SVGAnimatedNumber> m_amplitude;
58+
GC::Ptr<SVGAnimatedNumber> m_exponent;
59+
GC::Ptr<SVGAnimatedNumber> m_offset;
60+
};
61+
62+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#import <SVG/SVGElement.idl>
2+
3+
// https://www.w3.org/TR/filter-effects-1/#InterfaceSVGComponentTransferFunctionElement
4+
[Exposed=Window]
5+
interface SVGComponentTransferFunctionElement : SVGElement {
6+
7+
// Component Transfer Types
8+
const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN = 0;
9+
const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY = 1;
10+
const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_TABLE = 2;
11+
const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE = 3;
12+
const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_LINEAR = 4;
13+
const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_GAMMA = 5;
14+
15+
readonly attribute SVGAnimatedEnumeration type;
16+
readonly attribute SVGAnimatedNumberList tableValues;
17+
readonly attribute SVGAnimatedNumber slope;
18+
readonly attribute SVGAnimatedNumber intercept;
19+
readonly attribute SVGAnimatedNumber amplitude;
20+
readonly attribute SVGAnimatedNumber exponent;
21+
readonly attribute SVGAnimatedNumber offset;
22+
};

Libraries/LibWeb/idl_files.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,7 @@ libweb_js_bindings(SVG/SVGAnimatedString)
378378
libweb_js_bindings(SVG/SVGAnimatedTransformList)
379379
libweb_js_bindings(SVG/SVGAnimationElement)
380380
libweb_js_bindings(SVG/SVGClipPathElement)
381+
libweb_js_bindings(SVG/SVGComponentTransferFunctionElement)
381382
libweb_js_bindings(SVG/SVGDefsElement)
382383
libweb_js_bindings(SVG/SVGDescElement)
383384
libweb_js_bindings(SVG/SVGElement)

Tests/LibWeb/Text/expected/all-window-properties.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,7 @@ SVGAnimatedTransformList
372372
SVGAnimationElement
373373
SVGCircleElement
374374
SVGClipPathElement
375+
SVGComponentTransferFunctionElement
375376
SVGDefsElement
376377
SVGDescElement
377378
SVGElement

0 commit comments

Comments
 (0)