mirror of
https://github.com/RGBCube/serenity
synced 2025-07-17 01:47:35 +00:00
LibWeb: Move line boxes from Layout::Box to BlockContainer
Per the spec, only a BlockContainer" can have line boxes, so let's not clutter up every Layout::Box with line boxes. This also allows us to establish an invariant that BFC and IFC always operate on a Layout::BlockContainer. Note that if BlockContainer has all block-level children, its line boxes are not used for anything. They are only used in the all inline-level children scenario.
This commit is contained in:
parent
a0bea52a5f
commit
f73aa8e2bd
13 changed files with 80 additions and 74 deletions
|
@ -147,4 +147,17 @@ bool BlockContainer::handle_mousewheel(Badge<EventHandler>, const Gfx::IntPoint&
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LineBox& BlockContainer::ensure_last_line_box()
|
||||||
|
{
|
||||||
|
if (m_line_boxes.is_empty())
|
||||||
|
return add_line_box();
|
||||||
|
return m_line_boxes.last();
|
||||||
|
}
|
||||||
|
|
||||||
|
LineBox& BlockContainer::add_line_box()
|
||||||
|
{
|
||||||
|
m_line_boxes.append(LineBox());
|
||||||
|
return m_line_boxes.last();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,15 @@ public:
|
||||||
const Gfx::FloatPoint& scroll_offset() const { return m_scroll_offset; }
|
const Gfx::FloatPoint& scroll_offset() const { return m_scroll_offset; }
|
||||||
void set_scroll_offset(const Gfx::FloatPoint&);
|
void set_scroll_offset(const Gfx::FloatPoint&);
|
||||||
|
|
||||||
|
Vector<LineBox>& line_boxes() { return m_line_boxes; }
|
||||||
|
const Vector<LineBox>& line_boxes() const { return m_line_boxes; }
|
||||||
|
|
||||||
|
LineBox& ensure_last_line_box();
|
||||||
|
LineBox& add_line_box();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Vector<LineBox> m_line_boxes;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool is_block_container() const final { return true; }
|
virtual bool is_block_container() const final { return true; }
|
||||||
virtual bool wants_mouse_events() const override { return false; }
|
virtual bool wants_mouse_events() const override { return false; }
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
* Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
namespace Web::Layout {
|
namespace Web::Layout {
|
||||||
|
|
||||||
BlockFormattingContext::BlockFormattingContext(Box& root, FormattingContext* parent)
|
BlockFormattingContext::BlockFormattingContext(BlockContainer& root, FormattingContext* parent)
|
||||||
: FormattingContext(root, parent)
|
: FormattingContext(root, parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -46,9 +46,9 @@ void BlockFormattingContext::run(Box& box, LayoutMode layout_mode)
|
||||||
compute_width(box);
|
compute_width(box);
|
||||||
|
|
||||||
if (box.children_are_inline()) {
|
if (box.children_are_inline()) {
|
||||||
layout_inline_children(box, layout_mode);
|
layout_inline_children(verify_cast<BlockContainer>(box), layout_mode);
|
||||||
} else {
|
} else {
|
||||||
layout_block_level_children(box, layout_mode);
|
layout_block_level_children(verify_cast<BlockContainer>(box), layout_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layout_mode == LayoutMode::Default) {
|
if (layout_mode == LayoutMode::Default) {
|
||||||
|
@ -289,7 +289,7 @@ void BlockFormattingContext::compute_width_for_block_level_replaced_element_in_n
|
||||||
box.set_width(compute_width_for_replaced_element(box));
|
box.set_width(compute_width_for_replaced_element(box));
|
||||||
}
|
}
|
||||||
|
|
||||||
static float compute_auto_height_for_block_level_element(const Box& box)
|
static float compute_auto_height_for_block_level_element(Box const& box)
|
||||||
{
|
{
|
||||||
Optional<float> top;
|
Optional<float> top;
|
||||||
Optional<float> bottom;
|
Optional<float> bottom;
|
||||||
|
@ -297,12 +297,13 @@ static float compute_auto_height_for_block_level_element(const Box& box)
|
||||||
if (box.children_are_inline()) {
|
if (box.children_are_inline()) {
|
||||||
// If it only has inline-level children, the height is the distance between
|
// If it only has inline-level children, the height is the distance between
|
||||||
// the top of the topmost line box and the bottom of the bottommost line box.
|
// the top of the topmost line box and the bottom of the bottommost line box.
|
||||||
if (!box.line_boxes().is_empty()) {
|
auto& block_container = verify_cast<Layout::BlockContainer>(box);
|
||||||
for (auto& fragment : box.line_boxes().first().fragments()) {
|
if (!block_container.line_boxes().is_empty()) {
|
||||||
|
for (auto& fragment : block_container.line_boxes().first().fragments()) {
|
||||||
if (!top.has_value() || fragment.offset().y() < top.value())
|
if (!top.has_value() || fragment.offset().y() < top.value())
|
||||||
top = fragment.offset().y();
|
top = fragment.offset().y();
|
||||||
}
|
}
|
||||||
for (auto& fragment : box.line_boxes().last().fragments()) {
|
for (auto& fragment : block_container.line_boxes().last().fragments()) {
|
||||||
if (!bottom.has_value() || (fragment.offset().y() + fragment.height()) > bottom.value())
|
if (!bottom.has_value() || (fragment.offset().y() + fragment.height()) > bottom.value())
|
||||||
bottom = fragment.offset().y() + fragment.height();
|
bottom = fragment.offset().y() + fragment.height();
|
||||||
}
|
}
|
||||||
|
@ -415,23 +416,23 @@ void BlockFormattingContext::compute_position(Box& box)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockFormattingContext::layout_inline_children(Box& box, LayoutMode layout_mode)
|
void BlockFormattingContext::layout_inline_children(BlockContainer& block_container, LayoutMode layout_mode)
|
||||||
{
|
{
|
||||||
InlineFormattingContext context(box, this);
|
InlineFormattingContext context(block_container, this);
|
||||||
context.run(box, layout_mode);
|
context.run(block_container, layout_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockFormattingContext::layout_block_level_children(Box& box, LayoutMode layout_mode)
|
void BlockFormattingContext::layout_block_level_children(BlockContainer& block_container, LayoutMode layout_mode)
|
||||||
{
|
{
|
||||||
float content_height = 0;
|
float content_height = 0;
|
||||||
float content_width = 0;
|
float content_width = 0;
|
||||||
|
|
||||||
box.for_each_child_of_type<Box>([&](auto& child_box) {
|
block_container.for_each_child_of_type<Box>([&](Box& child_box) {
|
||||||
if (child_box.is_absolutely_positioned())
|
if (child_box.is_absolutely_positioned())
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
|
|
||||||
if (child_box.is_floating()) {
|
if (child_box.is_floating()) {
|
||||||
layout_floating_child(child_box, box);
|
layout_floating_child(child_box, block_container);
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,9 +444,9 @@ void BlockFormattingContext::layout_block_level_children(Box& box, LayoutMode la
|
||||||
compute_position(child_box);
|
compute_position(child_box);
|
||||||
|
|
||||||
if (is<ReplacedBox>(child_box))
|
if (is<ReplacedBox>(child_box))
|
||||||
place_block_level_replaced_element_in_normal_flow(child_box, box);
|
place_block_level_replaced_element_in_normal_flow(child_box, block_container);
|
||||||
else if (is<BlockContainer>(child_box))
|
else if (is<BlockContainer>(child_box))
|
||||||
place_block_level_non_replaced_element_in_normal_flow(child_box, box);
|
place_block_level_non_replaced_element_in_normal_flow(child_box, block_container);
|
||||||
|
|
||||||
// FIXME: This should be factored differently. It's uncool that we mutate the tree *during* layout!
|
// FIXME: This should be factored differently. It's uncool that we mutate the tree *during* layout!
|
||||||
// Instead, we should generate the marker box during the tree build.
|
// Instead, we should generate the marker box during the tree build.
|
||||||
|
@ -458,12 +459,12 @@ void BlockFormattingContext::layout_block_level_children(Box& box, LayoutMode la
|
||||||
});
|
});
|
||||||
|
|
||||||
if (layout_mode != LayoutMode::Default) {
|
if (layout_mode != LayoutMode::Default) {
|
||||||
if (box.computed_values().width().is_undefined() || box.computed_values().width().is_auto())
|
if (block_container.computed_values().width().is_undefined() || block_container.computed_values().width().is_auto())
|
||||||
box.set_width(content_width);
|
block_container.set_width(content_width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockFormattingContext::place_block_level_replaced_element_in_normal_flow(Box& child_box, Box& containing_block)
|
void BlockFormattingContext::place_block_level_replaced_element_in_normal_flow(Box& child_box, BlockContainer const& containing_block)
|
||||||
{
|
{
|
||||||
VERIFY(!containing_block.is_absolutely_positioned());
|
VERIFY(!containing_block.is_absolutely_positioned());
|
||||||
auto& replaced_element_box_model = child_box.box_model();
|
auto& replaced_element_box_model = child_box.box_model();
|
||||||
|
@ -485,7 +486,7 @@ void BlockFormattingContext::place_block_level_replaced_element_in_normal_flow(B
|
||||||
child_box.set_offset(x, y);
|
child_box.set_offset(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockFormattingContext::place_block_level_non_replaced_element_in_normal_flow(Box& child_box, Box& containing_block)
|
void BlockFormattingContext::place_block_level_non_replaced_element_in_normal_flow(Box& child_box, BlockContainer const& containing_block)
|
||||||
{
|
{
|
||||||
auto& box_model = child_box.box_model();
|
auto& box_model = child_box.box_model();
|
||||||
auto& computed_values = child_box.computed_values();
|
auto& computed_values = child_box.computed_values();
|
||||||
|
@ -600,7 +601,7 @@ static Gfx::FloatRect rect_in_coordinate_space(const Box& box, const Box& contex
|
||||||
return rect;
|
return rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockFormattingContext::layout_floating_child(Box& box, Box& containing_block)
|
void BlockFormattingContext::layout_floating_child(Box& box, BlockContainer const& containing_block)
|
||||||
{
|
{
|
||||||
VERIFY(box.is_floating());
|
VERIFY(box.is_floating());
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
#include <LibWeb/Forward.h>
|
#include <LibWeb/Forward.h>
|
||||||
|
#include <LibWeb/Layout/BlockContainer.h>
|
||||||
#include <LibWeb/Layout/FormattingContext.h>
|
#include <LibWeb/Layout/FormattingContext.h>
|
||||||
|
|
||||||
namespace Web::Layout {
|
namespace Web::Layout {
|
||||||
|
@ -15,7 +16,7 @@ namespace Web::Layout {
|
||||||
// https://drafts.csswg.org/css-display/#block-formatting-context
|
// https://drafts.csswg.org/css-display/#block-formatting-context
|
||||||
class BlockFormattingContext : public FormattingContext {
|
class BlockFormattingContext : public FormattingContext {
|
||||||
public:
|
public:
|
||||||
explicit BlockFormattingContext(Box&, FormattingContext* parent);
|
explicit BlockFormattingContext(BlockContainer&, FormattingContext* parent);
|
||||||
~BlockFormattingContext();
|
~BlockFormattingContext();
|
||||||
|
|
||||||
virtual void run(Box&, LayoutMode) override;
|
virtual void run(Box&, LayoutMode) override;
|
||||||
|
@ -25,12 +26,12 @@ public:
|
||||||
const Vector<Box*>& left_floating_boxes() const { return m_left_floating_boxes; }
|
const Vector<Box*>& left_floating_boxes() const { return m_left_floating_boxes; }
|
||||||
const Vector<Box*>& right_floating_boxes() const { return m_right_floating_boxes; }
|
const Vector<Box*>& right_floating_boxes() const { return m_right_floating_boxes; }
|
||||||
|
|
||||||
static float compute_theoretical_height(const Box&);
|
static float compute_theoretical_height(Box const&);
|
||||||
void compute_width(Box&);
|
void compute_width(Box&);
|
||||||
|
|
||||||
// https://drafts.csswg.org/css-display/#block-formatting-context-root
|
// https://drafts.csswg.org/css-display/#block-formatting-context-root
|
||||||
Box& root() { return context_box(); }
|
BlockContainer& root() { return static_cast<BlockContainer&>(context_box()); }
|
||||||
Box const& root() const { return context_box(); }
|
BlockContainer const& root() const { return static_cast<BlockContainer const&>(context_box()); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void compute_height(Box&);
|
static void compute_height(Box&);
|
||||||
|
@ -45,13 +46,13 @@ private:
|
||||||
|
|
||||||
void layout_initial_containing_block(LayoutMode);
|
void layout_initial_containing_block(LayoutMode);
|
||||||
|
|
||||||
void layout_block_level_children(Box&, LayoutMode);
|
void layout_block_level_children(BlockContainer&, LayoutMode);
|
||||||
void layout_inline_children(Box&, LayoutMode);
|
void layout_inline_children(BlockContainer&, LayoutMode);
|
||||||
|
|
||||||
void place_block_level_replaced_element_in_normal_flow(Box& child, Box& container);
|
void place_block_level_replaced_element_in_normal_flow(Box& child, BlockContainer const&);
|
||||||
void place_block_level_non_replaced_element_in_normal_flow(Box& child, Box& container);
|
void place_block_level_non_replaced_element_in_normal_flow(Box& child, BlockContainer const&);
|
||||||
|
|
||||||
void layout_floating_child(Box&, Box& containing_block);
|
void layout_floating_child(Box& child, BlockContainer const& containing_block);
|
||||||
|
|
||||||
void apply_transformations_to_children(Box&);
|
void apply_transformations_to_children(Box&);
|
||||||
|
|
||||||
|
|
|
@ -238,19 +238,6 @@ StackingContext* Box::enclosing_stacking_context()
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
LineBox& Box::ensure_last_line_box()
|
|
||||||
{
|
|
||||||
if (m_line_boxes.is_empty())
|
|
||||||
return add_line_box();
|
|
||||||
return m_line_boxes.last();
|
|
||||||
}
|
|
||||||
|
|
||||||
LineBox& Box::add_line_box()
|
|
||||||
{
|
|
||||||
m_line_boxes.append(LineBox());
|
|
||||||
return m_line_boxes.last();
|
|
||||||
}
|
|
||||||
|
|
||||||
float Box::width_of_logical_containing_block() const
|
float Box::width_of_logical_containing_block() const
|
||||||
{
|
{
|
||||||
auto* containing_block = this->containing_block();
|
auto* containing_block = this->containing_block();
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
|
|
||||||
#include <AK/OwnPtr.h>
|
#include <AK/OwnPtr.h>
|
||||||
#include <LibGfx/Rect.h>
|
#include <LibGfx/Rect.h>
|
||||||
#include <LibWeb/Layout/LineBox.h>
|
|
||||||
#include <LibWeb/Layout/Node.h>
|
#include <LibWeb/Layout/Node.h>
|
||||||
#include <LibWeb/Painting/BorderPainting.h>
|
#include <LibWeb/Painting/BorderPainting.h>
|
||||||
#include <LibWeb/Painting/StackingContext.h>
|
#include <LibWeb/Painting/StackingContext.h>
|
||||||
|
@ -118,12 +117,6 @@ public:
|
||||||
virtual void paint_box_shadow(PaintContext& context);
|
virtual void paint_box_shadow(PaintContext& context);
|
||||||
virtual void paint_background(PaintContext& context);
|
virtual void paint_background(PaintContext& context);
|
||||||
|
|
||||||
Vector<LineBox>& line_boxes() { return m_line_boxes; }
|
|
||||||
const Vector<LineBox>& line_boxes() const { return m_line_boxes; }
|
|
||||||
|
|
||||||
LineBox& ensure_last_line_box();
|
|
||||||
LineBox& add_line_box();
|
|
||||||
|
|
||||||
virtual float width_of_logical_containing_block() const;
|
virtual float width_of_logical_containing_block() const;
|
||||||
|
|
||||||
Painting::BorderRadiusData normalized_border_radius_data();
|
Painting::BorderRadiusData normalized_border_radius_data();
|
||||||
|
@ -141,8 +134,6 @@ protected:
|
||||||
|
|
||||||
virtual void did_set_rect() { }
|
virtual void did_set_rect() { }
|
||||||
|
|
||||||
Vector<LineBox> m_line_boxes;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool is_box() const final { return true; }
|
virtual bool is_box() const final { return true; }
|
||||||
|
|
||||||
|
|
|
@ -84,9 +84,10 @@ void FlexFormattingContext::run(Box& box, LayoutMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!main_constrained && box.children_are_inline()) {
|
if (!main_constrained && box.children_are_inline()) {
|
||||||
BlockFormattingContext bfc(box, this);
|
auto& block_container = verify_cast<BlockContainer>(box);
|
||||||
|
BlockFormattingContext bfc(block_container, this);
|
||||||
bfc.run(box, LayoutMode::Default);
|
bfc.run(box, LayoutMode::Default);
|
||||||
InlineFormattingContext ifc(box, &bfc);
|
InlineFormattingContext ifc(block_container, &bfc);
|
||||||
|
|
||||||
if (is_row) {
|
if (is_row) {
|
||||||
ifc.run(box, LayoutMode::OnlyRequiredLineBreaks);
|
ifc.run(box, LayoutMode::OnlyRequiredLineBreaks);
|
||||||
|
@ -236,9 +237,10 @@ void FlexFormattingContext::run(Box& box, LayoutMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cross_constrained && box.children_are_inline()) {
|
if (!cross_constrained && box.children_are_inline()) {
|
||||||
BlockFormattingContext bfc(box, this);
|
auto& block_container = verify_cast<BlockContainer>(box);
|
||||||
|
BlockFormattingContext bfc(block_container, this);
|
||||||
bfc.run(box, LayoutMode::Default);
|
bfc.run(box, LayoutMode::Default);
|
||||||
InlineFormattingContext ifc(box, &bfc);
|
InlineFormattingContext ifc(block_container, &bfc);
|
||||||
ifc.run(box, LayoutMode::OnlyRequiredLineBreaks);
|
ifc.run(box, LayoutMode::OnlyRequiredLineBreaks);
|
||||||
|
|
||||||
if (is_row)
|
if (is_row)
|
||||||
|
@ -248,7 +250,7 @@ void FlexFormattingContext::run(Box& box, LayoutMode)
|
||||||
if (is_row) {
|
if (is_row) {
|
||||||
return BlockFormattingContext::compute_theoretical_height(box);
|
return BlockFormattingContext::compute_theoretical_height(box);
|
||||||
} else {
|
} else {
|
||||||
BlockFormattingContext context(box, this);
|
BlockFormattingContext context(verify_cast<BlockContainer>(box), this);
|
||||||
context.compute_width(box);
|
context.compute_width(box);
|
||||||
return box.width();
|
return box.width();
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,13 +94,13 @@ void FormattingContext::layout_inside(Box& child_box, LayoutMode layout_mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (creates_block_formatting_context(child_box)) {
|
if (creates_block_formatting_context(child_box)) {
|
||||||
BlockFormattingContext context(child_box, this);
|
BlockFormattingContext context(verify_cast<BlockContainer>(child_box), this);
|
||||||
context.run(child_box, layout_mode);
|
context.run(child_box, layout_mode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (child_display.is_table_inside()) {
|
if (child_display.is_table_inside()) {
|
||||||
TableFormattingContext context(child_box, this);
|
TableFormattingContext context(verify_cast<TableBox>(child_box), this);
|
||||||
context.run(child_box, layout_mode);
|
context.run(child_box, layout_mode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,7 @@ void FormattingContext::layout_inside(Box& child_box, LayoutMode layout_mode)
|
||||||
VERIFY(is_block_formatting_context());
|
VERIFY(is_block_formatting_context());
|
||||||
|
|
||||||
if (child_box.children_are_inline()) {
|
if (child_box.children_are_inline()) {
|
||||||
InlineFormattingContext context(child_box, this);
|
InlineFormattingContext context(verify_cast<BlockContainer>(child_box), this);
|
||||||
context.run(child_box, layout_mode);
|
context.run(child_box, layout_mode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -117,11 +117,11 @@ void FormattingContext::layout_inside(Box& child_box, LayoutMode layout_mode)
|
||||||
run(child_box, layout_mode);
|
run(child_box, layout_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static float greatest_child_width(const Box& box)
|
static float greatest_child_width(Box const& box)
|
||||||
{
|
{
|
||||||
float max_width = 0;
|
float max_width = 0;
|
||||||
if (box.children_are_inline()) {
|
if (box.children_are_inline()) {
|
||||||
for (auto& child : box.line_boxes()) {
|
for (auto& child : verify_cast<BlockContainer>(box).line_boxes()) {
|
||||||
max_width = max(max_width, child.width());
|
max_width = max(max_width, child.width());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -186,7 +186,7 @@ static Gfx::FloatSize solve_replaced_size_constraint(float w, float h, const Rep
|
||||||
return { w, h };
|
return { w, h };
|
||||||
}
|
}
|
||||||
|
|
||||||
static float compute_auto_height_for_block_level_element(const Box& box)
|
static float compute_auto_height_for_block_level_element(Box const& box)
|
||||||
{
|
{
|
||||||
Optional<float> top;
|
Optional<float> top;
|
||||||
Optional<float> bottom;
|
Optional<float> bottom;
|
||||||
|
@ -194,12 +194,13 @@ static float compute_auto_height_for_block_level_element(const Box& box)
|
||||||
if (box.children_are_inline()) {
|
if (box.children_are_inline()) {
|
||||||
// If it only has inline-level children, the height is the distance between
|
// If it only has inline-level children, the height is the distance between
|
||||||
// the top of the topmost line box and the bottom of the bottommost line box.
|
// the top of the topmost line box and the bottom of the bottommost line box.
|
||||||
if (!box.line_boxes().is_empty()) {
|
auto& block_container = verify_cast<BlockContainer>(box);
|
||||||
for (auto& fragment : box.line_boxes().first().fragments()) {
|
if (!block_container.line_boxes().is_empty()) {
|
||||||
|
for (auto& fragment : block_container.line_boxes().first().fragments()) {
|
||||||
if (!top.has_value() || fragment.offset().y() < top.value())
|
if (!top.has_value() || fragment.offset().y() < top.value())
|
||||||
top = fragment.offset().y();
|
top = fragment.offset().y();
|
||||||
}
|
}
|
||||||
for (auto& fragment : box.line_boxes().last().fragments()) {
|
for (auto& fragment : block_container.line_boxes().last().fragments()) {
|
||||||
if (!bottom.has_value() || (fragment.offset().y() + fragment.height()) > bottom.value())
|
if (!bottom.has_value() || (fragment.offset().y() + fragment.height()) > bottom.value())
|
||||||
bottom = fragment.offset().y() + fragment.height();
|
bottom = fragment.offset().y() + fragment.height();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
namespace Web::Layout {
|
namespace Web::Layout {
|
||||||
|
|
||||||
InlineFormattingContext::InlineFormattingContext(Box& containing_block, FormattingContext* parent)
|
InlineFormattingContext::InlineFormattingContext(BlockContainer& containing_block, FormattingContext* parent)
|
||||||
: FormattingContext(containing_block, parent)
|
: FormattingContext(containing_block, parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,17 +8,18 @@
|
||||||
|
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
#include <LibWeb/Forward.h>
|
#include <LibWeb/Forward.h>
|
||||||
|
#include <LibWeb/Layout/BlockContainer.h>
|
||||||
#include <LibWeb/Layout/FormattingContext.h>
|
#include <LibWeb/Layout/FormattingContext.h>
|
||||||
|
|
||||||
namespace Web::Layout {
|
namespace Web::Layout {
|
||||||
|
|
||||||
class InlineFormattingContext final : public FormattingContext {
|
class InlineFormattingContext final : public FormattingContext {
|
||||||
public:
|
public:
|
||||||
InlineFormattingContext(Box& containing_block, FormattingContext* parent);
|
InlineFormattingContext(BlockContainer& containing_block, FormattingContext* parent);
|
||||||
~InlineFormattingContext();
|
~InlineFormattingContext();
|
||||||
|
|
||||||
Box& containing_block() { return context_box(); }
|
BlockContainer& containing_block() { return static_cast<BlockContainer&>(context_box()); }
|
||||||
const Box& containing_block() const { return context_box(); }
|
BlockContainer const& containing_block() const { return static_cast<BlockContainer const&>(context_box()); }
|
||||||
|
|
||||||
virtual void run(Box&, LayoutMode) override;
|
virtual void run(Box&, LayoutMode) override;
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ InlineNode::~InlineNode()
|
||||||
|
|
||||||
void InlineNode::split_into_lines(InlineFormattingContext& context, LayoutMode layout_mode)
|
void InlineNode::split_into_lines(InlineFormattingContext& context, LayoutMode layout_mode)
|
||||||
{
|
{
|
||||||
auto& containing_block = context.context_box();
|
auto& containing_block = context.containing_block();
|
||||||
|
|
||||||
if (!computed_values().padding().left.is_undefined_or_auto()) {
|
if (!computed_values().padding().left.is_undefined_or_auto()) {
|
||||||
float padding_left = computed_values().padding().left.resolved(CSS::Length::make_px(0), *this, containing_block.width()).to_px(*this);
|
float padding_left = computed_values().padding().left.resolved(CSS::Length::make_px(0), *this, containing_block.width()).to_px(*this);
|
||||||
|
|
|
@ -16,8 +16,8 @@
|
||||||
|
|
||||||
namespace Web::Layout {
|
namespace Web::Layout {
|
||||||
|
|
||||||
TableFormattingContext::TableFormattingContext(Box& context_box, FormattingContext* parent)
|
TableFormattingContext::TableFormattingContext(BlockContainer& block_container, FormattingContext* parent)
|
||||||
: BlockFormattingContext(context_box, parent)
|
: BlockFormattingContext(block_container, parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace Web::Layout {
|
||||||
|
|
||||||
class TableFormattingContext final : public BlockFormattingContext {
|
class TableFormattingContext final : public BlockFormattingContext {
|
||||||
public:
|
public:
|
||||||
explicit TableFormattingContext(Box&, FormattingContext* parent);
|
explicit TableFormattingContext(BlockContainer&, FormattingContext* parent);
|
||||||
~TableFormattingContext();
|
~TableFormattingContext();
|
||||||
|
|
||||||
virtual void run(Box&, LayoutMode) override;
|
virtual void run(Box&, LayoutMode) override;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue