diff --git a/Userland/Libraries/LibWeb/DOM/CharacterData.cpp b/Userland/Libraries/LibWeb/DOM/CharacterData.cpp index 3bf4232ff7c..dc08575961e 100644 --- a/Userland/Libraries/LibWeb/DOM/CharacterData.cpp +++ b/Userland/Libraries/LibWeb/DOM/CharacterData.cpp @@ -157,20 +157,20 @@ WebIDL::ExceptionOr CharacterData::delete_data(size_t offset, size_t count return replace_data(offset, count, String {}); } -Unicode::Segmenter& CharacterData::grapheme_segmenter() +Unicode::Segmenter& CharacterData::grapheme_segmenter() const { if (!m_grapheme_segmenter) { - m_grapheme_segmenter = Unicode::Segmenter::create(Unicode::SegmenterGranularity::Grapheme); + m_grapheme_segmenter = document().grapheme_segmenter().clone(); m_grapheme_segmenter->set_segmented_text(m_data); } return *m_grapheme_segmenter; } -Unicode::Segmenter& CharacterData::word_segmenter() +Unicode::Segmenter& CharacterData::word_segmenter() const { if (!m_word_segmenter) { - m_word_segmenter = Unicode::Segmenter::create(Unicode::SegmenterGranularity::Word); + m_word_segmenter = document().word_segmenter().clone(); m_word_segmenter->set_segmented_text(m_data); } diff --git a/Userland/Libraries/LibWeb/DOM/CharacterData.h b/Userland/Libraries/LibWeb/DOM/CharacterData.h index 1ce793d3456..c744417bcde 100644 --- a/Userland/Libraries/LibWeb/DOM/CharacterData.h +++ b/Userland/Libraries/LibWeb/DOM/CharacterData.h @@ -40,8 +40,8 @@ public: WebIDL::ExceptionOr delete_data(size_t offset_in_utf16_code_units, size_t count_in_utf16_code_units); WebIDL::ExceptionOr replace_data(size_t offset_in_utf16_code_units, size_t count_in_utf16_code_units, String const&); - Unicode::Segmenter& grapheme_segmenter(); - Unicode::Segmenter& word_segmenter(); + Unicode::Segmenter& grapheme_segmenter() const; + Unicode::Segmenter& word_segmenter() const; protected: CharacterData(Document&, NodeType, String const&); @@ -51,8 +51,8 @@ protected: private: String m_data; - OwnPtr m_grapheme_segmenter; - OwnPtr m_word_segmenter; + mutable OwnPtr m_grapheme_segmenter; + mutable OwnPtr m_word_segmenter; }; } diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index c5bac24f370..c22c2eaab3e 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -5606,4 +5607,18 @@ RefPtr Document::record_display_list(PaintConfig config) return display_list; } +Unicode::Segmenter& Document::grapheme_segmenter() const +{ + if (!m_grapheme_segmenter) + m_grapheme_segmenter = Unicode::Segmenter::create(Unicode::SegmenterGranularity::Grapheme); + return *m_grapheme_segmenter; +} + +Unicode::Segmenter& Document::word_segmenter() const +{ + if (!m_word_segmenter) + m_word_segmenter = Unicode::Segmenter::create(Unicode::SegmenterGranularity::Word); + return *m_word_segmenter; +} + } diff --git a/Userland/Libraries/LibWeb/DOM/Document.h b/Userland/Libraries/LibWeb/DOM/Document.h index 28e04800e42..a05db414b10 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.h +++ b/Userland/Libraries/LibWeb/DOM/Document.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -720,6 +721,9 @@ public: void invalidate_display_list(); + Unicode::Segmenter& grapheme_segmenter() const; + Unicode::Segmenter& word_segmenter() const; + protected: virtual void initialize(JS::Realm&) override; virtual void visit_edges(Cell::Visitor&) override; @@ -998,6 +1002,9 @@ private: Optional m_cached_display_list_paint_config; RefPtr m_cached_display_list; + + mutable OwnPtr m_grapheme_segmenter; + mutable OwnPtr m_word_segmenter; }; template<> diff --git a/Userland/Libraries/LibWeb/Layout/InlineLevelIterator.cpp b/Userland/Libraries/LibWeb/Layout/InlineLevelIterator.cpp index 3c8f4738d03..1aee0946197 100644 --- a/Userland/Libraries/LibWeb/Layout/InlineLevelIterator.cpp +++ b/Userland/Libraries/LibWeb/Layout/InlineLevelIterator.cpp @@ -357,7 +357,7 @@ void InlineLevelIterator::enter_text_node(Layout::TextNode const& text_node) .do_respect_linebreaks = do_respect_linebreaks, .is_first_chunk = true, .is_last_chunk = false, - .chunk_iterator = TextNode::ChunkIterator { text_node.text_for_rendering(), do_wrap_lines, do_respect_linebreaks, text_node.computed_values().font_list() }, + .chunk_iterator = TextNode::ChunkIterator { text_node, do_wrap_lines, do_respect_linebreaks }, }; } diff --git a/Userland/Libraries/LibWeb/Layout/TextNode.cpp b/Userland/Libraries/LibWeb/Layout/TextNode.cpp index d0998f2e74e..1bb3ee5cc7a 100644 --- a/Userland/Libraries/LibWeb/Layout/TextNode.cpp +++ b/Userland/Libraries/LibWeb/Layout/TextNode.cpp @@ -391,14 +391,23 @@ void TextNode::compute_text_for_rendering() m_text_for_rendering = MUST(builder.to_string()); } -TextNode::ChunkIterator::ChunkIterator(String const& text, bool wrap_lines, bool respect_linebreaks, Gfx::FontCascadeList const& font_cascade_list) +Unicode::Segmenter& TextNode::grapheme_segmenter() const +{ + if (!m_grapheme_segmenter) { + m_grapheme_segmenter = document().grapheme_segmenter().clone(); + m_grapheme_segmenter->set_segmented_text(text_for_rendering()); + } + + return *m_grapheme_segmenter; +} + +TextNode::ChunkIterator::ChunkIterator(TextNode const& text_node, bool wrap_lines, bool respect_linebreaks) : m_wrap_lines(wrap_lines) , m_respect_linebreaks(respect_linebreaks) - , m_utf8_view(text) - , m_font_cascade_list(font_cascade_list) - , m_segmenter(Unicode::Segmenter::create(Unicode::SegmenterGranularity::Grapheme)) + , m_utf8_view(text_node.text_for_rendering()) + , m_font_cascade_list(text_node.computed_values().font_list()) + , m_grapheme_segmenter(text_node.grapheme_segmenter()) { - m_segmenter->set_segmented_text(text); } static Gfx::GlyphRun::TextType text_type_for_code_point(u32 code_point) @@ -470,7 +479,7 @@ Optional TextNode::ChunkIterator::next_without_peek() return *m_utf8_view.iterator_at_byte_offset_without_validation(m_current_index); }; auto next_grapheme_boundary = [this]() { - return m_segmenter->next_boundary(m_current_index).value_or(m_utf8_view.byte_length()); + return m_grapheme_segmenter.next_boundary(m_current_index).value_or(m_utf8_view.byte_length()); }; auto code_point = current_code_point(); diff --git a/Userland/Libraries/LibWeb/Layout/TextNode.h b/Userland/Libraries/LibWeb/Layout/TextNode.h index 40a9cd62bfa..1499ea9b3dd 100644 --- a/Userland/Libraries/LibWeb/Layout/TextNode.h +++ b/Userland/Libraries/LibWeb/Layout/TextNode.h @@ -39,7 +39,7 @@ public: class ChunkIterator { public: - ChunkIterator(String const& text, bool wrap_lines, bool respect_linebreaks, Gfx::FontCascadeList const&); + ChunkIterator(TextNode const&, bool wrap_lines, bool respect_linebreaks); Optional next(); Optional peek(size_t); @@ -53,7 +53,7 @@ public: Utf8View m_utf8_view; Gfx::FontCascadeList const& m_font_cascade_list; - NonnullOwnPtr m_segmenter; + Unicode::Segmenter& m_grapheme_segmenter; size_t m_current_index { 0 }; Vector m_peek_queue; @@ -62,12 +62,15 @@ public: void invalidate_text_for_rendering(); void compute_text_for_rendering(); + Unicode::Segmenter& grapheme_segmenter() const; + virtual JS::GCPtr create_paintable() const override; private: virtual bool is_text_node() const final { return true; } Optional m_text_for_rendering; + mutable OwnPtr m_grapheme_segmenter; }; template<> diff --git a/Userland/Libraries/LibWeb/Page/EventHandler.cpp b/Userland/Libraries/LibWeb/Page/EventHandler.cpp index e74867449b6..6a948f6ecd2 100644 --- a/Userland/Libraries/LibWeb/Page/EventHandler.cpp +++ b/Userland/Libraries/LibWeb/Page/EventHandler.cpp @@ -1225,7 +1225,7 @@ void EventHandler::update_selection_range_for_input_or_textarea() Unicode::Segmenter& EventHandler::word_segmenter() { if (!m_word_segmenter) - m_word_segmenter = Unicode::Segmenter::create(Unicode::SegmenterGranularity::Word); + m_word_segmenter = m_navigable->active_document()->word_segmenter().clone(); return *m_word_segmenter; }