mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-20 09:49:15 +03:00
LibWeb: Remove old Layout::Node::split_into_lines() API
Now that we build lines incrementally, we no longer need the atomic line splitting API. The new InlineLevelIterator and LineBuilder setup does have some regressions from the old behavior, but we can deal with them as we go.
This commit is contained in:
parent
ba49dc82e0
commit
766d816db3
Notes:
sideshowbarker
2024-07-18 00:41:35 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/766d816db36
@ -104,23 +104,6 @@ HitTestResult BlockContainer::hit_test(const Gfx::IntPoint& position, HitTestTyp
|
||||
return { absolute_rect().contains(position.x(), position.y()) ? this : nullptr };
|
||||
}
|
||||
|
||||
void BlockContainer::split_into_lines(InlineFormattingContext& context, LayoutMode layout_mode)
|
||||
{
|
||||
auto& containing_block = context.containing_block();
|
||||
auto* line_box = &containing_block.ensure_last_line_box();
|
||||
|
||||
context.dimension_box_on_line(*this, layout_mode);
|
||||
|
||||
float available_width = context.available_width_at_line(containing_block.line_boxes().size() - 1);
|
||||
|
||||
if (layout_mode == LayoutMode::AllPossibleLineBreaks && line_box->width() > 0) {
|
||||
line_box = &containing_block.add_line_box();
|
||||
} else if (layout_mode == LayoutMode::Default && line_box->width() > 0 && line_box->width() + border_box_width() > available_width) {
|
||||
line_box = &containing_block.add_line_box();
|
||||
}
|
||||
line_box->add_fragment(*this, 0, 0, border_box_width(), height());
|
||||
}
|
||||
|
||||
bool BlockContainer::is_scrollable() const
|
||||
{
|
||||
// FIXME: Support horizontal scroll as well (overflow-x)
|
||||
|
@ -32,8 +32,6 @@ public:
|
||||
template<typename Callback>
|
||||
void for_each_fragment(Callback) const;
|
||||
|
||||
virtual void split_into_lines(InlineFormattingContext&, LayoutMode) override;
|
||||
|
||||
bool is_scrollable() const;
|
||||
const Gfx::FloatPoint& scroll_offset() const { return m_scroll_offset; }
|
||||
void set_scroll_offset(const Gfx::FloatPoint&);
|
||||
|
@ -20,12 +20,6 @@ BreakNode::~BreakNode()
|
||||
{
|
||||
}
|
||||
|
||||
void BreakNode::split_into_lines(InlineFormattingContext& context, LayoutMode)
|
||||
{
|
||||
auto& line_box = context.containing_block().add_line_box();
|
||||
line_box.add_fragment(*this, 0, 0, 0, context.containing_block().line_height());
|
||||
}
|
||||
|
||||
void BreakNode::paint(PaintContext&, PaintPhase)
|
||||
{
|
||||
}
|
||||
|
@ -21,8 +21,6 @@ public:
|
||||
private:
|
||||
virtual bool is_break_node() const final { return true; }
|
||||
virtual void paint(PaintContext&, PaintPhase) override;
|
||||
|
||||
virtual void split_into_lines(InlineFormattingContext&, LayoutMode) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
|
@ -27,27 +27,6 @@ InlineNode::~InlineNode()
|
||||
{
|
||||
}
|
||||
|
||||
void InlineNode::split_into_lines(InlineFormattingContext& context, LayoutMode layout_mode)
|
||||
{
|
||||
auto& containing_block = context.containing_block();
|
||||
|
||||
auto is_not_undefined_or_auto = [](auto const& length_percentage) {
|
||||
return !(length_percentage.is_length() && length_percentage.length().is_undefined_or_auto());
|
||||
};
|
||||
|
||||
if (is_not_undefined_or_auto(computed_values().padding().left)) {
|
||||
float padding_left = computed_values().padding().left.resolved(CSS::Length::make_px(containing_block.width())).resolved(CSS::Length::make_px(0), *this).to_px(*this);
|
||||
containing_block.ensure_last_line_box().add_fragment(*this, 0, 0, padding_left, 0, LineBoxFragment::Type::Leading);
|
||||
}
|
||||
|
||||
NodeWithStyleAndBoxModelMetrics::split_into_lines(context, layout_mode);
|
||||
|
||||
if (is_not_undefined_or_auto(computed_values().padding().right)) {
|
||||
float padding_right = computed_values().padding().right.resolved(CSS::Length::make_px(containing_block.width())).resolved(CSS::Length::make_px(0), *this).to_px(*this);
|
||||
containing_block.ensure_last_line_box().add_fragment(*this, 0, 0, padding_right, 0, LineBoxFragment::Type::Trailing);
|
||||
}
|
||||
}
|
||||
|
||||
void InlineNode::paint(PaintContext& context, PaintPhase phase)
|
||||
{
|
||||
auto& painter = context.painter();
|
||||
|
@ -17,8 +17,6 @@ public:
|
||||
|
||||
virtual void paint(PaintContext&, PaintPhase) override;
|
||||
|
||||
virtual void split_into_lines(InlineFormattingContext&, LayoutMode) override;
|
||||
|
||||
private:
|
||||
template<typename Callback>
|
||||
void for_each_fragment(Callback);
|
||||
|
@ -115,13 +115,6 @@ InitialContainingBlock& Node::root()
|
||||
return *document().layout_node();
|
||||
}
|
||||
|
||||
void Node::split_into_lines(InlineFormattingContext& context, LayoutMode layout_mode)
|
||||
{
|
||||
for_each_child([&](auto& child) {
|
||||
child.split_into_lines(context, layout_mode);
|
||||
});
|
||||
}
|
||||
|
||||
void Node::set_needs_display()
|
||||
{
|
||||
if (auto* block = containing_block()) {
|
||||
|
@ -134,8 +134,6 @@ public:
|
||||
void removed_from(Node&) { }
|
||||
void children_changed() { }
|
||||
|
||||
virtual void split_into_lines(InlineFormattingContext&, LayoutMode);
|
||||
|
||||
bool is_visible() const { return m_visible; }
|
||||
void set_visible(bool visible) { m_visible = visible; }
|
||||
|
||||
|
@ -22,17 +22,4 @@ ReplacedBox::~ReplacedBox()
|
||||
{
|
||||
}
|
||||
|
||||
void ReplacedBox::split_into_lines(InlineFormattingContext& context, LayoutMode layout_mode)
|
||||
{
|
||||
auto& containing_block = context.containing_block();
|
||||
|
||||
prepare_for_replaced_layout();
|
||||
context.dimension_box_on_line(*this, layout_mode);
|
||||
|
||||
auto* line_box = &containing_block.ensure_last_line_box();
|
||||
if (line_box->width() > 0 && line_box->width() + width() > context.available_width_at_line(containing_block.line_boxes().size() - 1))
|
||||
line_box = &containing_block.add_line_box();
|
||||
line_box->add_fragment(*this, 0, 0, width(), height());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -31,9 +31,6 @@ public:
|
||||
|
||||
virtual bool can_have_children() const override { return false; }
|
||||
|
||||
protected:
|
||||
virtual void split_into_lines(InlineFormattingContext&, LayoutMode) override;
|
||||
|
||||
private:
|
||||
Optional<float> m_intrinsic_width;
|
||||
Optional<float> m_intrinsic_height;
|
||||
|
@ -192,95 +192,6 @@ void TextNode::compute_text_for_rendering(bool collapse, bool previous_is_empty_
|
||||
m_text_for_rendering = builder.to_string();
|
||||
}
|
||||
|
||||
void TextNode::split_into_lines_by_rules(InlineFormattingContext& context, LayoutMode layout_mode, bool do_collapse, bool do_wrap_lines, bool do_respect_linebreaks)
|
||||
{
|
||||
auto& containing_block = context.containing_block();
|
||||
|
||||
auto& font = this->font();
|
||||
|
||||
auto& line_boxes = containing_block.line_boxes();
|
||||
containing_block.ensure_last_line_box();
|
||||
float available_width = context.available_width_at_line(line_boxes.size() - 1) - line_boxes.last().width();
|
||||
|
||||
compute_text_for_rendering(do_collapse, line_boxes.last().is_empty_or_ends_in_whitespace());
|
||||
ChunkIterator iterator(m_text_for_rendering, layout_mode, do_wrap_lines, do_respect_linebreaks);
|
||||
|
||||
for (;;) {
|
||||
auto chunk_opt = iterator.next();
|
||||
if (!chunk_opt.has_value())
|
||||
break;
|
||||
auto& chunk = chunk_opt.value();
|
||||
|
||||
// Collapse entire fragment into non-existence if previous fragment on line ended in whitespace.
|
||||
if (do_collapse && line_boxes.last().is_empty_or_ends_in_whitespace() && chunk.is_all_whitespace)
|
||||
continue;
|
||||
|
||||
float chunk_width;
|
||||
if (do_wrap_lines) {
|
||||
if (do_collapse && is_ascii_space(*chunk.view.begin()) && (line_boxes.last().is_empty_or_ends_in_whitespace() || line_boxes.last().ends_with_forced_line_break())) {
|
||||
// This is a non-empty chunk that starts with collapsible whitespace.
|
||||
// We are at either at the start of a new line, or after something that ended in whitespace,
|
||||
// so we don't need to contribute our own whitespace to the line. Skip over it instead!
|
||||
++chunk.start;
|
||||
--chunk.length;
|
||||
chunk.view = chunk.view.substring_view(1, chunk.view.byte_length() - 1);
|
||||
}
|
||||
|
||||
chunk_width = font.width(chunk.view) + font.glyph_spacing();
|
||||
|
||||
if (line_boxes.last().width() > 0 && chunk_width > available_width) {
|
||||
containing_block.add_line_box();
|
||||
available_width = context.available_width_at_line(line_boxes.size() - 1);
|
||||
|
||||
if (do_collapse && chunk.is_all_whitespace)
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
chunk_width = font.width(chunk.view);
|
||||
}
|
||||
|
||||
line_boxes.last().add_fragment(*this, chunk.start, chunk.length, chunk_width, font.glyph_height());
|
||||
available_width -= chunk_width;
|
||||
|
||||
if (do_wrap_lines && available_width < 0) {
|
||||
containing_block.add_line_box();
|
||||
available_width = context.available_width_at_line(line_boxes.size() - 1);
|
||||
}
|
||||
|
||||
if (do_respect_linebreaks && chunk.has_breaking_newline) {
|
||||
containing_block.add_line_box();
|
||||
available_width = context.available_width_at_line(line_boxes.size() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TextNode::split_into_lines(InlineFormattingContext& context, LayoutMode layout_mode)
|
||||
{
|
||||
bool do_collapse = true;
|
||||
bool do_wrap_lines = true;
|
||||
bool do_respect_linebreaks = false;
|
||||
|
||||
if (computed_values().white_space() == CSS::WhiteSpace::Nowrap) {
|
||||
do_collapse = true;
|
||||
do_wrap_lines = false;
|
||||
do_respect_linebreaks = false;
|
||||
} else if (computed_values().white_space() == CSS::WhiteSpace::Pre) {
|
||||
do_collapse = false;
|
||||
do_wrap_lines = false;
|
||||
do_respect_linebreaks = true;
|
||||
} else if (computed_values().white_space() == CSS::WhiteSpace::PreLine) {
|
||||
do_collapse = true;
|
||||
do_wrap_lines = true;
|
||||
do_respect_linebreaks = true;
|
||||
} else if (computed_values().white_space() == CSS::WhiteSpace::PreWrap) {
|
||||
do_collapse = false;
|
||||
do_wrap_lines = true;
|
||||
do_respect_linebreaks = true;
|
||||
}
|
||||
|
||||
split_into_lines_by_rules(context, layout_mode, do_collapse, do_wrap_lines, do_respect_linebreaks);
|
||||
}
|
||||
|
||||
bool TextNode::wants_mouse_events() const
|
||||
{
|
||||
return parent() && is<Label>(parent());
|
||||
|
@ -25,8 +25,6 @@ public:
|
||||
|
||||
virtual void paint_fragment(PaintContext&, const LineBoxFragment&, PaintPhase) const override;
|
||||
|
||||
virtual void split_into_lines(InlineFormattingContext&, LayoutMode) override;
|
||||
|
||||
struct Chunk {
|
||||
Utf8View view;
|
||||
size_t start { 0 };
|
||||
@ -60,7 +58,6 @@ private:
|
||||
virtual void handle_mousedown(Badge<EventHandler>, const Gfx::IntPoint&, unsigned button, unsigned modifiers) override;
|
||||
virtual void handle_mouseup(Badge<EventHandler>, const Gfx::IntPoint&, unsigned button, unsigned modifiers) override;
|
||||
virtual void handle_mousemove(Badge<EventHandler>, const Gfx::IntPoint&, unsigned button, unsigned modifiers) override;
|
||||
void split_into_lines_by_rules(InlineFormattingContext&, LayoutMode, bool do_collapse, bool do_wrap_lines, bool do_respect_linebreaks);
|
||||
void paint_cursor_if_needed(PaintContext&, const LineBoxFragment&) const;
|
||||
void paint_text_decoration(Gfx::Painter&, LineBoxFragment const&) const;
|
||||
virtual void paint(PaintContext&, PaintPhase) override;
|
||||
|
Loading…
Reference in New Issue
Block a user