1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 22:07:35 +00:00

LibWeb: Override width calculation for table wrappers

Introduce `TableWrapper` type so table wrappers could be
distinguished from block containers and override width
calculation for table wrappers (CSS 2.2 spec, section 17.5.2)
 inside BFCs in the way that their width should be equal to
width of table box they wrap.
This commit is contained in:
Aliaksandr Kalenik 2023-01-14 14:48:20 +01:00 committed by Andreas Kling
parent 7526f9a8b7
commit 709fe01f52
8 changed files with 74 additions and 1 deletions

View file

@ -347,6 +347,7 @@ set(SOURCES
Layout/TableFormattingContext.cpp
Layout/TableRowBox.cpp
Layout/TableRowGroupBox.cpp
Layout/TableWrapper.cpp
Layout/TextNode.cpp
Layout/TreeBuilder.cpp
Loader/ContentFilter.cpp

View file

@ -454,6 +454,7 @@ class NodeWithStyle;
class NodeWithStyleAndBoxModelMetrics;
class RadioButton;
class ReplacedBox;
class TableWrapper;
class TextNode;
}

View file

@ -17,6 +17,8 @@
#include <LibWeb/Layout/ListItemBox.h>
#include <LibWeb/Layout/ListItemMarkerBox.h>
#include <LibWeb/Layout/ReplacedBox.h>
#include <LibWeb/Layout/TableBox.h>
#include <LibWeb/Layout/TableWrapper.h>
namespace Web::Layout {
@ -193,6 +195,8 @@ void BlockFormattingContext::compute_width(Box const& box, AvailableSpace const&
};
auto input_width = [&] {
if (is<TableWrapper>(box))
return CSS::Length::make_px(compute_width_for_table_wrapper(box, available_space));
if (should_treat_width_as_auto(box, available_space))
return CSS::Length::make_auto();
return calculate_inner_width(box, available_space.width, computed_values.width());
@ -312,6 +316,18 @@ void BlockFormattingContext::compute_width_for_block_level_replaced_element_in_n
m_state.get_mutable(box).set_content_width(compute_width_for_replaced_element(m_state, box, available_space));
}
CSSPixels BlockFormattingContext::compute_width_for_table_wrapper(Box const& box, AvailableSpace const& available_space)
{
// 17.5.2
// Table wrapper width should be equal to width of table box it contains
LayoutState throwaway_state(&m_state);
auto context = create_independent_formatting_context_if_needed(throwaway_state, box);
VERIFY(context);
context->run(box, LayoutMode::IntrinsicSizing, m_state.get(box).available_inner_space_or_constraints_from(available_space));
auto const* table_box = box.first_child_of_type<TableBox>();
return throwaway_state.get(*table_box).content_width();
}
void BlockFormattingContext::compute_height(Box const& box, AvailableSpace const& available_space)
{
auto const& computed_values = box.computed_values();

View file

@ -59,6 +59,8 @@ private:
void compute_width_for_block_level_replaced_element_in_normal_flow(ReplacedBox const&, AvailableSpace const&);
CSSPixels compute_width_for_table_wrapper(Box const&, AvailableSpace const&);
void layout_initial_containing_block(LayoutMode, AvailableSpace const&);
void layout_block_level_children(BlockContainer const&, LayoutMode, AvailableSpace const&);

View file

@ -90,6 +90,7 @@ public:
virtual bool is_label() const { return false; }
virtual bool is_replaced_box() const { return false; }
virtual bool is_list_item_marker_box() const { return false; }
virtual bool is_table_wrapper() const { return false; }
template<typename T>
bool fast_is() const = delete;

View file

@ -0,0 +1,23 @@
/*
* Copyright (c) 2023, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Layout/TableWrapper.h>
namespace Web::Layout {
TableWrapper::TableWrapper(DOM::Document& document, DOM::Node* node, NonnullRefPtr<CSS::StyleProperties> style)
: BlockContainer(document, node, move(style))
{
}
TableWrapper::TableWrapper(DOM::Document& document, DOM::Node* node, CSS::ComputedValues computed_values)
: BlockContainer(document, node, move(computed_values))
{
}
TableWrapper::~TableWrapper() = default;
}

View file

@ -0,0 +1,28 @@
/*
* Copyright (c) 2023, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/Layout/BlockContainer.h>
namespace Web::Layout {
class TableWrapper : public BlockContainer {
JS_CELL(TableWrapper, BlockContainer);
public:
TableWrapper(DOM::Document&, DOM::Node*, NonnullRefPtr<CSS::StyleProperties>);
TableWrapper(DOM::Document&, DOM::Node*, CSS::ComputedValues);
virtual ~TableWrapper() override;
private:
virtual bool is_table_wrapper() const final { return true; }
};
template<>
inline bool Node::fast_is<TableWrapper>() const { return is_table_wrapper(); }
}

View file

@ -24,6 +24,7 @@
#include <LibWeb/Layout/TableBox.h>
#include <LibWeb/Layout/TableCellBox.h>
#include <LibWeb/Layout/TableRowBox.h>
#include <LibWeb/Layout/TableWrapper.h>
#include <LibWeb/Layout/TextNode.h>
#include <LibWeb/Layout/TreeBuilder.h>
#include <LibWeb/SVG/SVGForeignObjectElement.h>
@ -598,7 +599,7 @@ void TreeBuilder::generate_missing_parents(NodeWithStyle& root)
mutable_wrapper_computed_values.set_margin(table_box->computed_values().margin());
table_box->reset_table_box_computed_values_used_by_wrapper_to_init_values();
auto wrapper = parent.heap().allocate_without_realm<BlockContainer>(parent.document(), nullptr, move(wrapper_computed_values));
auto wrapper = parent.heap().allocate_without_realm<TableWrapper>(parent.document(), nullptr, move(wrapper_computed_values));
parent.remove_child(*table_box);
wrapper->append_child(*table_box);