Title: [247644] trunk/Source/WebCore
Revision
247644
Author
za...@apple.com
Date
2019-07-19 06:35:42 -0700 (Fri, 19 Jul 2019)

Log Message

[LFC][IFC] Add partial content handling
https://bugs.webkit.org/show_bug.cgi?id=199930

Reviewed by Antti Koivisto.

Move the actual inline item placement to a dedicated functions. This enables us to
construct a dedicated InlineItem for the partial content and pass it in to this function.

<span>The quick brown fox jumps over the lazy dog</span> <- inline content
[The][ ][quick][ ][brown][ ][fox][ ][jumps][ ][over][ ][the][ ][lazy][ ][dog] <- InlineItems

Line breaking:
[The][ ][qu]
[ick] <- Partial InlineItem (position: 6 length: 3) from [quick] (position: 4 length: 5)

* layout/inlineformatting/InlineFormattingContextLineLayout.cpp:
(WebCore::Layout::LineLayout::close):
(WebCore::Layout::LineLayout::placeInlineItem):
(WebCore::Layout::LineLayout::layout):
(WebCore::Layout::LineInput::LineInput):
(WebCore::Layout::InlineFormattingContext::InlineLayout::layout const):
(WebCore::Layout::InlineFormattingContext::InlineLayout::computedIntrinsicWidth const):
* layout/inlineformatting/InlineTextItem.cpp:
(WebCore::Layout::InlineTextItem::split):
* layout/inlineformatting/InlineTextItem.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (247643 => 247644)


--- trunk/Source/WebCore/ChangeLog	2019-07-19 11:43:34 UTC (rev 247643)
+++ trunk/Source/WebCore/ChangeLog	2019-07-19 13:35:42 UTC (rev 247644)
@@ -1,3 +1,31 @@
+2019-07-19  Zalan Bujtas  <za...@apple.com>
+
+        [LFC][IFC] Add partial content handling
+        https://bugs.webkit.org/show_bug.cgi?id=199930
+
+        Reviewed by Antti Koivisto.
+
+        Move the actual inline item placement to a dedicated functions. This enables us to
+        construct a dedicated InlineItem for the partial content and pass it in to this function.
+
+        <span>The quick brown fox jumps over the lazy dog</span> <- inline content
+        [The][ ][quick][ ][brown][ ][fox][ ][jumps][ ][over][ ][the][ ][lazy][ ][dog] <- InlineItems
+
+        Line breaking:
+        [The][ ][qu]
+        [ick] <- Partial InlineItem (position: 6 length: 3) from [quick] (position: 4 length: 5)
+
+        * layout/inlineformatting/InlineFormattingContextLineLayout.cpp:
+        (WebCore::Layout::LineLayout::close):
+        (WebCore::Layout::LineLayout::placeInlineItem):
+        (WebCore::Layout::LineLayout::layout):
+        (WebCore::Layout::LineInput::LineInput):
+        (WebCore::Layout::InlineFormattingContext::InlineLayout::layout const):
+        (WebCore::Layout::InlineFormattingContext::InlineLayout::computedIntrinsicWidth const):
+        * layout/inlineformatting/InlineTextItem.cpp:
+        (WebCore::Layout::InlineTextItem::split):
+        * layout/inlineformatting/InlineTextItem.h:
+
 2019-07-19  Charlie Turner  <ctur...@igalia.com>
 
         [GStreamer] Flush get_range calls during PAUSED->READY in WebKitWebSource

Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContextLineLayout.cpp (247643 => 247644)


--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContextLineLayout.cpp	2019-07-19 11:43:34 UTC (rev 247643)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContextLineLayout.cpp	2019-07-19 13:35:42 UTC (rev 247644)
@@ -72,24 +72,28 @@
     return displayBox.width();
 }
 
-struct InlineIndexAndSplitPosition {
+struct IndexAndRange {
     unsigned index { 0 };
-    Optional<unsigned> splitPosition;
+    struct Range {
+        unsigned start { 0 };
+        unsigned length { 0 };
+    };
+    Optional<Range> partialContext;
 };
 
 struct LineInput {
-    LineInput(const Line::InitialConstraints& initialLineConstraints, Line::SkipVerticalAligment, InlineIndexAndSplitPosition firstToProcess, const InlineItems&);
+    LineInput(const Line::InitialConstraints& initialLineConstraints, Line::SkipVerticalAligment, IndexAndRange firstToProcess, const InlineItems&);
 
     Line::InitialConstraints initialConstraints;
     // FIXME Alternatively we could just have a second pass with vertical positioning (preferred width computation opts out) 
     Line::SkipVerticalAligment skipVerticalAligment;
-    InlineIndexAndSplitPosition firstInlineItem;
+    IndexAndRange firstInlineItem;
     const InlineItems& inlineItems;
     Optional<LayoutUnit> floatMinimumLogicalBottom;
 };
 
 struct LineContent {
-    Optional<InlineIndexAndSplitPosition> lastCommitted;
+    Optional<IndexAndRange> lastCommitted;
     Vector<WeakPtr<InlineItem>> floats;
     std::unique_ptr<Line::Content> runs;
 };
@@ -102,6 +106,8 @@
 
 private:
     const LayoutState& layoutState() const { return m_layoutState; }
+    enum class IsEndOfLine { No, Yes };
+    IsEndOfLine placeInlineItem(const InlineItem&);
     void commitPendingContent();
     LineContent close();
     
@@ -132,7 +138,6 @@
     UncommittedContent m_uncommittedContent;
     unsigned m_committedInlineItemCount { 0 };
     Vector<WeakPtr<InlineItem>> m_floats;
-    Optional<unsigned> m_splitPosition;
 };
 
 void LineLayout::UncommittedContent::add(const InlineItem& inlineItem, LayoutUnit logicalWidth)
@@ -170,62 +175,82 @@
     ASSERT(m_committedInlineItemCount || m_lineHasFloatBox);
     if (!m_committedInlineItemCount)
         return LineContent { WTF::nullopt, WTFMove(m_floats), m_line.close() };
-    auto lastCommitedItem = InlineIndexAndSplitPosition { m_lineInput.firstInlineItem.index + (m_committedInlineItemCount - 1), m_splitPosition };
+    // FIXME Add partial context if applicable.
+    auto lastCommitedItem = IndexAndRange { m_lineInput.firstInlineItem.index + (m_committedInlineItemCount - 1), { } };
     return LineContent { lastCommitedItem, WTFMove(m_floats), m_line.close() };
 }
 
