) [36.03125,25 28.40625x17]
+ TextPaintable (TextNode<#text>)
+ PaintableWithLines (BlockContainer
) [64.4375,25 26.671875x17]
+ TextPaintable (TextNode<#text>)
+ PaintableWithLines (BlockContainer(anonymous)) [8,42 784x0]
diff --git a/Tests/LibWeb/Layout/input/writing-modes-direction-flex.html b/Tests/LibWeb/Layout/input/writing-modes-direction-flex.html
new file mode 100644
index 0000000000..bdfe7aa1f4
--- /dev/null
+++ b/Tests/LibWeb/Layout/input/writing-modes-direction-flex.html
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/Userland/Libraries/LibWeb/CSS/ComputedValues.h b/Userland/Libraries/LibWeb/CSS/ComputedValues.h
index 82873ef911..b3d6b72625 100644
--- a/Userland/Libraries/LibWeb/CSS/ComputedValues.h
+++ b/Userland/Libraries/LibWeb/CSS/ComputedValues.h
@@ -178,6 +178,7 @@ public:
static CSS::TableLayout table_layout() { return CSS::TableLayout::Auto; }
static QuotesData quotes() { return QuotesData { .type = QuotesData::Type::Auto }; }
static CSS::TransformBox transform_box() { return CSS::TransformBox::ViewBox; }
+ static CSS::Direction direction() { return CSS::Direction::Ltr; }
// https://www.w3.org/TR/SVG/geometry.html
static LengthPercentage cx() { return CSS::Length::make_px(0); }
@@ -422,6 +423,7 @@ public:
Vector
> const& grid_template_areas() const { return m_noninherited.grid_template_areas; }
CSS::ObjectFit object_fit() const { return m_noninherited.object_fit; }
CSS::ObjectPosition object_position() const { return m_noninherited.object_position; }
+ CSS::Direction direction() const { return m_inherited.direction; }
CSS::LengthBox const& inset() const { return m_noninherited.inset; }
const CSS::LengthBox& margin() const { return m_noninherited.margin; }
@@ -531,6 +533,7 @@ protected:
CSS::ListStylePosition list_style_position { InitialValues::list_style_position() };
CSS::Visibility visibility { InitialValues::visibility() };
CSS::QuotesData quotes { InitialValues::quotes() };
+ CSS::Direction direction { InitialValues::direction() };
Optional fill;
CSS::FillRule fill_rule { InitialValues::fill_rule() };
@@ -756,6 +759,7 @@ public:
void set_quotes(CSS::QuotesData value) { m_inherited.quotes = value; }
void set_object_fit(CSS::ObjectFit value) { m_noninherited.object_fit = value; }
void set_object_position(CSS::ObjectPosition value) { m_noninherited.object_position = value; }
+ void set_direction(CSS::Direction value) { m_inherited.direction = value; }
void set_fill(SVGPaint value) { m_inherited.fill = value; }
void set_stroke(SVGPaint value) { m_inherited.stroke = value; }
diff --git a/Userland/Libraries/LibWeb/CSS/Enums.json b/Userland/Libraries/LibWeb/CSS/Enums.json
index 74fc49c9c0..b5c47d7195 100644
--- a/Userland/Libraries/LibWeb/CSS/Enums.json
+++ b/Userland/Libraries/LibWeb/CSS/Enums.json
@@ -144,6 +144,10 @@
"zoom-in",
"zoom-out"
],
+ "direction": [
+ "ltr",
+ "rtl"
+ ],
"display-box": [
"contents",
"none"
diff --git a/Userland/Libraries/LibWeb/CSS/Properties.json b/Userland/Libraries/LibWeb/CSS/Properties.json
index 1a89a8ecb1..a3b2a70f46 100644
--- a/Userland/Libraries/LibWeb/CSS/Properties.json
+++ b/Userland/Libraries/LibWeb/CSS/Properties.json
@@ -1065,9 +1065,8 @@
"animation-type": "none",
"inherited": true,
"initial": "ltr",
- "valid-identifiers": [
- "ltr",
- "rtl"
+ "valid-types": [
+ "direction"
]
},
"display": {
diff --git a/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp b/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp
index 486204bda8..9c8c4e6188 100644
--- a/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp
+++ b/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp
@@ -1085,6 +1085,12 @@ Optional StyleProperties::table_layout() const
return value_id_to_table_layout(value->to_identifier());
}
+Optional StyleProperties::direction() const
+{
+ auto value = property(CSS::PropertyID::Direction);
+ return value_id_to_direction(value->to_identifier());
+}
+
Optional StyleProperties::mask_type() const
{
auto value = property(CSS::PropertyID::MaskType);
diff --git a/Userland/Libraries/LibWeb/CSS/StyleProperties.h b/Userland/Libraries/LibWeb/CSS/StyleProperties.h
index d6dad7a51f..233263c61b 100644
--- a/Userland/Libraries/LibWeb/CSS/StyleProperties.h
+++ b/Userland/Libraries/LibWeb/CSS/StyleProperties.h
@@ -130,6 +130,7 @@ public:
Optional object_fit() const;
CSS::ObjectPosition object_position() const;
Optional table_layout() const;
+ Optional direction() const;
static Vector transformations_for_style_value(StyleValue const& value);
Vector transformations() const;
diff --git a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp
index 9c0978e5d0..069a6dfa1b 100644
--- a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp
+++ b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp
@@ -194,6 +194,19 @@ void FlexFormattingContext::parent_context_did_dimension_child_root_box()
});
}
+// https://www.w3.org/TR/css-flexbox-1/#flex-direction-property
+bool FlexFormattingContext::is_direction_reverse() const
+{
+ switch (flex_container().computed_values().direction()) {
+ case CSS::Direction::Ltr:
+ return m_flex_direction == CSS::FlexDirection::ColumnReverse || m_flex_direction == CSS::FlexDirection::RowReverse;
+ case CSS::Direction::Rtl:
+ return m_flex_direction == CSS::FlexDirection::ColumnReverse || m_flex_direction == CSS::FlexDirection::Row;
+ default:
+ VERIFY_NOT_REACHED();
+ }
+}
+
void FlexFormattingContext::populate_specified_margins(FlexItem& item, CSS::FlexDirection flex_direction) const
{
auto width_of_containing_block = m_flex_container_state.content_width();
diff --git a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.h b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.h
index 29ce48054d..8f18950314 100644
--- a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.h
+++ b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.h
@@ -195,7 +195,7 @@ private:
bool is_row_layout() const { return m_flex_direction == CSS::FlexDirection::Row || m_flex_direction == CSS::FlexDirection::RowReverse; }
bool is_single_line() const { return flex_container().computed_values().flex_wrap() == CSS::FlexWrap::Nowrap; }
- bool is_direction_reverse() const { return m_flex_direction == CSS::FlexDirection::ColumnReverse || m_flex_direction == CSS::FlexDirection::RowReverse; }
+ bool is_direction_reverse() const;
void populate_specified_margins(FlexItem&, CSS::FlexDirection) const;
void determine_intrinsic_size_of_flex_container();
diff --git a/Userland/Libraries/LibWeb/Layout/Node.cpp b/Userland/Libraries/LibWeb/Layout/Node.cpp
index 3221a4af97..8a18aa07ac 100644
--- a/Userland/Libraries/LibWeb/Layout/Node.cpp
+++ b/Userland/Libraries/LibWeb/Layout/Node.cpp
@@ -872,6 +872,9 @@ void NodeWithStyle::apply_style(const CSS::StyleProperties& computed_style)
computed_values.set_object_position(computed_style.object_position());
+ if (auto direction = computed_style.direction(); direction.has_value())
+ computed_values.set_direction(direction.value());
+
if (auto scrollbar_width = computed_style.scrollbar_width(); scrollbar_width.has_value())
computed_values.set_scrollbar_width(scrollbar_width.value());