Diff
Modified: trunk/Source/WebCore/ChangeLog (231641 => 231642)
--- trunk/Source/WebCore/ChangeLog 2018-05-10 16:16:11 UTC (rev 231641)
+++ trunk/Source/WebCore/ChangeLog 2018-05-10 16:46:54 UTC (rev 231642)
@@ -1,3 +1,33 @@
+2018-05-10 Zalan Bujtas <[email protected]>
+
+ [LFC] Implement height computation for non-replaced inflow elements.
+ https://bugs.webkit.org/show_bug.cgi?id=185474
+
+ Reviewed by Antti Koivisto.
+
+ Initial implementation. Does not cover all the cases.
+
+ * layout/FormattingContext.cpp:
+ (WebCore::Layout::FormattingContext::computeHeight const):
+ * layout/FormattingContext.h:
+ * layout/blockformatting/BlockFormattingContext.cpp:
+ (WebCore::Layout::BlockFormattingContext::layout const):
+ (WebCore::Layout::BlockFormattingContext::computeInFlowHeight const):
+ (WebCore::Layout::BlockFormattingContext::computeInFlowNonReplacedHeight const):
+ * layout/blockformatting/BlockFormattingContext.h:
+ * layout/blockformatting/BlockMarginCollapse.cpp:
+ (WebCore::Layout::collapsedMarginBottomFromLastChild):
+ (WebCore::Layout::BlockMarginCollapse::isMarginBottomCollapsedWithParent):
+ (WebCore::Layout::BlockMarginCollapse::isMarginTopCollapsedWithParentMarginBottom):
+ (WebCore::Layout::isMarginBottomCollapsedWithParent): Deleted.
+ * layout/blockformatting/BlockMarginCollapse.h:
+ * layout/inlineformatting/InlineFormattingContext.cpp:
+ (WebCore::Layout::InlineFormattingContext::computeInFlowHeight const):
+ * layout/inlineformatting/InlineFormattingContext.h:
+ * layout/layouttree/LayoutBox.cpp:
+ (WebCore::Layout::Box::isReplaced const):
+ * layout/layouttree/LayoutBox.h:
+
2018-05-10 Thibault Saunier <[email protected]>
[GTK] Implement ImageBuffer::toBGRAData
Modified: trunk/Source/WebCore/layout/FormattingContext.cpp (231641 => 231642)
--- trunk/Source/WebCore/layout/FormattingContext.cpp 2018-05-10 16:16:11 UTC (rev 231641)
+++ trunk/Source/WebCore/layout/FormattingContext.cpp 2018-05-10 16:46:54 UTC (rev 231642)
@@ -68,13 +68,13 @@
return computeInFlowWidth(layoutBox, displayBox);
}
-void FormattingContext::computeHeight(const Box& layoutBox, Display::Box& displayBox) const
+void FormattingContext::computeHeight(LayoutContext& layoutContext, const Box& layoutBox, Display::Box& displayBox) const
{
if (layoutBox.isOutOfFlowPositioned())
return computeOutOfFlowHeight(layoutBox, displayBox);
if (layoutBox.isFloatingPositioned())
return computeFloatingHeight(layoutBox, displayBox);
- return computeInFlowHeight(layoutBox, displayBox);
+ return computeInFlowHeight(layoutContext, layoutBox, displayBox);
}
void FormattingContext::computeOutOfFlowWidth(const Box&, Display::Box&) const
Modified: trunk/Source/WebCore/layout/FormattingContext.h (231641 => 231642)
--- trunk/Source/WebCore/layout/FormattingContext.h 2018-05-10 16:16:11 UTC (rev 231641)
+++ trunk/Source/WebCore/layout/FormattingContext.h 2018-05-10 16:46:54 UTC (rev 231642)
@@ -69,7 +69,7 @@
virtual void computeOutOfFlowPosition(const Box&, Display::Box&) const;
virtual void computeWidth(const Box&, Display::Box&) const;
- virtual void computeHeight(const Box&, Display::Box&) const;
+ virtual void computeHeight(LayoutContext&, const Box&, Display::Box&) const;
virtual void computeOutOfFlowWidth(const Box&, Display::Box&) const;
virtual void computeFloatingWidth(const Box&, Display::Box&) const;
@@ -77,7 +77,7 @@
virtual void computeOutOfFlowHeight(const Box&, Display::Box&) const;
virtual void computeFloatingHeight(const Box&, Display::Box&) const;
- virtual void computeInFlowHeight(const Box&, Display::Box&) const = 0;
+ virtual void computeInFlowHeight(LayoutContext&, const Box&, Display::Box&) const = 0;
virtual LayoutUnit marginTop(const Box&) const;
virtual LayoutUnit marginLeft(const Box&) const;
Modified: trunk/Source/WebCore/layout/blockformatting/BlockFormattingContext.cpp (231641 => 231642)
--- trunk/Source/WebCore/layout/blockformatting/BlockFormattingContext.cpp 2018-05-10 16:16:11 UTC (rev 231641)
+++ trunk/Source/WebCore/layout/blockformatting/BlockFormattingContext.cpp 2018-05-10 16:46:54 UTC (rev 231642)
@@ -94,7 +94,7 @@
auto& layoutBox = layoutPair->layoutBox;
auto& displayBox = layoutPair->displayBox;
- computeHeight(layoutBox, displayBox);
+ computeHeight(layoutContext, layoutBox, displayBox);
// Adjust position now that we have all the previous floats placed in this context -if needed.
floatingContext.computePosition(layoutBox, displayBox);
if (!is<Container>(layoutBox))
@@ -147,8 +147,13 @@
{
}
-void BlockFormattingContext::computeInFlowHeight(const Box&, Display::Box&) const
+void BlockFormattingContext::computeInFlowHeight(LayoutContext& layoutContext, const Box& layoutBox, Display::Box& displayBox) const
{
+ if (!layoutBox.isReplaced()) {
+ computeInFlowNonReplacedHeight(layoutContext, layoutBox, displayBox);
+ return;
+ }
+ ASSERT_NOT_REACHED();
}
LayoutUnit BlockFormattingContext::marginTop(const Box& layoutBox) const
@@ -161,7 +166,62 @@
return BlockMarginCollapse::marginBottom(layoutBox);
}
+void BlockFormattingContext::computeInFlowNonReplacedHeight(LayoutContext& layoutContext, const Box& layoutBox, Display::Box& displayBox) const
+{
+ // https://www.w3.org/TR/CSS22/visudet.html
+ // If 'height' is 'auto', the height depends on whether the element has any block-level children and whether it has padding or borders:
+ // The element's height is the distance from its top content edge to the first applicable of the following:
+ // 1. the bottom edge of the last line box, if the box establishes a inline formatting context with one or more lines
+ // 2. the bottom edge of the bottom (possibly collapsed) margin of its last in-flow child, if the child's bottom margin
+ // does not collapse with the element's bottom margin
+ // 3. the bottom border edge of the last in-flow child whose top margin doesn't collapse with the element's bottom margin
+ // 4. zero, otherwise
+ // Only children in the normal flow are taken into account (i.e., floating boxes and absolutely positioned boxes are ignored,
+ // and relatively positioned boxes are considered without their offset). Note that the child box may be an anonymous block box.
+ if (!layoutBox.style().logicalHeight().isAuto()) {
+ // FIXME: Only fixed values yet.
+ displayBox.setHeight(layoutBox.style().logicalHeight().value());
+ return;
+ }
+
+ if (!is<Container>(layoutBox) || !downcast<Container>(layoutBox).hasInFlowChild()) {
+ displayBox.setHeight(0);
+ return;
+ }
+
+ // 1. the bottom edge of the last line box, if the box establishes a inline formatting context with one or more lines
+ if (layoutBox.establishesInlineFormattingContext()) {
+ // height = lastLineBox().bottom();
+ displayBox.setHeight(0);
+ return;
+ }
+
+ // 2. the bottom edge of the bottom (possibly collapsed) margin of its last in-flow child, if the child's bottom margin...
+ auto* lastInFlowChild = downcast<Container>(layoutBox).lastInFlowChild();
+ ASSERT(lastInFlowChild);
+ if (!BlockMarginCollapse::isMarginBottomCollapsedWithParent(*lastInFlowChild)) {
+ auto* lastInFlowDisplayBox = layoutContext.displayBoxForLayoutBox(*lastInFlowChild);
+ ASSERT(lastInFlowDisplayBox);
+ displayBox.setHeight(lastInFlowDisplayBox->bottom() + lastInFlowDisplayBox->marginBottom());
+ return;
+ }
+
+ // 3. the bottom border edge of the last in-flow child whose top margin doesn't collapse with the element's bottom margin
+ auto* inFlowChild = lastInFlowChild;
+ while (inFlowChild && BlockMarginCollapse::isMarginTopCollapsedWithParentMarginBottom(*inFlowChild))
+ inFlowChild = inFlowChild->previousInFlowSibling();
+ if (inFlowChild) {
+ auto* inFlowDisplayBox = layoutContext.displayBoxForLayoutBox(*inFlowChild);
+ ASSERT(inFlowDisplayBox);
+ displayBox.setHeight(inFlowDisplayBox->top() + inFlowDisplayBox->borderBox().height());
+ return;
+ }
+
+ // 4. zero, otherwise
+ displayBox.setHeight(0);
}
+
}
+}
#endif
Modified: trunk/Source/WebCore/layout/blockformatting/BlockFormattingContext.h (231641 => 231642)
--- trunk/Source/WebCore/layout/blockformatting/BlockFormattingContext.h 2018-05-10 16:16:11 UTC (rev 231641)
+++ trunk/Source/WebCore/layout/blockformatting/BlockFormattingContext.h 2018-05-10 16:46:54 UTC (rev 231642)
@@ -49,10 +49,11 @@
std::unique_ptr<FormattingState> createFormattingState(Ref<FloatingState>&&) const override;
Ref<FloatingState> createOrFindFloatingState(LayoutContext&) const override;
-protected:
+private:
void computeStaticPosition(LayoutContext&, const Box&, Display::Box&) const override;
void computeInFlowWidth(const Box&, Display::Box&) const override;
- void computeInFlowHeight(const Box&, Display::Box&) const override;
+ void computeInFlowHeight(LayoutContext&, const Box&, Display::Box&) const override;
+ void computeInFlowNonReplacedHeight(LayoutContext&, const Box&, Display::Box&) const;
LayoutUnit marginTop(const Box&) const override;
LayoutUnit marginBottom(const Box&) const override;
Modified: trunk/Source/WebCore/layout/blockformatting/BlockMarginCollapse.cpp (231641 => 231642)
--- trunk/Source/WebCore/layout/blockformatting/BlockMarginCollapse.cpp 2018-05-10 16:16:11 UTC (rev 231641)
+++ trunk/Source/WebCore/layout/blockformatting/BlockMarginCollapse.cpp 2018-05-10 16:46:54 UTC (rev 231642)
@@ -114,42 +114,6 @@
return true;
}
-static bool isMarginBottomCollapsedWithParent(const Box& layoutBox)
-{
- // last inflow box to parent.
- // https://www.w3.org/TR/CSS21/box.html#collapsing-margins
- if (layoutBox.isAnonymous())
- return false;
-
- if (layoutBox.isFloatingOrOutOfFlowPositioned())
- return false;
-
- // We never margin collapse the initial containing block.
- ASSERT(layoutBox.parent());
- auto& parent = *layoutBox.parent();
- // Is this the last inlflow child?
- if (parent.lastInFlowChild() != &layoutBox)
- return false;
-
- if (parent.establishesBlockFormattingContext())
- return false;
-
- // Margins of the root element's box do not collapse.
- if (parent.isInitialContainingBlock())
- return false;
-
- if (!parent.style().borderTop().nonZero())
- return false;
-
- if (!parent.style().paddingTop().isZero())
- return false;
-
- if (!parent.style().height().isAuto())
- return false;
-
- return true;
-}
-
static LayoutUnit collapsedMarginTopFromFirstChild(const Box& layoutBox)
{
// Check if the first child collapses its margin top.
@@ -171,7 +135,7 @@
return 0;
auto& lastInFlowChild = *downcast<Container>(layoutBox).lastInFlowChild();
- if (!isMarginBottomCollapsedWithParent(lastInFlowChild))
+ if (!BlockMarginCollapse::isMarginBottomCollapsedWithParent(lastInFlowChild))
return 0;
// Collect collapsed margin bottom recursively.
@@ -249,6 +213,47 @@
return nonCollapsedMarginBottom(layoutBox);
}
+bool BlockMarginCollapse::isMarginBottomCollapsedWithParent(const Box& layoutBox)
+{
+ // last inflow box to parent.
+ // https://www.w3.org/TR/CSS21/box.html#collapsing-margins
+ if (layoutBox.isAnonymous())
+ return false;
+
+ if (layoutBox.isFloatingOrOutOfFlowPositioned())
+ return false;
+
+ // We never margin collapse the initial containing block.
+ ASSERT(layoutBox.parent());
+ auto& parent = *layoutBox.parent();
+ // Is this the last inlflow child?
+ if (parent.lastInFlowChild() != &layoutBox)
+ return false;
+
+ if (parent.establishesBlockFormattingContext())
+ return false;
+
+ // Margins of the root element's box do not collapse.
+ if (parent.isInitialContainingBlock())
+ return false;
+
+ if (!parent.style().borderTop().nonZero())
+ return false;
+
+ if (!parent.style().paddingTop().isZero())
+ return false;
+
+ if (!parent.style().height().isAuto())
+ return false;
+
+ return true;
}
+
+bool BlockMarginCollapse::isMarginTopCollapsedWithParentMarginBottom(const Box&)
+{
+ return false;
}
+
+}
+}
#endif
Modified: trunk/Source/WebCore/layout/blockformatting/BlockMarginCollapse.h (231641 => 231642)
--- trunk/Source/WebCore/layout/blockformatting/BlockMarginCollapse.h 2018-05-10 16:16:11 UTC (rev 231641)
+++ trunk/Source/WebCore/layout/blockformatting/BlockMarginCollapse.h 2018-05-10 16:46:54 UTC (rev 231642)
@@ -42,6 +42,9 @@
public:
static LayoutUnit marginTop(const Box&);
static LayoutUnit marginBottom(const Box&);
+
+ static bool isMarginBottomCollapsedWithParent(const Box&);
+ static bool isMarginTopCollapsedWithParentMarginBottom(const Box&);
};
}
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp (231641 => 231642)
--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp 2018-05-10 16:16:11 UTC (rev 231641)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp 2018-05-10 16:46:54 UTC (rev 231642)
@@ -70,7 +70,7 @@
{
}
-void InlineFormattingContext::computeInFlowHeight(const Box&, Display::Box&) const
+void InlineFormattingContext::computeInFlowHeight(LayoutContext&, const Box&, Display::Box&) const
{
}
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h (231641 => 231642)
--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h 2018-05-10 16:16:11 UTC (rev 231641)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h 2018-05-10 16:46:54 UTC (rev 231642)
@@ -49,7 +49,7 @@
private:
void computeInFlowWidth(const Box&, Display::Box&) const override;
- void computeInFlowHeight(const Box&, Display::Box&) const override;
+ void computeInFlowHeight(LayoutContext&, const Box&, Display::Box&) const override;
};
Modified: trunk/Source/WebCore/layout/layouttree/LayoutBox.cpp (231641 => 231642)
--- trunk/Source/WebCore/layout/layouttree/LayoutBox.cpp 2018-05-10 16:16:11 UTC (rev 231641)
+++ trunk/Source/WebCore/layout/layouttree/LayoutBox.cpp 2018-05-10 16:46:54 UTC (rev 231642)
@@ -179,6 +179,12 @@
return !parent();
}
+bool Box::isReplaced() const
+{
+ // HTMLAudioElement || HTMLCanvasElement || HTMLEmbedElement || HTMLIFrameElement || HTMLImageElement || HTMLInputElement || HTMLObjectElement || HTMLVideoElement
+ return false;
+}
+
const Box* Box::nextInFlowSibling() const
{
if (auto* nextSibling = this->nextSibling()) {
Modified: trunk/Source/WebCore/layout/layouttree/LayoutBox.h (231641 => 231642)
--- trunk/Source/WebCore/layout/layouttree/LayoutBox.h 2018-05-10 16:16:11 UTC (rev 231641)
+++ trunk/Source/WebCore/layout/layouttree/LayoutBox.h 2018-05-10 16:46:54 UTC (rev 231642)
@@ -72,6 +72,7 @@
bool isInlineBlockBox() const;
bool isBlockContainerBox() const;
bool isInitialContainingBlock() const;
+ bool isReplaced() const;
const Container* parent() const { return m_parent; }
const Box* nextSibling() const { return m_nextSibling; }