-LineContent LineLayout::layout()
+LineLayout::IsEndOfLine LineLayout::placeInlineItem(const InlineItem& inlineItem)
 {
-    // Iterate through the inline content and place the inline boxes on the current line.
-    for (auto inlineItemIndex = m_lineInput.firstInlineItem.index; inlineItemIndex < m_lineInput.inlineItems.size(); ++inlineItemIndex) {
-        auto availableWidth = m_line.availableWidth() - m_uncommittedContent.width();
-        auto currentLogicalRight = m_line.contentLogicalRight() + m_uncommittedContent.width();
-        auto& inlineItem = m_lineInput.inlineItems[inlineItemIndex];
-        auto itemLogicalWidth = inlineItemWidth(layoutState(), *inlineItem, currentLogicalRight);
+    auto availableWidth = m_line.availableWidth() - m_uncommittedContent.width();
+    auto currentLogicalRight = m_line.contentLogicalRight() + m_uncommittedContent.width();
+    auto itemLogicalWidth = inlineItemWidth(layoutState(), inlineItem, currentLogicalRight);
 
-        // FIXME: Ensure LineContext::trimmableWidth includes uncommitted content if needed.
-        auto lineIsConsideredEmpty = !m_line.hasContent() && !m_lineHasFloatBox;
-        auto breakingContext = m_lineBreaker.breakingContext(*inlineItem, itemLogicalWidth, { availableWidth, currentLogicalRight, m_line.trailingTrimmableWidth(), lineIsConsideredEmpty });
-        if (breakingContext.isAtBreakingOpportunity)
-            commitPendingContent();
+    // FIXME: Ensure LineContext::trimmableWidth includes uncommitted content if needed.
+    auto lineIsConsideredEmpty = !m_line.hasContent() && !m_lineHasFloatBox;
+    auto breakingContext = m_lineBreaker.breakingContext(inlineItem, itemLogicalWidth, { availableWidth, currentLogicalRight, m_line.trailingTrimmableWidth(), lineIsConsideredEmpty });
+    if (breakingContext.isAtBreakingOpportunity)
+        commitPendingContent();
 
-        // Content does not fit the current line.
-        if (breakingContext.breakingBehavior == LineBreaker::BreakingBehavior::Wrap)
-            return close();
+    // Content does not fit the current line.
+    if (breakingContext.breakingBehavior == LineBreaker::BreakingBehavior::Wrap)
+        return IsEndOfLine::Yes;
 
-        // Partial content stays on the current line. 
-        if (breakingContext.breakingBehavior == LineBreaker::BreakingBehavior::Split) {
-            ASSERT(inlineItem->isText());
+    // Partial content stays on the current line.
+    if (breakingContext.breakingBehavior == LineBreaker::BreakingBehavior::Split) {
+        ASSERT(inlineItem.isText());
 
-            ASSERT_NOT_IMPLEMENTED_YET();
-            return close();
-        }
+        ASSERT_NOT_IMPLEMENTED_YET();
+        return IsEndOfLine::Yes;
+    }
 
-        ASSERT(breakingContext.breakingBehavior == LineBreaker::BreakingBehavior::Keep);
-        if (inlineItem->isFloat()) {
-            auto& floatBox = inlineItem->layoutBox();
-            ASSERT(layoutState().hasDisplayBox(floatBox));
-            // Shrink availble space for current line and move existing inline runs.
-            auto floatBoxWidth = layoutState().displayBoxForLayoutBox(floatBox).marginBoxWidth();
-            floatBox.isLeftFloatingPositioned() ? m_line.moveLogicalLeft(floatBoxWidth) : m_line.moveLogicalRight(floatBoxWidth);
-            m_floats.append(makeWeakPtr(*inlineItem));
-            ++m_committedInlineItemCount;
-            m_lineHasFloatBox = true;
-            continue;
-        }
+    ASSERT(breakingContext.breakingBehavior == LineBreaker::BreakingBehavior::Keep);
+    if (inlineItem.isFloat()) {
+        auto& floatBox = inlineItem.layoutBox();
+        ASSERT(layoutState().hasDisplayBox(floatBox));
+        // Shrink available space for current line and move existing inline runs.
+        auto floatBoxWidth = layoutState().displayBoxForLayoutBox(floatBox).marginBoxWidth();
+        floatBox.isLeftFloatingPositioned() ? m_line.moveLogicalLeft(floatBoxWidth) : m_line.moveLogicalRight(floatBoxWidth);
+        m_floats.append(makeWeakPtr(inlineItem));
+        ++m_committedInlineItemCount;
+        m_lineHasFloatBox = true;
+        return IsEndOfLine::No;
+    }
 
-        m_uncommittedContent.add(*inlineItem, itemLogicalWidth);
-        if (breakingContext.isAtBreakingOpportunity)
-            commitPendingContent();
+    m_uncommittedContent.add(inlineItem, itemLogicalWidth);
+    if (breakingContext.isAtBreakingOpportunity)
+        commitPendingContent();
 
-        if (inlineItem->isHardLineBreak())
+    return inlineItem.isHardLineBreak() ? IsEndOfLine::Yes : IsEndOfLine::No;
+}
+
+LineContent LineLayout::layout()
+{
+    // Iterate through the inline content and place the inline boxes on the current line.
+    // Start with the partial text from the previous line.
+    auto firstInlineItem = m_lineInput.firstInlineItem;
+    unsigned firstNonPartialIndex = firstInlineItem.index;
+    if (firstInlineItem.partialContext) {
+        // Handle partial inline item (split text from the previous line).
+        auto& originalTextItem = m_lineInput.inlineItems[firstInlineItem.index];
+        RELEASE_ASSERT(originalTextItem->isText());
+
+        auto textRange = *firstInlineItem.partialContext;
+        auto partialInlineItem = downcast<InlineTextItem>(*originalTextItem).split(textRange.start, textRange.length);
+        if (placeInlineItem(partialInlineItem) == IsEndOfLine::Yes)
             return close();
+        ++firstNonPartialIndex;
     }
+
+    for (auto inlineItemIndex = firstNonPartialIndex; inlineItemIndex < m_lineInput.inlineItems.size(); ++inlineItemIndex) {
+        if (placeInlineItem(*m_lineInput.inlineItems[inlineItemIndex]) == IsEndOfLine::Yes)
+            return close();
+    }
     commitPendingContent();
     return close();
 }
 
-LineInput::LineInput(const Line::InitialConstraints& initialLineConstraints, Line::SkipVerticalAligment skipVerticalAligment, InlineIndexAndSplitPosition firstToProcess, const InlineItems& inlineItems)
+LineInput::LineInput(const Line::InitialConstraints& initialLineConstraints, Line::SkipVerticalAligment skipVerticalAligment, IndexAndRange firstToProcess, const InlineItems& inlineItems)
     : initialConstraints(initialLineConstraints)
     , skipVerticalAligment(skipVerticalAligment)
     , firstInlineItem(firstToProcess)
@@ -285,7 +310,7 @@
         lineInput.initialConstraints.logicalTopLeft.setX(lineLogicalLeft);
     };
 
