#include "config.h"
#include "LayoutContext.h"
#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
#include "DisplayBox.h"
#include "LayoutBox.h"
#include "LayoutContainer.h"
#include "LayoutTreeBuilder.h"
#include "RenderBox.h"
#include "RenderView.h"
#include <wtf/text/TextStream.h>
namespace WebCore {
namespace Layout {
static bool outputMismatchingBoxInformationIfNeeded(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) {
if (firstMismatchingRect) {
stream << (renderer.element() ? renderer.element()->nodeName().utf8().data() : "") << " " << renderer.renderName() << "(" << &renderer << ") layoutBox(" << &layoutBox << ")";
stream.nextLine();
firstMismatchingRect = false;
}
stream << prefix.utf8().data() << "\trenderer->(" << rendererRect.x() << "," << rendererRect.y() << ") (" << rendererRect.width() << "x" << rendererRect.height() << ")"
<< "\tlayout->(" << layoutRect.x() << "," << layoutRect.y() << ") (" << layoutRect.width() << "x" << layoutRect.height() << ")";
stream.nextLine();
};
auto* displayBox = context.displayBoxForLayoutBox(layoutBox);
ASSERT(displayBox);
auto frameRect = renderer.frameRect();
if (renderer.isInFlowPositioned())
frameRect.move(renderer.offsetForInFlowPosition());
if (frameRect != displayBox->rect()) {
outputRect("frameBox", renderer.frameRect(), displayBox->rect());
return true;
}
if (renderer.marginBoxRect() != displayBox->nonCollapsedMarginBox()) {
outputRect("marginBox", renderer.marginBoxRect(), displayBox->nonCollapsedMarginBox());
return true;
}
if (renderer.borderBoxRect() != displayBox->borderBox()) {
outputRect("borderBox", renderer.borderBoxRect(), displayBox->borderBox());
return true;
}
if (renderer.paddingBoxRect() != displayBox->paddingBox()) {
outputRect("paddingBox", renderer.paddingBoxRect(), displayBox->paddingBox());
return true;
}
if (renderer.contentBoxRect() != displayBox->contentBox()) {
outputRect("contentBox", renderer.contentBoxRect(), displayBox->contentBox());
return true;
}
return false;
}
static bool verifyAndOutputSubtree(TextStream& stream, const LayoutContext& context, const RenderBox& renderer, const Box& layoutBox)
{
auto mismtachingGeometry = outputMismatchingBoxInformationIfNeeded(stream, context, renderer, layoutBox);
if (!is<Container>(layoutBox))
return mismtachingGeometry;
auto& container = downcast<Container>(layoutBox);
auto* childBox = container.firstChild();
auto* childRenderer = renderer.firstChild();
while (childRenderer) {
if (!is<RenderBox>(*childRenderer)) {
childRenderer = childRenderer->nextSibling();
continue;
}
auto mismatchingSubtreeGeometry = verifyAndOutputSubtree(stream, context, downcast<RenderBox>(*childRenderer), *childBox);
mismtachingGeometry |= mismatchingSubtreeGeometry;
childBox = childBox->nextSibling();
childRenderer = childRenderer->nextSibling();
}
return mismtachingGeometry;
}
void LayoutContext::verifyAndOutputMismatchingLayoutTree(const RenderView& renderView) const
{
TextStream stream;
auto mismatchingGeometry = verifyAndOutputSubtree(stream, *this, renderView, *m_root.get());
if (!mismatchingGeometry)
return;
#if ENABLE(TREE_DEBUGGING)
showRenderTree(&renderView);
TreeBuilder::showLayoutTree(*this, *m_root.get());
#endif
WTFLogAlways("%s", stream.release().utf8().data());
}
}
}
#endif