Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(38)

Unified Diff: third_party/WebKit/Source/core/editing/LayoutTreePrinter.cpp

Issue 1756763002: 2016-03-02T18:53:01 LayoutPosition Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: 2016-04-25T19:02:18 Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/editing/LayoutTreePrinter.cpp
diff --git a/third_party/WebKit/Source/core/editing/LayoutTreePrinter.cpp b/third_party/WebKit/Source/core/editing/LayoutTreePrinter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..61d276ff8abf92fb086b5aee129ac5d2852baad9
--- /dev/null
+++ b/third_party/WebKit/Source/core/editing/LayoutTreePrinter.cpp
@@ -0,0 +1,395 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/editing/LayoutTreePrinter.h"
+
+#include "core/editing/LayoutPosition.h"
+#include "core/frame/FrameView.h"
+#include "core/layout/LayoutBlock.h"
+#include "core/layout/LayoutBox.h"
+#include "core/layout/LayoutObject.h"
+#include "core/layout/LayoutView.h"
+#include "core/layout/api/LineLayoutAPIShim.h"
+#include "core/layout/api/LineLayoutItem.h"
+#include "core/layout/line/InlineTextBox.h"
+#include "core/layout/line/LineBoxList.h"
+#include "wtf/Allocator.h"
+#include "wtf/Assertions.h"
+#include "wtf/HexNumber.h"
+#include "wtf/Noncopyable.h"
+#include "wtf/text/StringBuilder.h"
+
+#ifndef NDEBUG
+#include <iostream> // NOLINT
+
+namespace blink {
+
+namespace {
+struct LayoutTreeAsText {
+ const InlineBox* inlineBox;
+ const LayoutObject* layoutObject;
+
+ explicit LayoutTreeAsText(const InlineBox& passedInlineBox)
+ : inlineBox(&passedInlineBox)
+ , layoutObject(nullptr)
+ {
+ }
+
+ explicit LayoutTreeAsText(const LayoutObject& passedLayoutObject)
+ : inlineBox(nullptr)
+ , layoutObject(&passedLayoutObject)
+ {
+ }
+};
+} // namespace
+
+class LayoutTreePrinter {
+ STACK_ALLOCATED();
+ WTF_MAKE_NONCOPYABLE(LayoutTreePrinter);
+public:
+ LayoutTreePrinter(std::ostream*, const LayoutTreeAsText&);
+
+ static void print(const InlineBox*);
+ static void print(const LayoutObject*);
+ static void print(const LayoutPosition&);
+ void print();
+
+private:
+ class ScopedIndent {
+ STACK_ALLOCATED();
+ WTF_MAKE_NONCOPYABLE(ScopedIndent);
+ public:
+ ScopedIndent(LayoutTreePrinter* Context, int amount)
+ : m_amount(amount)
+ , m_context(Context)
+ {
+ DCHECK_GE(m_amount, 1);
+ m_context->m_indentAmount += m_amount;
+ }
+
+ ~ScopedIndent()
+ {
+ DCHECK_GE(m_context->m_indentAmount, m_amount);
+ m_context->m_indentAmount -= m_amount;
+ }
+
+ private:
+ const int m_amount;
+ LayoutTreePrinter* const m_context;
+ };
+
+ void arrow() const;
+ void indent() const;
+ void visitInlineFlowBox(const InlineFlowBox&);
+ void visitLayoutObjct(const LayoutObject&);
+
+ int m_indentAmount = 0;
+ const InlineBox* const m_markedInlineBox;
+ const LayoutObject* const m_markedLayoutObject;
+ std::ostream* const m_stream;
+};
+
+namespace {
+
+struct CodeUnitAsText {
+ UChar codeUnit;
+ explicit CodeUnitAsText(UChar passedCodeUnit)
+ : codeUnit(passedCodeUnit)
+ {
+ }
+};
+
+struct InlineBoxAsText {
+ const InlineBox* inlineBox;
+
+ explicit InlineBoxAsText(const InlineBox& passedInlineBox)
+ : inlineBox(&passedInlineBox)
+ {
+ }
+};
+
+struct LayoutObjectAsText {
+ const LayoutObject* layoutObject;
+
+ explicit LayoutObjectAsText(const LayoutObject& passedLayoutObject)
+ : layoutObject(&passedLayoutObject)
+ {
+ }
+};
+
+struct StringAsText {
+ const String* string;
+
+ explicit StringAsText(const String& passedString)
+ : string(&passedString)
+ {
+ }
+};
+
+struct NodeAsText {
+ const Node* node;
+
+ explicit NodeAsText(const Node& passedNode)
+ : node(&passedNode)
+ {
+ }
+};
+
+struct LayoutRectAsText {
+ const LayoutRect* layoutRect;
+
+ explicit LayoutRectAsText(const LayoutRect& passedLayoutRect)
+ : layoutRect(&passedLayoutRect)
+ {
+ }
+};
+
+// -- Printers
+std::ostream& operator<<(std::ostream&, const CodeUnitAsText&);
+std::ostream& operator<<(std::ostream&, const InlineBoxAsText&);
+std::ostream& operator<<(std::ostream&, const LayoutObjectAsText&);
+std::ostream& operator<<(std::ostream&, const LayoutRectAsText&);
+std::ostream& operator<<(std::ostream&, const LayoutTreeAsText&);
+std::ostream& operator<<(std::ostream&, const NodeAsText&);
+std::ostream& operator<<(std::ostream&, const StringAsText&);
+
+std::ostream& operator<<(std::ostream& ostream, const CodeUnitAsText& wrapper)
+{
+ const UChar codeUnit = wrapper.codeUnit;
+ if (codeUnit == '\n')
+ return ostream << "\\n";
+ if (codeUnit == '\t')
+ return ostream << "\\t";
+ if (codeUnit == '"')
+ return ostream << "\\\"";
+ if (codeUnit == '\\')
+ return ostream << "\\\\";
+ if (codeUnit >= ' ' && codeUnit <= 0x7E)
+ return ostream << static_cast<char>(codeUnit);
+ StringBuilder builder;
+ appendUnsignedAsHexFixedSize(codeUnit, builder, 4);
+ return ostream << "\\u" << builder.toString().utf8().data();
+}
+
+std::ostream& operator<<(std::ostream& ostream, const LayoutRectAsText& wrapper)
+{
+ const LayoutRect& rect = *wrapper.layoutRect;
+ return ostream << '(' << rect.x().toFloat() << ',' << rect.y().toFloat() << ")+" << rect.width().toFloat() << 'x' << rect.height().toFloat();
+}
+
+std::ostream& operator<<(std::ostream& ostream, const InlineBoxAsText& wrapper)
+{
+ const InlineBox& inlineBox = *wrapper.inlineBox;
+ ostream << static_cast<const void*>(&inlineBox) << ' ' << inlineBox.boxName();
+ if (Node* node = inlineBox.getLineLayoutItem().node()) {
+ if (!node->isTextNode())
+ ostream << ' ' << node->debugName().utf8().data();
+ } else {
+ ostream << " (anonymous)";
+ }
+ if (inlineBox.isInlineTextBox()) {
+ const InlineTextBox& textBox = toInlineTextBox(inlineBox);
+ ostream << " " << StringAsText(textBox.text()) << " start=" << textBox.start() << " end=" << textBox.end();
+ } else if (inlineBox.isInlineFlowBox()) {
+ ostream << " frameRect=" << LayoutRectAsText(toInlineFlowBox(inlineBox).frameRect());
+ }
+ return ostream << " bidiLevel=" << static_cast<int>(inlineBox.bidiLevel());
+}
+
+std::ostream& operator<<(std::ostream& ostream, const LayoutObjectAsText& wrapper)
+{
+ const LayoutObject& layoutObject = *wrapper.layoutObject;
+ ostream << static_cast<const void*>(&layoutObject) << ' ' << layoutObject.name();
+ if (Node* node = layoutObject.node()) {
+ ostream << " {" << NodeAsText(*node) << '}';
+ if (node->hasEditableStyle())
+ ostream << " (editable)";
+ } else {
+ ostream << " (anonymous)";
+ }
+ if (layoutObject.isBox())
+ ostream << ' ' << LayoutRectAsText(toLayoutBox(layoutObject).frameRect());
+ return ostream;
+}
+
+std::ostream& operator<<(std::ostream& ostream, const LayoutTreeAsText& wrapper)
+{
+ LayoutTreePrinter(&ostream, wrapper).print();
+ return ostream;
+}
+
+std::ostream& operator<<(std::ostream& ostream, const NodeAsText& wrapper)
+{
+ const Node& node = *wrapper.node;
+ if (node.isTextNode())
+ ostream << StringAsText(toText(node).data());
+ else
+ ostream << node.debugName().utf8().data();
+ return ostream;
+}
+
+std::ostream& operator<<(std::ostream& ostream, const StringAsText& wrapper)
+{
+ const String& string = *wrapper.string;
+ const int kMaxChars = 40;
+ ostream << '"';
+ if (string.is8Bit()) {
+ const LChar* const start = string.characters8();
+ const LChar* const end = start + string.length();
+ const LChar* const middle = std::min(start + kMaxChars / 2, end);
+ for (const LChar* runner = start; runner < middle; ++runner)
+ ostream << CodeUnitAsText(*runner);
+ if (end != middle)
+ ostream << " ... ";
+ for (const LChar* runner = middle; runner < end; ++runner)
+ ostream << CodeUnitAsText(*runner);
+ } else {
+ const UChar* const start = string.characters16();
+ const UChar* const end = start + string.length();
+ const UChar* const middle = std::min(start + kMaxChars / 2, end);
+ for (const UChar* runner = start; runner < middle; ++runner)
+ ostream << CodeUnitAsText(*runner);
+ if (end != middle)
+ ostream << " ... ";
+ for (const UChar* runner = middle; runner < end; ++runner)
+ ostream << CodeUnitAsText(*runner);
+ }
+ return ostream << '"';
+}
+
+} // namespace
+
+// -- LayoutTreePrinter
+LayoutTreePrinter::LayoutTreePrinter(std::ostream* stream, const LayoutTreeAsText& wrapper)
+ : m_markedInlineBox(wrapper.inlineBox)
+ , m_markedLayoutObject(wrapper.layoutObject)
+ , m_stream(stream)
+{
+}
+
+void LayoutTreePrinter::arrow() const
+{
+ for (int index = 0; index < m_indentAmount; ++index)
+ *m_stream << "---";
+ *m_stream << '>';
+}
+
+void LayoutTreePrinter::print()
+{
+ if (m_markedInlineBox) {
+ visitLayoutObjct(*m_markedInlineBox->getLineLayoutItem().document().layoutView());
+ return;
+ }
+ visitLayoutObjct(*m_markedLayoutObject->document().layoutView());
+}
+
+void LayoutTreePrinter::indent() const
+{
+ for (int index = 0; index < m_indentAmount; ++index)
+ *m_stream << "| ";
+ *m_stream << '+';
+}
+
+void LayoutTreePrinter::visitInlineFlowBox(const InlineFlowBox& inlineFlowBox)
+{
+ if (m_markedInlineBox == &inlineFlowBox)
+ arrow();
+ else
+ indent();
+ *m_stream << '-' << InlineBoxAsText(inlineFlowBox) << std::endl;
+ ScopedIndent lineScope(this, 1);
+ for (const InlineBox* child = inlineFlowBox.firstChild(); child; child = child->nextOnLine()) {
+ if (m_markedInlineBox == child)
+ arrow();
+ else
+ indent();
+ *m_stream << InlineBoxAsText(*child) << std::endl;
+ if (child->isLeaf())
+ continue;
+ visitInlineFlowBox(*toInlineFlowBox(child));
+ }
+}
+
+void LayoutTreePrinter::visitLayoutObjct(const LayoutObject& layoutObject)
+{
+ if (m_markedLayoutObject == &layoutObject)
+ arrow();
+ else
+ indent();
+ *m_stream << LayoutObjectAsText(layoutObject) << std::endl;
+ ScopedIndent childrenScope(this, 1);
+ if (layoutObject.isLayoutBlock()) {
+ ScopedIndent linesScope(this, 2);
+ const auto& lines = toLayoutBlock(layoutObject).lineBoxes();
+ for (const InlineFlowBox* lineBox = lines.firstLineBox(); lineBox; lineBox = lineBox->nextLineBox())
+ visitInlineFlowBox(*lineBox);
+ }
+ for (const LayoutObject* child = layoutObject.slowFirstChild(); child; child = child->nextSibling())
+ visitLayoutObjct(*child);
+}
+
+void LayoutTreePrinter::print(const InlineBox* inlineBox)
+{
+ if (!inlineBox) {
+ VLOG(0) << "(null)";
+ return;
+ }
+ VLOG(0) << "Layout tree dump of " << static_cast<const void*>(inlineBox) << std::endl << LayoutTreeAsText(*inlineBox);
+}
+
+void LayoutTreePrinter::print(const LayoutObject* layoutObject)
+{
+ if (!layoutObject) {
+ VLOG(0) << "(null)";
+ return;
+ }
+ VLOG(0) << "Layout tree dump of " << static_cast<const void*>(layoutObject) << std::endl << LayoutTreeAsText(*layoutObject);
+}
+
+void LayoutTreePrinter::print(const LayoutPosition& position)
+{
+ if (position.isNull()) {
+ VLOG(0) << "(null)";
+ return;
+ }
+ if (const InlineBox* inlineBox = position.m_inlineBox) {
+ VLOG(0) << "Layout tree dump of " << position << std::endl << LayoutTreeAsText(*inlineBox);
+ return;
+ }
+ VLOG(0) << "Layout tree dump of " << position << std::endl << LayoutTreeAsText(*position.m_layoutObject);
+}
+
+} // namespace blink
+
+void dumpLayoutTree(const blink::InlineBox* inlineBox)
+{
+ blink::LayoutTreePrinter::print(inlineBox);
+}
+
+void dumpLayoutTree(const blink::LayoutObject* layoutObject)
+{
+ blink::LayoutTreePrinter::print(layoutObject);
+}
+
+void dumpLayoutTree(const blink::LayoutPosition& position)
+{
+ blink::LayoutTreePrinter::print(position);
+}
+
+void dumpLayoutTree(const blink::Node* node)
+{
+ dumpLayoutTree(node->layoutObject());
+}
+
+void dumpLayoutTree(const blink::Position& position)
+{
+ dumpLayoutTree(position.anchorNode());
+}
+
+void dumpLayoutTree(const blink::VisiblePosition& position)
+{
+ dumpLayoutTree(position.deepEquivalent());
+}
+
+#endif

Powered by Google App Engine
This is Rietveld 408576698