[LFC] Add LayoutTreeBuilder class to generate the layout tree
https://bugs.webkit.org/show_bug.cgi?id=185108

Reviewed by Antti Koivisto.

This is for testing purposes.

* WebCore.xcodeproj/project.pbxproj:
* layout/FormattingState.cpp:
(WebCore::Layout::FormattingState::~FormattingState):
* layout/FormattingState.h:
* layout/LayoutContext.h:
* layout/blockformatting/BlockFormattingState.cpp:
(WebCore::Layout::BlockFormattingState::~BlockFormattingState):
* layout/blockformatting/BlockFormattingState.h:
* layout/inlineformatting/InlineFormattingState.cpp:
(WebCore::Layout::InlineFormattingState::~InlineFormattingState):
* layout/inlineformatting/InlineFormattingState.h:
* layout/layouttree/LayoutBlockContainer.h:
* layout/layouttree/LayoutBox.h:
* layout/layouttree/LayoutContainer.h:
* layout/layouttree/LayoutInlineContainer.h:
* layout/layouttree/LayoutTreeBuilder.cpp: Added.
(WebCore::Layout::TreeBuilder::createLayoutTree):
(WebCore::Layout::TreeBuilder::createSubTree):
(WebCore::Layout::outputLayoutBox):
(WebCore::Layout::outputLayoutTree):
(WebCore::Layout::TreeBuilder::showLayoutTree):
(WebCore::Layout::printLayoutTreeForLiveDocuments):
* layout/layouttree/LayoutTreeBuilder.h: Copied from Source/WebCore/layout/layouttree/LayoutBlockContainer.h.
* page/mac/PageMac.mm:
(WebCore::Page::platformInitialize):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@231141 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index f37324f..a9717c7 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,5 +1,40 @@
 2018-04-28  Zalan Bujtas  <zalan@apple.com>
 
+        [LFC] Add LayoutTreeBuilder class to generate the layout tree
+        https://bugs.webkit.org/show_bug.cgi?id=185108
+
+        Reviewed by Antti Koivisto.
+
+        This is for testing purposes.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * layout/FormattingState.cpp:
+        (WebCore::Layout::FormattingState::~FormattingState):
+        * layout/FormattingState.h:
+        * layout/LayoutContext.h:
+        * layout/blockformatting/BlockFormattingState.cpp:
+        (WebCore::Layout::BlockFormattingState::~BlockFormattingState):
+        * layout/blockformatting/BlockFormattingState.h:
+        * layout/inlineformatting/InlineFormattingState.cpp:
+        (WebCore::Layout::InlineFormattingState::~InlineFormattingState):
+        * layout/inlineformatting/InlineFormattingState.h:
+        * layout/layouttree/LayoutBlockContainer.h:
+        * layout/layouttree/LayoutBox.h:
+        * layout/layouttree/LayoutContainer.h:
+        * layout/layouttree/LayoutInlineContainer.h:
+        * layout/layouttree/LayoutTreeBuilder.cpp: Added.
+        (WebCore::Layout::TreeBuilder::createLayoutTree):
+        (WebCore::Layout::TreeBuilder::createSubTree):
+        (WebCore::Layout::outputLayoutBox):
+        (WebCore::Layout::outputLayoutTree):
+        (WebCore::Layout::TreeBuilder::showLayoutTree):
+        (WebCore::Layout::printLayoutTreeForLiveDocuments):
+        * layout/layouttree/LayoutTreeBuilder.h: Copied from Source/WebCore/layout/layouttree/LayoutBlockContainer.h.
+        * page/mac/PageMac.mm:
+        (WebCore::Page::platformInitialize):
+
+2018-04-28  Zalan Bujtas  <zalan@apple.com>
+
         [LFC] Implement BlockMarginCollapse functions.
         https://bugs.webkit.org/show_bug.cgi?id=185036
 
diff --git a/Source/WebCore/Sources.txt b/Source/WebCore/Sources.txt
index 4bac2c0..73c1351 100644
--- a/Source/WebCore/Sources.txt
+++ b/Source/WebCore/Sources.txt
@@ -1229,6 +1229,7 @@
 layout/layouttree/LayoutContainer.cpp
 layout/layouttree/LayoutInlineBox.cpp
 layout/layouttree/LayoutInlineContainer.cpp
