Skip to content

Commit da88387

Browse files
committed
LibWeb/CSS: Implement CSSSkewY
Equivalent to the skewY() transform function. +27 WPT subtests.
1 parent b0cc1c6 commit da88387

File tree

10 files changed

+196
-32
lines changed

10 files changed

+196
-32
lines changed

Libraries/LibWeb/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ set(SOURCES
140140
CSS/CSSScale.cpp
141141
CSS/CSSSkew.cpp
142142
CSS/CSSSkewX.cpp
143+
CSS/CSSSkewY.cpp
143144
CSS/CSSStyleDeclaration.cpp
144145
CSS/CSSStyleProperties.cpp
145146
CSS/CSSStyleRule.cpp

Libraries/LibWeb/CSS/CSSSkewY.cpp

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
* Copyright (c) 2025, Sam Atkins <sam@ladybird.org>
3+
*
4+
* SPDX-License-Identifier: BSD-2-Clause
5+
*/
6+
7+
#include "CSSSkewY.h"
8+
#include <LibWeb/Bindings/CSSSkewYPrototype.h>
9+
#include <LibWeb/Bindings/Intrinsics.h>
10+
#include <LibWeb/CSS/CSSNumericValue.h>
11+
#include <LibWeb/CSS/CSSUnitValue.h>
12+
#include <LibWeb/Geometry/DOMMatrix.h>
13+
#include <LibWeb/WebIDL/ExceptionOr.h>
14+
15+
namespace Web::CSS {
16+
17+
GC_DEFINE_ALLOCATOR(CSSSkewY);
18+
19+
GC::Ref<CSSSkewY> CSSSkewY::create(JS::Realm& realm, GC::Ref<CSSNumericValue> ay)
20+
{
21+
return realm.create<CSSSkewY>(realm, ay);
22+
}
23+
24+
// https://drafts.css-houdini.org/css-typed-om-1/#dom-cssskewy-cssskewy
25+
WebIDL::ExceptionOr<GC::Ref<CSSSkewY>> CSSSkewY::construct_impl(JS::Realm& realm, GC::Ref<CSSNumericValue> ay)
26+
{
27+
// The CSSSkewY(ay) constructor must, when invoked, perform the following steps:
28+
29+
// 1. If ay does not match <angle>, throw a TypeError.
30+
if (!ay->type().matches_angle({}))
31+
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "CSSSkewY ay component doesn't match <angle>"sv };
32+
33+
// 2. Return a new CSSSkewY object with its ay internal slot set to ay, and its is2D internal slot set to true.
34+
return CSSSkewY::create(realm, ay);
35+
}
36+
37+
CSSSkewY::CSSSkewY(JS::Realm& realm, GC::Ref<CSSNumericValue> ay)
38+
: CSSTransformComponent(realm, Is2D::Yes)
39+
, m_ay(ay)
40+
{
41+
}
42+
43+
CSSSkewY::~CSSSkewY() = default;
44+
45+
void CSSSkewY::initialize(JS::Realm& realm)
46+
{
47+
WEB_SET_PROTOTYPE_FOR_INTERFACE(CSSSkewY);
48+
Base::initialize(realm);
49+
}
50+
51+
void CSSSkewY::visit_edges(Visitor& visitor)
52+
{
53+
Base::visit_edges(visitor);
54+
visitor.visit(m_ay);
55+
}
56+
57+
// https://drafts.css-houdini.org/css-typed-om-1/#serialize-a-cssskewy
58+
WebIDL::ExceptionOr<Utf16String> CSSSkewY::to_string() const
59+
{
60+
// 1. Let s initially be "skewY(".
61+
StringBuilder builder { StringBuilder::Mode::UTF16 };
62+
builder.append("skewY("sv);
63+
64+
// 2. Serialize this’s ay internal slot, and append it to s.
65+
builder.append(m_ay->to_string());
66+
67+
// 3. Append ")" to s, and return s.
68+
builder.append(")"sv);
69+
return builder.to_utf16_string();
70+
}
71+
72+
// https://drafts.css-houdini.org/css-typed-om-1/#dom-csstransformcomponent-tomatrix
73+
WebIDL::ExceptionOr<GC::Ref<Geometry::DOMMatrix>> CSSSkewY::to_matrix() const
74+
{
75+
// 1. Let matrix be a new DOMMatrix object, initialized to this’s equivalent 4x4 transform matrix, as defined in
76+
// CSS Transforms 1 § 12. Mathematical Description of Transform Functions, and with its is2D internal slot set
77+
// to the same value as this’s is2D internal slot.
78+
// NOTE: Recall that the is2D flag affects what transform, and thus what equivalent matrix, a
79+
// CSSTransformComponent represents.
80+
// As the entries of such a matrix are defined relative to the px unit, if any <length>s in this involved in
81+
// generating the matrix are not compatible units with px (such as relative lengths or percentages), throw a
82+
// TypeError.
83+
auto matrix = Geometry::DOMMatrix::create(realm());
84+
85+
// NB: to() throws a TypeError if the conversion can't be done.
86+
auto ay_rad = TRY(m_ay->to("rad"_fly_string))->value();
87+
matrix->set_m12(tanf(ay_rad));
88+
89+
// 2. Return matrix.
90+
return matrix;
91+
}
92+
93+
WebIDL::ExceptionOr<void> CSSSkewY::set_ay(GC::Ref<CSSNumericValue> ay)
94+
{
95+
// AD-HOC: Not specced. https://github.com/w3c/css-houdini-drafts/issues/1153
96+
// WPT expects this to throw for invalid values.
97+
if (!ay->type().matches_angle({}))
98+
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "CSSSkewY ay component doesn't match <angle>"sv };
99+
m_ay = ay;
100+
return {};
101+
}
102+
103+
// https://drafts.css-houdini.org/css-typed-om-1/#dom-cssskew-is2d
104+
void CSSSkewY::set_is_2d(bool)
105+
{
106+
// The is2D attribute of a CSSSkewY, CSSSkewYX, or CSSSkewYY object must, on setting, do nothing.
107+
}
108+
109+
}

