mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2026-06-29 04:30:24 +00:00
Move the layout tree from GC allocation to refcounted ownership so removed layout and paint subtrees are destroyed synchronously instead of waiting for the next GC sweep. This dramatically reduces GC memory usage peaks after layout tree churn and makes it easier for memory use to fall back after large document updates. Update layout factories, tree traversal, SVG layout node creation, paintable back-pointers, and pseudo-element layout links to use RefPtr ownership. Make display: contents follow the same shape as Blink and WebKit: the element itself does not create a layout node, and its children are flattened into the nearest layout parent. Wrap direct non-whitespace text in an anonymous inline node when the boxless element contributes inherited style to that text. Use an internal inline wrapper for display: contents pseudo-elements so generated content can still participate in layout, painting, hit testing, and pseudo-element queries. Keep CSSOM reporting the computed display value from the pseudo style, not the internal wrapper. Remove the retained out-of-tree layout node list and its testing hook, since the flattened model does not need a side owner for boxless elements. Add coverage for inherited text style, dynamic insertion order, pseudo-element hit testing, and computed style queries.
93 lines
3.5 KiB
C++
93 lines
3.5 KiB
C++
/*
|
|
* Copyright (c) 2018-2020, Andreas Kling <andreas@ladybird.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/Assertions.h>
|
|
#include <AK/WeakPtr.h>
|
|
#include <LibGC/Ptr.h>
|
|
#include <LibGfx/Rect.h>
|
|
#include <LibGfx/TextLayout.h>
|
|
#include <LibWeb/CSS/Enums.h>
|
|
#include <LibWeb/PixelUnits.h>
|
|
|
|
namespace Web::Layout {
|
|
|
|
class LineBoxFragment {
|
|
friend class LineBox;
|
|
|
|
public:
|
|
LineBoxFragment(Node const& layout_node, size_t start, size_t length, CSSPixels inline_offset, CSSPixels block_offset, CSSPixels inline_length, CSSPixels block_length, CSSPixels border_box_top, CSS::Direction, CSS::WritingMode, RefPtr<Gfx::GlyphRun>);
|
|
|
|
Node const& layout_node() const
|
|
{
|
|
VERIFY(m_layout_node);
|
|
return *m_layout_node;
|
|
}
|
|
size_t start() const { return m_start; }
|
|
size_t length_in_code_units() const { return m_length_in_code_units; }
|
|
|
|
CSSPixelPoint offset() const;
|
|
CSSPixels inline_offset() const { return m_inline_offset; }
|
|
CSSPixels block_offset() const { return m_block_offset; }
|
|
void set_inline_offset(CSSPixels inline_offset) { m_inline_offset = inline_offset; }
|
|
void set_block_offset(CSSPixels block_offset) { m_block_offset = block_offset; }
|
|
|
|
// The baseline of a fragment is the number of pixels from the top to the text baseline.
|
|
void set_baseline(CSSPixels y) { m_baseline = y; }
|
|
CSSPixels baseline() const { return m_baseline; }
|
|
|
|
CSSPixelSize size() const;
|
|
CSSPixels width() const { return size().width(); }
|
|
CSSPixels height() const { return size().height(); }
|
|
CSSPixels inline_length() const { return m_inline_length; }
|
|
CSSPixels block_length() const { return m_block_length; }
|
|
void set_inline_length(CSSPixels inline_length) { m_inline_length = inline_length; }
|
|
void set_block_length(CSSPixels block_length) { m_block_length = block_length; }
|
|
|
|
CSSPixels border_box_top() const { return m_border_box_top; }
|
|
|
|
bool ends_in_whitespace() const;
|
|
bool is_justifiable_whitespace() const;
|
|
Utf16View text() const;
|
|
|
|
bool is_atomic_inline() const;
|
|
|
|
RefPtr<Gfx::GlyphRun> glyph_run() const { return m_glyph_run; }
|
|
CSS::WritingMode writing_mode() const { return m_writing_mode; }
|
|
void append_glyph_run(RefPtr<Gfx::GlyphRun> const&, CSSPixels run_width);
|
|
|
|
bool has_trailing_whitespace() const { return m_has_trailing_whitespace; }
|
|
void set_has_trailing_whitespace(bool value) { m_has_trailing_whitespace = value; }
|
|
|
|
bool is_fully_truncated() const { return m_is_fully_truncated; }
|
|
void set_fully_truncated(bool value) { m_is_fully_truncated = value; }
|
|
|
|
private:
|
|
CSS::Direction resolve_glyph_run_direction(Gfx::GlyphRun::TextType) const;
|
|
void append_glyph_run_ltr(RefPtr<Gfx::GlyphRun> const&, CSSPixels run_width);
|
|
void append_glyph_run_rtl(RefPtr<Gfx::GlyphRun> const&, CSSPixels run_width);
|
|
|
|
WeakPtr<Node const> m_layout_node;
|
|
size_t m_start { 0 };
|
|
size_t m_length_in_code_units { 0 };
|
|
CSSPixels m_inline_offset;
|
|
CSSPixels m_block_offset;
|
|
CSSPixels m_inline_length;
|
|
CSSPixels m_block_length;
|
|
CSSPixels m_border_box_top { 0 };
|
|
CSSPixels m_baseline { 0 };
|
|
CSS::Direction m_direction { CSS::Direction::Ltr };
|
|
CSS::WritingMode m_writing_mode { CSS::WritingMode::HorizontalTb };
|
|
|
|
RefPtr<Gfx::GlyphRun> m_glyph_run;
|
|
float m_insert_position { 0 };
|
|
CSS::Direction m_current_insert_direction { CSS::Direction::Ltr };
|
|
bool m_has_trailing_whitespace { false };
|
|
bool m_is_fully_truncated { false };
|
|
};
|
|
|
|
}
|