[LFC][Inline formatting context] Add basic text content handling.
authorzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 20 Jul 2018 17:05:16 +0000 (17:05 +0000)
committerzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 20 Jul 2018 17:05:16 +0000 (17:05 +0000)
https://bugs.webkit.org/show_bug.cgi?id=187860

Reviewed by Antti Koivisto.

InlineFormattingContext::layout() walks through the formatting root's descendant list in a post-order fashion and
feeds the TextContentProvider.
Eventually this would turn into a more generic loop where we stop and process the text content when finding a non-text content box (float, inline-box etc), but right now
this is about text content only.

* layout/displaytree/DisplayBox.h:
(WebCore::Display::Box::contentBoxBottom const):
(WebCore::Display::Box::contentBoxRight const):
* layout/inlineformatting/InlineFormattingContext.cpp:
(WebCore::Layout::InlineFormattingContext::layout const):
* layout/inlineformatting/textlayout/TextContentProvider.cpp:
(WebCore::Layout::TextContentProvider::textRuns): Add a helper function to support the case when all we need is just the run list in one go.
* layout/inlineformatting/textlayout/TextContentProvider.h:
* layout/layouttree/LayoutBox.cpp:
(WebCore::Layout::Box::isDescendantOf const):
* layout/layouttree/LayoutBox.h:
* layout/layouttree/LayoutInlineBox.h:
(WebCore::Layout::InlineBox::textContent const):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@234048 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/layout/displaytree/DisplayBox.h
Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp
Source/WebCore/layout/inlineformatting/textlayout/TextContentProvider.cpp
Source/WebCore/layout/inlineformatting/textlayout/TextContentProvider.h
Source/WebCore/layout/layouttree/LayoutBox.cpp
Source/WebCore/layout/layouttree/LayoutBox.h
Source/WebCore/layout/layouttree/LayoutInlineBox.h

index dd7ad6a..34b1dfc 100644 (file)
@@ -1,3 +1,29 @@
+2018-07-20  Zalan Bujtas  <zalan@apple.com>
+
+        [LFC][Inline formatting context] Add basic text content handling.
+        https://bugs.webkit.org/show_bug.cgi?id=187860
+
+        Reviewed by Antti Koivisto.
+
+        InlineFormattingContext::layout() walks through the formatting root's descendant list in a post-order fashion and
+        feeds the TextContentProvider.
+        Eventually this would turn into a more generic loop where we stop and process the text content when finding a non-text content box (float, inline-box etc), but right now
+        this is about text content only.
+
+        * layout/displaytree/DisplayBox.h:
+        (WebCore::Display::Box::contentBoxBottom const):
+        (WebCore::Display::Box::contentBoxRight const):
+        * layout/inlineformatting/InlineFormattingContext.cpp:
+        (WebCore::Layout::InlineFormattingContext::layout const):
+        * layout/inlineformatting/textlayout/TextContentProvider.cpp:
+        (WebCore::Layout::TextContentProvider::textRuns): Add a helper function to support the case when all we need is just the run list in one go.
+        * layout/inlineformatting/textlayout/TextContentProvider.h:
+        * layout/layouttree/LayoutBox.cpp:
+        (WebCore::Layout::Box::isDescendantOf const):
+        * layout/layouttree/LayoutBox.h:
+        * layout/layouttree/LayoutInlineBox.h:
+        (WebCore::Layout::InlineBox::textContent const):
+
 2018-07-20  Youenn Fablet  <youenn@apple.com>
 
         FetchResponse should close its stream when loading finishes
index 758023c..d34cddd 100644 (file)
@@ -146,6 +146,8 @@ public:
 
     LayoutUnit contentBoxTop() const { return borderTop() + paddingTop(); }
     LayoutUnit contentBoxLeft() const { return borderLeft() + paddingLeft(); }
+    LayoutUnit contentBoxBottom() const { return contentBoxTop() + contentBoxHeight(); }
+    LayoutUnit contentBoxRight() const { return contentBoxLeft() + contentBoxWidth(); }
     LayoutUnit contentBoxHeight() const;
     LayoutUnit contentBoxWidth() const;
 
index 6ef0e39..dbe7bdf 100644 (file)
 #include "FloatingState.h"
 #include "InlineFormattingState.h"
 #include "LayoutBox.h"
+#include "LayoutContainer.h"
 #include "LayoutContext.h"
+#include "LayoutInlineBox.h"
+#include "LayoutInlineContainer.h"
+#include "Logging.h"
+#include "SimpleLineBreaker.h"
+#include "TextContentProvider.h"
 #include <wtf/IsoMallocInlines.h>