+layout/layouttree/LayoutTreeBuilder.cpp
 
 loader/ContentFilter.cpp
 loader/CookieJar.cpp
diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
index f27ed18..36a443f 100644
--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -5719,6 +5719,8 @@
 		11100FC72092764C0081AA6C /* LayoutIterator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LayoutIterator.h; sourceTree = "<group>"; };
 		11100FC920927CBC0081AA6C /* LayoutChildIterator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LayoutChildIterator.h; sourceTree = "<group>"; };
 		11100FCA2092868D0081AA6C /* LayoutAncestorIterator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LayoutAncestorIterator.h; sourceTree = "<group>"; };
+		11100FD5209514DE0081AA6C /* LayoutTreeBuilder.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = LayoutTreeBuilder.cpp; sourceTree = "<group>"; };
+		11100FD7209514DF0081AA6C /* LayoutTreeBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LayoutTreeBuilder.h; sourceTree = "<group>"; };
 		112B34D01E60B8A700BB310A /* SimpleLineLayoutPagination.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SimpleLineLayoutPagination.cpp; sourceTree = "<group>"; };
 		112B34D41E60B98300BB310A /* SimpleLineLayoutPagination.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimpleLineLayoutPagination.h; sourceTree = "<group>"; };
 		113409D7203E038000C66915 /* RenderTreeBuilderContinuation.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTreeBuilderContinuation.cpp; sourceTree = "<group>"; };
@@ -15669,6 +15671,8 @@
 				1199FA4E208E3899002358CC /* LayoutInlineContainer.cpp */,
 				1199FA4D208E3899002358CC /* LayoutInlineContainer.h */,
 				11100FC72092764C0081AA6C /* LayoutIterator.h */,
+				11100FD5209514DE0081AA6C /* LayoutTreeBuilder.cpp */,
+				11100FD7209514DF0081AA6C /* LayoutTreeBuilder.h */,
 			);
 			path = layouttree;
 			sourceTree = "<group>";
@@ -31018,8 +31022,7 @@
 		1C09D0501E31C32900725F18 /* libPAL.a */ = {
 			isa = PBXReferenceProxy;
 			fileType = archive.ar;
-			name = libPAL.a;
-			path = lib.a;
+			path = libPAL.a;
 			remoteRef = 1C09D04F1E31C32900725F18 /* PBXContainerItemProxy */;
 			sourceTree = BUILT_PRODUCTS_DIR;
 		};
diff --git a/Source/WebCore/layout/FormattingState.cpp b/Source/WebCore/layout/FormattingState.cpp
index 0e28e85..ff691a7 100644
--- a/Source/WebCore/layout/FormattingState.cpp
+++ b/Source/WebCore/layout/FormattingState.cpp
@@ -40,6 +40,10 @@
 {
 }
 
+FormattingState::~FormattingState()
+{
+}
+
 }
 }
 #endif
diff --git a/Source/WebCore/layout/FormattingState.h b/Source/WebCore/layout/FormattingState.h
index 698b3c7..10c3a42 100644
--- a/Source/WebCore/layout/FormattingState.h
+++ b/Source/WebCore/layout/FormattingState.h
@@ -41,6 +41,7 @@
     WTF_MAKE_ISO_ALLOCATED(FormattingState);
 public:
     FormattingState(Ref<FloatingState>&&);
+    virtual ~FormattingState();
 
     FloatingState& floatingState() const { return m_floatingState; }
 
diff --git a/Source/WebCore/layout/LayoutContext.h b/Source/WebCore/layout/LayoutContext.h
index 5768bd2..a99b15f 100644
--- a/Source/WebCore/layout/LayoutContext.h
+++ b/Source/WebCore/layout/LayoutContext.h
@@ -27,6 +27,8 @@
 
 #if ENABLE(LAYOUT_FORMATTING_CONTEXT)
 
+#include "FormattingContext.h"
+#include "FormattingState.h"
 #include "LayoutBox.h"
 #include <wtf/IsoMalloc.h>
 
