Diff
Modified: trunk/Source/WebCore/ChangeLog (248261 => 248262)
--- trunk/Source/WebCore/ChangeLog 2019-08-04 03:24:27 UTC (rev 248261)
+++ trunk/Source/WebCore/ChangeLog 2019-08-04 10:16:06 UTC (rev 248262)
@@ -1,3 +1,80 @@
+2019-08-04 Zalan Bujtas <[email protected]>
+
+ [LFC] Cleanup preferred width computation
+ https://bugs.webkit.org/show_bug.cgi?id=200426
+ <rdar://problem/53912607>
+
+ Reviewed by Antti Koivisto.
+
+ The intrinsic width for a formatting root box has 2 sets of values now. One set(min/max) is stored in the established formatting context's state
+ while the other is in the formatting context's state where the box lives.
+
+ <div style="position: absolute"><div style="float: left; border: 1px solid green">foobar</div></div>
+
+ The float box participates in the formatting context established by the absolutely position box, but it also establishes an inline formatting context.
+ The min/max width pair in the established context is the width of the "foobar" (same value for min/max). This set is stored in the inline formatting state.
+ However the float box has horizontal border so the "final" min/max width pair is expanded by this border value and stored in the formatting state where
+ the box lives (which is different from the one it establishes).
+
+ This and the "remove the formatting context type classes from the tree" changes open up interesting optimization opportunities.
+ Here is a very simple case:
+ <div style="display: inline-block; width: auto;">
+ <div style="float: left">some text</div>
+ <div style="float: left">some super long .... text</div>
+ <div></div>
+ </div>
+ In order to lay out this content properly, we
+ 1. Compute the min/max width of the first float (expensive text measuring)
+ 2. Compute the min/max width of the second float (some more expensive text measuring)
+ 3. Compute the min/max width of the inline-block (that is pretty much the 2 float's min/max)
+ 4. Lay out the 2 floats, the empty div and the inline-block using these min/max width pairs.
+
+ Now if the inline-block box's display value is changed to "block" and the positioning is to absolute (style="display: box; position: absolute;")
+ we currently(on trunk) tear down the render tree, build a new one and run all the steps again from #1 to #4.
+
+ In LFC, we start with the following layout tree
+ <container> -> block formatting context
+ <container> -> inline formatting context
+ <anonymous inline box>
+ <container> -> inline formatting context
+ <anonymous inline box>
+ <container> -> inline formatting context
+ and when the style change happens, we don't need to tear down the tree at all. Not only that, but since every formatting contexts stay the same
+ we can just reuse their states and actually skip all the steps (even the positioning since the absolutely positioned container has static top/bottom/left/right).
+
+ Surprisingly the final layout produces the exact same "display boxes" as the original layout.
+
+ * layout/FormattingContext.h:
+ (WebCore::Layout::FormattingContext::IntrinsicWidthConstraints::expand):
+ * layout/FormattingContextGeometry.cpp:
+ (WebCore::Layout::FormattingContext::Geometry::shrinkToFitWidth):
+ * layout/FormattingState.h:
+ (WebCore::Layout::FormattingState::setIntrinsicWidthConstraints):
+ (WebCore::Layout::FormattingState::intrinsicWidthConstraints const):
+ (WebCore::Layout::FormattingState::setIntrinsicWidthConstraintsForBox):
+ (WebCore::Layout::FormattingState::clearIntrinsicWidthConstraints):
+ (WebCore::Layout::FormattingState::intrinsicWidthConstraintsForBox const):
+ * layout/blockformatting/BlockFormattingContext.cpp:
+ (WebCore::Layout::BlockFormattingContext::computedIntrinsicWidthConstraints const):
+ (WebCore::Layout::BlockFormattingContext::computeIntrinsicWidthConstraints const): Deleted.
+ * layout/blockformatting/BlockFormattingContext.h:
+ * layout/blockformatting/BlockFormattingContextGeometry.cpp:
+ (WebCore::Layout::BlockFormattingContext::Geometry::intrinsicWidthConstraints):
+ (WebCore::Layout::BlockFormattingContext::Geometry::intrinsicWidthConstraintsNeedChildrenWidth): Deleted.
+ * layout/displaytree/DisplayBox.h:
+ (WebCore::Display::Box::horizontalMarginBorderAndPadding const):
+ * layout/inlineformatting/InlineFormattingContext.cpp:
+ (WebCore::Layout::nextInPreOrder):
+ (WebCore::Layout::InlineFormattingContext::computedIntrinsicWidthConstraints const):
+ (WebCore::Layout::InlineFormattingContext::computeIntrinsicWidthForFormattingRoot const):
+ (WebCore::Layout::InlineFormattingContext::computeIntrinsicWidthConstraints const): Deleted.
+ (WebCore::Layout::InlineFormattingContext::computeIntrinsicWidthForFloatBox const): Deleted.
+ (WebCore::Layout::InlineFormattingContext::computeIntrinsicWidthForInlineBlock const): Deleted.
+ * layout/inlineformatting/InlineFormattingContext.h:
+ * layout/tableformatting/TableFormattingContext.cpp:
+ (WebCore::Layout::TableFormattingContext::computedIntrinsicWidthConstraints const):
+ * layout/tableformatting/TableFormattingContext.h:
+
2019-08-03 Devin Rousso <[email protected]>
Web Inspector: DOM: add a special breakpoint for "All Events"
Modified: trunk/Source/WebCore/layout/FormattingContext.h (248261 => 248262)
--- trunk/Source/WebCore/layout/FormattingContext.h 2019-08-04 03:24:27 UTC (rev 248261)
+++ trunk/Source/WebCore/layout/FormattingContext.h 2019-08-04 10:16:06 UTC (rev 248262)
@@ -53,10 +53,12 @@
void layoutOutOfFlowDescendants(const Box&) const;
struct IntrinsicWidthConstraints {
+ void expand(LayoutUnit horizontalValue);
+
LayoutUnit minimum;
LayoutUnit maximum;
};
- virtual void computeIntrinsicWidthConstraints() const = 0;
+ virtual IntrinsicWidthConstraints computedIntrinsicWidthConstraints() const = 0;
static Display::Box mapBoxToAncestor(const LayoutState&, const Box&, const Container& ancestor);
static LayoutUnit mapTopToAncestor(const LayoutState&, const Box&, const Container& ancestor);
@@ -139,6 +141,12 @@
FormattingState& m_formattingState;
};
+inline void FormattingContext::IntrinsicWidthConstraints::expand(LayoutUnit horizontalValue)
+{
+ minimum += horizontalValue;
+ maximum += horizontalValue;
}
+
}
+}
#endif
Modified: trunk/Source/WebCore/layout/FormattingContextGeometry.cpp (248261 => 248262)
--- trunk/Source/WebCore/layout/FormattingContextGeometry.cpp 2019-08-04 03:24:27 UTC (rev 248261)
+++ trunk/Source/WebCore/layout/FormattingContextGeometry.cpp 2019-08-04 10:16:06 UTC (rev 248262)
@@ -250,12 +250,10 @@
// 'padding-left', 'padding-right', 'border-right-width', 'margin-right', and the widths of any relevant scroll bars.
// Then the shrink-to-fit width is: min(max(preferred minimum width, available width), preferred width).
- auto& formattingStateForRoot = layoutState.formattingStateForBox(formattingRoot);
- auto intrinsicWidthConstraints = formattingStateForRoot.intrinsicWidthConstraints(formattingRoot);
- if (!intrinsicWidthConstraints) {
- layoutState.createFormattingContext(formattingRoot)->computeIntrinsicWidthConstraints();
- intrinsicWidthConstraints = formattingStateForRoot.intrinsicWidthConstraints(formattingRoot);
- }
+ auto& formattingStateForRoot = layoutState.createFormattingStateForFormattingRootIfNeeded(formattingRoot);
+ auto intrinsicWidthConstraints = formattingStateForRoot.intrinsicWidthConstraints();
+ if (!intrinsicWidthConstraints)
+ intrinsicWidthConstraints = layoutState.createFormattingContext(formattingRoot)->computedIntrinsicWidthConstraints();
auto availableWidth = *usedValues.containingBlockWidth;
return std::min(std::max(intrinsicWidthConstraints->minimum, availableWidth), intrinsicWidthConstraints->maximum);
}
Modified: trunk/Source/WebCore/layout/FormattingState.h (248261 => 248262)
--- trunk/Source/WebCore/layout/FormattingState.h 2019-08-04 03:24:27 UTC (rev 248261)
+++ trunk/Source/WebCore/layout/FormattingState.h 2019-08-04 10:16:06 UTC (rev 248262)
@@ -51,10 +51,13 @@
void markNeedsLayout(const Box&, StyleDiff);
bool needsLayout(const Box&);
- void setIntrinsicWidthConstraints(const Box&, FormattingContext::IntrinsicWidthConstraints);
+ void setIntrinsicWidthConstraintsForBox(const Box&, FormattingContext::IntrinsicWidthConstraints);
+ Optional<FormattingContext::IntrinsicWidthConstraints> intrinsicWidthConstraintsForBox(const Box&) const;
void clearIntrinsicWidthConstraints(const Box&);
- Optional<FormattingContext::IntrinsicWidthConstraints> intrinsicWidthConstraints(const Box&) const;
+ void setIntrinsicWidthConstraints(FormattingContext::IntrinsicWidthConstraints intrinsicWidthConstraints) { m_intrinsicWidthConstraints = intrinsicWidthConstraints; }
+ Optional<FormattingContext::IntrinsicWidthConstraints> intrinsicWidthConstraints() const { return m_intrinsicWidthConstraints; }
+
bool isBlockFormattingState() const { return m_type == Type::Block; }
bool isInlineFormattingState() const { return m_type == Type::Inline; }
bool isTableFormattingState() const { return m_type == Type::Table; }
@@ -68,27 +71,29 @@
private:
LayoutState& m_layoutState;
Ref<FloatingState> m_floatingState;
- HashMap<const Box*, FormattingContext::IntrinsicWidthConstraints> m_intrinsicWidthConstraints;
+ HashMap<const Box*, FormattingContext::IntrinsicWidthConstraints> m_intrinsicWidthConstraintsForBoxes;
+ Optional<FormattingContext::IntrinsicWidthConstraints> m_intrinsicWidthConstraints;
Type m_type;
};
-inline void FormattingState::setIntrinsicWidthConstraints(const Box& layoutBox, FormattingContext::IntrinsicWidthConstraints intrinsicWidthConstraints)
+inline void FormattingState::setIntrinsicWidthConstraintsForBox(const Box& layoutBox, FormattingContext::IntrinsicWidthConstraints intrinsicWidthConstraints)
{
- ASSERT(!m_intrinsicWidthConstraints.contains(&layoutBox));
+ ASSERT(!m_intrinsicWidthConstraintsForBoxes.contains(&layoutBox));
ASSERT(&m_layoutState.formattingStateForBox(layoutBox) == this);
- m_intrinsicWidthConstraints.set(&layoutBox, intrinsicWidthConstraints);
+ m_intrinsicWidthConstraintsForBoxes.set(&layoutBox, intrinsicWidthConstraints);
}
inline void FormattingState::clearIntrinsicWidthConstraints(const Box& layoutBox)
{
- m_intrinsicWidthConstraints.remove(&layoutBox);
+ m_intrinsicWidthConstraints = { };
+ m_intrinsicWidthConstraintsForBoxes.remove(&layoutBox);
}
-inline Optional<FormattingContext::IntrinsicWidthConstraints> FormattingState::intrinsicWidthConstraints(const Box& layoutBox) const
+inline Optional<FormattingContext::IntrinsicWidthConstraints> FormattingState::intrinsicWidthConstraintsForBox(const Box& layoutBox) const
{
ASSERT(&m_layoutState.formattingStateForBox(layoutBox) == this);
- auto iterator = m_intrinsicWidthConstraints.find(&layoutBox);
- if (iterator == m_intrinsicWidthConstraints.end())
+ auto iterator = m_intrinsicWidthConstraintsForBoxes.find(&layoutBox);
+ if (iterator == m_intrinsicWidthConstraintsForBoxes.end())
return { };
return iterator->value;
}
Modified: trunk/Source/WebCore/layout/blockformatting/BlockFormattingContext.cpp (248261 => 248262)
--- trunk/Source/WebCore/layout/blockformatting/BlockFormattingContext.cpp 2019-08-04 03:24:27 UTC (rev 248261)
+++ trunk/Source/WebCore/layout/blockformatting/BlockFormattingContext.cpp 2019-08-04 10:16:06 UTC (rev 248262)
@@ -452,17 +452,13 @@
MarginCollapse::updateMarginAfterForPreviousSibling(layoutState, layoutBox);
}
-void BlockFormattingContext::computeIntrinsicWidthConstraints() const
+FormattingContext::IntrinsicWidthConstraints BlockFormattingContext::computedIntrinsicWidthConstraints() const
{
auto& layoutState = this->layoutState();
auto& formattingRoot = root();
- auto& formattingStateForRoot = layoutState.formattingStateForBox(formattingRoot);
- ASSERT(!formattingStateForRoot.intrinsicWidthConstraints(formattingRoot));
+ auto& formattingState = this->formattingState();
+ ASSERT(!formattingState.intrinsicWidthConstraints());
- // Can we just compute them without checking the children?
- if (!Geometry::intrinsicWidthConstraintsNeedChildrenWidth(formattingRoot))
- return formattingStateForRoot.setIntrinsicWidthConstraints(formattingRoot, Geometry::intrinsicWidthConstraints(layoutState, formattingRoot));
-
// Visit the in-flow descendants and compute their min/max intrinsic width if needed.
// 1. Go all the way down to the leaf node
// 2. Check if actually need to visit all the boxes as we traverse down (already computed, container's min/max does not depend on descendants etc)
@@ -469,50 +465,38 @@
// 3. As we climb back on the tree, compute min/max intrinsic width
// (Any subtrees with new formatting contexts need to layout synchronously)
Vector<const Box*> queue;
- ASSERT(is<Container>(formattingRoot));
- if (auto* firstChild = downcast<Container>(formattingRoot).firstInFlowOrFloatingChild())
- queue.append(firstChild);
+ if (is<Container>(formattingRoot) && downcast<Container>(formattingRoot).hasInFlowOrFloatingChild())
+ queue.append(downcast<Container>(formattingRoot).firstInFlowOrFloatingChild());
- auto& formattingState = this->formattingState();
+ IntrinsicWidthConstraints constraints;
while (!queue.isEmpty()) {
while (true) {
- auto& childBox = *queue.last();
- auto childIntrinsicWidthConstraints = formattingState.intrinsicWidthConstraints(childBox);
- auto skipDescendants = childIntrinsicWidthConstraints || !Geometry::intrinsicWidthConstraintsNeedChildrenWidth(childBox) || childBox.establishesFormattingContext();
-
- if (skipDescendants) {
- if (!childIntrinsicWidthConstraints) {
- if (!Geometry::intrinsicWidthConstraintsNeedChildrenWidth(childBox))
- formattingState.setIntrinsicWidthConstraints(childBox, Geometry::intrinsicWidthConstraints(layoutState, childBox));
- else if (childBox.establishesFormattingContext())
- layoutState.createFormattingContext(childBox)->computeIntrinsicWidthConstraints();
- else
- ASSERT_NOT_REACHED();
- }
- queue.removeLast();
- if (!childBox.nextInFlowOrFloatingSibling())
- break;
- queue.append(childBox.nextInFlowOrFloatingSibling());
- // Skip descendants
- continue;
- }
- if (!is<Container>(childBox) || !downcast<Container>(childBox).hasInFlowOrFloatingChild())
+ auto& layoutBox = *queue.last();
+ auto hasInFlowOrFloatingChild = is<Container>(layoutBox) && downcast<Container>(layoutBox).hasInFlowOrFloatingChild();
+ auto skipDescendants = formattingState.intrinsicWidthConstraintsForBox(layoutBox) || !hasInFlowOrFloatingChild || layoutBox.establishesFormattingContext() || layoutBox.style().width().isFixed();
+ if (skipDescendants)
break;
- queue.append(downcast<Container>(childBox).firstInFlowOrFloatingChild());
+ queue.append(downcast<Container>(layoutBox).firstInFlowOrFloatingChild());
}
-
- // Compute min/max intrinsic width bottom up.
+ // Compute min/max intrinsic width bottom up if needed.
while (!queue.isEmpty()) {
- auto& childBox = *queue.takeLast();
- formattingState.setIntrinsicWidthConstraints(childBox, Geometry::intrinsicWidthConstraints(layoutState, childBox));
+ auto& layoutBox = *queue.takeLast();
+ auto desdendantConstraints = formattingState.intrinsicWidthConstraintsForBox(layoutBox);
+ if (!desdendantConstraints) {
+ desdendantConstraints = Geometry::intrinsicWidthConstraints(layoutState, layoutBox);
+ formattingState.setIntrinsicWidthConstraintsForBox(layoutBox, *desdendantConstraints);
+ }
+ constraints.minimum = std::max(constraints.minimum, desdendantConstraints->minimum);
+ constraints.maximum = std::max(constraints.maximum, desdendantConstraints->maximum);
// Move over to the next sibling or take the next box in the queue.
- if (auto* nextSibling = childBox.nextInFlowOrFloatingSibling()) {
+ if (auto* nextSibling = layoutBox.nextInFlowOrFloatingSibling()) {
queue.append(nextSibling);
break;
}
}
}
- formattingStateForRoot.setIntrinsicWidthConstraints(formattingRoot, Geometry::intrinsicWidthConstraints(layoutState, formattingRoot));
+ formattingState.setIntrinsicWidthConstraints(constraints);
+ return constraints;
}
LayoutUnit BlockFormattingContext::verticalPositionWithMargin(const Box& layoutBox, const UsedVerticalMargin& verticalMargin) const
Modified: trunk/Source/WebCore/layout/blockformatting/BlockFormattingContext.h (248261 => 248262)
--- trunk/Source/WebCore/layout/blockformatting/BlockFormattingContext.h 2019-08-04 03:24:27 UTC (rev 248261)
+++ trunk/Source/WebCore/layout/blockformatting/BlockFormattingContext.h 2019-08-04 10:16:06 UTC (rev 248262)
@@ -69,7 +69,7 @@
void computeEstimatedVerticalPositionForFormattingRoot(const Box&) const;
void computeEstimatedVerticalPositionForFloatClear(const FloatingContext&, const Box&) const;
- void computeIntrinsicWidthConstraints() const override;
+ IntrinsicWidthConstraints computedIntrinsicWidthConstraints() const override;
LayoutUnit verticalPositionWithMargin(const Box&, const UsedVerticalMargin&) const;
// This class implements positioning and sizing for boxes participating in a block formatting context.
@@ -82,8 +82,7 @@
static LayoutUnit staticVerticalPosition(const LayoutState&, const Box&);
static LayoutUnit staticHorizontalPosition(const LayoutState&, const Box&);
- static bool intrinsicWidthConstraintsNeedChildrenWidth(const Box&);
- static IntrinsicWidthConstraints intrinsicWidthConstraints(const LayoutState&, const Box&);
+ static IntrinsicWidthConstraints intrinsicWidthConstraints(LayoutState&, const Box&);
private:
static HeightAndMargin inFlowNonReplacedHeightAndMargin(const LayoutState&, const Box&, UsedVerticalValues);
Modified: trunk/Source/WebCore/layout/blockformatting/BlockFormattingContextGeometry.cpp (248261 => 248262)
--- trunk/Source/WebCore/layout/blockformatting/BlockFormattingContextGeometry.cpp 2019-08-04 03:24:27 UTC (rev 248261)
+++ trunk/Source/WebCore/layout/blockformatting/BlockFormattingContextGeometry.cpp 2019-08-04 10:16:06 UTC (rev 248262)
@@ -285,15 +285,18 @@
return inFlowReplacedWidthAndMargin(layoutState, layoutBox, usedValues);
}
-bool BlockFormattingContext::Geometry::intrinsicWidthConstraintsNeedChildrenWidth(const Box& layoutBox)
+FormattingContext::IntrinsicWidthConstraints BlockFormattingContext::Geometry::intrinsicWidthConstraints(LayoutState& layoutState, const Box& layoutBox)
{
- if (!is<Container>(layoutBox) || !downcast<Container>(layoutBox).hasInFlowOrFloatingChild())
- return false;
- return layoutBox.style().width().isAuto();
-}
+ auto fixedMarginBorderAndPadding = [&](auto& layoutBox) {
+ auto& style = layoutBox.style();
+ return fixedValue(style.marginStart()).valueOr(0)
+ + LayoutUnit { style.borderLeftWidth() }
+ + fixedValue(style.paddingLeft()).valueOr(0)
+ + fixedValue(style.paddingRight()).valueOr(0)
+ + LayoutUnit { style.borderRightWidth() }
+ + fixedValue(style.marginEnd()).valueOr(0);
+ };
-FormattingContext::IntrinsicWidthConstraints BlockFormattingContext::Geometry::intrinsicWidthConstraints(const LayoutState& layoutState, const Box& layoutBox)
-{
auto computedIntrinsicWidthConstraints = [&]() -> IntrinsicWidthConstraints {
auto& style = layoutBox.style();
if (auto width = fixedValue(style.logicalWidth()))
@@ -311,32 +314,31 @@
return { };
}
- if (!is<Container>(layoutBox))
+ if (layoutBox.establishesFormattingContext())
+ return layoutState.createFormattingContext(layoutBox)->computedIntrinsicWidthConstraints();
+
+ if (!is<Container>(layoutBox) || !downcast<Container>(layoutBox).hasInFlowOrFloatingChild())
return { };
auto intrinsicWidthConstraints = IntrinsicWidthConstraints { };
+ auto& formattingState = layoutState.formattingStateForBox(layoutBox);
for (auto& child : childrenOfType<Box>(downcast<Container>(layoutBox))) {
if (child.isOutOfFlowPositioned())
continue;
- const auto& formattingState = layoutState.formattingStateForBox(child);
- ASSERT(formattingState.isBlockFormattingState());
- auto childIntrinsicWidthConstraints = formattingState.intrinsicWidthConstraints(child);
+ auto childIntrinsicWidthConstraints = formattingState.intrinsicWidthConstraintsForBox(child);
ASSERT(childIntrinsicWidthConstraints);
- auto& childStyle = child.style();
- auto marginBorderAndPadding = fixedValue(childStyle.marginStart()).valueOr(0)
- + LayoutUnit { childStyle.borderLeftWidth() }
- + fixedValue(childStyle.paddingLeft()).valueOr(0)
- + fixedValue(childStyle.paddingRight()).valueOr(0)
- + LayoutUnit { childStyle.borderRightWidth() }
- + fixedValue(childStyle.marginEnd()).valueOr(0);
+ // FIXME Check for box-sizing: border-box;
+ auto marginBorderAndPadding = fixedMarginBorderAndPadding(child);
intrinsicWidthConstraints.minimum = std::max(intrinsicWidthConstraints.minimum, childIntrinsicWidthConstraints->minimum + marginBorderAndPadding);
intrinsicWidthConstraints.maximum = std::max(intrinsicWidthConstraints.maximum, childIntrinsicWidthConstraints->maximum + marginBorderAndPadding);
}
return intrinsicWidthConstraints;
};
-
- return constrainByMinMaxWidth(layoutBox, computedIntrinsicWidthConstraints());
+ // FIXME Check for box-sizing: border-box;
+ auto intrinsicWidthConstraints = constrainByMinMaxWidth(layoutBox, computedIntrinsicWidthConstraints());
+ intrinsicWidthConstraints.expand(fixedMarginBorderAndPadding(layoutBox));
+ return intrinsicWidthConstraints;
}
}
Modified: trunk/Source/WebCore/layout/displaytree/DisplayBox.h (248261 => 248262)
--- trunk/Source/WebCore/layout/displaytree/DisplayBox.h 2019-08-04 03:24:27 UTC (rev 248261)
+++ trunk/Source/WebCore/layout/displaytree/DisplayBox.h 2019-08-04 10:16:06 UTC (rev 248262)
@@ -124,6 +124,8 @@
LayoutUnit marginBoxHeight() const { return marginBefore() + borderBoxHeight() + marginAfter(); }
LayoutUnit marginBoxWidth() const { return marginStart() + borderBoxWidth() + marginEnd(); }
+ LayoutUnit horizontalMarginBorderAndPadding() const { return marginStart() + horizontalBorder() + horizontalPadding().valueOr(0) + marginEnd(); }
+
Rect marginBox() const;
Rect nonCollapsedMarginBox() const;
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp (248261 => 248262)
--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp 2019-08-04 03:24:27 UTC (rev 248261)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp 2019-08-04 10:16:06 UTC (rev 248262)
@@ -49,13 +49,13 @@
{
}
-static inline const Box* nextInPreOrder(const Box& layoutBox, const Container& root)
+static inline const Box* nextInPreOrder(const Box& layoutBox, const Container& stayWithin)
{
const Box* nextInPreOrder = nullptr;
if (!layoutBox.establishesFormattingContext() && is<Container>(layoutBox) && downcast<Container>(layoutBox).hasInFlowOrFloatingChild())
return downcast<Container>(layoutBox).firstInFlowOrFloatingChild();
- for (nextInPreOrder = &layoutBox; nextInPreOrder && nextInPreOrder != &root; nextInPreOrder = nextInPreOrder->parent()) {
+ for (nextInPreOrder = &layoutBox; nextInPreOrder && nextInPreOrder != &stayWithin; nextInPreOrder = nextInPreOrder->parent()) {
if (auto* nextSibling = nextInPreOrder->nextInFlowOrFloatingSibling())
return nextSibling;
}
@@ -99,18 +99,18 @@
LOG_WITH_STREAM(FormattingContextLayout, stream << "[End] -> inline formatting context -> formatting root(" << &root << ")");
}
-void InlineFormattingContext::computeIntrinsicWidthConstraints() const
+FormattingContext::IntrinsicWidthConstraints InlineFormattingContext::computedIntrinsicWidthConstraints() const
{
auto& layoutState = this->layoutState();
- ASSERT(!layoutState.formattingStateForBox(root()).intrinsicWidthConstraints(root()));
+ ASSERT(!formattingState().intrinsicWidthConstraints());
- ASSERT(is<Container>(root()));
- auto& root = downcast<Container>(this->root());
- if (!root.hasInFlowOrFloatingChild()) {
- layoutState.formattingStateForBox(root).setIntrinsicWidthConstraints(root, Geometry::constrainByMinMaxWidth(root, { 0, 0 }));
- return;
+ if (!is<Container>(root()) || !downcast<Container>(root()).hasInFlowOrFloatingChild()) {
+ auto constraints = Geometry::constrainByMinMaxWidth(root(), { });
+ formattingState().setIntrinsicWidthConstraints(constraints);
+ return constraints;
}
+ auto& root = downcast<Container>(this->root());
Vector<const Box*> formattingContextRootList;
auto usedValues = UsedHorizontalValues { };
auto* layoutBox = root.firstInFlowOrFloatingChild();
@@ -117,16 +117,11 @@
while (layoutBox) {
if (layoutBox->establishesFormattingContext()) {
formattingContextRootList.append(layoutBox);
- if (layoutBox->isFloatingPositioned())
- computeIntrinsicWidthForFloatBox(*layoutBox);
- else if (layoutBox->isInlineBlockBox())
- computeIntrinsicWidthForInlineBlock(*layoutBox);
- else
- ASSERT_NOT_REACHED();
+ computeIntrinsicWidthForFormattingRoot(*layoutBox);
} else if (layoutBox->isReplaced() || is<Container>(*layoutBox)) {
computeBorderAndPadding(*layoutBox, usedValues);
// inline-block and replaced.
- auto needsWidthComputation = layoutBox->isReplaced() || layoutBox->establishesFormattingContext();
+ auto needsWidthComputation = layoutBox->isReplaced();
if (needsWidthComputation)
computeWidthAndMargin(*layoutBox, usedValues);
else {
@@ -142,14 +137,17 @@
auto maximumLineWidth = [&](auto availableWidth) {
// Switch to the min/max formatting root width values before formatting the lines.
for (auto* formattingRoot : formattingContextRootList) {
- auto intrinsicWidths = layoutState.formattingStateForBox(*formattingRoot).intrinsicWidthConstraints(*formattingRoot);
- layoutState.displayBoxForLayoutBox(*formattingRoot).setContentBoxWidth(availableWidth ? intrinsicWidths->maximum : intrinsicWidths->minimum);
+ auto intrinsicWidths = layoutState.formattingStateForBox(*formattingRoot).intrinsicWidthConstraintsForBox(*formattingRoot);
+ auto& displayBox = layoutState.displayBoxForLayoutBox(*formattingRoot);
+ auto contentWidth = (availableWidth ? intrinsicWidths->maximum : intrinsicWidths->minimum) - displayBox.horizontalMarginBorderAndPadding();
+ displayBox.setContentBoxWidth(contentWidth);
}
return InlineLayout(*this).computedIntrinsicWidth(formattingState().inlineItems(), availableWidth);
};
- auto intrinsicWidthConstraints = Geometry::constrainByMinMaxWidth(root, { maximumLineWidth(0), maximumLineWidth(LayoutUnit::max()) });
- layoutState.formattingStateForBox(root).setIntrinsicWidthConstraints(root, intrinsicWidthConstraints);
+ auto constraints = Geometry::constrainByMinMaxWidth(root, { maximumLineWidth(0), maximumLineWidth(LayoutUnit::max()) });
+ formattingState().setIntrinsicWidthConstraints(constraints);
+ return constraints;
}
void InlineFormattingContext::initializeMarginBorderAndPaddingForGenericInlineBox(const Box& layoutBox) const
@@ -171,24 +169,23 @@
layoutState().displayBoxForLayoutBox(container).setVerticalMargin({ { }, { } });
}
-void InlineFormattingContext::computeIntrinsicWidthForFloatBox(const Box& layoutBox) const
+void InlineFormattingContext::computeIntrinsicWidthForFormattingRoot(const Box& formattingRoot) const
{
- ASSERT(layoutBox.isFloatingPositioned());
+ ASSERT(formattingRoot.establishesFormattingContext());
+ auto& layoutState = this->layoutState();
auto usedValues = UsedHorizontalValues { };
- computeBorderAndPadding(layoutBox, usedValues);
- computeHorizontalMargin(layoutBox, usedValues);
- layoutState().createFormattingContext(layoutBox)->computeIntrinsicWidthConstraints();
-}
+ computeBorderAndPadding(formattingRoot, usedValues);
+ computeHorizontalMargin(formattingRoot, usedValues);
-void InlineFormattingContext::computeIntrinsicWidthForInlineBlock(const Box& layoutBox) const
-{
- ASSERT(layoutBox.isInlineBlockBox());
-
- auto usedValues = UsedHorizontalValues { };
- computeBorderAndPadding(layoutBox, usedValues);
- computeHorizontalMargin(layoutBox, usedValues);
- layoutState().createFormattingContext(layoutBox)->computeIntrinsicWidthConstraints();
+ IntrinsicWidthConstraints constraints;
+ if (auto fixedWidth = Geometry::fixedValue(formattingRoot.style().logicalWidth()))
+ constraints = { *fixedWidth, *fixedWidth };
+ else
+ constraints = layoutState.createFormattingContext(formattingRoot)->computedIntrinsicWidthConstraints();
+ constraints = Geometry::constrainByMinMaxWidth(formattingRoot, constraints);
+ constraints.expand(layoutState.displayBoxForLayoutBox(formattingRoot).horizontalMarginBorderAndPadding());
+ formattingState().setIntrinsicWidthConstraintsForBox(formattingRoot, constraints);
}
void InlineFormattingContext::computeHorizontalMargin(const Box& layoutBox, UsedHorizontalValues usedValues) const
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h (248261 => 248262)
--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h 2019-08-04 03:24:27 UTC (rev 248261)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h 2019-08-04 10:16:06 UTC (rev 248262)
@@ -49,7 +49,7 @@
void layout() const override;
private:
- void computeIntrinsicWidthConstraints() const override;
+ IntrinsicWidthConstraints computedIntrinsicWidthConstraints() const override;
class InlineLayout {
public:
@@ -81,10 +81,9 @@
};
void layoutFormattingContextRoot(const Box&, UsedHorizontalValues) const;
- void computeIntrinsicWidthForFloatBox(const Box&) const;
void computeMarginBorderAndPaddingForInlineContainer(const Container&, UsedHorizontalValues) const;
void initializeMarginBorderAndPaddingForGenericInlineBox(const Box&) const;
- void computeIntrinsicWidthForInlineBlock(const Box&) const;
+ void computeIntrinsicWidthForFormattingRoot(const Box&) const;
void computeWidthAndHeightForReplacedInlineBox(const Box&, UsedHorizontalValues) const;
void computeHorizontalMargin(const Box&, UsedHorizontalValues) const;
void computeHeightAndMargin(const Box&) const;
Modified: trunk/Source/WebCore/layout/tableformatting/TableFormattingContext.cpp (248261 => 248262)
--- trunk/Source/WebCore/layout/tableformatting/TableFormattingContext.cpp 2019-08-04 03:24:27 UTC (rev 248261)
+++ trunk/Source/WebCore/layout/tableformatting/TableFormattingContext.cpp 2019-08-04 10:16:06 UTC (rev 248262)
@@ -46,7 +46,12 @@
{
}
+FormattingContext::IntrinsicWidthConstraints TableFormattingContext::computedIntrinsicWidthConstraints() const
+{
+ return { };
}
+
}
+}
#endif
Modified: trunk/Source/WebCore/layout/tableformatting/TableFormattingContext.h (248261 => 248262)
--- trunk/Source/WebCore/layout/tableformatting/TableFormattingContext.h 2019-08-04 03:24:27 UTC (rev 248261)
+++ trunk/Source/WebCore/layout/tableformatting/TableFormattingContext.h 2019-08-04 10:16:06 UTC (rev 248262)
@@ -41,6 +41,9 @@
public:
TableFormattingContext(const Box& formattingContextRoot, TableFormattingState&);
void layout() const override;
+
+private:
+ IntrinsicWidthConstraints computedIntrinsicWidthConstraints() const override;
};
}