Modified: trunk/Source/WebCore/ChangeLog (245810 => 245811)
--- trunk/Source/WebCore/ChangeLog 2019-05-28 14:48:57 UTC (rev 245810)
+++ trunk/Source/WebCore/ChangeLog 2019-05-28 14:51:16 UTC (rev 245811)
@@ -1,5 +1,24 @@
2019-05-28 Zalan Bujtas <[email protected]>
+ [LFC][IFC] Move intrinsic width computation from InlineFormattingContext to LineLayout
+ https://bugs.webkit.org/show_bug.cgi?id=198258
+
+ Reviewed by Antti Koivisto.
+
+ This is in preparation for sharing even more code between line layout and preferred width computation.
+
+ * layout/inlineformatting/InlineFormattingContext.cpp:
+ (WebCore::Layout::InlineFormattingContext::layout const):
+ (WebCore::Layout::InlineFormattingContext::computeIntrinsicWidthConstraints const):
+ * layout/inlineformatting/InlineFormattingContext.h:
+ * layout/inlineformatting/InlineFormattingContextLineLayout.cpp:
+ (WebCore::Layout::InlineFormattingContext::LineLayout::initializeLine const):
+ (WebCore::Layout::InlineFormattingContext::LineLayout::layout const):
+ (WebCore::Layout::InlineFormattingContext::LineLayout::computedIntrinsicWidth const):
+ (WebCore::Layout::InlineFormattingContext::LineLayout::closeLine const):
+
+2019-05-28 Zalan Bujtas <[email protected]>
+
[LFC[IFC] Ignore the initial strut's height when the line does not have any content.
https://bugs.webkit.org/show_bug.cgi?id=198268
<rdar://problem/51150057>
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp (245810 => 245811)
--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp 2019-05-28 14:48:57 UTC (rev 245810)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp 2019-05-28 14:51:16 UTC (rev 245811)
@@ -71,7 +71,8 @@
LOG_WITH_STREAM(FormattingContextLayout, stream << "[Start] -> inline formatting context -> formatting root(" << &root() << ")");
auto& root = downcast<Container>(this->root());
- auto usedValues = UsedHorizontalValues { layoutState().displayBoxForLayoutBox(root).contentBoxWidth() };
+ auto availableWidth = layoutState().displayBoxForLayoutBox(root).contentBoxWidth();
+ auto usedValues = UsedHorizontalValues { availableWidth };
auto* layoutBox = root.firstInFlowOrFloatingChild();
// Compute width/height for non-text content and margin/border/padding for inline containers.
while (layoutBox) {
@@ -93,7 +94,7 @@
formattingState().inlineRuns().clear();
collectInlineContent();
- LineLayout(*this).layout();
+ LineLayout(*this).layout(availableWidth);
LOG_WITH_STREAM(FormattingContextLayout, stream << "[End] -> inline formatting context -> formatting root(" << &root << ")");
}
@@ -139,20 +140,7 @@
auto intrinsicWidths = layoutState.formattingStateForBox(*formattingRoot).intrinsicWidthConstraints(*formattingRoot);
layoutState.displayBoxForLayoutBox(*formattingRoot).setContentBoxWidth(availableWidth ? intrinsicWidths->maximum : intrinsicWidths->minimum);
}
- LayoutUnit maxContentLogicalRight;
- LayoutUnit lineLogicalRight;
-
- LineBreaker lineBreaker(layoutState);
- auto& inlineContent = formattingState().inlineItems();
- for (auto& inlineItem : inlineContent) {
- auto breakingContext = lineBreaker.breakingContext(*inlineItem, { availableWidth, lineLogicalRight, !lineLogicalRight });
- if (breakingContext.breakingBehavior == LineBreaker::BreakingBehavior::Wrap)
- lineLogicalRight = 0;
- lineLogicalRight += inlineItem->width();
-
- maxContentLogicalRight = std::max(maxContentLogicalRight, lineLogicalRight);
- }
- return maxContentLogicalRight;
+ return LineLayout(*this).computedIntrinsicWidth(availableWidth);
};
auto intrinsicWidthConstraints = Geometry::constrainByMinMaxWidth(root, { maximumLineWidth(0), maximumLineWidth(LayoutUnit::max()) });
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h (245810 => 245811)
--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h 2019-05-28 14:48:57 UTC (rev 245810)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h 2019-05-28 14:51:16 UTC (rev 245811)
@@ -53,11 +53,12 @@
class LineLayout {
public:
LineLayout(const InlineFormattingContext&);
- void layout() const;
+ void layout(LayoutUnit widthConstraint) const;
+ LayoutUnit computedIntrinsicWidth(LayoutUnit widthConstraint) const;
private:
LayoutState& layoutState() const { return m_formattingContext.layoutState(); }
- void initializeLine(Line&, LayoutUnit lineLogicalTop) const;
+ void initializeLine(Line&, LayoutUnit lineLogicalTop, LayoutUnit widthConstraint) const;
void closeLine(Line&) const;
void commitInlineItemToLine(Line&, const InlineItem&) const;
void handleFloat(Line&, const FloatingContext&, const InlineItem& floatBox) const;
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContextLineLayout.cpp (245810 => 245811)
--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContextLineLayout.cpp 2019-05-28 14:48:57 UTC (rev 245810)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContextLineLayout.cpp 2019-05-28 14:51:16 UTC (rev 245811)
@@ -363,11 +363,10 @@
{
}
-void InlineFormattingContext::LineLayout::initializeLine(Line& line, LayoutUnit lineLogicalTop) const
+void InlineFormattingContext::LineLayout::initializeLine(Line& line, LayoutUnit lineLogicalTop, LayoutUnit availableWidth) const
{
auto& formattingRootDisplayBox = layoutState().displayBoxForLayoutBox(m_formattingRoot);
auto lineLogicalLeft = formattingRootDisplayBox.contentBoxLeft();
- auto availableWidth = formattingRootDisplayBox.contentBoxWidth();
// Check for intruding floats and adjust logical left/available width for this line accordingly.
if (!m_floatingState.isEmpty()) {
@@ -399,11 +398,11 @@
line.reset({ lineLogicalLeft, lineLogicalTop }, availableWidth, mimimumLineHeight, baselineOffset);
}
-void InlineFormattingContext::LineLayout::layout() const
+void InlineFormattingContext::LineLayout::layout(LayoutUnit widthConstraint) const
{
auto floatingContext = FloatingContext { m_floatingState };
Line line(layoutState());
- initializeLine(line, layoutState().displayBoxForLayoutBox(m_formattingRoot).contentBoxTop());
+ initializeLine(line, layoutState().displayBoxForLayoutBox(m_formattingRoot).contentBoxTop(), widthConstraint);
UncommittedContent uncommittedContent;
auto commitPendingContent = [&] {
@@ -412,15 +411,19 @@
uncommittedContent.reset();
};
+ auto closeCurrentAndInitializeNewLine = [&] {
+ closeLine(line);
+ initializeLine(line, line.logicalBottom(), widthConstraint);
+ };
+
LineBreaker lineBreaker(layoutState());
auto& inlineContent = m_formattingState.inlineItems();
for (auto& inlineItem : inlineContent) {
// Iterate through the inline content and try to put the inline boxes on the current line.
if (inlineItem->isHardLineBreak()) {
- // Close the current line then create and immediately close another one.
commitPendingContent();
commitInlineItemToLine(line, *inlineItem);
- closeLine(line);
+ closeCurrentAndInitializeNewLine();
} else {
auto availableWidth = line.availableWidth() - uncommittedContent.width();
auto currentLogicalRight = line.contentLogicalRight() + uncommittedContent.width();
@@ -435,7 +438,7 @@
}
if (breakingContext.breakingBehavior == LineBreaker::BreakingBehavior::Wrap)
- closeLine(line);
+ closeCurrentAndInitializeNewLine();
if (inlineItem->isFloat())
handleFloat(line, floatingContext, *inlineItem);
@@ -450,12 +453,40 @@
// Process remaining uncommitted content.
if (!uncommittedContent.isEmpty()) {
if (line.availableWidth() < uncommittedContent.width())
- closeLine(line);
+ closeCurrentAndInitializeNewLine();
commitPendingContent();
}
closeLine(line);
}
+LayoutUnit InlineFormattingContext::LineLayout::computedIntrinsicWidth(LayoutUnit widthConstraint) const
+{
+ // FIXME: Consider running it through layout().
+ LayoutUnit maximumLineWidth;
+ LayoutUnit lineLogicalRight;
+ LayoutUnit trimmableTrailingWidth;
+
+ LineBreaker lineBreaker(layoutState());
+ auto& inlineContent = m_formattingState.inlineItems();
+ for (auto& inlineItem : inlineContent) {
+ auto breakingContext = lineBreaker.breakingContext(*inlineItem, { widthConstraint, lineLogicalRight, !lineLogicalRight });
+ if (breakingContext.breakingBehavior == LineBreaker::BreakingBehavior::Wrap) {
+ maximumLineWidth = std::max(maximumLineWidth, lineLogicalRight - trimmableTrailingWidth);
+ trimmableTrailingWidth = { };
+ lineLogicalRight = { };
+ }
+ if (isTrimmableContent(*inlineItem)) {
+ // Skip leading whitespace.
+ if (!lineLogicalRight)
+ continue;
+ trimmableTrailingWidth += inlineItem->width();
+ } else
+ trimmableTrailingWidth = { };
+ lineLogicalRight += inlineItem->width();
+ }
+ return std::max(maximumLineWidth, lineLogicalRight - trimmableTrailingWidth);
+}
+
void InlineFormattingContext::LineLayout::closeLine(Line& line) const
{
auto& lineItems = line.close();
@@ -556,7 +587,6 @@
m_formattingState.addLineBox({ lineBox });
if (line.hasContent())
alignRuns(m_formattingRoot.style().textAlign(), previousLineLastRunIndex.valueOr(-1) + 1, line.availableWidth());
- initializeLine(line, line.logicalBottom());
}
void InlineFormattingContext::LineLayout::handleFloat(Line& line, const FloatingContext& floatingContext, const InlineItem& floatItem) const