@@ -38,8 +40,6 @@
 
 namespace Layout {
 
-class FormattingContext;
-class FormattingState;
 class StyleDiff;
 
 // LayoutContext is the entry point for layout. It takes a (formatting root)container which acts as the root of the layout context.
diff --git a/Source/WebCore/layout/blockformatting/BlockFormattingState.cpp b/Source/WebCore/layout/blockformatting/BlockFormattingState.cpp
index 95a8a0b..c951eee 100644
--- a/Source/WebCore/layout/blockformatting/BlockFormattingState.cpp
+++ b/Source/WebCore/layout/blockformatting/BlockFormattingState.cpp
@@ -40,6 +40,10 @@
 {
 }
 
+BlockFormattingState::~BlockFormattingState()
+{
+}
+
 }
 }
 #endif
diff --git a/Source/WebCore/layout/blockformatting/BlockFormattingState.h b/Source/WebCore/layout/blockformatting/BlockFormattingState.h
index 6202310..44e5d83 100644
--- a/Source/WebCore/layout/blockformatting/BlockFormattingState.h
+++ b/Source/WebCore/layout/blockformatting/BlockFormattingState.h
@@ -39,6 +39,7 @@
     WTF_MAKE_ISO_ALLOCATED(BlockFormattingState);
 public:
     BlockFormattingState(Ref<FloatingState>&&);
+    virtual ~BlockFormattingState();
 };
 
 }
diff --git a/Source/WebCore/layout/inlineformatting/InlineFormattingState.cpp b/Source/WebCore/layout/inlineformatting/InlineFormattingState.cpp
index 99970d1..721d829 100644
--- a/Source/WebCore/layout/inlineformatting/InlineFormattingState.cpp
+++ b/Source/WebCore/layout/inlineformatting/InlineFormattingState.cpp
@@ -40,6 +40,10 @@
 {
 }
 
+InlineFormattingState::~InlineFormattingState()
+{
+}
+
 }
 }
 #endif
diff --git a/Source/WebCore/layout/inlineformatting/InlineFormattingState.h b/Source/WebCore/layout/inlineformatting/InlineFormattingState.h
index c7b5d7b..5623dd9 100644
--- a/Source/WebCore/layout/inlineformatting/InlineFormattingState.h
+++ b/Source/WebCore/layout/inlineformatting/InlineFormattingState.h
@@ -39,6 +39,7 @@
     WTF_MAKE_ISO_ALLOCATED(InlineFormattingState);
 public:
     InlineFormattingState(Ref<FloatingState>&&);
+    virtual ~InlineFormattingState();
 };
 
 }
diff --git a/Source/WebCore/layout/layouttree/LayoutBlockContainer.h b/Source/WebCore/layout/layouttree/LayoutBlockContainer.h
index 98c41a3..dade706 100644
--- a/Source/WebCore/layout/layouttree/LayoutBlockContainer.h
+++ b/Source/WebCore/layout/layouttree/LayoutBlockContainer.h
@@ -39,9 +39,13 @@
 class BlockContainer : public Container {
     WTF_MAKE_ISO_ALLOCATED(BlockContainer);
 public:
-    BlockContainer(RenderStyle&&, BaseTypeFlags);
+    friend class TreeBuilder;
 
     bool establishesInlineFormattingContext() const final;
+
+protected:
+    BlockContainer(RenderStyle&&, BaseTypeFlags = BlockContainerFlag);
+
 };
 
 }
diff --git a/Source/WebCore/layout/layouttree/LayoutBox.h b/Source/WebCore/layout/layouttree/LayoutBox.h
index 8aa330d..5c4563c 100644
--- a/Source/WebCore/layout/layouttree/LayoutBox.h
+++ b/Source/WebCore/layout/layouttree/LayoutBox.h
@@ -42,9 +42,7 @@
     WTF_MAKE_ISO_ALLOCATED(Box);
 public:
     friend class TreeBuilder;
-    typedef unsigned BaseTypeFlags;
 
-    Box(RenderStyle&&, BaseTypeFlags);
     virtual ~Box();
 
     bool establishesFormattingContext() const;
@@ -83,6 +81,7 @@
     const Box* previousInFlowSibling() const;
     const Box* previousInFlowOrFloatingSibling() const;
 
+    typedef unsigned BaseTypeFlags;
     bool isContainer() const { return m_baseTypeFlags & ContainerFlag; }
     bool isBlockContainer() const { return m_baseTypeFlags & BlockContainerFlag; }
     bool isInlineBox() const { return m_baseTypeFlags & InlineBoxFlag; }
@@ -98,6 +97,7 @@
         InlineBoxFlag         = 1 << 2,
         InlineContainerFlag   = 1 << 3
     };