+#include <wtf/text/TextStream.h>
 
 namespace WebCore {
 namespace Layout {
@@ -44,8 +51,52 @@ InlineFormattingContext::InlineFormattingContext(const Box& formattingContextRoo
 {
 }
 
-void InlineFormattingContext::layout(LayoutContext&, FormattingState&) const
+void InlineFormattingContext::layout(LayoutContext& layoutContext, FormattingState&) const
 {
+    if (!is<Container>(root()))
+        return;
+
+    LOG_WITH_STREAM(FormattingContextLayout, stream << "[Start] -> inline formatting context -> layout context(" << &layoutContext << ") formatting root(" << &root() << ")");
+
+    TextContentProvider textContentProvider;
+    auto& formattingRoot = downcast<Container>(root());
+    auto* layoutBox = formattingRoot.firstInFlowOrFloatingChild();
+    // Casually walk through the block's descendants and place the inline boxes one after the other as much as we can (yeah, I am looking at you floats).
+    while (layoutBox) {
+        if (is<Container>(layoutBox)) {
+            ASSERT(is<InlineContainer>(layoutBox));
+            layoutBox = downcast<Container>(*layoutBox).firstInFlowOrFloatingChild();
+            continue;
+        }
+        auto& inlineBox = downcast<InlineBox>(*layoutBox);
+        // Only text content at this point.
+        if (inlineBox.textContent())
+            textContentProvider.appendText(*inlineBox.textContent(), inlineBox.style(), true);
+
+        for (; layoutBox; layoutBox = layoutBox->containingBlock()) {
+            if (layoutBox == &formattingRoot) {
+                layoutBox = nullptr;
+                break;
+            }
+            if (auto* nextSibling = layoutBox->nextInFlowOrFloatingSibling()) {
+                layoutBox = nextSibling;
+                break;
+            }
+        }
+        ASSERT(!layoutBox || layoutBox->isDescendantOf(formattingRoot));
+    }
+
+    auto& formattingRootDisplayBox = *layoutContext.displayBoxForLayoutBox(formattingRoot);
+    auto lineLeft = formattingRootDisplayBox.contentBoxLeft();
+    auto lineRight = formattingRootDisplayBox.contentBoxRight();
+
+    auto textRuns = textContentProvider.textRuns();
+    SimpleLineBreaker::LineConstraintList constraints;
+    constraints.append({ { }, lineLeft, lineRight });
+    SimpleLineBreaker simpleLineBreaker(textRuns, textContentProvider, WTFMove(constraints), formattingRoot.style());
+    auto layoutRuns = simpleLineBreaker.runs();
+
+    LOG_WITH_STREAM(FormattingContextLayout, stream << "[End] -> inline formatting context -> layout context(" << &layoutContext << ") formatting root(" << &root() << ")");
 }
 
 std::unique_ptr<FormattingState> InlineFormattingContext::createFormattingState(Ref<FloatingState>&& floatingState, const LayoutContext& layoutContext) const
index 322d70d..e22bbbc 100644 (file)
@@ -209,6 +209,18 @@ TextContentProvider::Iterator TextContentProvider::iterator()
     return Iterator(*this);
 }
 
+TextContentProvider::TextRunList TextContentProvider::textRuns()
+{
+    TextRunList textRunList;
+
+    auto textRunIterator = iterator();
+    while (auto textRum = textRunIterator.current()) {
+        textRunList.append(*textRum);
+        ++textRunIterator;
+    }
+    return textRunList;
+}
+
 void TextContentProvider::findNextRun()
 {
     m_simpleTextRunGenerator->findNextRun();
index 6a80bc7..a71543c 100644 (file)
@@ -89,9 +89,11 @@ public:
 
         TextContentProvider& m_contentProvider;
     };
-
     Iterator iterator();
 
+    using TextRunList = Vector<TextRun>;
+    TextRunList textRuns();
+
 private:
     friend class Iterator;
 
index 591c9b2..24bcc06 100644 (file)
@@ -141,7 +141,7 @@ const Container& Box::formattingContextRoot() const
     RELEASE_ASSERT_NOT_REACHED();
 }
 
-bool Box::isDescendantOf(Container& container) const
+bool Box::isDescendantOf(const Container& container) const
 { 
     for (auto* ancestor = containingBlock(); ancestor; ancestor = ancestor->containingBlock()) {
         if (ancestor == &container)
index b1ea8e0..fe2c1ea 100644 (file)
@@ -64,7 +64,7 @@ public:
 
     const Container* containingBlock() const;
     const Container& formattingContextRoot() const;
-    bool isDescendantOf(Container&) const;
+    bool isDescendantOf(const Container&) const;
 
     bool isAnonymous() const { return !m_elementAttributes; }
 
index d5a6b7f..09191c7 100644 (file)
@@ -42,9 +42,10 @@ public:
     InlineBox(std::optional<ElementAttributes>, RenderStyle&&);
 
     void setTextContent(String text) { m_textContent = text; }
+    std::optional<String> textContent() const { return m_textContent; }
 
 private:
-    String m_textContent;
+    std::optional<String> m_textContent;
 };
 
 }