[LFC][IFC] Add verification for inline text runs.
authorzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 21 Jul 2018 18:49:23 +0000 (18:49 +0000)
committerzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 21 Jul 2018 18:49:23 +0000 (18:49 +0000)
https://bugs.webkit.org/show_bug.cgi?id=187879

Reviewed by Antti Koivisto.

* layout/Verification.cpp:
(WebCore::Layout::outputMismatchingSimpleLineInformationIfNeeded):
(WebCore::Layout::outputMismatchingComplexLineInformationIfNeeded):
(WebCore::Layout::outputMismatchingBlockBoxInformationIfNeeded):
(WebCore::Layout::verifyAndOutputSubtree):
(WebCore::Layout::outputMismatchingBoxInformationIfNeeded): Deleted.
* layout/inlineformatting/InlineFormattingContext.cpp:
(WebCore::Layout::InlineFormattingContext::layout const):
* layout/inlineformatting/InlineFormattingState.h:
(WebCore::Layout::InlineFormattingState::addLayoutRuns):
(WebCore::Layout::InlineFormattingState::layoutRuns const):
* layout/layouttree/LayoutTreeBuilder.cpp:
(WebCore::Layout::outputLayoutBox):
(WebCore::Layout::outputLayoutTree):
(WebCore::Layout::TreeBuilder::showLayoutTree):

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

Source/WebCore/ChangeLog
Source/WebCore/layout/Verification.cpp
Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp
Source/WebCore/layout/inlineformatting/InlineFormattingState.h
Source/WebCore/layout/layouttree/LayoutTreeBuilder.cpp

index 66ac5f3..2063d41 100644 (file)
@@ -1,5 +1,28 @@
 2018-07-21  Zalan Bujtas  <zalan@apple.com>
 
+        [LFC][IFC] Add verification for inline text runs.
+        https://bugs.webkit.org/show_bug.cgi?id=187879
+
+        Reviewed by Antti Koivisto.
+
+        * layout/Verification.cpp:
+        (WebCore::Layout::outputMismatchingSimpleLineInformationIfNeeded):
+        (WebCore::Layout::outputMismatchingComplexLineInformationIfNeeded):
+        (WebCore::Layout::outputMismatchingBlockBoxInformationIfNeeded):
+        (WebCore::Layout::verifyAndOutputSubtree):
+        (WebCore::Layout::outputMismatchingBoxInformationIfNeeded): Deleted.
+        * layout/inlineformatting/InlineFormattingContext.cpp:
+        (WebCore::Layout::InlineFormattingContext::layout const):
+        * layout/inlineformatting/InlineFormattingState.h:
+        (WebCore::Layout::InlineFormattingState::addLayoutRuns):
+        (WebCore::Layout::InlineFormattingState::layoutRuns const):
+        * layout/layouttree/LayoutTreeBuilder.cpp:
+        (WebCore::Layout::outputLayoutBox):
+        (WebCore::Layout::outputLayoutTree):
+        (WebCore::Layout::TreeBuilder::showLayoutTree):
+
+2018-07-21  Zalan Bujtas  <zalan@apple.com>
+
         [LFC] Do not use virtual methods to construct floating/formatting states.
         https://bugs.webkit.org/show_bug.cgi?id=187875
 
index 6bab581..e211a7d 100644 (file)
@@ -29,6 +29,7 @@
 #if ENABLE(LAYOUT_FORMATTING_CONTEXT)
 
 #include "DisplayBox.h"