+    Box(RenderStyle&&, BaseTypeFlags);
 
     bool isOverflowVisible() const;
 
@@ -114,7 +114,7 @@
     Box* m_previousSibling { nullptr };
     Box* m_nextSibling { nullptr };
 
-    unsigned m_baseTypeFlags : 3;
+    unsigned m_baseTypeFlags : 4;
     unsigned m_isAnonymous : 1;
 
 };
diff --git a/Source/WebCore/layout/layouttree/LayoutContainer.h b/Source/WebCore/layout/layouttree/LayoutContainer.h
index dacd6b4..6ba89ae 100644
--- a/Source/WebCore/layout/layouttree/LayoutContainer.h
+++ b/Source/WebCore/layout/layouttree/LayoutContainer.h
@@ -42,8 +42,6 @@
 public:
     friend class TreeBuilder;
 
-    Container(RenderStyle&&, BaseTypeFlags);
-
     const Box* firstChild() const { return m_firstChild; }
     const Box* firstInFlowChild() const;
     const Box* firstInFlowOrFloatingChild() const;
@@ -57,6 +55,9 @@
 
     const Vector<WeakPtr<Box>>& outOfFlowDescendants() { return m_outOfFlowDescendants; }
 
+protected:
+    Container(RenderStyle&&, BaseTypeFlags);
+
 private:
     void setFirstChild(Box&);
     void setLastChild(Box&);
diff --git a/Source/WebCore/layout/layouttree/LayoutInlineContainer.h b/Source/WebCore/layout/layouttree/LayoutInlineContainer.h
index a93a690..aaa21d5 100644
--- a/Source/WebCore/layout/layouttree/LayoutInlineContainer.h
+++ b/Source/WebCore/layout/layouttree/LayoutInlineContainer.h
@@ -39,7 +39,10 @@
 class InlineContainer : public Container {
     WTF_MAKE_ISO_ALLOCATED(InlineContainer);
 public:
-    InlineContainer(RenderStyle&&, BaseTypeFlags);
+    friend class TreeBuilder;
+
+protected:
+    InlineContainer(RenderStyle&&, BaseTypeFlags = InlineContainerFlag);
 };
 
 }
