Diff
Modified: trunk/Source/WebCore/ChangeLog (233468 => 233469)
--- trunk/Source/WebCore/ChangeLog 2018-07-03 18:25:36 UTC (rev 233468)
+++ trunk/Source/WebCore/ChangeLog 2018-07-03 18:29:35 UTC (rev 233469)
@@ -1,3 +1,54 @@
+2018-07-03 Zalan Bujtas <[email protected]>
+
+ [LFC] Implement minimum/maximum content width logic.
+ https://bugs.webkit.org/show_bug.cgi?id=187241
+
+ Reviewed by Antti Koivisto.
+
+ Compute the minimum/maximum content width if needed and cache the values on the formatting state.
+
+ * layout/FormattingContext.cpp:
+ (WebCore::Layout::FormattingContext::computeFloatingWidthAndMargin const):
+ (WebCore::Layout::FormattingContext::computeOutOfFlowHorizontalGeometry const):
+ (WebCore::Layout::FormattingContext::layoutOutOfFlowDescendants const):
+ * layout/FormattingContext.h:
+ * layout/FormattingContextGeometry.cpp:
+ (WebCore::Layout::FormattingContext::Geometry::shrinkToFitWidth):
+ (WebCore::Layout::FormattingContext::Geometry::outOfFlowNonReplacedHorizontalGeometry):
+ (WebCore::Layout::FormattingContext::Geometry::floatingNonReplacedWidthAndMargin):
+ (WebCore::Layout::FormattingContext::Geometry::outOfFlowHorizontalGeometry):
+ (WebCore::Layout::FormattingContext::Geometry::floatingWidthAndMargin):
+ (WebCore::Layout::shrinkToFitWidth): Deleted.
+ * layout/FormattingState.cpp:
+ (WebCore::Layout::FormattingState::FormattingState):
+ * layout/FormattingState.h:
+ (WebCore::Layout::FormattingState::setMinimumMaximumContentWidth):
+ (WebCore::Layout::FormattingState::clearMinimumMaximumContentWidth):
+ (WebCore::Layout::FormattingState::minimumMaximumContentWidth const):
+ * layout/LayoutContext.cpp:
+ (WebCore::Layout::LayoutContext::establishedFormattingState):
+ * layout/LayoutContext.h:
+ * layout/Verification.cpp:
+ (WebCore::Layout::LayoutContext::verifyAndOutputMismatchingLayoutTree const):
+ * layout/blockformatting/BlockFormattingContext.cpp:
+ (WebCore::Layout::BlockFormattingContext::createFormattingState const):
+ (WebCore::Layout::BlockFormattingContext::minimumMaximumContentWidth const):
+ * layout/blockformatting/BlockFormattingContext.h:
+ * layout/blockformatting/BlockFormattingContextGeometry.cpp:
+ (WebCore::Layout::BlockFormattingContext::Geometry::minimumMaximumContentWidthNeedsChildrenWidth):
+ (WebCore::Layout::BlockFormattingContext::Geometry::minimumMaximumContentWidth):
+ * layout/blockformatting/BlockFormattingState.cpp:
+ (WebCore::Layout::BlockFormattingState::BlockFormattingState):
+ * layout/blockformatting/BlockFormattingState.h:
+ * layout/inlineformatting/InlineFormattingContext.cpp:
+ (WebCore::Layout::InlineFormattingContext::createFormattingState const):
+ (WebCore::Layout::InlineFormattingContext::minimumMaximumContentWidth const):
+ * layout/inlineformatting/InlineFormattingContext.h:
+ * layout/inlineformatting/InlineFormattingState.cpp:
+ (WebCore::Layout::InlineFormattingState::InlineFormattingState):
+ * layout/inlineformatting/InlineFormattingState.h:
+ * page/FrameViewLayoutContext.cpp:
+
2018-07-03 Jonathan Bedard <[email protected]>
Unreviewed, rolling out r233461.
Modified: trunk/Source/WebCore/layout/FormattingContext.cpp (233468 => 233469)
--- trunk/Source/WebCore/layout/FormattingContext.cpp 2018-07-03 18:25:36 UTC (rev 233468)
+++ trunk/Source/WebCore/layout/FormattingContext.cpp 2018-07-03 18:29:35 UTC (rev 233469)
@@ -63,7 +63,7 @@
void FormattingContext::computeFloatingWidthAndMargin(LayoutContext& layoutContext, const Box& layoutBox, Display::Box& displayBox) const
{
- auto widthAndMargin = Geometry::floatingWidthAndMargin(layoutContext, layoutBox);
+ auto widthAndMargin = Geometry::floatingWidthAndMargin(layoutContext, *this, layoutBox);
displayBox.setContentBoxWidth(widthAndMargin.width);
displayBox.moveHorizontally(widthAndMargin.margin.left);
displayBox.setHorizontalMargin(widthAndMargin.margin);
@@ -71,7 +71,7 @@
void FormattingContext::computeOutOfFlowHorizontalGeometry(LayoutContext& layoutContext, const Box& layoutBox, Display::Box& displayBox) const
{
- auto horizontalGeometry = Geometry::outOfFlowHorizontalGeometry(layoutContext, layoutBox);
+ auto horizontalGeometry = Geometry::outOfFlowHorizontalGeometry(layoutContext, *this, layoutBox);
displayBox.setLeft(horizontalGeometry.left + horizontalGeometry.widthAndMargin.margin.left);
displayBox.setContentBoxWidth(horizontalGeometry.widthAndMargin.width);
displayBox.setHorizontalMargin(horizontalGeometry.widthAndMargin.margin);
@@ -128,16 +128,14 @@
auto& layoutBox = *outOfFlowBox;
auto& displayBox = layoutContext.createDisplayBox(layoutBox);
- // The term "static position" (of an element) refers, roughly, to the position an element would have had in the normal flow.
- // More precisely, the static position for 'top' is the distance from the top edge of the containing block to the top margin edge
- // of a hypothetical box that would have been the first box of the element if its specified 'position' value had been 'static' and
- // its specified 'float' had been 'none' and its specified 'clear' had been 'none'.
+ ASSERT(layoutBox.establishesFormattingContext());
+ auto formattingContext = layoutContext.formattingContext(layoutBox);
+ auto& establishedFormattingState = layoutContext.establishedFormattingState(layoutBox, *formattingContext);
+
computeBorderAndPadding(layoutContext, layoutBox, displayBox);
computeOutOfFlowHorizontalGeometry(layoutContext, layoutBox, displayBox);
- ASSERT(layoutBox.establishesFormattingContext());
- auto formattingContext = layoutContext.formattingContext(layoutBox);
- formattingContext->layout(layoutContext, layoutContext.establishedFormattingState(layoutBox, *formattingContext));
+ formattingContext->layout(layoutContext, establishedFormattingState);
computeOutOfFlowVerticalGeometry(layoutContext, layoutBox, displayBox);
layoutOutOfFlowDescendants(layoutContext, layoutBox);
Modified: trunk/Source/WebCore/layout/FormattingContext.h (233468 => 233469)
--- trunk/Source/WebCore/layout/FormattingContext.h 2018-07-03 18:25:36 UTC (rev 233468)
+++ trunk/Source/WebCore/layout/FormattingContext.h 2018-07-03 18:29:35 UTC (rev 233469)
@@ -52,9 +52,15 @@
virtual void layout(LayoutContext&, FormattingState&) const = 0;
void layoutOutOfFlowDescendants(LayoutContext&, const Box&) const;
- virtual std::unique_ptr<FormattingState> createFormattingState(Ref<FloatingState>&&) const = 0;
+ virtual std::unique_ptr<FormattingState> createFormattingState(Ref<FloatingState>&&, const LayoutContext&) const = 0;
virtual Ref<FloatingState> createOrFindFloatingState(LayoutContext&) const = 0;
+ struct InstrinsicWidthConstraints {
+ LayoutUnit minimum;
+ LayoutUnit maximum;
+ };
+ virtual InstrinsicWidthConstraints instrinsicWidthConstraints(LayoutContext&, const Box&) const = 0;
+
protected:
struct LayoutPair {
const Box& layoutBox;
@@ -112,10 +118,10 @@
};
static VerticalGeometry outOfFlowVerticalGeometry(LayoutContext&, const Box&);
- static HorizontalGeometry outOfFlowHorizontalGeometry(LayoutContext&, const Box&);
+ static HorizontalGeometry outOfFlowHorizontalGeometry(LayoutContext&, const FormattingContext&, const Box&);
static HeightAndMargin floatingHeightAndMargin(LayoutContext&, const Box&);
- static WidthAndMargin floatingWidthAndMargin(LayoutContext&, const Box&);
+ static WidthAndMargin floatingWidthAndMargin(LayoutContext&, const FormattingContext&, const Box&);
static HeightAndMargin inlineReplacedHeightAndMargin(LayoutContext&, const Box&);
static WidthAndMargin inlineReplacedWidthAndMargin(LayoutContext&, const Box&, std::optional<LayoutUnit> precomputedMarginLeft = { },
@@ -128,6 +134,7 @@
static Display::Box::VerticalEdges computedNonCollapsedVerticalMarginValue(const LayoutContext&, const Box&);
static std::optional<LayoutUnit> computedValueIfNotAuto(const Length& geometryProperty, LayoutUnit containingBlockWidth);
+ static std::optional<LayoutUnit> fixedValue(const Length& geometryProperty);
private:
static VerticalGeometry outOfFlowReplacedVerticalGeometry(LayoutContext&, const Box&);
@@ -134,13 +141,15 @@
static HorizontalGeometry outOfFlowReplacedHorizontalGeometry(LayoutContext&, const Box&);
static VerticalGeometry outOfFlowNonReplacedVerticalGeometry(LayoutContext&, const Box&);
- static HorizontalGeometry outOfFlowNonReplacedHorizontalGeometry(LayoutContext&, const Box&);
+ static HorizontalGeometry outOfFlowNonReplacedHorizontalGeometry(LayoutContext&, const FormattingContext&, const Box&);
static HeightAndMargin floatingReplacedHeightAndMargin(LayoutContext&, const Box&);
static WidthAndMargin floatingReplacedWidthAndMargin(LayoutContext&, const Box&);
static HeightAndMargin floatingNonReplacedHeightAndMargin(LayoutContext&, const Box&);
- static WidthAndMargin floatingNonReplacedWidthAndMargin(LayoutContext&, const Box&);
+ static WidthAndMargin floatingNonReplacedWidthAndMargin(LayoutContext&, const FormattingContext&, const Box&);
+
+ static LayoutUnit shrinkToFitWidth(LayoutContext&, const FormattingContext&, const Box&);
};
private:
Modified: trunk/Source/WebCore/layout/FormattingContextGeometry.cpp (233468 => 233469)
--- trunk/Source/WebCore/layout/FormattingContextGeometry.cpp 2018-07-03 18:25:36 UTC (rev 233468)
+++ trunk/Source/WebCore/layout/FormattingContextGeometry.cpp 2018-07-03 18:29:35 UTC (rev 233469)
@@ -62,12 +62,6 @@
return computedHeight;
}
-static LayoutUnit shrinkToFitWidth(LayoutContext&, const Box& layoutBox)
-{
- LOG_WITH_STREAM(FormattingContextLayout, stream << "[Width] -> shrink to fit -> unsupported -> width(" << LayoutUnit { } << "px) layoutBox: " << &layoutBox << ")");
- return { };
-}
-
std::optional<LayoutUnit> FormattingContext::Geometry::computedValueIfNotAuto(const Length& geometryProperty, LayoutUnit containingBlockWidth)
{
if (geometryProperty.isAuto())
@@ -75,6 +69,13 @@
return valueForLength(geometryProperty, containingBlockWidth);
}
+std::optional<LayoutUnit> FormattingContext::Geometry::fixedValue(const Length& geometryProperty)
+{
+ if (!geometryProperty.isFixed())
+ return std::nullopt;
+ return { geometryProperty.value() };
+}
+
static LayoutUnit staticVerticalPositionForOutOfFlowPositioned(const LayoutContext& layoutContext, const Box& layoutBox)
{
ASSERT(layoutBox.isOutOfFlowPositioned());
@@ -129,6 +130,21 @@
return left;
}
+LayoutUnit FormattingContext::Geometry::shrinkToFitWidth(LayoutContext& layoutContext, const FormattingContext& formattingContext, const Box& layoutBox)
+{
+ LOG_WITH_STREAM(FormattingContextLayout, stream << "[Width] -> shrink to fit -> unsupported -> width(" << LayoutUnit { } << "px) layoutBox: " << &layoutBox << ")");
+ // Calculation of the shrink-to-fit width is similar to calculating the width of a table cell using the automatic table layout algorithm.
+ // Roughly: calculate the preferred width by formatting the content without breaking lines other than where explicit line breaks occur,
+ // and also calculate the preferred minimum width, e.g., by trying all possible line breaks. CSS 2.2 does not define the exact algorithm.
+ // Thirdly, find the available width: in this case, this is the width of the containing block minus the used values of 'margin-left', 'border-left-width',
+ // '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 availableWidth = layoutContext.displayBoxForLayoutBox(*layoutBox.containingBlock())->width();
+ auto instrinsicWidthConstraints = formattingContext.instrinsicWidthConstraints(layoutContext, layoutBox);
+ return std::min(std::max(instrinsicWidthConstraints.minimum, availableWidth), instrinsicWidthConstraints.maximum);
+}
+
FormattingContext::Geometry::VerticalGeometry FormattingContext::Geometry::outOfFlowNonReplacedVerticalGeometry(LayoutContext& layoutContext, const Box& layoutBox)
{
ASSERT(layoutBox.isOutOfFlowPositioned() && !layoutBox.replaced());
@@ -245,7 +261,7 @@
return { *top, *bottom, { *height, { *marginTop, *marginBottom }, { } } };
}
-FormattingContext::Geometry::HorizontalGeometry FormattingContext::Geometry::outOfFlowNonReplacedHorizontalGeometry(LayoutContext& layoutContext, const Box& layoutBox)
+FormattingContext::Geometry::HorizontalGeometry FormattingContext::Geometry::outOfFlowNonReplacedHorizontalGeometry(LayoutContext& layoutContext, const FormattingContext& formattingContext, const Box& layoutBox)
{
ASSERT(layoutBox.isOutOfFlowPositioned() && !layoutBox.replaced());
@@ -352,7 +368,7 @@
if (!left && !width && right) {
// #1
- width = shrinkToFitWidth(layoutContext, layoutBox);
+ width = shrinkToFitWidth(layoutContext, formattingContext, layoutBox);
left = containingBlockWidth - (*marginLeft + borderLeft + paddingLeft + *width + paddingRight + borderRight + *marginRight + *right);
} else if (!left && !right && width) {
// #2
@@ -366,7 +382,7 @@
}
} else if (!width && !right && left) {
// #3
- width = shrinkToFitWidth(layoutContext, layoutBox);
+ width = shrinkToFitWidth(layoutContext, formattingContext, layoutBox);
right = containingBlockWidth - (*left + *marginLeft + borderLeft + paddingLeft + *width + paddingRight + borderRight + *marginRight);
} else if (!left && width && right) {
// #4
@@ -588,7 +604,7 @@
return FormattingContext::Geometry::HeightAndMargin { *height, { *marginTop, *marginBottom }, { } };
}
-FormattingContext::Geometry::WidthAndMargin FormattingContext::Geometry::floatingNonReplacedWidthAndMargin(LayoutContext& layoutContext, const Box& layoutBox)
+FormattingContext::Geometry::WidthAndMargin FormattingContext::Geometry::floatingNonReplacedWidthAndMargin(LayoutContext& layoutContext, const FormattingContext& formattingContext, const Box& layoutBox)
{
ASSERT(layoutBox.isFloatingPositioned() && !layoutBox.replaced());
@@ -605,7 +621,7 @@
// #2
auto width = computedValueIfNotAuto(layoutBox.style().logicalWidth(), containingBlockWidth);
if (!width)
- width = shrinkToFitWidth(layoutContext, layoutBox);
+ width = shrinkToFitWidth(layoutContext, formattingContext, layoutBox);
LOG_WITH_STREAM(FormattingContextLayout, stream << "[Width][Margin] -> floating non-replaced -> width(" << *width << "px) margin(" << margin.left << "px, " << margin.right << "px) -> layoutBox(" << &layoutBox << ")");
return FormattingContext::Geometry::WidthAndMargin { *width, margin };
@@ -644,12 +660,12 @@
return outOfFlowReplacedVerticalGeometry(layoutContext, layoutBox);
}
-FormattingContext::Geometry::HorizontalGeometry FormattingContext::Geometry::outOfFlowHorizontalGeometry(LayoutContext& layoutContext, const Box& layoutBox)
+FormattingContext::Geometry::HorizontalGeometry FormattingContext::Geometry::outOfFlowHorizontalGeometry(LayoutContext& layoutContext, const FormattingContext& formattingContext, const Box& layoutBox)
{
ASSERT(layoutBox.isOutOfFlowPositioned());
if (!layoutBox.replaced())
- return outOfFlowNonReplacedHorizontalGeometry(layoutContext, layoutBox);
+ return outOfFlowNonReplacedHorizontalGeometry(layoutContext, formattingContext, layoutBox);
return outOfFlowReplacedHorizontalGeometry(layoutContext, layoutBox);
}
@@ -662,12 +678,12 @@
return floatingReplacedHeightAndMargin(layoutContext, layoutBox);
}
-FormattingContext::Geometry::WidthAndMargin FormattingContext::Geometry::floatingWidthAndMargin(LayoutContext& layoutContext, const Box& layoutBox)
+FormattingContext::Geometry::WidthAndMargin FormattingContext::Geometry::floatingWidthAndMargin(LayoutContext& layoutContext, const FormattingContext& formattingContext, const Box& layoutBox)
{
ASSERT(layoutBox.isFloatingPositioned());
if (!layoutBox.replaced())
- return floatingNonReplacedWidthAndMargin(layoutContext, layoutBox);
+ return floatingNonReplacedWidthAndMargin(layoutContext, formattingContext, layoutBox);
return floatingReplacedWidthAndMargin(layoutContext, layoutBox);
}
Modified: trunk/Source/WebCore/layout/FormattingState.cpp (233468 => 233469)
--- trunk/Source/WebCore/layout/FormattingState.cpp 2018-07-03 18:25:36 UTC (rev 233468)
+++ trunk/Source/WebCore/layout/FormattingState.cpp 2018-07-03 18:29:35 UTC (rev 233469)
@@ -35,8 +35,9 @@
WTF_MAKE_ISO_ALLOCATED_IMPL(FormattingState);
-FormattingState::FormattingState(Ref<FloatingState>&& floatingState, Type type)
- : m_floatingState(WTFMove(floatingState))
+FormattingState::FormattingState(Ref<FloatingState>&& floatingState, Type type, const LayoutContext& layoutContext)
+ : m_layoutContext(layoutContext)
+ , m_floatingState(WTFMove(floatingState))
, m_type(type)
{
}
Modified: trunk/Source/WebCore/layout/FormattingState.h (233468 => 233469)
--- trunk/Source/WebCore/layout/FormattingState.h 2018-07-03 18:25:36 UTC (rev 233468)
+++ trunk/Source/WebCore/layout/FormattingState.h 2018-07-03 18:29:35 UTC (rev 233469)
@@ -28,6 +28,9 @@
#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
#include "FloatingState.h"
+#include "LayoutBox.h"
+#include "LayoutContext.h"
+#include "LayoutUnit.h"
#include <wtf/IsoMalloc.h>
namespace WebCore {
@@ -47,21 +50,49 @@
void markNeedsLayout(const Box&, StyleDiff);
bool needsLayout(const Box&);
+ void setInstrinsicWidthConstraints(const Box&, FormattingContext::InstrinsicWidthConstraints);
+ void clearInstrinsicWidthConstraints(const Box&);
+ std::optional<FormattingContext::InstrinsicWidthConstraints> instrinsicWidthConstraints(const Box&) const;
+
bool isBlockFormattingState() const { return m_type == Type::Block; }
bool isInlineFormattingState() const { return m_type == Type::Inline; }
protected:
enum class Type { Block, Inline };
- FormattingState(Ref<FloatingState>&&, Type);
+ FormattingState(Ref<FloatingState>&&, Type, const LayoutContext&);
+ const LayoutContext& m_layoutContext;
+
private:
Ref<FloatingState> m_floatingState;
+ HashMap<const Box*, FormattingContext::InstrinsicWidthConstraints> m_instrinsicWidthConstraints;
Type m_type;
};
+inline void FormattingState::setInstrinsicWidthConstraints(const Box& layoutBox, FormattingContext::InstrinsicWidthConstraints instrinsicWidthConstraints)
+{
+ ASSERT(!m_instrinsicWidthConstraints.contains(&layoutBox));
+ ASSERT(&m_layoutContext.formattingStateForBox(layoutBox) == this);
+ m_instrinsicWidthConstraints.set(&layoutBox, instrinsicWidthConstraints);
}
+
+inline void FormattingState::clearInstrinsicWidthConstraints(const Box& layoutBox)
+{
+ m_instrinsicWidthConstraints.remove(&layoutBox);
}
+inline std::optional<FormattingContext::InstrinsicWidthConstraints> FormattingState::instrinsicWidthConstraints(const Box& layoutBox) const
+{
+ ASSERT(&m_layoutContext.formattingStateForBox(layoutBox) == this);
+ auto iterator = m_instrinsicWidthConstraints.find(&layoutBox);
+ if (iterator == m_instrinsicWidthConstraints.end())
+ return { };
+ return iterator->value;
+}
+
+}
+}
+
#define SPECIALIZE_TYPE_TRAITS_LAYOUT_FORMATTING_STATE(ToValueTypeName, predicate) \
SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::Layout::ToValueTypeName) \
static bool isType(const WebCore::Layout::FormattingState& formattingState) { return formattingState.predicate; } \
Modified: trunk/Source/WebCore/layout/LayoutContext.cpp (233468 => 233469)
--- trunk/Source/WebCore/layout/LayoutContext.cpp 2018-07-03 18:25:36 UTC (rev 233468)
+++ trunk/Source/WebCore/layout/LayoutContext.cpp 2018-07-03 18:29:35 UTC (rev 233469)
@@ -122,7 +122,7 @@
FormattingState& LayoutContext::establishedFormattingState(const Box& formattingContextRoot, const FormattingContext& context)
{
return *m_formattingStates.ensure(&formattingContextRoot, [this, &context] {
- return context.createFormattingState(context.createOrFindFloatingState(*this));
+ return context.createFormattingState(context.createOrFindFloatingState(*this), *this);
}).iterator->value;
}
Modified: trunk/Source/WebCore/layout/LayoutContext.h (233468 => 233469)
--- trunk/Source/WebCore/layout/LayoutContext.h 2018-07-03 18:25:36 UTC (rev 233468)
+++ trunk/Source/WebCore/layout/LayoutContext.h 2018-07-03 18:29:35 UTC (rev 233469)
@@ -28,7 +28,6 @@
#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
#include "FormattingContext.h"
-#include "FormattingState.h"
#include <wtf/HashSet.h>
#include <wtf/IsoMalloc.h>
#include <wtf/OptionSet.h>
@@ -48,6 +47,7 @@
enum class StyleDiff;
class Box;
class Container;
+class FormattingState;
// LayoutContext is the entry point for layout. It takes a (formatting root)container which acts as the root of the layout context.
// LayoutContext::layout() generates the display tree for the root container's subtree (it does not run layout on the root though).
Modified: trunk/Source/WebCore/layout/Verification.cpp (233468 => 233469)
--- trunk/Source/WebCore/layout/Verification.cpp 2018-07-03 18:25:36 UTC (rev 233468)
+++ trunk/Source/WebCore/layout/Verification.cpp 2018-07-03 18:29:35 UTC (rev 233469)
@@ -120,11 +120,11 @@
{
TextStream stream;
auto mismatchingGeometry = verifyAndOutputSubtree(stream, *this, renderView, *m_root.get());
+ if (!mismatchingGeometry)
+ return;
#if ENABLE(TREE_DEBUGGING)
- if (mismatchingGeometry) {
- showRenderTree(&renderView);
- TreeBuilder::showLayoutTree(*this, *m_root.get());
- }
+ showRenderTree(&renderView);
+ TreeBuilder::showLayoutTree(*this, *m_root.get());
#endif
WTFLogAlways("%s", stream.release().utf8().data());
}
Modified: trunk/Source/WebCore/layout/blockformatting/BlockFormattingContext.cpp (233468 => 233469)
--- trunk/Source/WebCore/layout/blockformatting/BlockFormattingContext.cpp 2018-07-03 18:25:36 UTC (rev 233468)
+++ trunk/Source/WebCore/layout/blockformatting/BlockFormattingContext.cpp 2018-07-03 18:29:35 UTC (rev 233469)
@@ -152,9 +152,9 @@
formattingContext->layoutOutOfFlowDescendants(layoutContext, layoutBox);
}
-std::unique_ptr<FormattingState> BlockFormattingContext::createFormattingState(Ref<FloatingState>&& floatingState) const
+std::unique_ptr<FormattingState> BlockFormattingContext::createFormattingState(Ref<FloatingState>&& floatingState, const LayoutContext& layoutContext) const
{
- return std::make_unique<BlockFormattingState>(WTFMove(floatingState));
+ return std::make_unique<BlockFormattingState>(WTFMove(floatingState), layoutContext);
}
Ref<FloatingState> BlockFormattingContext::createOrFindFloatingState(LayoutContext&) const
@@ -212,7 +212,76 @@
displayBox.setHorizontalMargin(widthAndMargin.margin);
}
+FormattingContext::InstrinsicWidthConstraints BlockFormattingContext::instrinsicWidthConstraints(LayoutContext& layoutContext, const Box& layoutBox) const
+{
+ auto& formattingState = layoutContext.formattingStateForBox(layoutBox);
+ ASSERT(formattingState.isBlockFormattingState());
+ if (auto instrinsicWidthConstraints = formattingState.instrinsicWidthConstraints(layoutBox))
+ return *instrinsicWidthConstraints;
+
+ // Can we just compute them without checking the children?
+ if (!Geometry::instrinsicWidthConstraintsNeedChildrenWidth(layoutBox)) {
+ auto instrinsicWidthConstraints = Geometry::instrinsicWidthConstraints(layoutContext, layoutBox);
+ formattingState.setInstrinsicWidthConstraints(layoutBox, instrinsicWidthConstraints);
+ return instrinsicWidthConstraints;
+ }
+
+ // 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)
+ // 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;
+ // Non-containers early return.
+ ASSERT(is<Container>(layoutBox));
+ if (auto* firstChild = downcast<Container>(layoutBox).firstInFlowOrFloatingChild())
+ queue.append(firstChild);
+
+ auto& formattingStateForChildren = layoutBox.establishesFormattingContext() ? layoutContext.establishedFormattingState(layoutBox, *this) : formattingState;
+ while (!queue.isEmpty()) {
+ while (true) {
+ auto& childBox = *queue.last();
+ // Already computed?
+ auto instrinsicWidthConstraints = formattingStateForChildren.instrinsicWidthConstraints(childBox);
+ // Can we just compute them without checking the children?
+ if (!instrinsicWidthConstraints && !Geometry::instrinsicWidthConstraintsNeedChildrenWidth(childBox))
+ instrinsicWidthConstraints = Geometry::instrinsicWidthConstraints(layoutContext, childBox);
+ // Is it a formatting context root?
+ if (!instrinsicWidthConstraints && childBox.establishesFormattingContext())
+ instrinsicWidthConstraints = layoutContext.formattingContext(childBox)->instrinsicWidthConstraints(layoutContext, childBox);
+ // Go to the next sibling (and skip the descendants) if this box's min/max width is computed.
+ if (instrinsicWidthConstraints) {
+ formattingStateForChildren.setInstrinsicWidthConstraints(childBox, *instrinsicWidthConstraints);
+ queue.removeLast();
+ if (!childBox.nextInFlowOrFloatingSibling())
+ break;
+ queue.append(childBox.nextInFlowOrFloatingSibling());
+ continue;
+ }
+
+ if (!is<Container>(childBox) || !downcast<Container>(childBox).hasInFlowOrFloatingChild())
+ break;
+
+ queue.append(downcast<Container>(childBox).firstInFlowOrFloatingChild());
+ }
+
+ // Compute min/max intrinsic width bottom up.
+ while (!queue.isEmpty()) {
+ auto& childBox = *queue.takeLast();
+ formattingStateForChildren.setInstrinsicWidthConstraints(childBox, Geometry::instrinsicWidthConstraints(layoutContext, childBox));
+ // Move over to the next sibling or take the next box in the queue.
+ if (!is<Container>(childBox) || !downcast<Container>(childBox).nextInFlowOrFloatingSibling())
+ continue;
+ queue.append(downcast<Container>(childBox).nextInFlowOrFloatingSibling());
+ }
+ }
+
+ auto instrinsicWidthConstraints = Geometry::instrinsicWidthConstraints(layoutContext, layoutBox);
+ formattingState.setInstrinsicWidthConstraints(layoutBox, instrinsicWidthConstraints);
+ return instrinsicWidthConstraints;
}
+
}
+}
#endif
Modified: trunk/Source/WebCore/layout/blockformatting/BlockFormattingContext.h (233468 => 233469)
--- trunk/Source/WebCore/layout/blockformatting/BlockFormattingContext.h 2018-07-03 18:25:36 UTC (rev 233468)
+++ trunk/Source/WebCore/layout/blockformatting/BlockFormattingContext.h 2018-07-03 18:29:35 UTC (rev 233469)
@@ -47,7 +47,7 @@
BlockFormattingContext(const Box& formattingContextRoot);
void layout(LayoutContext&, FormattingState&) const override;
- std::unique_ptr<FormattingState> createFormattingState(Ref<FloatingState>&&) const override;
+ std::unique_ptr<FormattingState> createFormattingState(Ref<FloatingState>&&, const LayoutContext&) const override;
Ref<FloatingState> createOrFindFloatingState(LayoutContext&) const override;
private:
@@ -61,6 +61,8 @@
void computeInFlowWidthAndMargin(LayoutContext&, const Box&, Display::Box&) const;
void computeInFlowHeightAndMargin(LayoutContext&, const Box&, Display::Box&) const;
+ FormattingContext::InstrinsicWidthConstraints instrinsicWidthConstraints(LayoutContext&, const Box&) const override;
+
// This class implements positioning and sizing for boxes participating in a block formatting context.
class Geometry {
public:
@@ -70,6 +72,9 @@
static FormattingContext::Geometry::Position staticPosition(LayoutContext&, const Box&);
static FormattingContext::Geometry::Position inFlowPositionedPosition(LayoutContext&, const Box&);
+ static bool instrinsicWidthConstraintsNeedChildrenWidth(const Box&);
+ static FormattingContext::InstrinsicWidthConstraints instrinsicWidthConstraints(LayoutContext&, const Box&);
+
private:
static FormattingContext::Geometry::HeightAndMargin inFlowNonReplacedHeightAndMargin(LayoutContext&, const Box&);
static FormattingContext::Geometry::WidthAndMargin inFlowNonReplacedWidthAndMargin(LayoutContext&, const Box&, std::optional<LayoutUnit> precomputedWidth = std::nullopt);
Modified: trunk/Source/WebCore/layout/blockformatting/BlockFormattingContextGeometry.cpp (233468 => 233469)
--- trunk/Source/WebCore/layout/blockformatting/BlockFormattingContextGeometry.cpp 2018-07-03 18:25:36 UTC (rev 233468)
+++ trunk/Source/WebCore/layout/blockformatting/BlockFormattingContextGeometry.cpp 2018-07-03 18:29:35 UTC (rev 233469)
@@ -29,6 +29,7 @@
#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
#include "FormattingContext.h"
+#include "LayoutChildIterator.h"
#include "Logging.h"
#include <wtf/text/TextStream.h>
@@ -373,7 +374,53 @@
return inFlowReplacedWidthAndMargin(layoutContext, layoutBox);
}
+bool BlockFormattingContext::Geometry::instrinsicWidthConstraintsNeedChildrenWidth(const Box& layoutBox)
+{
+ if (!is<Container>(layoutBox) || !downcast<Container>(layoutBox).hasInFlowOrFloatingChild())
+ return false;
+ return layoutBox.style().width().isAuto();
}
+
+FormattingContext::InstrinsicWidthConstraints BlockFormattingContext::Geometry::instrinsicWidthConstraints(LayoutContext& layoutContext, const Box& layoutBox)
+{
+ auto& style = layoutBox.style();
+ if (auto width = FormattingContext::Geometry::fixedValue(style.logicalWidth()))
+ return { *width, *width };
+
+ // Minimum/maximum width can't be depending on the containing block's width.
+ if (!style.logicalWidth().isAuto())
+ return { };
+
+ if (!is<Container>(layoutBox))
+ return { };
+
+ LayoutUnit minimumIntrinsicWidth;
+ LayoutUnit maximumIntrinsicWidth;
+
+ for (auto& child : childrenOfType<Box>(downcast<Container>(layoutBox))) {
+ if (child.isOutOfFlowPositioned())
+ continue;
+ auto& formattingState = layoutContext.formattingStateForBox(child);
+ ASSERT(formattingState.isBlockFormattingState());
+ auto childInstrinsicWidthConstraints = formattingState.instrinsicWidthConstraints(child);
+ ASSERT(childInstrinsicWidthConstraints);
+
+ auto& style = child.style();
+ auto horizontalMarginBorderAndPadding = FormattingContext::Geometry::fixedValue(style.marginLeft()).value_or(0)
+ + LayoutUnit { style.borderLeftWidth() }
+ + FormattingContext::Geometry::fixedValue(style.paddingLeft()).value_or(0)
+ + FormattingContext::Geometry::fixedValue(style.paddingRight()).value_or(0)
+ + LayoutUnit { style.borderRightWidth() }
+ + FormattingContext::Geometry::fixedValue(style.marginRight()).value_or(0);
+
+ minimumIntrinsicWidth = std::max(minimumIntrinsicWidth, childInstrinsicWidthConstraints->minimum + horizontalMarginBorderAndPadding);
+ maximumIntrinsicWidth = std::max(maximumIntrinsicWidth, childInstrinsicWidthConstraints->maximum + horizontalMarginBorderAndPadding);
+ }
+
+ return { minimumIntrinsicWidth, maximumIntrinsicWidth };
}
+}
+}
+
#endif
Modified: trunk/Source/WebCore/layout/blockformatting/BlockFormattingState.cpp (233468 => 233469)
--- trunk/Source/WebCore/layout/blockformatting/BlockFormattingState.cpp 2018-07-03 18:25:36 UTC (rev 233468)
+++ trunk/Source/WebCore/layout/blockformatting/BlockFormattingState.cpp 2018-07-03 18:29:35 UTC (rev 233469)
@@ -28,6 +28,8 @@
#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
+#include "FormattingContext.h"
+#include "LayoutBox.h"
#include <wtf/IsoMallocInlines.h>
namespace WebCore {
@@ -35,8 +37,8 @@
WTF_MAKE_ISO_ALLOCATED_IMPL(BlockFormattingState);
-BlockFormattingState::BlockFormattingState(Ref<FloatingState>&& floatingState)
- : FormattingState(WTFMove(floatingState), Type::Block)
+BlockFormattingState::BlockFormattingState(Ref<FloatingState>&& floatingState, const LayoutContext& layoutContext)
+ : FormattingState(WTFMove(floatingState), Type::Block, layoutContext)
{
}
Modified: trunk/Source/WebCore/layout/blockformatting/BlockFormattingState.h (233468 => 233469)
--- trunk/Source/WebCore/layout/blockformatting/BlockFormattingState.h 2018-07-03 18:25:36 UTC (rev 233468)
+++ trunk/Source/WebCore/layout/blockformatting/BlockFormattingState.h 2018-07-03 18:29:35 UTC (rev 233469)
@@ -38,7 +38,7 @@
class BlockFormattingState : public FormattingState {
WTF_MAKE_ISO_ALLOCATED(BlockFormattingState);
public:
- BlockFormattingState(Ref<FloatingState>&&);
+ BlockFormattingState(Ref<FloatingState>&&, const LayoutContext&);
virtual ~BlockFormattingState();
};
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp (233468 => 233469)
--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp 2018-07-03 18:25:36 UTC (rev 233468)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp 2018-07-03 18:29:35 UTC (rev 233469)
@@ -48,9 +48,9 @@
{
}
-std::unique_ptr<FormattingState> InlineFormattingContext::createFormattingState(Ref<FloatingState>&& floatingState) const
+std::unique_ptr<FormattingState> InlineFormattingContext::createFormattingState(Ref<FloatingState>&& floatingState, const LayoutContext& layoutContext) const
{
- return std::make_unique<InlineFormattingState>(WTFMove(floatingState));
+ return std::make_unique<InlineFormattingState>(WTFMove(floatingState), layoutContext);
}
Ref<FloatingState> InlineFormattingContext::createOrFindFloatingState(LayoutContext& layoutContext) const
@@ -74,7 +74,12 @@
{
}
+FormattingContext::InstrinsicWidthConstraints InlineFormattingContext::instrinsicWidthConstraints(LayoutContext&, const Box&) const
+{
+ return { };
}
+
}
+}
#endif
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h (233468 => 233469)
--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h 2018-07-03 18:25:36 UTC (rev 233468)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h 2018-07-03 18:29:35 UTC (rev 233469)
@@ -44,7 +44,7 @@
InlineFormattingContext(const Box& formattingContextRoot);
void layout(LayoutContext&, FormattingState&) const override;
- std::unique_ptr<FormattingState> createFormattingState(Ref<FloatingState>&&) const override;
+ std::unique_ptr<FormattingState> createFormattingState(Ref<FloatingState>&&, const LayoutContext&) const override;
Ref<FloatingState> createOrFindFloatingState(LayoutContext&) const override;
private:
@@ -51,6 +51,7 @@
void computeStaticPosition(LayoutContext&, const Box&, Display::Box&) const override;
void computeInFlowPositionedPosition(LayoutContext&, const Box&, Display::Box&) const override;
+ InstrinsicWidthConstraints instrinsicWidthConstraints(LayoutContext&, const Box&) const override;
};
}
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingState.cpp (233468 => 233469)
--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingState.cpp 2018-07-03 18:25:36 UTC (rev 233468)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingState.cpp 2018-07-03 18:29:35 UTC (rev 233469)
@@ -35,8 +35,8 @@
WTF_MAKE_ISO_ALLOCATED_IMPL(InlineFormattingState);
-InlineFormattingState::InlineFormattingState(Ref<FloatingState>&& floatingState)
- : FormattingState(WTFMove(floatingState), Type::Inline)
+InlineFormattingState::InlineFormattingState(Ref<FloatingState>&& floatingState, const LayoutContext& layoutContext)
+ : FormattingState(WTFMove(floatingState), Type::Inline, layoutContext)
{
}
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingState.h (233468 => 233469)
--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingState.h 2018-07-03 18:25:36 UTC (rev 233468)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingState.h 2018-07-03 18:29:35 UTC (rev 233469)
@@ -38,7 +38,7 @@
class InlineFormattingState : public FormattingState {
WTF_MAKE_ISO_ALLOCATED(InlineFormattingState);
public:
- InlineFormattingState(Ref<FloatingState>&&);
+ InlineFormattingState(Ref<FloatingState>&&, const LayoutContext&);
virtual ~InlineFormattingState();
};
Modified: trunk/Source/WebCore/page/FrameViewLayoutContext.cpp (233468 => 233469)
--- trunk/Source/WebCore/page/FrameViewLayoutContext.cpp 2018-07-03 18:25:36 UTC (rev 233468)
+++ trunk/Source/WebCore/page/FrameViewLayoutContext.cpp 2018-07-03 18:29:35 UTC (rev 233469)
@@ -40,6 +40,7 @@
#include "Settings.h"
#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
+#include "FormattingState.h"
#include "LayoutContainer.h"
#include "LayoutContext.h"
#include "LayoutTreeBuilder.h"