mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-10-19 22:49:47 +00:00
Some checks are pending
CI / macOS, arm64, Sanitizer, Clang (push) Waiting to run
CI / Linux, x86_64, Fuzzers, Clang (push) Waiting to run
CI / Linux, x86_64, Sanitizer, GNU (push) Waiting to run
CI / Linux, x86_64, Sanitizer, Clang (push) Waiting to run
Package the js repl as a binary artifact / Linux, arm64 (push) Waiting to run
Package the js repl as a binary artifact / macOS, arm64 (push) Waiting to run
Package the js repl as a binary artifact / Linux, x86_64 (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
Previously, we were collapsing whitespace in Layout::TextNode and then passed the resulting string for further processing through ChunkIterator -> InlineLevelIterator -> InlineFormattingContext -> LineBuilder -> LineBoxFragment -> PaintableFragment. Our painting tree is where we deal with things like range offsets into the underlying text nodes, but since we modified the original string, the offsets were wrong. This changes the way we generate fragments: * Layout::TextNode no longer collapses whitespace as part of its stored "text for rendering", but moves this logic to ChunkIterator which splits up this text into separate views whenever whitespace needs to be collapsed. * Layout::LineBox now only extends the last fragment if its end offset is equal to the new fragment's start offset. Otherwise, there's a gap caused by collapsing whitespace and we need to generate a separate fragment for that in order to have a correct start offset. Some tests need new baselines because of the fixed start offsets. Fixes #566.
89 lines
2.6 KiB
C++
89 lines
2.6 KiB
C++
/*
|
|
* Copyright (c) 2018-2020, Andreas Kling <andreas@ladybird.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/Utf16String.h>
|
|
#include <AK/Utf16View.h>
|
|
#include <LibGfx/TextLayout.h>
|
|
#include <LibUnicode/Segmenter.h>
|
|
#include <LibWeb/DOM/Text.h>
|
|
#include <LibWeb/Layout/Node.h>
|
|
|
|
namespace Web::Layout {
|
|
|
|
class LineBoxFragment;
|
|
|
|
class TextNode final : public Node {
|
|
GC_CELL(TextNode, Node);
|
|
GC_DECLARE_ALLOCATOR(TextNode);
|
|
|
|
public:
|
|
TextNode(DOM::Document&, DOM::Text&);
|
|
virtual ~TextNode() override;
|
|
|
|
DOM::Text const& dom_node() const { return static_cast<DOM::Text const&>(*Node::dom_node()); }
|
|
|
|
Utf16String const& text_for_rendering() const;
|
|
|
|
struct Chunk {
|
|
Utf16View view;
|
|
NonnullRefPtr<Gfx::Font const> font;
|
|
size_t start { 0 };
|
|
size_t length { 0 };
|
|
bool has_breaking_newline { false };
|
|
bool has_breaking_tab { false };
|
|
bool is_all_whitespace { false };
|
|
Gfx::GlyphRun::TextType text_type;
|
|
};
|
|
|
|
class ChunkIterator {
|
|
public:
|
|
ChunkIterator(TextNode const&, bool should_wrap_lines, bool should_respect_linebreaks);
|
|
ChunkIterator(TextNode const&, Utf16View const&, Unicode::Segmenter&, bool should_wrap_lines, bool should_respect_linebreaks);
|
|
|
|
bool should_wrap_lines() const { return m_should_wrap_lines; }
|
|
bool should_respect_linebreaks() const { return m_should_respect_linebreaks; }
|
|
bool should_collapse_whitespace() const { return m_should_collapse_whitespace; }
|
|
|
|
Optional<Chunk> next();
|
|
Optional<Chunk> peek(size_t);
|
|
|
|
private:
|
|
Optional<Chunk> next_without_peek();
|
|
Optional<Chunk> try_commit_chunk(size_t start, size_t end, bool has_breaking_newline, bool has_breaking_tab, Gfx::Font const&, Gfx::GlyphRun::TextType) const;
|
|
|
|
bool const m_should_wrap_lines;
|
|
bool const m_should_respect_linebreaks;
|
|
bool m_should_collapse_whitespace;
|
|
Utf16View m_view;
|
|
Gfx::FontCascadeList const& m_font_cascade_list;
|
|
|
|
Unicode::Segmenter& m_grapheme_segmenter;
|
|
size_t m_current_index { 0 };
|
|
|
|
Vector<Chunk> m_peek_queue;
|
|
};
|
|
|
|
void invalidate_text_for_rendering();
|
|
|
|
Unicode::Segmenter& grapheme_segmenter() const;
|
|
|
|
virtual GC::Ptr<Painting::Paintable> create_paintable() const override;
|
|
|
|
private:
|
|
virtual bool is_text_node() const final { return true; }
|
|
|
|
void compute_text_for_rendering();
|
|
|
|
Optional<Utf16String> m_text_for_rendering;
|
|
mutable OwnPtr<Unicode::Segmenter> m_grapheme_segmenter;
|
|
};
|
|
|
|
template<>
|
|
inline bool Node::fast_is<TextNode>() const { return is_text_node(); }
|
|
|
|
}
|