Changeset 252861 in webkit


Ignore:
Timestamp:
Nov 25, 2019 8:13:18 AM (4 years ago)
Author:
Alan Bujtas
Message:

[LFC][IFC] Construct only one LineLayout object per inline formatting context
https://bugs.webkit.org/show_bug.cgi?id=204561
<rdar://problem/57463666>

Reviewed by Antti Koivisto.

Let's construct only one LineLayout object per IFC.

  • layout/inlineformatting/InlineFormattingContext.cpp:

(WebCore::Layout::InlineFormattingContext::lineLayout):
(WebCore::Layout::InlineFormattingContext::computedIntrinsicWidthForConstraint const):

  • layout/inlineformatting/InlineLineLayout.cpp:

(WebCore::Layout::LineLayout::LineLayout):
(WebCore::Layout::LineLayout::layout):
(WebCore::Layout::LineLayout::close):
(WebCore::Layout::LineLayout::LineInput::LineInput): Deleted.

  • layout/inlineformatting/InlineLineLayout.h:
Location:
trunk/Source/WebCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r252859 r252861  
     12019-11-25  Zalan Bujtas  <zalan@apple.com>
     2
     3        [LFC][IFC] Construct only one LineLayout object per inline formatting context
     4        https://bugs.webkit.org/show_bug.cgi?id=204561
     5        <rdar://problem/57463666>
     6
     7        Reviewed by Antti Koivisto.
     8
     9        Let's construct only one LineLayout object per IFC.
     10
     11        * layout/inlineformatting/InlineFormattingContext.cpp:
     12        (WebCore::Layout::InlineFormattingContext::lineLayout):
     13        (WebCore::Layout::InlineFormattingContext::computedIntrinsicWidthForConstraint const):
     14        * layout/inlineformatting/InlineLineLayout.cpp:
     15        (WebCore::Layout::LineLayout::LineLayout):
     16        (WebCore::Layout::LineLayout::layout):
     17        (WebCore::Layout::LineLayout::close):
     18        (WebCore::Layout::LineLayout::LineInput::LineInput): Deleted.
     19        * layout/inlineformatting/InlineLineLayout.h:
     20
    1212019-11-25  Zalan Bujtas  <zalan@apple.com>
    222
  • trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp

    r252859 r252861  
    9797    Optional<LineLayout::PartialContent> leadingPartialContent;
    9898    auto line = Line { *this, root().style().textAlign(), Line::SkipAlignment::No };
     99    auto lineLayout = LineLayout { *this, inlineItems };
    99100
    100101    while (leadingInlineItemIndex < inlineItems.size()) {
    101102        line.initialize(constraintsForLine(usedHorizontalValues, lineLogicalTop));
    102         auto lineInput = LineLayout::LineInput { inlineItems, leadingInlineItemIndex, leadingPartialContent };
    103         auto lineLayout = LineLayout { *this, lineInput, line };
    104 
    105         auto lineContent = lineLayout.layout();
     103        auto lineContent = lineLayout.layout(line, leadingInlineItemIndex, leadingPartialContent);
    106104        setDisplayBoxesForLine(lineContent, usedHorizontalValues);
    107105
     
    237235    unsigned leadingInlineItemIndex = 0;
    238236    auto line = Line { *this, root().style().textAlign(), Line::SkipAlignment::Yes };
     237    auto lineLayout = LineLayout { *this, inlineItems };
    239238    while (leadingInlineItemIndex < inlineItems.size()) {
    240239        // Only the horiztonal available width is constrained when computing intrinsic width.
    241240        line.initialize(Line::Constraints { { }, usedHorizontalValues.constraints.width, false, { } });
    242         auto lineInput = LineLayout::LineInput { inlineItems, leadingInlineItemIndex, { } };
    243 
    244         auto lineContent = LineLayout(*this, lineInput, line).layout();
     241        auto lineContent = lineLayout.layout(line, leadingInlineItemIndex, { });
    245242
    246243        leadingInlineItemIndex = *lineContent.trailingInlineItemIndex + 1;
  • trunk/Source/WebCore/layout/inlineformatting/InlineLineLayout.cpp

    r252859 r252861  
    6868}
    6969
    70 LineLayout::LineInput::LineInput(const InlineItems& inlineItems, unsigned leadingInlineItemIndex, Optional<PartialContent> leadingPartialContent)
    71     : inlineItems(inlineItems)
    72     , leadingInlineItemIndex(leadingInlineItemIndex)
    73     , leadingPartialContent(leadingPartialContent)
    74 {
    75 }
    76 
    7770void LineLayout::UncommittedContent::add(const InlineItem& inlineItem, LayoutUnit logicalWidth)
    7871{
     
    8780}
    8881
    89 LineLayout::LineLayout(const InlineFormattingContext& inlineFormattingContext, const LineInput& lineInput, Line& line)
     82LineLayout::LineLayout(const InlineFormattingContext& inlineFormattingContext, const InlineItems& inlineItems)
    9083    : m_inlineFormattingContext(inlineFormattingContext)
    91     , m_lineInput(lineInput)
    92     , m_line(line)
    93 {
    94 }
    95 
    96 LineLayout::LineContent LineLayout::layout()
    97 {
     84    , m_inlineItems(inlineItems)
     85{
     86}
     87
     88LineLayout::LineContent LineLayout::layout(Line& line, unsigned leadingInlineItemIndex, Optional<PartialContent> leadingPartialContent)
     89{
     90    auto initialize = [&] {
     91        m_committedInlineItemCount = 0;
     92        m_uncommittedContent.reset();
     93        m_leadingPartialTextItem = { };
     94        m_trailingPartialTextItem = { };
     95        m_overflowTextLength = { };
     96    };
     97    initialize();
    9898    // Iterate through the inline content and place the inline boxes on the current line.
    9999    // Start with the partial leading text from the previous line.
    100     auto firstNonPartialInlineItemIndex = m_lineInput.leadingInlineItemIndex;
    101     if (m_lineInput.leadingPartialContent) {
     100    auto firstNonPartialInlineItemIndex = leadingInlineItemIndex;
     101    if (leadingPartialContent) {
    102102        // Handle partial inline item (split text from the previous line).
    103         auto& leadingTextItem = m_lineInput.inlineItems[m_lineInput.leadingInlineItemIndex];
     103        auto& leadingTextItem = m_inlineItems[leadingInlineItemIndex];
    104104        RELEASE_ASSERT(leadingTextItem->isText());
    105105        // Construct a partial leading inline item.
    106106        ASSERT(!m_leadingPartialTextItem);
    107         m_leadingPartialTextItem = downcast<InlineTextItem>(*leadingTextItem).right(m_lineInput.leadingPartialContent->length);
    108         if (placeInlineItem(*m_leadingPartialTextItem) == IsEndOfLine::Yes)
    109             return close();
     107        m_leadingPartialTextItem = downcast<InlineTextItem>(*leadingTextItem).right(leadingPartialContent->length);
     108        if (placeInlineItem(line, *m_leadingPartialTextItem) == IsEndOfLine::Yes)
     109            return close(line, leadingInlineItemIndex);
    110110        ++firstNonPartialInlineItemIndex;
    111111    }
    112112
    113     for (auto inlineItemIndex = firstNonPartialInlineItemIndex; inlineItemIndex < m_lineInput.inlineItems.size(); ++inlineItemIndex) {
     113    for (auto inlineItemIndex = firstNonPartialInlineItemIndex; inlineItemIndex < m_inlineItems.size(); ++inlineItemIndex) {
    114114        // FIXME: We should not need to re-measure the dropped, uncommitted content when re-using them on the next line.
    115         if (placeInlineItem(*m_lineInput.inlineItems[inlineItemIndex]) == IsEndOfLine::Yes)
    116             return close();
     115        if (placeInlineItem(line, *m_inlineItems[inlineItemIndex]) == IsEndOfLine::Yes)
     116            return close(line, leadingInlineItemIndex);
    117117    }
    118118    // Check the uncommitted content whether they fit now that we know we are at a commit boundary.
    119119    if (!m_uncommittedContent.isEmpty())
    120         processUncommittedContent();
    121     return close();
    122 }
    123 
    124 void LineLayout::commitPendingContent()
     120        processUncommittedContent(line);
     121    return close(line, leadingInlineItemIndex);
     122}
     123
     124void LineLayout::commitPendingContent(Line& line)
    125125{
    126126    if (m_uncommittedContent.isEmpty())
     
    128128    m_committedInlineItemCount += m_uncommittedContent.size();
    129129    for (auto& uncommittedRun : m_uncommittedContent.runs())
    130         m_line.append(uncommittedRun.inlineItem, uncommittedRun.logicalWidth);
     130        line.append(uncommittedRun.inlineItem, uncommittedRun.logicalWidth);
    131131    m_uncommittedContent.reset();
    132132}
    133133
    134 LineLayout::LineContent LineLayout::close()
    135 {
    136     ASSERT(m_committedInlineItemCount || m_line.hasIntrusiveFloat());
     134LineLayout::LineContent LineLayout::close(Line& line, unsigned leadingInlineItemIndex)
     135{
     136    ASSERT(m_committedInlineItemCount || line.hasIntrusiveFloat());
    137137    m_uncommittedContent.reset();
    138138    if (!m_committedInlineItemCount)
    139         return LineContent { { }, { }, WTFMove(m_floats), m_line.close(), m_line.lineBox() };
     139        return LineContent { { }, { }, WTFMove(m_floats), line.close(), line.lineBox() };
    140140
    141141    Optional<PartialContent> overflowContent;
    142142    if (m_overflowTextLength)
    143143        overflowContent = PartialContent { *m_overflowTextLength };
    144     auto trailingInlineItemIndex = m_lineInput.leadingInlineItemIndex + m_committedInlineItemCount - 1;
     144    auto trailingInlineItemIndex = leadingInlineItemIndex + m_committedInlineItemCount - 1;
    145145
    146146    auto isLastLineWithInlineContent = [&] {
     
    148148            return Line::IsLastLineWithInlineContent::No;
    149149        // Skip floats backwards to see if this is going to be the last line with inline content.
    150         for (auto i = m_lineInput.inlineItems.size(); i--;) {
    151             if (!m_lineInput.inlineItems[i]->isFloat())
     150        for (auto i = m_inlineItems.size(); i--;) {
     151            if (!m_inlineItems[i]->isFloat())
    152152                return i == trailingInlineItemIndex ? Line::IsLastLineWithInlineContent::Yes : Line::IsLastLineWithInlineContent::No;
    153153        }
     
    157157    };
    158158
    159     return LineContent { trailingInlineItemIndex, overflowContent, WTFMove(m_floats), m_line.close(isLastLineWithInlineContent()), m_line.lineBox() };
    160 }
    161 
    162 LineLayout::IsEndOfLine LineLayout::placeInlineItem(const InlineItem& inlineItem)
    163 {
    164     auto currentLogicalRight = m_line.lineBox().logicalRight();
     159    return LineContent { trailingInlineItemIndex, overflowContent, WTFMove(m_floats), line.close(isLastLineWithInlineContent()), line.lineBox() };
     160}
     161
     162LineLayout::IsEndOfLine LineLayout::placeInlineItem(Line& line, const InlineItem& inlineItem)
     163{
     164    auto currentLogicalRight = line.lineBox().logicalRight();
    165165    auto itemLogicalWidth = inlineItemWidth(formattingContext(), inlineItem, currentLogicalRight);
    166166
     
    172172        // Let's just commit the pending content and try placing the float for now.
    173173        if (!m_uncommittedContent.isEmpty()) {
    174             if (processUncommittedContent() == IsEndOfLine::Yes)
     174            if (processUncommittedContent(line) == IsEndOfLine::Yes)
    175175                return IsEndOfLine::Yes;
    176176        }
    177         auto lineIsConsideredEmpty = m_line.isVisuallyEmpty() && !m_line.hasIntrusiveFloat();
    178         if (LineBreaker().shouldWrapFloatBox(itemLogicalWidth, m_line.availableWidth() + m_line.trailingTrimmableWidth(), lineIsConsideredEmpty))
     177        auto lineIsConsideredEmpty = line.isVisuallyEmpty() && !line.hasIntrusiveFloat();
     178        if (LineBreaker().shouldWrapFloatBox(itemLogicalWidth, line.availableWidth() + line.trailingTrimmableWidth(), lineIsConsideredEmpty))
    179179            return IsEndOfLine::Yes;
    180180
     
    182182        auto& floatBox = inlineItem.layoutBox();
    183183        // Shrink available space for current line and move existing inline runs.
    184         floatBox.isLeftFloatingPositioned() ? m_line.moveLogicalLeft(itemLogicalWidth) : m_line.moveLogicalRight(itemLogicalWidth);
     184        floatBox.isLeftFloatingPositioned() ? line.moveLogicalLeft(itemLogicalWidth) : line.moveLogicalRight(itemLogicalWidth);
    185185        m_floats.append(makeWeakPtr(inlineItem));
    186186        ++m_committedInlineItemCount;
    187         m_line.setHasIntrusiveFloat();
     187        line.setHasIntrusiveFloat();
    188188        return IsEndOfLine::No;
    189189    }
    190190    // Forced line breaks are also special.
    191191    if (inlineItem.isForcedLineBreak()) {
    192         auto isEndOfLine = !m_uncommittedContent.isEmpty() ? processUncommittedContent() : IsEndOfLine::No;
     192        auto isEndOfLine = !m_uncommittedContent.isEmpty() ? processUncommittedContent(line) : IsEndOfLine::No;
    193193        // When the uncommitted content fits(or the line is empty), add the line break to this line as well.
    194194        if (isEndOfLine == IsEndOfLine::No) {
    195195            m_uncommittedContent.add(inlineItem, itemLogicalWidth);
    196             commitPendingContent();
     196            commitPendingContent(line);
    197197        }
    198198        return IsEndOfLine::Yes;
     
    201201    auto isEndOfLine = IsEndOfLine::No;
    202202    if (!m_uncommittedContent.isEmpty() && shouldProcessUncommittedContent(inlineItem))
    203         isEndOfLine = processUncommittedContent();
     203        isEndOfLine = processUncommittedContent(line);
    204204    // The current item might fit as well.
    205205    if (isEndOfLine == IsEndOfLine::No)
     
    208208}
    209209
    210 LineLayout::IsEndOfLine LineLayout::processUncommittedContent()
     210LineLayout::IsEndOfLine LineLayout::processUncommittedContent(Line& line)
    211211{
    212212    // Check if the pending content fits.
    213     auto lineIsConsideredEmpty = m_line.isVisuallyEmpty() && !m_line.hasIntrusiveFloat();
    214     auto breakingContext = LineBreaker().breakingContextForInlineContent(m_uncommittedContent.runs(), m_uncommittedContent.width(), m_line.availableWidth(), lineIsConsideredEmpty);
     213    auto lineIsConsideredEmpty = line.isVisuallyEmpty() && !line.hasIntrusiveFloat();
     214    auto breakingContext = LineBreaker().breakingContextForInlineContent(m_uncommittedContent.runs(), m_uncommittedContent.width(), line.availableWidth(), lineIsConsideredEmpty);
    215215    // The uncommitted content can fully, partially fit the current line (commit/partial commit) or not at all (reset).
    216216    if (breakingContext.contentBreak == LineBreaker::BreakingContext::ContentBreak::Keep)
    217         commitPendingContent();
     217        commitPendingContent(line);
    218218    else if (breakingContext.contentBreak == LineBreaker::BreakingContext::ContentBreak::Split) {
    219219        ASSERT(breakingContext.trailingPartialContent);
     
    231231        m_uncommittedContent.trim(overflowInlineTextItemIndex);
    232232        m_uncommittedContent.add(*m_trailingPartialTextItem, breakingContext.trailingPartialContent->logicalWidth);
    233         commitPendingContent();
     233        commitPendingContent(line);
    234234    } else if (breakingContext.contentBreak == LineBreaker::BreakingContext::ContentBreak::Wrap)
    235235        m_uncommittedContent.reset();
  • trunk/Source/WebCore/layout/inlineformatting/InlineLineLayout.h

    r252859 r252861  
    3636class LineLayout {
    3737public:
    38     struct LineInput;
    39     LineLayout(const InlineFormattingContext&, const LineInput&, Line&);
    40 
    41     struct LineContent;
    42     LineContent layout();
     38    LineLayout(const InlineFormattingContext&, const InlineItems&);
    4339
    4440    struct PartialContent {
     
    4642        unsigned length;
    4743    };
    48     struct LineInput {
    49         LineInput(const InlineItems&, unsigned leadingInlineItemIndex, Optional<PartialContent> leadingPartialContent);
    50 
    51         const InlineItems& inlineItems;
    52         unsigned leadingInlineItemIndex { 0 };
    53         Optional<PartialContent> leadingPartialContent;
    54         Optional<LayoutUnit> floatMinimumLogicalBottom;
    55     };
    56 
    5744    struct LineContent {
    5845        Optional<unsigned> trailingInlineItemIndex;
     
    6249        const LineBox lineBox;
    6350    };
     51    LineContent layout(Line&, unsigned leadingInlineItemIndex, Optional<PartialContent> leadingPartialContent);
    6452
    6553    struct Run {
     
    7361    const InlineFormattingContext& formattingContext() const { return m_inlineFormattingContext; }
    7462    enum class IsEndOfLine { No, Yes };
    75     IsEndOfLine placeInlineItem(const InlineItem&);
    76     void commitPendingContent();
    77     LineContent close();
     63    IsEndOfLine placeInlineItem(Line&, const InlineItem&);
     64    void commitPendingContent(Line&);
     65    LineContent close(Line&, unsigned leadingInlineItemIndex);
    7866    bool shouldProcessUncommittedContent(const InlineItem&) const;
    79     IsEndOfLine processUncommittedContent();
     67    IsEndOfLine processUncommittedContent(Line&);
    8068   
    8169    struct UncommittedContent {
     
    9684
    9785    const InlineFormattingContext& m_inlineFormattingContext;
    98     const LineInput& m_lineInput;
    99     Line& m_line;
     86    const InlineItems& m_inlineItems;
    10087    UncommittedContent m_uncommittedContent;
    10188    unsigned m_committedInlineItemCount { 0 };
Note: See TracChangeset for help on using the changeset viewer.