From 2ac190dc5fd2d22ced31c18fc123c99ee9e7577c Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 9 Oct 2019 16:29:23 +0200 Subject: LibHTML: Collapse whitespace in LayoutText unless white-space: pre; Before breaking the Text node contents into words, collapse all of the whitespace into single space (' ') characters. This fixes broken rendering of paragraphs with newlines in them. :^) --- Libraries/LibHTML/Layout/LayoutText.cpp | 24 ++++++++++++++++++++---- Libraries/LibHTML/Layout/LayoutText.h | 2 ++ 2 files changed, 22 insertions(+), 4 deletions(-) (limited to 'Libraries') diff --git a/Libraries/LibHTML/Layout/LayoutText.cpp b/Libraries/LibHTML/Layout/LayoutText.cpp index 581760d11c..ff1c072010 100644 --- a/Libraries/LibHTML/Layout/LayoutText.cpp +++ b/Libraries/LibHTML/Layout/LayoutText.cpp @@ -48,13 +48,13 @@ void LayoutText::render_fragment(RenderingContext& context, const LineBoxFragmen if (is_underline) painter.draw_line(fragment.rect().bottom_left().translated(0, -1), fragment.rect().bottom_right().translated(0, -1), color); - painter.draw_text(fragment.rect(), node().data().substring_view(fragment.start(), fragment.length()), TextAlignment::TopLeft, color); + painter.draw_text(fragment.rect(), m_text_for_rendering.substring_view(fragment.start(), fragment.length()), TextAlignment::TopLeft, color); } template void LayoutText::for_each_word(Callback callback) const { - Utf8View view(node().data()); + Utf8View view(m_text_for_rendering); if (view.is_empty()) return; @@ -90,7 +90,7 @@ void LayoutText::for_each_word(Callback callback) const template void LayoutText::for_each_source_line(Callback callback) const { - Utf8View view(node().data()); + Utf8View view(m_text_for_rendering); if (view.is_empty()) return; @@ -133,6 +133,7 @@ void LayoutText::split_into_lines(LayoutBlock& container) bool is_preformatted = style().string_or_fallback(CSS::PropertyID::WhiteSpace, "normal") == "pre"; if (is_preformatted) { + m_text_for_rendering = node().data(); for_each_source_line([&](const Utf8View& view, int start, int length) { line_boxes.last().add_fragment(*this, start, length, font.width(view), line_height); line_boxes.append(LineBox()); @@ -140,6 +141,21 @@ void LayoutText::split_into_lines(LayoutBlock& container) return; } + // Collapse whitespace into single spaces + auto& raw_text = node().data(); + StringBuilder builder(raw_text.length()); + for (int i = 0; i < raw_text.length(); ++i) { + if (!isspace(raw_text[i])) { + builder.append(raw_text[i]); + } else { + builder.append(' '); + while (i < raw_text.length() && isspace(raw_text[i])) + ++i; + --i; + } + } + m_text_for_rendering = builder.to_string(); + struct Word { Utf8View view; int start; @@ -170,7 +186,7 @@ void LayoutText::split_into_lines(LayoutBlock& container) if (is_whitespace && line_boxes.last().fragments().is_empty()) continue; - line_boxes.last().add_fragment(*this, word.start, word.length, word_width, line_height); + line_boxes.last().add_fragment(*this, word.start, is_whitespace ? 1 : word.length, word_width, line_height); available_width -= word_width; if (available_width < 0) { diff --git a/Libraries/LibHTML/Layout/LayoutText.h b/Libraries/LibHTML/Layout/LayoutText.h index 9b70ecdc4c..afa3a808c7 100644 --- a/Libraries/LibHTML/Layout/LayoutText.h +++ b/Libraries/LibHTML/Layout/LayoutText.h @@ -28,4 +28,6 @@ private: void for_each_word(Callback) const; template void for_each_source_line(Callback) const; + + String m_text_for_rendering; }; -- cgit v1.2.3