Diff
Modified: trunk/Source/WebCore/ChangeLog (234084 => 234085)
--- trunk/Source/WebCore/ChangeLog 2018-07-21 18:47:01 UTC (rev 234084)
+++ trunk/Source/WebCore/ChangeLog 2018-07-21 18:49:23 UTC (rev 234085)
@@ -1,5 +1,28 @@
2018-07-21 Zalan Bujtas <[email protected]>
+ [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 <[email protected]>
+
[LFC] Do not use virtual methods to construct floating/formatting states.
https://bugs.webkit.org/show_bug.cgi?id=187875
Modified: trunk/Source/WebCore/layout/Verification.cpp (234084 => 234085)
--- trunk/Source/WebCore/layout/Verification.cpp 2018-07-21 18:47:01 UTC (rev 234084)
+++ trunk/Source/WebCore/layout/Verification.cpp 2018-07-21 18:49:23 UTC (rev 234085)
@@ -29,6 +29,7 @@
#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
#include "DisplayBox.h"
+#include "InlineTextBox.h"
#include "LayoutBox.h"
#include "LayoutContainer.h"
#include "LayoutTreeBuilder.h"
@@ -39,8 +40,74 @@
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) {
if (firstMismatchingRect) {
@@ -92,7 +159,7 @@
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 @@
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();
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp (234084 => 234085)
--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp 2018-07-21 18:47:01 UTC (rev 234084)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp 2018-07-21 18:49:23 UTC (rev 234085)
@@ -51,7 +51,7 @@
{
}
-void InlineFormattingContext::layout(LayoutContext& layoutContext, FormattingState&) const
+void InlineFormattingContext::layout(LayoutContext& layoutContext, FormattingState& inlineFormattingState) const
{
if (!is<Container>(root()))
return;
@@ -90,12 +90,15 @@
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() << ")");
}
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingState.h (234084 => 234085)
--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingState.h 2018-07-21 18:47:01 UTC (rev 234084)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingState.h 2018-07-21 18:49:23 UTC (rev 234085)
@@ -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 @@
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;
};
}
Modified: trunk/Source/WebCore/layout/layouttree/LayoutTreeBuilder.cpp (234084 => 234085)
--- trunk/Source/WebCore/layout/layouttree/LayoutTreeBuilder.cpp 2018-07-21 18:47:01 UTC (rev 234084)
+++ trunk/Source/WebCore/layout/layouttree/LayoutTreeBuilder.cpp 2018-07-21 18:49:23 UTC (rev 234085)
@@ -118,7 +118,7 @@
}
#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 @@
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 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 @@
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());
}