Modified: trunk/Source/WebCore/ChangeLog (270426 => 270427)
--- trunk/Source/WebCore/ChangeLog 2020-12-04 09:41:08 UTC (rev 270426)
+++ trunk/Source/WebCore/ChangeLog 2020-12-04 12:26:38 UTC (rev 270427)
@@ -1,3 +1,25 @@
+2020-12-04 Zalan Bujtas <[email protected]>
+
+ [LFC][IFC] Decouple inline content and float handling in LineBuilder
+ https://bugs.webkit.org/show_bug.cgi?id=219522
+
+ Reviewed by Antti Koivisto.
+
+ The line candidate content is either a list of inline runs or an individual float box. Let's process them separately.
+
+ This is in preparation for adding support for "vertically stretchy" lines vs. intrusive floats where the line height
+ may change as we add new inline level boxes and we need to probe against existing floats.
+
+ * layout/inlineformatting/InlineLineBuilder.cpp:
+ (WebCore::Layout::LineCandidate::InlineContent::continuousContent const):
+ (WebCore::Layout::LineCandidate::InlineContent::isEmpty const):
+ (WebCore::Layout::LineBuilder::placeInlineContent):
+ (WebCore::Layout::LineBuilder::handleFloatContent):
+ (WebCore::Layout::LineBuilder::handleInlineContent):
+ (WebCore::Layout::LineCandidate::InlineContent::operator() const): Deleted.
+ (WebCore::Layout::LineBuilder::handleFloatOrInlineContent): Deleted.
+ * layout/inlineformatting/InlineLineBuilder.h:
+
2020-12-03 Simon Fraser <[email protected]>
Only the first wheel event in a gesture should be cancelable
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp (270426 => 270427)
--- trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp 2020-12-04 09:41:08 UTC (rev 270426)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp 2020-12-04 12:26:38 UTC (rev 270427)
@@ -129,7 +129,7 @@
struct InlineContent {
InlineContent(bool ignoreTrailingLetterSpacing);
- const InlineContentBreaker::ContinuousContent& operator()() const { return m_continuousContent; }
+ const InlineContentBreaker::ContinuousContent& continuousContent() const { return m_continuousContent; }
const InlineItem* trailingLineBreak() const { return m_trailingLineBreak; }
const InlineItem* trailingWordBreakOpportunity() const { return m_trailingWordBreakOpportunity; }
@@ -137,6 +137,7 @@
void appendTrailingLineBreak(const InlineItem& lineBreakItem) { m_trailingLineBreak = &lineBreakItem; }
void appendtrailingWordBreakOpportunity(const InlineItem& wordBreakItem) { m_trailingWordBreakOpportunity = &wordBreakItem; }
void reset();
+ bool isEmpty() const { return m_continuousContent.runs().isEmpty() && !trailingWordBreakOpportunity() && !trailingLineBreak(); }
private:
bool m_ignoreTrailingLetterSpacing { false };
@@ -289,10 +290,15 @@
// 4. Return if we are at the end of the line either by not being able to fit more content or because of an explicit line break.
candidateContentForLine(lineCandidate, currentItemIndex, needsLayoutRange, partialLeadingContentLength, m_line.contentLogicalWidth());
// Now check if we can put this content on the current line.
- auto result = handleFloatOrInlineContent(inlineContentBreaker, needsLayoutRange, lineCandidate);
+ auto result = Result { };
+ if (lineCandidate.floatItem) {
+ ASSERT(lineCandidate.inlineContent.isEmpty());
+ result = handleFloatContent(*lineCandidate.floatItem);
+ } else
+ result = handleInlineContent(inlineContentBreaker, needsLayoutRange, lineCandidate);
committedInlineItemCount = result.committedCount.isRevert ? result.committedCount.value : committedInlineItemCount + result.committedCount.value;
auto& inlineContent = lineCandidate.inlineContent;
- auto inlineContentIsFullyCommitted = inlineContent().runs().size() == result.committedCount.value && !result.partialTrailingContentLength;
+ auto inlineContentIsFullyCommitted = inlineContent.continuousContent().runs().size() == result.committedCount.value && !result.partialTrailingContentLength;
auto isEndOfLine = result.isEndOfLine == InlineContentBreaker::IsEndOfLine::Yes;
if (inlineContentIsFullyCommitted) {
@@ -523,28 +529,30 @@
return layoutRange.end;
}
-LineBuilder::Result LineBuilder::handleFloatOrInlineContent(InlineContentBreaker& inlineContentBreaker, const InlineItemRange& layoutRange, const LineCandidate& lineCandidate)
+LineBuilder::Result LineBuilder::handleFloatContent(const InlineItem& floatItem)
{
- if (lineCandidate.inlineContent().runs().isEmpty() && !lineCandidate.floatItem) {
- auto& inlineContent = lineCandidate.inlineContent;
+ auto availableWidth = m_horizontalSpaceForLine - m_line.contentLogicalWidth();
+ auto floatBoxWidth = inlineItemWidth(floatItem, { });
+ if (floatBoxWidth > availableWidth && !m_line.isConsideredEmpty())
+ return { InlineContentBreaker::IsEndOfLine::Yes };
+ // This float shrinks the current line.
+ auto& floatBox = floatItem.layoutBox();
+ m_floats.append(&floatBox);
+ m_contentIsConstrainedByFloat = true;
+ if (floatBox.isLeftFloatingPositioned())
+ m_line.moveLogicalLeft(floatBoxWidth);
+ m_horizontalSpaceForLine -= floatBoxWidth;
+ return { InlineContentBreaker::IsEndOfLine::No };
+}
+
+LineBuilder::Result LineBuilder::handleInlineContent(InlineContentBreaker& inlineContentBreaker, const InlineItemRange& layoutRange, const LineCandidate& lineCandidate)
+{
+ auto& inlineContent = lineCandidate.inlineContent;
+ if (inlineContent.continuousContent().runs().isEmpty()) {
ASSERT(inlineContent.trailingLineBreak() || inlineContent.trailingWordBreakOpportunity());
return { inlineContent.trailingLineBreak() ? InlineContentBreaker::IsEndOfLine::Yes : InlineContentBreaker::IsEndOfLine::No };
}
auto availableWidth = m_horizontalSpaceForLine - m_line.contentLogicalWidth();
- if (lineCandidate.floatItem) {
- auto floatBoxWidth = inlineItemWidth(*lineCandidate.floatItem, { });
- if (floatBoxWidth > availableWidth && !m_line.isConsideredEmpty())
- return { InlineContentBreaker::IsEndOfLine::Yes };
- // This float shrinks the current line.
- auto& floatBox = lineCandidate.floatItem->layoutBox();
- m_floats.append(&floatBox);
- m_contentIsConstrainedByFloat = true;
- if (floatBox.isLeftFloatingPositioned())
- m_line.moveLogicalLeft(floatBoxWidth);
- m_horizontalSpaceForLine -= floatBoxWidth;
- return { InlineContentBreaker::IsEndOfLine::No };
- }
-
auto shouldDisableHyphenation = [&] {
auto& style = root().style();
unsigned limitLines = style.hyphenationLimitLines() == RenderStyle::initialHyphenationLimitLines() ? std::numeric_limits<unsigned>::max() : style.hyphenationLimitLines();
@@ -554,7 +562,7 @@
inlineContentBreaker.setHyphenationDisabled();
// Check if this new content fits.
- auto& continuousInlineContent = lineCandidate.inlineContent();
+ auto& continuousInlineContent = lineCandidate.inlineContent.continuousContent();
auto isLineConsideredEmpty = m_line.isConsideredEmpty() && !m_contentIsConstrainedByFloat;
auto lineStatus = InlineContentBreaker::LineStatus { m_line.contentLogicalWidth(), availableWidth, m_line.trimmableTrailingWidth(), m_line.trailingSoftHyphenWidth(), m_line.isTrailingRunFullyTrimmable(), isLineConsideredEmpty };
auto result = inlineContentBreaker.processInlineContent(continuousInlineContent, lineStatus);
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.h (270426 => 270427)
--- trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.h 2020-12-04 09:41:08 UTC (rev 270426)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.h 2020-12-04 12:26:38 UTC (rev 270427)
@@ -87,7 +87,8 @@
bool isConstrainedByFloat { false };
};
UsedConstraints constraintsForLine(const InlineRect& initialLineConstraints, bool isFirstLine);
- Result handleFloatOrInlineContent(InlineContentBreaker&, const InlineItemRange& needsLayoutRange, const LineCandidate&);
+ Result handleFloatContent(const InlineItem&);
+ Result handleInlineContent(InlineContentBreaker&, const InlineItemRange& needsLayoutRange, const LineCandidate&);
size_t rebuildLine(const InlineItemRange& needsLayoutRange, const InlineItem& lastInlineItemToAdd);
size_t rebuildLineForTrailingSoftHyphen(const InlineItemRange& layoutRange);
void commitPartialContent(const InlineContentBreaker::ContinuousContent::RunList&, const InlineContentBreaker::Result::PartialTrailingContent&);