Title: [271931] trunk/Source/WebCore
- Revision
- 271931
- Author
- [email protected]
- Date
- 2021-01-26 18:42:19 -0800 (Tue, 26 Jan 2021)
Log Message
[LFC][IFC] Do not create empty runs for empty lines
https://bugs.webkit.org/show_bug.cgi?id=220994
Reviewed by Antti Koivisto.
Add a fast path for cases when the line has some inline level boxes but we don't consider them "contentful".
e.g. <div><span></span><span></span></div>
It is a relatively common when block level boxes are wrapped inside inline level boxes and
we end up constructing "empty" pre/post blocks (see continuation) e.g. <span><div>content</div></span>.
Such content generates "empty" lines and while this is clearly a performance improvement, it is
also a correctness fix as RenderBlockFlow checks for the number of lines to see if the block is empty and
the integration layer checks the number of runs on the line to decide if the line is "empty" (see LineLayout::lineCount).
(In LFC we check if the lines are empty and not if the line count is 0 since according to the spec even "empty" content generates (empty)lines)
* layout/inlineformatting/InlineFormattingContext.cpp:
(WebCore::Layout::InlineFormattingContext::computeGeometryForLineContent):
* layout/inlineformatting/InlineFormattingContextGeometry.cpp:
(WebCore::Layout::LineBoxBuilder::constructInlineLevelBoxes):
* layout/inlineformatting/InlineLineBox.h:
(WebCore::Layout::LineBox::hasContent const):
(WebCore::Layout::LineBox::setHasContent):
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (271930 => 271931)
--- trunk/Source/WebCore/ChangeLog 2021-01-27 02:38:15 UTC (rev 271930)
+++ trunk/Source/WebCore/ChangeLog 2021-01-27 02:42:19 UTC (rev 271931)
@@ -1,3 +1,27 @@
+2021-01-26 Zalan Bujtas <[email protected]>
+
+ [LFC][IFC] Do not create empty runs for empty lines
+ https://bugs.webkit.org/show_bug.cgi?id=220994
+
+ Reviewed by Antti Koivisto.
+
+ Add a fast path for cases when the line has some inline level boxes but we don't consider them "contentful".
+ e.g. <div><span></span><span></span></div>
+ It is a relatively common when block level boxes are wrapped inside inline level boxes and
+ we end up constructing "empty" pre/post blocks (see continuation) e.g. <span><div>content</div></span>.
+ Such content generates "empty" lines and while this is clearly a performance improvement, it is
+ also a correctness fix as RenderBlockFlow checks for the number of lines to see if the block is empty and
+ the integration layer checks the number of runs on the line to decide if the line is "empty" (see LineLayout::lineCount).
+ (In LFC we check if the lines are empty and not if the line count is 0 since according to the spec even "empty" content generates (empty)lines)
+
+ * layout/inlineformatting/InlineFormattingContext.cpp:
+ (WebCore::Layout::InlineFormattingContext::computeGeometryForLineContent):
+ * layout/inlineformatting/InlineFormattingContextGeometry.cpp:
+ (WebCore::Layout::LineBoxBuilder::constructInlineLevelBoxes):
+ * layout/inlineformatting/InlineLineBox.h:
+ (WebCore::Layout::LineBox::hasContent const):
+ (WebCore::Layout::LineBox::setHasContent):
+
2021-01-26 Antti Koivisto <[email protected]>
REGRESSION (r271584): Hovering slowly over and out of "Top 100" items on liberation.fr does not restore animated state
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp (271930 => 271931)
--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp 2021-01-27 02:38:15 UTC (rev 271930)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp 2021-01-27 02:42:19 UTC (rev 271931)
@@ -448,6 +448,28 @@
const auto& lineBox = formattingState.lineBoxes().last();
auto lineIndex = formattingState.lines().size();
auto& lineBoxLogicalRect = lineBox.logicalRect();
+ if (!lineBox.hasContent()) {
+ // Fast path for lines with no content e.g. <div><span></span><span></span></div> or <span><div></div></span> where we construct empty pre and post blocks.
+ ASSERT(!lineContent.contentLogicalWidth);
+ ASSERT(!lineBoxLogicalRect.width() && !lineBoxLogicalRect.height());
+ if (lineBox.hasInlineBox()) {
+ for (auto& inlineLevelBox : lineBox.nonRootInlineLevelBoxes()) {
+ if (!inlineLevelBox->isInlineBox())
+ continue;
+ auto& layoutBox = inlineLevelBox->layoutBox();
+ auto& boxGeometry = formattingState.boxGeometry(layoutBox);
+ auto inlineBoxMarginRect = lineBox.logicalMarginRectForInlineLevelBox(layoutBox, boxGeometry);
+ boxGeometry.setContentBoxHeight(LayoutUnit::fromFloatCeil(inlineBoxMarginRect.height()));
+ ASSERT(!inlineBoxMarginRect.width());
+ boxGeometry.setContentBoxWidth({ });
+
+ boxGeometry.setLogicalTopLeft({ });
+ }
+ }
+ formattingState.addLine({ lineBoxLogicalRect, { { }, { } }, { }, { }, { } });
+ return lineBoxLogicalRect;
+ }
+
auto rootInlineBoxLogicalRect = lineBox.logicalRectForRootInlineBox();
auto enclosingTopAndBottom = InlineLineGeometry::EnclosingTopAndBottom { lineBoxLogicalRect.top() + rootInlineBoxLogicalRect.top(), lineBoxLogicalRect.top() + rootInlineBoxLogicalRect.bottom() };
HashSet<const Box*> inlineBoxStartSet;
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContextGeometry.cpp (271930 => 271931)
--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContextGeometry.cpp 2021-01-27 02:38:15 UTC (rev 271930)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContextGeometry.cpp 2021-01-27 02:42:19 UTC (rev 271931)
@@ -369,6 +369,7 @@
ASSERT_NOT_REACHED();
}
+ lineBox.setHasContent(lineHasContent);
if (!m_inlineLevelBoxesNeedVerticalAlignment) {
if (!lineHasContent) {
simplifiedVerticalAlignment.rootInlineBoxTop = -rootInlineBox.baseline();
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLineBox.h (271930 => 271931)
--- trunk/Source/WebCore/layout/inlineformatting/InlineLineBox.h 2021-01-27 02:38:15 UTC (rev 271930)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineBox.h 2021-01-27 02:42:19 UTC (rev 271931)
@@ -139,6 +139,9 @@
InlineLayoutSize logicalSize() const { return logicalRect().size(); }
Optional<InlineLayoutUnit> horizontalAlignmentOffset() const { return m_horizontalAlignmentOffset; }
+
+ // Note that the line can have many inline boxes and be "empty" the same time e.g. <div><span></span><span></span></div>
+ bool hasContent() const { return m_hasContent; }
bool hasInlineBox() const { return m_boxTypes.contains(InlineLevelBox::Type::InlineBox); }
bool hasNonInlineBox() const { return m_boxTypes.containsAny({ InlineLevelBox::Type::AtomicInlineLevelBox, InlineLevelBox::Type::LineBreakBox, InlineLevelBox::Type::GenericInlineLevelBox }); }
@@ -167,8 +170,11 @@
InlineLevelBox& inlineLevelBoxForLayoutBox(const Box& layoutBox) { return *m_inlineLevelBoxRectMap.get(&layoutBox); }
+ void setHasContent(bool hasContent) { m_hasContent = hasContent; }
+
private:
InlineRect m_logicalRect;
+ bool m_hasContent { false };
Optional<InlineLayoutUnit> m_horizontalAlignmentOffset;
OptionSet<InlineLevelBox::Type> m_boxTypes;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes