diff options
17 files changed, 163 insertions, 41 deletions
diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index 8d2d0b11f3..317fb3163d 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -809,7 +809,11 @@ void Document::update_layout() icb_state.set_content_width(viewport_rect.width()); icb_state.set_content_height(viewport_rect.height()); - root_formatting_context.run(*m_layout_root, Layout::LayoutMode::Normal); + root_formatting_context.run( + *m_layout_root, + Layout::LayoutMode::Normal, + Layout::AvailableSpace::make_definite(viewport_rect.width()), + Layout::AvailableSpace::make_definite(viewport_rect.height())); } layout_state.commit(); diff --git a/Userland/Libraries/LibWeb/Layout/AvailableSpace.cpp b/Userland/Libraries/LibWeb/Layout/AvailableSpace.cpp new file mode 100644 index 0000000000..026fe90311 --- /dev/null +++ b/Userland/Libraries/LibWeb/Layout/AvailableSpace.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2022, Andreas Kling <kling@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <LibWeb/Layout/AvailableSpace.h> +#include <math.h> + +namespace Web::Layout { + +AvailableSpace AvailableSpace::make_definite(float value) +{ + return AvailableSpace { Type::Definite, value }; +} + +AvailableSpace AvailableSpace::make_indefinite() +{ + return AvailableSpace { Type::Indefinite, INFINITY }; +} + +AvailableSpace AvailableSpace::make_min_content() +{ + return AvailableSpace { Type::MinContent, 0 }; +} + +AvailableSpace AvailableSpace::make_max_content() +{ + return AvailableSpace { Type::MaxContent, INFINITY }; +} + +String AvailableSpace::to_string() const +{ + switch (m_type) { + case Type::Definite: + return String::formatted("definite({})", m_value); + case Type::Indefinite: + return "indefinite"; + case Type::MinContent: + return "min-content"; + case Type::MaxContent: + return "max-content"; + } + VERIFY_NOT_REACHED(); +} + +AvailableSpace::AvailableSpace(Type type, float value) + : m_type(type) + , m_value(value) +{ +} + +} diff --git a/Userland/Libraries/LibWeb/Layout/AvailableSpace.h b/Userland/Libraries/LibWeb/Layout/AvailableSpace.h new file mode 100644 index 0000000000..7f319ab9cb --- /dev/null +++ b/Userland/Libraries/LibWeb/Layout/AvailableSpace.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2022, Andreas Kling <kling@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/Format.h> +#include <AK/String.h> +#include <LibWeb/Forward.h> + +namespace Web::Layout { + +class AvailableSpace { +public: + enum class Type { + Definite, + Indefinite, + MinContent, + MaxContent, + }; + + static AvailableSpace make_definite(float); + static AvailableSpace make_indefinite(); + static AvailableSpace make_min_content(); + static AvailableSpace make_max_content(); + + bool is_definite() const { return m_type == Type::Definite; } + bool is_indefinite() const { return m_type == Type::Indefinite; } + bool is_min_content() const { return m_type == Type::MinContent; } + bool is_max_content() const { return m_type == Type::MaxContent; } + bool is_intrinsic_sizing_constraint() const { return is_min_content() || is_max_content(); } + + float definite_value() const + { + VERIFY(is_definite()); + return m_value; + } + + float to_px() const + { + return m_value; + } + + String to_string() const; + +private: + AvailableSpace(Type type, float); + + Type m_type {}; + float m_value {}; +}; + +} + +template<> +struct AK::Formatter<Web::Layout::AvailableSpace> : Formatter<StringView> { + ErrorOr<void> format(FormatBuilder& builder, Web::Layout::AvailableSpace const& available_space) + { + return Formatter<StringView>::format(builder, available_space.to_string()); + } +}; diff --git a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp index 773f352d75..9732a86363 100644 --- a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp @@ -44,7 +44,7 @@ float BlockFormattingContext::automatic_content_height() const return compute_auto_height_for_block_formatting_context_root(m_state, root()); } -void BlockFormattingContext::run(Box const&, LayoutMode layout_mode) +void BlockFormattingContext::run(Box const&, LayoutMode layout_mode, [[maybe_unused]] AvailableSpace const& available_width, [[maybe_unused]] AvailableSpace const& available_height) { if (is_initial()) { layout_initial_containing_block(layout_mode); @@ -366,7 +366,11 @@ void BlockFormattingContext::layout_inline_children(BlockContainer const& block_ } InlineFormattingContext context(m_state, block_container, *this); - context.run(block_container, layout_mode); + context.run( + block_container, + layout_mode, + AvailableSpace::make_definite(containing_block_width_for(block_container)), + AvailableSpace::make_definite(containing_block_height_for(block_container))); float max_line_width = 0; float content_height = 0; @@ -419,7 +423,7 @@ void BlockFormattingContext::layout_block_level_box(Box const& box, BlockContain } else { independent_formatting_context = create_independent_formatting_context_if_needed(m_state, box); if (independent_formatting_context) - independent_formatting_context->run(box, layout_mode); + independent_formatting_context->run(box, layout_mode, AvailableSpace::make_indefinite(), AvailableSpace::make_indefinite()); else layout_block_level_children(verify_cast<BlockContainer>(box), layout_mode); } @@ -442,19 +446,6 @@ void BlockFormattingContext::layout_block_level_box(Box const& box, BlockContain independent_formatting_context->parent_context_did_dimension_child_root_box(); } -void BlockFormattingContext::run_intrinsic_sizing(Box const& box) -{ - auto& box_state = m_state.get_mutable(box); - - if (box_state.has_definite_width()) - box_state.set_content_width(box.computed_values().width().resolved(box, CSS::Length::make_px(containing_block_width_for(box))).to_px(box)); - - if (box_state.has_definite_height()) - box_state.set_content_height(box.computed_values().height().resolved(box, CSS::Length::make_px(containing_block_height_for(box))).to_px(box)); - - run(box, LayoutMode::IntrinsicSizing); -} - void BlockFormattingContext::layout_block_level_children(BlockContainer const& block_container, LayoutMode layout_mode) { VERIFY(!block_container.children_are_inline()); diff --git a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h index 4d4b827ad0..03b1e5ef63 100644 --- a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h +++ b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h @@ -21,8 +21,7 @@ public: explicit BlockFormattingContext(LayoutState&, BlockContainer const&, FormattingContext* parent); ~BlockFormattingContext(); - virtual void run(Box const&, LayoutMode) override; - virtual void run_intrinsic_sizing(Box const&) override; + virtual void run(Box const&, LayoutMode, AvailableSpace const& available_width, AvailableSpace const& available_height) override; virtual float automatic_content_height() const override; bool is_initial() const; diff --git a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp index de329ee8f0..6159f29dc3 100644 --- a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp @@ -67,7 +67,7 @@ float FlexFormattingContext::automatic_content_height() const return m_state.get(flex_container()).content_height(); } -void FlexFormattingContext::run(Box const& run_box, LayoutMode layout_mode) +void FlexFormattingContext::run(Box const& run_box, LayoutMode layout_mode, [[maybe_unused]] AvailableSpace const& available_width, [[maybe_unused]] AvailableSpace const& available_height) { VERIFY(&run_box == &flex_container()); @@ -598,7 +598,7 @@ void FlexFormattingContext::determine_available_main_and_cross_space(bool& main_ cross_available_space = cross_max_size; } - m_available_space = AvailableSpace { .main = main_available_space, .cross = cross_available_space }; + m_available_space = AvailableSpaceForItems { .main = main_available_space, .cross = cross_available_space }; } float FlexFormattingContext::calculate_indefinite_main_size(FlexItem const& item) @@ -635,7 +635,7 @@ float FlexFormattingContext::calculate_indefinite_main_size(FlexItem const& item VERIFY(independent_formatting_context); box_state.set_content_width(fit_content_cross_size); - independent_formatting_context->run(item.box, LayoutMode::Normal); + independent_formatting_context->run(item.box, LayoutMode::Normal, AvailableSpace::make_indefinite(), AvailableSpace::make_indefinite()); return independent_formatting_context->automatic_content_height(); } @@ -1100,7 +1100,7 @@ void FlexFormattingContext::determine_hypothetical_cross_size_of_item(FlexItem& // NOTE: Flex items should always create an independent formatting context! VERIFY(independent_formatting_context); - independent_formatting_context->run(item.box, LayoutMode::Normal); + independent_formatting_context->run(item.box, LayoutMode::Normal, AvailableSpace::make_indefinite(), AvailableSpace::make_indefinite()); auto automatic_cross_size = is_row_layout() ? independent_formatting_context->automatic_content_height() : box_state.content_width(); diff --git a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.h b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.h index 4a95aa77ad..c9f786e828 100644 --- a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.h +++ b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.h @@ -18,7 +18,7 @@ public: virtual bool inhibits_floating() const override { return true; } - virtual void run(Box const&, LayoutMode) override; + virtual void run(Box const&, LayoutMode, AvailableSpace const& available_width, AvailableSpace const& available_height) override; virtual float automatic_content_height() const override; Box const& flex_container() const { return context_box(); } @@ -190,11 +190,11 @@ private: Vector<FlexItem> m_flex_items; CSS::FlexDirection m_flex_direction {}; - struct AvailableSpace { + struct AvailableSpaceForItems { Optional<float> main; Optional<float> cross; }; - Optional<AvailableSpace> m_available_space; + Optional<AvailableSpaceForItems> m_available_space; }; } diff --git a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp index 870e6c4183..1fe9effafb 100644 --- a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp @@ -39,7 +39,18 @@ void FormattingContext::run_intrinsic_sizing(Box const& box) if (box_state.has_definite_height()) box_state.set_content_height(box.computed_values().height().resolved(box, CSS::Length::make_px(containing_block_height_for(box))).to_px(box)); - run(box, LayoutMode::IntrinsicSizing); + auto to_available_space = [&](SizeConstraint constraint) { + if (constraint == SizeConstraint::MinContent) + return AvailableSpace::make_min_content(); + if (constraint == SizeConstraint::MaxContent) + return AvailableSpace::make_max_content(); + return AvailableSpace::make_indefinite(); + }; + + auto available_width = to_available_space(box_state.width_constraint); + auto available_height = to_available_space(box_state.height_constraint); + + run(box, LayoutMode::IntrinsicSizing, available_width, available_height); } bool FormattingContext::creates_block_formatting_context(Box const& box) @@ -104,7 +115,7 @@ OwnPtr<FormattingContext> FormattingContext::create_independent_formatting_conte { } virtual float automatic_content_height() const override { return 0; }; - virtual void run(Box const&, LayoutMode) override { } + virtual void run(Box const&, LayoutMode, AvailableSpace const&, AvailableSpace const&) override { } }; return make<ReplacedFormattingContext>(state, child_box); } @@ -146,7 +157,7 @@ OwnPtr<FormattingContext> FormattingContext::create_independent_formatting_conte { } virtual float automatic_content_height() const override { return 0; }; - virtual void run(Box const&, LayoutMode) override { } + virtual void run(Box const&, LayoutMode, AvailableSpace const&, AvailableSpace const&) override { } }; return make<DummyFormattingContext>(state, child_box); } @@ -176,9 +187,9 @@ OwnPtr<FormattingContext> FormattingContext::layout_inside(Box const& child_box, auto independent_formatting_context = create_independent_formatting_context_if_needed(m_state, child_box); if (independent_formatting_context) - independent_formatting_context->run(child_box, layout_mode); + independent_formatting_context->run(child_box, layout_mode, AvailableSpace::make_indefinite(), AvailableSpace::make_indefinite()); else - run(child_box, layout_mode); + run(child_box, layout_mode, AvailableSpace::make_indefinite(), AvailableSpace::make_indefinite()); return independent_formatting_context; } diff --git a/Userland/Libraries/LibWeb/Layout/FormattingContext.h b/Userland/Libraries/LibWeb/Layout/FormattingContext.h index e091d31c7d..76b7556a30 100644 --- a/Userland/Libraries/LibWeb/Layout/FormattingContext.h +++ b/Userland/Libraries/LibWeb/Layout/FormattingContext.h @@ -8,6 +8,7 @@ #include <AK/OwnPtr.h> #include <LibWeb/Forward.h> +#include <LibWeb/Layout/AvailableSpace.h> #include <LibWeb/Layout/LayoutState.h> namespace Web::Layout { @@ -24,7 +25,7 @@ public: SVG, }; - virtual void run(Box const&, LayoutMode) = 0; + virtual void run(Box const&, LayoutMode, AvailableSpace const& available_width, AvailableSpace const& available_height) = 0; // This function returns the automatic content height of the context's root box. virtual float automatic_content_height() const = 0; @@ -64,7 +65,7 @@ public: static float containing_block_width_for(Box const&, LayoutState const&); static float containing_block_height_for(Box const&, LayoutState const&); - virtual void run_intrinsic_sizing(Box const&); + void run_intrinsic_sizing(Box const&); float compute_box_y_position_with_respect_to_siblings(Box const&, LayoutState::UsedValues const&); diff --git a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp index c9f68f9c2f..1ac3ee8941 100644 --- a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp @@ -17,7 +17,7 @@ GridFormattingContext::GridFormattingContext(LayoutState& state, BlockContainer GridFormattingContext::~GridFormattingContext() = default; -void GridFormattingContext::run(Box const& box, LayoutMode) +void GridFormattingContext::run(Box const& box, LayoutMode, [[maybe_unused]] AvailableSpace const& available_width, [[maybe_unused]] AvailableSpace const& available_height) { auto should_skip_is_anonymous_text_run = [&](Box& child_box) -> bool { if (child_box.is_anonymous() && !child_box.first_child_of_type<BlockContainer>()) { diff --git a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h index 05696a3d38..09a5450ed3 100644 --- a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h +++ b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h @@ -17,7 +17,7 @@ public: explicit GridFormattingContext(LayoutState&, BlockContainer const&, FormattingContext* parent); ~GridFormattingContext(); - virtual void run(Box const&, LayoutMode) override; + virtual void run(Box const&, LayoutMode, AvailableSpace const& available_width, AvailableSpace const& available_height) override; virtual float automatic_content_height() const override; private: diff --git a/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp index c6f5069232..351288f67e 100644 --- a/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp @@ -83,7 +83,7 @@ float InlineFormattingContext::automatic_content_height() const return compute_auto_height_for_block_formatting_context_root(m_state, containing_block()); } -void InlineFormattingContext::run(Box const&, LayoutMode layout_mode) +void InlineFormattingContext::run(Box const&, LayoutMode layout_mode, [[maybe_unused]] AvailableSpace const& available_width, [[maybe_unused]] AvailableSpace const& available_height) { VERIFY(containing_block().children_are_inline()); generate_line_boxes(layout_mode); diff --git a/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.h b/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.h index e5dd3a29ed..8bb801f658 100644 --- a/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.h +++ b/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.h @@ -23,7 +23,7 @@ public: BlockContainer const& containing_block() const { return static_cast<BlockContainer const&>(context_box()); } - virtual void run(Box const&, LayoutMode) override; + virtual void run(Box const&, LayoutMode, AvailableSpace const& available_width, AvailableSpace const& available_height) override; virtual float automatic_content_height() const override; void dimension_box_on_line(Box const&, LayoutMode); diff --git a/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.cpp index e7cf8757fb..e7b0f5f154 100644 --- a/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.cpp @@ -25,7 +25,7 @@ float SVGFormattingContext::automatic_content_height() const return 0; } -void SVGFormattingContext::run(Box const& box, LayoutMode) +void SVGFormattingContext::run(Box const& box, LayoutMode, [[maybe_unused]] AvailableSpace const& available_width, [[maybe_unused]] AvailableSpace const& available_height) { auto& svg_svg_element = verify_cast<SVG::SVGSVGElement>(*box.dom_node()); diff --git a/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.h b/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.h index bfc561947f..6c6d011f1b 100644 --- a/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.h +++ b/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.h @@ -16,7 +16,7 @@ public: explicit SVGFormattingContext(LayoutState&, Box const&, FormattingContext* parent); ~SVGFormattingContext(); - virtual void run(Box const&, LayoutMode) override; + virtual void run(Box const&, LayoutMode, AvailableSpace const& available_width, AvailableSpace const& available_height) override; virtual float automatic_content_height() const override; }; diff --git a/Userland/Libraries/LibWeb/Layout/TableFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/TableFormattingContext.cpp index 23eca43e10..f391be5efb 100644 --- a/Userland/Libraries/LibWeb/Layout/TableFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/TableFormattingContext.cpp @@ -23,7 +23,7 @@ TableFormattingContext::TableFormattingContext(LayoutState& state, BlockContaine TableFormattingContext::~TableFormattingContext() = default; -void TableFormattingContext::run(Box const& box, LayoutMode) +void TableFormattingContext::run(Box const& box, LayoutMode, [[maybe_unused]] AvailableSpace const& available_width, [[maybe_unused]] AvailableSpace const& available_height) { auto& box_state = m_state.get_mutable(box); diff --git a/Userland/Libraries/LibWeb/Layout/TableFormattingContext.h b/Userland/Libraries/LibWeb/Layout/TableFormattingContext.h index 05690f8e8c..afef496e96 100644 --- a/Userland/Libraries/LibWeb/Layout/TableFormattingContext.h +++ b/Userland/Libraries/LibWeb/Layout/TableFormattingContext.h @@ -23,7 +23,7 @@ public: explicit TableFormattingContext(LayoutState&, BlockContainer const&, FormattingContext* parent); ~TableFormattingContext(); - virtual void run(Box const&, LayoutMode) override; + virtual void run(Box const&, LayoutMode, AvailableSpace const& available_width, AvailableSpace const& available_height) override; virtual float automatic_content_height() const override; private: |