-    InlineIndexAndSplitPosition currentInlineItem;
+    IndexAndRange currentInlineItem;
     while (currentInlineItem.index < inlineItems.size()) {
         auto lineInput = LineInput { { { lineLogicalLeft, lineLogicalTop }, widthConstraint, Quirks::lineHeightConstraints(layoutState(), m_formattingRoot) }, Line::SkipVerticalAligment::No, currentInlineItem, inlineItems };
         applyFloatConstraint(lineInput);
@@ -306,7 +331,7 @@
 LayoutUnit InlineFormattingContext::InlineLayout::computedIntrinsicWidth(const InlineItems& inlineItems, LayoutUnit widthConstraint) const
 {
     LayoutUnit maximumLineWidth;
-    InlineIndexAndSplitPosition currentInlineItem;
+    IndexAndRange currentInlineItem;
     while (currentInlineItem.index < inlineItems.size()) {
         auto lineContent = LineLayout(layoutState(), { { { }, widthConstraint, Quirks::lineHeightConstraints(layoutState(), m_formattingRoot) }, Line::SkipVerticalAligment::Yes, currentInlineItem, inlineItems }).layout();
         currentInlineItem = { lineContent.lastCommitted->index + 1, WTF::nullopt };

Modified: trunk/Source/WebCore/layout/inlineformatting/InlineTextItem.cpp (247643 => 247644)


--- trunk/Source/WebCore/layout/inlineformatting/InlineTextItem.cpp	2019-07-19 11:43:34 UTC (rev 247643)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineTextItem.cpp	2019-07-19 13:35:42 UTC (rev 247644)
@@ -127,6 +127,13 @@
 {
 }
 
+InlineTextItem InlineTextItem::split(unsigned splitPosition, unsigned length)
+{
+    RELEASE_ASSERT(splitPosition >= this->start());
+    RELEASE_ASSERT(splitPosition + length <= end());
+    return { downcast<InlineBox>(layoutBox()), splitPosition, length, isWhitespace(), isCollapsed() };
 }
+
 }
+}
 #endif

Modified: trunk/Source/WebCore/layout/inlineformatting/InlineTextItem.h (247643 => 247644)


--- trunk/Source/WebCore/layout/inlineformatting/InlineTextItem.h	2019-07-19 11:43:34 UTC (rev 247643)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineTextItem.h	2019-07-19 13:35:42 UTC (rev 247644)
@@ -46,6 +46,8 @@
     bool isWhitespace() const { return m_isWhitespace; }
     bool isCollapsed() const { return m_isCollapsed; }
 
+    InlineTextItem split(unsigned splitPosition, unsigned length);
+
 private:
     unsigned m_start { 0 };
     unsigned m_length { 0 };
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to