+#include "InlineTextBox.h"
 #include "LayoutBox.h"
 #include "LayoutContainer.h"
 #include "LayoutTreeBuilder.h"
 namespace WebCore {
 namespace Layout {
 
-static bool outputMismatchingBoxInformationIfNeeded(TextStream& stream, const LayoutContext& context, const RenderBox& renderer, const Box& layoutBox)
+static bool outputMismatchingSimpleLineInformationIfNeeded(TextStream& stream, const LayoutContext& layoutContext, const RenderBlockFlow& blockFlow, const Container& inlineFormattingRoot)
+{
+    auto* lineLayoutData = blockFlow.simpleLineLayout();
+    if (!lineLayoutData) {
+        ASSERT_NOT_REACHED();
+        return true;
+    }
+
+    auto& inlineFormattingState = const_cast<LayoutContext&>(layoutContext).establishedFormattingState(inlineFormattingRoot);
+    ASSERT(is<InlineFormattingState>(inlineFormattingState));
+    auto& layoutRuns = downcast<InlineFormattingState>(inlineFormattingState).layoutRuns();
+
+    if (layoutRuns.size() != lineLayoutData->runCount()) {
+        stream << "Mismatching number of runs: simple runs(" << lineLayoutData->runCount() << ") layout runs(" << layoutRuns.size() << ")";
+        stream.nextLine();
+        return true;
+    }
+
+    auto mismatched = false;
+    for (unsigned i = 0; i < lineLayoutData->runCount(); ++i) {
+        auto& simpleRun = lineLayoutData->runAt(i);
+        auto& layoutRun = layoutRuns[i];
+
+        if (simpleRun.start == layoutRun.start() && simpleRun.end == layoutRun.end() && simpleRun.logicalLeft == layoutRun.left() && simpleRun.logicalRight == layoutRun.right())
+            continue;
+
+        stream << "Mismatching: simple run(" << simpleRun.start << ", " << simpleRun.end << ") (" << simpleRun.logicalLeft << ", " << simpleRun.logicalRight << ") layout run(" << layoutRun.start() << ", " << layoutRun.end() << ") (" << layoutRun.left() << ", " << layoutRun.right() << ")";
+        stream.nextLine();
+        mismatched = true;
+    }
+    return mismatched;
+}
+
+static bool outputMismatchingComplexLineInformationIfNeeded(TextStream& stream, const LayoutContext& layoutContext, const RenderBlockFlow& blockFlow, const Container& inlineFormattingRoot)
+{
+    auto& inlineFormattingState = const_cast<LayoutContext&>(layoutContext).establishedFormattingState(inlineFormattingRoot);
+    ASSERT(is<InlineFormattingState>(inlineFormattingState));
+    auto& layoutRuns = downcast<InlineFormattingState>(inlineFormattingState).layoutRuns();
+
+    auto mismatched = false;
+    unsigned layoutRunIndex = 0;
+    for (auto* rootLine = blockFlow.firstRootBox(); rootLine; rootLine = rootLine->nextRootBox()) {
+        for (auto* lineBox = rootLine->firstChild(); lineBox; lineBox = lineBox->nextOnLine()) {
+            if (!is<InlineTextBox>(lineBox))
+                continue;
+
+            if (layoutRunIndex >= layoutRuns.size()) {
+                // FIXME: <span>foobar</span>foobar generates 2 inline text boxes while we only generate one layout run (which is much better, since it enables us to do kerning across inline elements).
+                stream << "Mismatching number of runs: layout runs(" << layoutRuns.size() << ")";
+                stream.nextLine();
+                return true;
+            }
+
+            auto& layoutRun = layoutRuns[layoutRunIndex];
+            auto& inlineTextBox = downcast<InlineTextBox>(*lineBox);
+            if (inlineTextBox.start() == layoutRun.start() && inlineTextBox.end() == layoutRun.end() && inlineTextBox.logicalLeft() == layoutRun.left() && inlineTextBox.logicalRight() == layoutRun.right()) {
+                stream << "Mismatching: simple run(" << inlineTextBox.start() << ", " << inlineTextBox.end() << ") (" << inlineTextBox.logicalLeft() << ", " << inlineTextBox.logicalRight() << ") layout run(" << layoutRun.start() << ", " << layoutRun.end() << ") (" << layoutRun.left() << ", " << layoutRun.right() << ")";
+                stream.nextLine();
+                mismatched = true;
+            }
+            ++layoutRunIndex;
+        }
+    }
+    return mismatched;
+}
+
+static bool outputMismatchingBlockBoxInformationIfNeeded(TextStream& stream, const LayoutContext& context, const RenderBox& renderer, const Box& layoutBox)
 {
     bool firstMismatchingRect = true;
     auto outputRect = [&] (const String& prefix, const LayoutRect& rendererRect, const LayoutRect& layoutRect) {
@@ -92,7 +159,7 @@ static bool outputMismatchingBoxInformationIfNeeded(TextStream& stream, const La
 
 static bool verifyAndOutputSubtree(TextStream& stream, const LayoutContext& context, const RenderBox& renderer, const Box& layoutBox)
 {
-    auto mismtachingGeometry = outputMismatchingBoxInformationIfNeeded(stream, context, renderer, layoutBox);
+    auto mismtachingGeometry = outputMismatchingBlockBoxInformationIfNeeded(stream, context, renderer, layoutBox);
 
     if (!is<Container>(layoutBox))
         return mismtachingGeometry;
@@ -107,8 +174,15 @@ static bool verifyAndOutputSubtree(TextStream& stream, const LayoutContext& cont
             continue;
         }
 
-        auto mismatchingSubtreeGeometry = verifyAndOutputSubtree(stream, context, downcast<RenderBox>(*childRenderer), *childBox);
-        mismtachingGeometry |= mismatchingSubtreeGeometry;
+        if (is<RenderBlockFlow>(*childRenderer) && childBox->establishesInlineFormattingContext()) {
+            ASSERT(childRenderer->childrenInline());
+            auto& blockFlow = downcast<RenderBlockFlow>(*childRenderer);
+            auto& formattingRoot = downcast<Container>(*childBox);
+            mismtachingGeometry |= blockFlow.lineLayoutPath() == RenderBlockFlow::SimpleLinesPath ? outputMismatchingSimpleLineInformationIfNeeded(stream, context, blockFlow, formattingRoot) : outputMismatchingComplexLineInformationIfNeeded(stream, context, blockFlow, formattingRoot);
+        } else {
+            auto mismatchingSubtreeGeometry = verifyAndOutputSubtree(stream, context, downcast<RenderBox>(*childRenderer), *childBox);
+            mismtachingGeometry |= mismatchingSubtreeGeometry;
+        }
 
         childBox = childBox->nextSibling();
         childRenderer = childRenderer->nextSibling();
index 1928fcb..e3f6aa2 100644 (file)
@@ -51,7 +51,7 @@ InlineFormattingContext::InlineFormattingContext(const Box& formattingContextRoo
 {
 }
 
-void InlineFormattingContext::layout(LayoutContext& layoutContext, FormattingState&) const
+void InlineFormattingContext::layout(LayoutContext& layoutContext, FormattingState& inlineFormattingState) const
 {
     if (!is<Container>(root()))
         return;
@@ -90,11 +90,14 @@ void InlineFormattingContext::layout(LayoutContext& layoutContext, FormattingSta
     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();
+    auto textRunList = textContentProvider.textRuns();
+    SimpleLineBreaker simpleLineBreaker(textRunList, textContentProvider, WTFMove(constraints), formattingRoot.style());
+
+    // Since we don't yet have a display tree context for inline boxes, let's just cache the runs on the state so that they can be verified against the sll/inline tree runs later.
+    ASSERT(is<InlineFormattingState>(inlineFormattingState));
+    downcast<InlineFormattingState>(inlineFormattingState).addLayoutRuns(simpleLineBreaker.runs());
 
     LOG_WITH_STREAM(FormattingContextLayout, stream << "[End] -> inline formatting context -> layout context(" << &layoutContext << ") formatting root(" << &root() << ")");
 }
index 997d33c..ef26277 100644 (file)
@@ -28,6 +28,7 @@
 #if ENABLE(LAYOUT_FORMATTING_CONTEXT)
 
 #include "FormattingState.h"
+#include "Runs.h"
 #include <wtf/IsoMalloc.h>
 
 namespace WebCore {
@@ -40,6 +41,13 @@ class InlineFormattingState : public FormattingState {
 public:
     InlineFormattingState(Ref<FloatingState>&&, const LayoutContext&);
     virtual ~InlineFormattingState();
+
+    // This is temporary. We need to construct a display tree context for inlines.
+    void addLayoutRuns(Vector<LayoutRun>&& layoutRuns) { m_layoutRuns = WTFMove(layoutRuns); }
+    const Vector<LayoutRun>& layoutRuns() const { return m_layoutRuns; }
+
+private:
+    Vector<LayoutRun> m_layoutRuns;
 };
 
 }
index d332ad3..e62f3f6 100644 (file)
@@ -118,7 +118,7 @@ void TreeBuilder::createSubTree(const RenderElement& rootRenderer, Container& ro
 }
 
 #if ENABLE(TREE_DEBUGGING)
-static void outputLayoutBox(TextStream& stream, const Box& layoutBox, const Display::Box& displayBox, unsigned depth)
+static void outputLayoutBox(TextStream& stream, const Box& layoutBox, const Display::Box* displayBox, unsigned depth)
 {
     unsigned printedCharacters = 0;
     while (++printedCharacters <= depth * 2)
@@ -134,7 +134,9 @@ static void outputLayoutBox(TextStream& stream, const Box& layoutBox, const Disp
         stream << "block container";
     } else
         stream << "box";
-    stream << " at [" << displayBox.left() << " " << displayBox.top() << "] size [" << displayBox.width() << " " << displayBox.height() << "]";
+    // FIXME: Inline text runs don't create display boxes yet.
+    if (displayBox)
+        stream << " at [" << displayBox->left() << " " << displayBox->top() << "] size [" << displayBox->width() << " " << displayBox->height() << "]";
     stream << " object [" << &layoutBox << "]";
 
     stream.nextLine();
@@ -143,7 +145,7 @@ static void outputLayoutBox(TextStream& stream, const Box& layoutBox, const Disp
 static void outputLayoutTree(const LayoutContext& layoutContext, TextStream& stream, const Container& rootContainer, unsigned depth)
 {
     for (auto& child : childrenOfType<Box>(rootContainer)) {
-        outputLayoutBox(stream, child, *layoutContext.displayBoxForLayoutBox(child), depth);
+        outputLayoutBox(stream, child, layoutContext.displayBoxForLayoutBox(child), depth);
         if (is<Container>(child))
             outputLayoutTree(layoutContext, stream, downcast<Container>(child), depth + 1);
     }
@@ -152,7 +154,7 @@ static void outputLayoutTree(const LayoutContext& layoutContext, TextStream& str
 void TreeBuilder::showLayoutTree(const LayoutContext& layoutContext, const Container& layoutBox)
 {
     TextStream stream(TextStream::LineMode::MultipleLine, TextStream::Formatting::SVGStyleRect);
-    outputLayoutBox(stream, layoutBox, *layoutContext.displayBoxForLayoutBox(layoutBox), 0);
+    outputLayoutBox(stream, layoutBox, layoutContext.displayBoxForLayoutBox(layoutBox), 0);
     outputLayoutTree(layoutContext, stream, layoutBox, 1);
     WTFLogAlways("%s", stream.release().utf8().data());
 }