mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-13 11:42:38 +03:00
412b2313f3
This patch combines a number of techniques to make inline content flow more correctly around floats: - During inline layout, BFC now lets LineBuilder decide the Y coordinate when inserting a new float. LineBuilder has more information about the currently accumulated line, and can make better breaking decisions. - When inserting a float on one side, and the top of the newly inserted float is below the bottommost float on the opposite side, we now reset the opposite side back to the start of that edge. This improves breaking behavior between opposite-side floats. - After inserting a float during inline layout, we now recalculate the available space on the line, but don't adjust X offsets of already existing fragments. This is handled by update_last_line() anyway, so it was pointless busywork. - When measuring whether a line can fit at a given Y coordinate, we now consider both the top and bottom Y values of the line. This fixes an issue where the bottom part of a line would bleed over other content (since we had only checked that the top Y coordinate of that line would fit.) There are some pretty brain-dead algorithms in here that we need to make smarter, but I didn't want to complicate this any further so I've left FIXMEs about them instead.
65 lines
1.8 KiB
C++
65 lines
1.8 KiB
C++
/*
|
|
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <LibWeb/Layout/InlineFormattingContext.h>
|
|
|
|
namespace Web::Layout {
|
|
|
|
class LineBuilder {
|
|
AK_MAKE_NONCOPYABLE(LineBuilder);
|
|
AK_MAKE_NONMOVABLE(LineBuilder);
|
|
|
|
public:
|
|
LineBuilder(InlineFormattingContext&, LayoutState&);
|
|
~LineBuilder();
|
|
|
|
void break_line(Optional<float> next_item_width = {});
|
|
void append_box(Box const&, float leading_size, float trailing_size, float leading_margin, float trailing_margin);
|
|
void append_text_chunk(TextNode const&, size_t offset_in_node, size_t length_in_node, float leading_size, float trailing_size, float leading_margin, float trailing_margin, float content_width, float content_height);
|
|
|
|
// Returns whether a line break occurred.
|
|
bool break_if_needed(float next_item_width)
|
|
{
|
|
if (should_break(next_item_width)) {
|
|
break_line(next_item_width);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
float available_width_for_current_line() const { return m_available_width_for_current_line; }
|
|
|
|
void update_last_line();
|
|
|
|
void remove_last_line_if_empty();
|
|
|
|
float current_y() const { return m_current_y; }
|
|
void set_current_y(float y) { m_current_y = y; }
|
|
|
|
void recalculate_available_space();
|
|
float y_for_float_to_be_inserted_here(Box const&);
|
|
|
|
private:
|
|
void begin_new_line(bool increment_y, bool is_first_break_in_sequence = true);
|
|
|
|
bool should_break(float next_item_width);
|
|
|
|
LineBox& ensure_last_line_box();
|
|
|
|
InlineFormattingContext& m_context;
|
|
LayoutState& m_layout_state;
|
|
LayoutState::UsedValues& m_containing_block_state;
|
|
float m_available_width_for_current_line { 0 };
|
|
float m_current_y { 0 };
|
|
float m_max_height_on_current_line { 0 };
|
|
|
|
bool m_last_line_needs_update { false };
|
|
};
|
|
|
|
}
|