Libraries/LibWeb/CSS/CSSSkewY.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright (c) 2025, Sam Atkins <sam@ladybird.org>
3+
*
4+
* SPDX-License-Identifier: BSD-2-Clause
5+
*/
6+
7+
#pragma once
8+
9+
#include <LibWeb/CSS/CSSTransformComponent.h>
10+
11+
namespace Web::CSS {
12+
13+
// https://drafts.css-houdini.org/css-typed-om-1/#cssskewy
14+
class CSSSkewY final : public CSSTransformComponent {
15+
WEB_PLATFORM_OBJECT(CSSSkewY, CSSTransformComponent);
16+
GC_DECLARE_ALLOCATOR(CSSSkewY);
17+
18+
public:
19+
[[nodiscard]] static GC::Ref<CSSSkewY> create(JS::Realm&, GC::Ref<CSSNumericValue> ay);
20+
static WebIDL::ExceptionOr<GC::Ref<CSSSkewY>> construct_impl(JS::Realm&, GC::Ref<CSSNumericValue> ay);
21+
22+
virtual ~CSSSkewY() override;
23+
24+
virtual WebIDL::ExceptionOr<Utf16String> to_string() const override;
25+
26+
virtual WebIDL::ExceptionOr<GC::Ref<Geometry::DOMMatrix>> to_matrix() const override;
27+
28+
GC::Ref<CSSNumericValue> ay() const { return m_ay; }
29+
WebIDL::ExceptionOr<void> set_ay(GC::Ref<CSSNumericValue> value);
30+
31+
virtual void set_is_2d(bool value) override;
32+
33+
private:
34+
explicit CSSSkewY(JS::Realm&, GC::Ref<CSSNumericValue> ay);
35+
36+
virtual void initialize(JS::Realm&) override;
37+
virtual void visit_edges(Visitor&) override;
38+
39+
GC::Ref<CSSNumericValue> m_ay;
40+
};
41+
42+
}

Libraries/LibWeb/CSS/CSSSkewY.idl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#import <CSS/CSSNumericValue.idl>
2+
#import <CSS/CSSTransformComponent.idl>
3+
4+
// https://drafts.css-houdini.org/css-typed-om-1/#cssskewy
5+
[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)]
6+
interface CSSSkewY : CSSTransformComponent {
7+
constructor(CSSNumericValue ay);
8+
attribute CSSNumericValue ay;
9+
};

Libraries/LibWeb/Forward.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ class CSSRuleList;
265265
class CSSScale;
266266
class CSSSkew;
267267
class CSSSkewX;
268+
class CSSSkewY;
268269
class CSSStyleDeclaration;
269270
class CSSStyleProperties;
270271
class CSSStyleRule;

Libraries/LibWeb/idl_files.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ libweb_js_bindings(CSS/CSSRuleList)
6060
libweb_js_bindings(CSS/CSSScale)
6161
libweb_js_bindings(CSS/CSSSkew)
6262
libweb_js_bindings(CSS/CSSSkewX)
63+
libweb_js_bindings(CSS/CSSSkewY)
6364
libweb_js_bindings(CSS/CSSStyleDeclaration)
6465
libweb_js_bindings(CSS/CSSStyleProperties)
6566
libweb_js_bindings(CSS/CSSStyleRule)

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ CSSRuleList
7272
CSSScale
7373
CSSSkew
7474
CSSSkewX
75+
CSSSkewY
7576
CSSStyleDeclaration
7677
CSSStyleProperties
7778
CSSStyleRule

Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/idlharness.txt

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ Harness status: OK
22

33
Found 545 tests
44

5-
339 Pass
6-
206 Fail
5+
346 Pass
6+
199 Fail
77
Pass idl_test setup
88
Pass idl_test validation
99
Pass Partial interface Element: original interface defined
@@ -352,13 +352,13 @@ Fail Stringification of skewX
352352
Fail CSSSkewX interface: skewX must inherit property "ax" with the proper type
353353
Fail CSSTransformComponent interface: skewX must inherit property "is2D" with the proper type
354354
Fail CSSTransformComponent interface: skewX must inherit property "toMatrix()" with the proper type
355-
Fail CSSSkewY interface: existence and properties of interface object
356-
Fail CSSSkewY interface object length
357-
Fail CSSSkewY interface object name
358-
Fail CSSSkewY interface: existence and properties of interface prototype object
359-
Fail CSSSkewY interface: existence and properties of interface prototype object's "constructor" property
360-
Fail CSSSkewY interface: existence and properties of interface prototype object's @@unscopables property
361-
Fail CSSSkewY interface: attribute ay
355+
Pass CSSSkewY interface: existence and properties of interface object
356+
Pass CSSSkewY interface object length
357+
Pass CSSSkewY interface object name
358+
Pass CSSSkewY interface: existence and properties of interface prototype object
359+
Pass CSSSkewY interface: existence and properties of interface prototype object's "constructor" property
360+
Pass CSSSkewY interface: existence and properties of interface prototype object's @@unscopables property
361+
Pass CSSSkewY interface: attribute ay
362362
Fail CSSSkewY must be primary interface of skewY
363363
Fail Stringification of skewY
364364
Fail CSSSkewY interface: skewY must inherit property "ay" with the proper type

Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/cssSkewY.tentative.txt

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,23 @@ Harness status: OK
22

33
Found 19 tests
44

