LibWeb: Lay out the fieldset's rendered legend

This commit is contained in:
Kostya Farber 2024-11-23 15:47:32 +00:00 committed by Tim Ledbetter
commit 81f8866606
Notes: github-actions[bot] 2024-11-29 12:51:25 +00:00
12 changed files with 356 additions and 15 deletions

View file

@ -12,7 +12,9 @@
#include <LibWeb/Layout/BlockContainer.h>
#include <LibWeb/Layout/BlockFormattingContext.h>
#include <LibWeb/Layout/Box.h>
#include <LibWeb/Layout/FieldSetBox.h>
#include <LibWeb/Layout/InlineFormattingContext.h>
#include <LibWeb/Layout/LegendBox.h>
#include <LibWeb/Layout/LineBuilder.h>
#include <LibWeb/Layout/ListItemBox.h>
#include <LibWeb/Layout/ListItemMarkerBox.h>
@ -73,6 +75,38 @@ void BlockFormattingContext::run(AvailableSpace const& available_space)
return;
}
if (is<FieldSetBox>(root())) {
if (root().children_are_inline())
layout_inline_children(root(), available_space);
else
layout_block_level_children(root(), available_space);
auto const& fieldset_box = verify_cast<FieldSetBox>(root());
if (!(fieldset_box.has_rendered_legend())) {
return;
}
auto const* legend = root().first_child_of_type<LegendBox>();
auto& legend_state = m_state.get_mutable(*legend);
auto& fieldset_state = m_state.get_mutable(root());
// The element is expected to be positioned in the block-flow direction such that
// its border box is centered over the border on the block-start side of the fieldset element.
// FIXME: this should take writing modes into consideration.
auto legend_height = legend_state.border_box_height();
auto new_y = -((legend_height) / 2) - fieldset_state.padding_top;
legend_state.set_content_offset({ legend_state.offset.x(), new_y });
// If the computed value of 'inline-size' is 'auto',
// then the used value is the fit-content inline size.
if (legend->computed_values().width().is_auto()) {
auto width = calculate_fit_content_width(*legend, available_space);
legend_state.set_content_width(width);
}
return;
}
if (root().children_are_inline())
layout_inline_children(root(), available_space);
else

View file

@ -7,6 +7,8 @@
#include <LibWeb/Forward.h>
#include <LibWeb/HTML/HTMLLegendElement.h>
#include <LibWeb/Layout/FieldSetBox.h>
#include <LibWeb/Layout/LegendBox.h>
#include <LibWeb/Painting/FieldSetPaintable.h>
namespace Web::Layout {
@ -22,13 +24,27 @@ FieldSetBox::~FieldSetBox() = default;
bool FieldSetBox::has_rendered_legend() const
{
// https://html.spec.whatwg.org/#rendered-legend
if (this->has_children() && this->first_child()->is_legend_box()) {
auto* first_child = this->first_child();
return first_child->computed_values().float_() == CSS::Float::None
&& first_child->computed_values().position() != CSS::Positioning::Absolute
&& first_child->computed_values().position() != CSS::Positioning::Fixed;
bool has_rendered_legend = false;
if (has_children()) {
for_each_child_of_type<Box>([&](Box const& child) {
if (child.is_anonymous())
return IterationDecision::Continue;
if (!child.is_legend_box())
return IterationDecision::Break;
has_rendered_legend = child.computed_values().float_() == CSS::Float::None
&& child.computed_values().position() != CSS::Positioning::Absolute
&& child.computed_values().position() != CSS::Positioning::Fixed;
return IterationDecision::Break;
});
}
return false;
return has_rendered_legend;
}
GC::Ptr<Painting::Paintable> FieldSetBox::create_paintable() const
{
return Painting::FieldSetPaintable::create(*this);
}
}

View file

@ -8,7 +8,7 @@
#include <LibWeb/Forward.h>
#include <LibWeb/Layout/BlockContainer.h>
#include <LibWeb/Painting/FieldSetPaintable.h>
namespace Web::Layout {
class FieldSetBox final : public BlockContainer {
@ -22,10 +22,10 @@ public:
DOM::Element& dom_node() { return static_cast<DOM::Element&>(*BlockContainer::dom_node()); }
DOM::Element const& dom_node() const { return static_cast<DOM::Element const&>(*BlockContainer::dom_node()); }
void layout_legend() const;
bool has_rendered_legend() const;
virtual GC::Ptr<Painting::Paintable> create_paintable() const override;
private:
bool has_rendered_legend() const;
virtual bool is_fieldset_box() const final
{
return true;

View file

@ -23,6 +23,7 @@
#include <LibWeb/HTML/HTMLLIElement.h>
#include <LibWeb/HTML/HTMLOListElement.h>
#include <LibWeb/HTML/HTMLSlotElement.h>
#include <LibWeb/Layout/FieldSetBox.h>
#include <LibWeb/Layout/ListItemBox.h>
#include <LibWeb/Layout/ListItemMarkerBox.h>
#include <LibWeb/Layout/Node.h>
@ -76,6 +77,9 @@ static Layout::Node& insertion_parent_for_inline_node(Layout::NodeWithStyle& lay
return *layout_parent.last_child();
};
if (is<FieldSetBox>(layout_parent))
return last_child_creating_anonymous_wrapper_if_needed(layout_parent);
if (layout_parent.display().is_inline_outside() && layout_parent.display().is_flow_inside())
return layout_parent;