diff --git a/Source/WebCore/layout/layouttree/LayoutTreeBuilder.cpp b/Source/WebCore/layout/layouttree/LayoutTreeBuilder.cpp
new file mode 100644
index 0000000..e785269
--- /dev/null
+++ b/Source/WebCore/layout/layouttree/LayoutTreeBuilder.cpp
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "LayoutTreeBuilder.h"
+
+#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
+
+#include "LayoutBlockContainer.h"
+#include "LayoutChildIterator.h"
+#include "LayoutContainer.h"
+#include "LayoutInlineBox.h"
+#include "LayoutInlineContainer.h"
+#include "RenderBlock.h"
+#include "RenderChildIterator.h"
+#include "RenderElement.h"
+#include "RenderInline.h"
+#include "RenderStyle.h"
+#include "RenderView.h"
+#include <wtf/text/TextStream.h>
+
+namespace WebCore {
+namespace Layout {
+
+std::unique_ptr<Container> TreeBuilder::createLayoutTree(const RenderView& renderView)
+{
+    std::unique_ptr<Container> initialContainingBlock(new BlockContainer(RenderStyle::clone(renderView.style())));
+    TreeBuilder::createSubTree(renderView, *initialContainingBlock);
+    return initialContainingBlock;
+}
+
+void TreeBuilder::createSubTree(const RenderElement& rootRenderer, Container& rootContainer)
+{
+    // Skip RenderText (and some others) for now.
+    for (auto& child : childrenOfType<RenderElement>(rootRenderer)) {
+        Box* box = nullptr;
+        if (is<RenderBlock>(child)) {
+            box = new BlockContainer(RenderStyle::clone(child.style()));
+            createSubTree(child, downcast<Container>(*box));
+        } else if (is<RenderInline>(child)) {
+            box = new InlineContainer(RenderStyle::clone(child.style()));
+            createSubTree(child, downcast<Container>(*box));
+        } else
+            ASSERT_NOT_REACHED();
+
+        if (!rootContainer.hasChild()) {
+            rootContainer.setFirstChild(*box);
+            rootContainer.setLastChild(*box);
+        } else {
+            auto* lastChild = const_cast<Box*>(rootContainer.lastChild());
+            box->setPreviousSibling(*lastChild);
+            lastChild->setNextSibling(*box);
+            rootContainer.setLastChild(*box);
+        }
+        box->setParent(rootContainer);
+    }
+}
+
+#if ENABLE(TREE_DEBUGGING)
+static void outputLayoutBox(TextStream& stream, const Box& layoutBox, unsigned depth)
+{
+    unsigned printedCharacters = 0;
+    while (++printedCharacters <= depth * 2)
+        stream << " ";
+
+    if (is<InlineContainer>(layoutBox))
+        stream << "inline container";
+    else if (is<InlineBox>(layoutBox))
+        stream << "inline box";
+    else if (is<BlockContainer>(layoutBox)) {
+        if (!layoutBox.parent())
+            stream << "initial ";
+        stream << "block container";
+    } else
+        stream << "box";
+    stream << " at [0 0] size [0 0]";
+    stream << " object [" << &layoutBox << "]";
+
+    stream.nextLine();
+}
+
+static void outputLayoutTree(TextStream& stream, const Container& rootContainer, unsigned depth)
+{
+    for (auto& child : childrenOfType<Box>(rootContainer)) {
+        outputLayoutBox(stream, child, depth);
+        if (is<Container>(child))
+            outputLayoutTree(stream, downcast<Container>(child), depth + 1);
+    }
+}
+
+void TreeBuilder::showLayoutTree(const Container& layoutBox)
+{
+    TextStream stream(TextStream::LineMode::MultipleLine, TextStream::Formatting::SVGStyleRect);
+    outputLayoutBox(stream, layoutBox, 0);
+    outputLayoutTree(stream, layoutBox, 1);
+    WTFLogAlways("%s", stream.release().utf8().data());
+}
+
+void printLayoutTreeForLiveDocuments()
+{
+    for (const auto* document : Document::allDocuments()) {
+        if (!document->renderView())
+            continue;
+        if (document->frame() && document->frame()->isMainFrame())
+            fprintf(stderr, "----------------------main frame--------------------------\n");
+        fprintf(stderr, "%s\n", document->url().string().utf8().data());
+        Layout::TreeBuilder::showLayoutTree(*TreeBuilder::createLayoutTree(*document->renderView()));
+    }
+}
+#endif
+
+}
+}
+
+#endif
diff --git a/Source/WebCore/layout/layouttree/LayoutTreeBuilder.h b/Source/WebCore/layout/layouttree/LayoutTreeBuilder.h
new file mode 100644
index 0000000..c3b87b9
--- /dev/null
+++ b/Source/WebCore/layout/layouttree/LayoutTreeBuilder.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
+
+namespace WebCore {
+
+class RenderElement;
+class RenderView;
+
+namespace Layout {
+
+class Container;
+
+class TreeBuilder {
+public:
+    static std::unique_ptr<Container> createLayoutTree(const RenderView&);
+    static void showLayoutTree(const Container&);
+
+private:
+    static void createSubTree(const RenderElement& rootRenderer, Container& rootContainer);
+};
+
+#if ENABLE(TREE_DEBUGGING)
+void printLayoutTreeForLiveDocuments();
+#endif
+
+}
+}
+
+#endif
diff --git a/Source/WebCore/page/mac/PageMac.mm b/Source/WebCore/page/mac/PageMac.mm
index aa030c5..edf1810 100644
--- a/Source/WebCore/page/mac/PageMac.mm
+++ b/Source/WebCore/page/mac/PageMac.mm
@@ -33,6 +33,7 @@
 #import "Frame.h"
 #import "FrameLoader.h"
 #import "FrameTree.h"
+#import "LayoutTreeBuilder.h"
 #import "Logging.h"
 #import "RenderObject.h"
 #import <pal/Logging.h>
@@ -56,6 +57,9 @@
     std::call_once(onceFlag, [] {
         PAL::registerNotifyCallback("com.apple.WebKit.showRenderTree", printRenderTreeForLiveDocuments);
         PAL::registerNotifyCallback("com.apple.WebKit.showLayerTree", printLayerTreeForLiveDocuments);
+#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
+        PAL::registerNotifyCallback("com.apple.WebKit.showLayoutTree", Layout::printLayoutTreeForLiveDocuments);
+#endif
     });
 #endif
 }