5-
19 Fail
6-
Fail Constructing a CSSSkewY with a keyword throws a TypeError
7-
Fail Constructing a CSSSkewY with a double throws a TypeError
8-
Fail Constructing a CSSSkewY with a unitless zero throws a TypeError
9-
Fail Constructing a CSSSkewY with a string angle throws a TypeError
10-
Fail Constructing a CSSSkewY with a number CSSUnitValue throws a TypeError
11-
Fail Constructing a CSSSkewY with a time dimension CSSUnitValue throws a TypeError
12-
Fail Constructing a CSSSkewY with a CSSMathValue of length type throws a TypeError
13-
Fail Updating CSSSkewY.ay with a keyword throws a TypeError
14-
Fail Updating CSSSkewY.ay with a double throws a TypeError
15-
Fail Updating CSSSkewY.ay with a unitless zero throws a TypeError
16-
Fail Updating CSSSkewY.ay with a string angle throws a TypeError
17-
Fail Updating CSSSkewY.ay with a number CSSUnitValue throws a TypeError
18-
Fail Updating CSSSkewY.ay with a time dimension CSSUnitValue throws a TypeError
19-
Fail Updating CSSSkewY.ay with a CSSMathValue of length type throws a TypeError
20-
Fail CSSSkewY can be constructed from an angle CSSUnitValue
21-
Fail CSSSkewY can be constructed from a CSSMathValue of angle type
22-
Fail CSSSkewY.ay can be updated to an angle CSSUnitValue
23-
Fail CSSSkewY.ay can be updated to a CSSMathValue of angle type
24-
Fail Modifying skewY.is2D is a no-op
5+
19 Pass
6+
Pass Constructing a CSSSkewY with a keyword throws a TypeError
7+
Pass Constructing a CSSSkewY with a double throws a TypeError
8+
Pass Constructing a CSSSkewY with a unitless zero throws a TypeError
9+
Pass Constructing a CSSSkewY with a string angle throws a TypeError
10+
Pass Constructing a CSSSkewY with a number CSSUnitValue throws a TypeError
11+
Pass Constructing a CSSSkewY with a time dimension CSSUnitValue throws a TypeError
12+
Pass Constructing a CSSSkewY with a CSSMathValue of length type throws a TypeError
13+
Pass Updating CSSSkewY.ay with a keyword throws a TypeError
14+
Pass Updating CSSSkewY.ay with a double throws a TypeError
15+
Pass Updating CSSSkewY.ay with a unitless zero throws a TypeError
16+
Pass Updating CSSSkewY.ay with a string angle throws a TypeError
17+
Pass Updating CSSSkewY.ay with a number CSSUnitValue throws a TypeError
18+
Pass Updating CSSSkewY.ay with a time dimension CSSUnitValue throws a TypeError
19+
Pass Updating CSSSkewY.ay with a CSSMathValue of length type throws a TypeError
20+
Pass CSSSkewY can be constructed from an angle CSSUnitValue
21+
Pass CSSSkewY can be constructed from a CSSMathValue of angle type
22+
Pass CSSSkewY.ay can be updated to an angle CSSUnitValue
23+
Pass CSSSkewY.ay can be updated to a CSSMathValue of angle type
24+
Pass Modifying skewY.is2D is a no-op

Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/cssTransformComponent-toMatrix.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ Harness status: OK
22

33
Found 8 tests
44

5-
5 Pass
6-
3 Fail
5+
6 Pass
6+
2 Fail
77
Pass CSSTranslate.toMatrix() returns correct matrix
88
Pass CSSRotate.toMatrix() returns correct matrix
99
Pass CSSScale.toMatrix() returns correct matrix
1010
Pass CSSSkew.toMatrix() returns correct matrix
1111
Pass CSSSkewX.toMatrix() returns correct matrix
12-
Fail CSSSkewY.toMatrix() returns correct matrix
12+
Pass CSSSkewY.toMatrix() returns correct matrix
1313
Fail CSSPerspective.toMatrix() returns correct matrix
1414
Fail CSSMatrixComponent.toMatrix() returns correct matrix

0 commit comments

Comments
 (0)