Changeset 237323 in webkit


Ignore:
Timestamp:
Oct 22, 2018 9:02:48 AM (6 years ago)
Author:
Alan Bujtas
Message:

[LFC][IFC] Add (right, center)text-align support.
https://bugs.webkit.org/show_bug.cgi?id=190745

Reviewed by Antti Koivisto.

Adjust the logical left of each run while closing the line.

  • layout/Verification.cpp:

(WebCore::Layout::outputMismatchingSimpleLineInformationIfNeeded):
(WebCore::Layout::outputMismatchingComplexLineInformationIfNeeded):

  • layout/inlineformatting/InlineFormattingContext.cpp:

(WebCore::Layout::trimLeadingRun):
(WebCore::Layout::InlineFormattingContext::layoutInlineContent const):

  • layout/inlineformatting/InlineFormattingContext.h:

(WebCore::Layout::InlineFormattingContext::Line::hasContent const):
(WebCore::Layout::InlineFormattingContext::Line::contentLogicalLeft const): Deleted.

  • layout/inlineformatting/InlineLineBreaker.cpp:

(WebCore::Layout::InlineLineBreaker::nextRun):
(WebCore::Layout::InlineLineBreaker::splitRun):

  • layout/inlineformatting/InlineLineBreaker.h:
  • layout/inlineformatting/InlineRun.h:

(WebCore::Layout::InlineRun::setLogicalLeft):
(WebCore::Layout::InlineRun::TextContext::start const):
(WebCore::Layout::InlineRun::createRun):
(WebCore::Layout::InlineRun::createTextRun):
(WebCore::Layout::InlineRun::InlineRun):
(WebCore::Layout::InlineRun::TextContext::TextContext):
(WebCore::Layout::InlineRun::TextContext::position const): Deleted.

  • layout/inlineformatting/Line.cpp:

(WebCore::Layout::InlineFormattingContext::Line::Line):
(WebCore::Layout::InlineFormattingContext::Line::init):
(WebCore::Layout::adjustedLineLogicalLeft):
(WebCore::Layout::InlineFormattingContext::Line::contentLogicalRight):
(WebCore::Layout::InlineFormattingContext::Line::appendContent):
(WebCore::Layout::InlineFormattingContext::Line::close):
(WebCore::Layout::InlineFormattingContext::Line::setConstraints): Deleted.

  • layout/layouttree/LayoutTreeBuilder.cpp:

(WebCore::Layout::outputInlineRuns):

Location:
trunk/Source/WebCore
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r237321 r237323  
     12018-10-22  Zalan Bujtas  <zalan@apple.com>
     2
     3        [LFC][IFC] Add (right, center)text-align support.
     4        https://bugs.webkit.org/show_bug.cgi?id=190745
     5
     6        Reviewed by Antti Koivisto.
     7
     8        Adjust the logical left of each run while closing the line.
     9
     10        * layout/Verification.cpp:
     11        (WebCore::Layout::outputMismatchingSimpleLineInformationIfNeeded):
     12        (WebCore::Layout::outputMismatchingComplexLineInformationIfNeeded):
     13        * layout/inlineformatting/InlineFormattingContext.cpp:
     14        (WebCore::Layout::trimLeadingRun):
     15        (WebCore::Layout::InlineFormattingContext::layoutInlineContent const):
     16        * layout/inlineformatting/InlineFormattingContext.h:
     17        (WebCore::Layout::InlineFormattingContext::Line::hasContent const):
     18        (WebCore::Layout::InlineFormattingContext::Line::contentLogicalLeft const): Deleted.
     19        * layout/inlineformatting/InlineLineBreaker.cpp:
     20        (WebCore::Layout::InlineLineBreaker::nextRun):
     21        (WebCore::Layout::InlineLineBreaker::splitRun):
     22        * layout/inlineformatting/InlineLineBreaker.h:
     23        * layout/inlineformatting/InlineRun.h:
     24        (WebCore::Layout::InlineRun::setLogicalLeft):
     25        (WebCore::Layout::InlineRun::TextContext::start const):
     26        (WebCore::Layout::InlineRun::createRun):
     27        (WebCore::Layout::InlineRun::createTextRun):
     28        (WebCore::Layout::InlineRun::InlineRun):
     29        (WebCore::Layout::InlineRun::TextContext::TextContext):
     30        (WebCore::Layout::InlineRun::TextContext::position const): Deleted.
     31        * layout/inlineformatting/Line.cpp:
     32        (WebCore::Layout::InlineFormattingContext::Line::Line):
     33        (WebCore::Layout::InlineFormattingContext::Line::init):
     34        (WebCore::Layout::adjustedLineLogicalLeft):
     35        (WebCore::Layout::InlineFormattingContext::Line::contentLogicalRight):
     36        (WebCore::Layout::InlineFormattingContext::Line::appendContent):
     37        (WebCore::Layout::InlineFormattingContext::Line::close):
     38        (WebCore::Layout::InlineFormattingContext::Line::setConstraints): Deleted.
     39        * layout/layouttree/LayoutTreeBuilder.cpp:
     40        (WebCore::Layout::outputInlineRuns):
     41
    1422018-10-22  Zalan Bujtas  <zalan@apple.com>
    243
  • trunk/Source/WebCore/layout/Verification.cpp

    r237289 r237323  
    7474        auto matchingRuns = areEssentiallyEqual(simpleRun.logicalLeft, inlineRun.logicalLeft()) && areEssentiallyEqual(simpleRun.logicalRight, inlineRun.logicalRight());
    7575        if (matchingRuns)
    76             matchingRuns = (simpleRun.start == inlineRun.textContext()->position() && simpleRun.end == (inlineRun.textContext()->position() + inlineRun.textContext()->length()));
     76            matchingRuns = (simpleRun.start == inlineRun.textContext()->start() && simpleRun.end == (inlineRun.textContext()->start() + inlineRun.textContext()->length()));
    7777        if (matchingRuns)
    7878            continue;
    7979
    80         stream << "Mismatching: simple run(" << simpleRun.start << ", " << simpleRun.end << ") (" << simpleRun.logicalLeft << ", " << simpleRun.logicalRight << ") layout run(" << inlineRun.textContext()->position() << ", " << inlineRun.textContext()->position() + inlineRun.textContext()->length() << ") (" << inlineRun.logicalLeft() << ", " << inlineRun.logicalRight() << ")";
     80        stream << "Mismatching: simple run(" << simpleRun.start << ", " << simpleRun.end << ") (" << simpleRun.logicalLeft << ", " << simpleRun.logicalRight << ") layout run(" << inlineRun.textContext()->start() << ", " << inlineRun.textContext()->start() + inlineRun.textContext()->length() << ") (" << inlineRun.logicalLeft() << ", " << inlineRun.logicalRight() << ")";
    8181        stream.nextLine();
    8282        mismatched = true;
     
    108108            if (matchingRuns && inlineTextBox) {
    109109                ASSERT(inlineRun.textContext());
    110                 matchingRuns = inlineTextBox->start() == inlineRun.textContext()->position() && inlineTextBox->end() + 1 == (inlineRun.textContext()->position() + inlineRun.textContext()->length());
     110                matchingRuns = inlineTextBox->start() == inlineRun.textContext()->start() && inlineTextBox->end() + 1 == (inlineRun.textContext()->start() + inlineRun.textContext()->length());
    111111            }
    112112
     
    120120                stream << "layout run ";
    121121                if (inlineRun.textContext())
    122                     stream << "(" << inlineRun.textContext()->position() << ", " << inlineRun.textContext()->position() + inlineRun.textContext()->length() << ") ";
     122                    stream << "(" << inlineRun.textContext()->start() << ", " << inlineRun.textContext()->start() + inlineRun.textContext()->length() << ") ";
    123123                stream << "(" << inlineRun.logicalLeft() << ", " << inlineRun.logicalRight() << ")";
    124124                stream.nextLine();
  • trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp

    r237288 r237323  
    9696    ASSERT(run.position == InlineLineBreaker::Run::Position::LineBegin);
    9797
    98     auto& inlineRun = run.inlineRun;
    99     if (!inlineRun.isWhitespace())
     98    if (!run.content.isWhitespace())
    10099        return false;
    101100
    102     return inlineRun.style().collapseWhiteSpace();
     101    return run.content.style().collapseWhiteSpace();
    103102}
    104103
     
    112111    auto previousRunPositionIsLineEnd = false;
    113112
    114     Line line(inlineFormattingState);
    115     line.setConstraints(lineLogicalLeft, availableWidth);
     113    Line line(inlineFormattingState, root());
     114    line.init(lineLogicalLeft, availableWidth);
    116115
    117116    InlineLineBreaker lineBreaker(layoutContext, inlineFormattingState.inlineContent(), inlineRunProvider.runs());
    118     while (auto run = lineBreaker.nextRun(line.contentLogicalLeft(), line.availableWidth(), !line.hasContent())) {
     117    while (auto run = lineBreaker.nextRun(line.contentLogicalRight(), line.availableWidth(), !line.hasContent())) {
    119118
    120119        if (run->position == InlineLineBreaker::Run::Position::LineBegin) {
     
    124123            if (!previousRunPositionIsLineEnd) {
    125124                line.close();
    126                 line.setConstraints(lineLogicalLeft, availableWidth);
     125                line.init(lineLogicalLeft, availableWidth);
    127126            }
    128127            // Skip leading whitespace.
     
    138137            // Move over to the next line.
    139138            line.close();
    140             line.setConstraints(lineLogicalLeft, availableWidth);
     139            line.init(lineLogicalLeft, availableWidth);
    141140            continue;
    142141        }
  • trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h

    r237288 r237323  
    5050    class Line {
    5151    public:
    52         Line(InlineFormattingState&);
     52        Line(InlineFormattingState&, const Box& formattingRoot);
    5353
    54         void setConstraints(LayoutUnit lineLogicalLeft, LayoutUnit availableWidth);
     54        void init(LayoutUnit lineLogicalLeft, LayoutUnit availableWidth);
    5555        void appendContent(const InlineLineBreaker::Run&);
    5656        void close();
    57         bool hasContent() const { return !m_isEmpty; }
    58         LayoutUnit contentLogicalLeft() const { return m_contentLogicalLeft; }
     57
     58        bool hasContent() const { return m_firstRunIndex.has_value(); }
     59        LayoutUnit contentLogicalRight();
    5960        LayoutUnit availableWidth() const { return m_availableWidth; }
    6061
     
    6566        };
    6667        std::optional<TrailingTrimmableContent> m_trailingTrimmableContent;
    67         InlineFormattingState& m_inlineFormattingState;
    68         LayoutUnit m_contentLogicalLeft;
     68        bool m_lastRunIsNotCollapsedText { true };
     69
     70        InlineFormattingState& m_formattingState;
     71        const Box& m_formattingRoot;
     72
     73        LayoutUnit m_lineLogicalLeft;
    6974        LayoutUnit m_availableWidth;
    70         bool m_isEmpty { true };
    71         bool m_lastRunIsNotCollapsedText { true };
     75        LayoutUnit m_lineWidth;
     76
     77        std::optional<unsigned> m_firstRunIndex;
    7278    };
    7379
  • trunk/Source/WebCore/layout/inlineformatting/InlineLineBreaker.cpp

    r237288 r237323  
    6161    if (currentInlineRun.isLineBreak()) {
    6262        ++m_currentRunIndex;
    63         return Run { Run::Position::LineEnd, currentInlineRun, 0 };
     63        return Run { Run::Position::LineEnd, 0, currentInlineRun };
    6464    }
    6565
     
    6868    if (contentWidth <= availableWidth) {
    6969        ++m_currentRunIndex;
    70         return Run { lineIsEmpty ? Run::Position::LineBegin : Run::Position::Undetermined, currentInlineRun, contentWidth };
     70        return Run { lineIsEmpty ? Run::Position::LineBegin : Run::Position::Undetermined, contentWidth, currentInlineRun };
    7171    }
    7272
     
    7474    if (availableWidth <= 0) {
    7575        ++m_currentRunIndex;
    76         return Run { Run::Position::LineBegin, currentInlineRun, contentWidth };
     76        return Run { Run::Position::LineBegin, contentWidth, currentInlineRun };
    7777    }
    7878
     
    8181    if (breakingBehavior == LineBreakingBehavior::Keep) {
    8282        ++m_currentRunIndex;
    83         return Run { lineIsEmpty ? Run::Position::LineBegin : Run::Position::Undetermined, currentInlineRun, contentWidth };
     83        return Run { lineIsEmpty ? Run::Position::LineBegin : Run::Position::Undetermined, contentWidth, currentInlineRun };
    8484    }
    8585
    8686    if (breakingBehavior == LineBreakingBehavior::WrapToNextLine) {
    8787        ++m_currentRunIndex;
    88         return Run { Run::Position::LineBegin, currentInlineRun, contentWidth };
     88        return Run { Run::Position::LineBegin, contentWidth, currentInlineRun };
    8989    }
    9090
     
    155155InlineLineBreaker::Run InlineLineBreaker::splitRun(const InlineRunProvider::Run& inlineRun, LayoutUnit, LayoutUnit, bool)
    156156{
    157     return { Run::Position::Undetermined, inlineRun, { } };
     157    return { Run::Position::Undetermined, { }, inlineRun };
    158158}
    159159
  • trunk/Source/WebCore/layout/inlineformatting/InlineLineBreaker.h

    r237288 r237323  
    4343        enum class Position { Undetermined, LineBegin, LineEnd };
    4444        Position position;
    45         InlineRunProvider::Run inlineRun;
    4645        LayoutUnit width;
     46        InlineRunProvider::Run content;
    4747    };
    4848    std::optional<Run> nextRun(LayoutUnit contentLogicalLeft, LayoutUnit availableWidth, bool lineIsEmpty);
  • trunk/Source/WebCore/layout/inlineformatting/InlineRun.h

    r237288 r237323  
    3535
    3636struct InlineRun {
    37     InlineRun(LayoutUnit logcialLeft, LayoutUnit width, const InlineItem&);
    38     InlineRun(LayoutUnit logcialLeft, LayoutUnit width, ItemPosition, unsigned length, const InlineItem&);
     37    static InlineRun createRun(LayoutUnit logcialLeft, LayoutUnit width, const InlineItem&);
     38    static InlineRun createTextRun(LayoutUnit logcialLeft, LayoutUnit width, ItemPosition, unsigned length, const InlineItem&);
    3939
    4040    LayoutUnit logicalLeft() const { return m_logicalLeft; }
     
    4343
    4444    void setWidth(LayoutUnit width) { m_width = width; }
     45    void setLogicalLeft(LayoutUnit logicalLeft) { m_logicalLeft = logicalLeft; }
    4546    void setLogicalRight(LayoutUnit logicalRight) { m_width -= (this->logicalRight() - logicalRight); }
    4647
     
    4950        TextContext(ItemPosition, unsigned length);
    5051
    51         ItemPosition position() const { return m_position; }
     52        ItemPosition start() const { return m_start; }
    5253        unsigned length() const { return m_length; }
    5354
     
    5556
    5657    private:
    57         ItemPosition m_position;
     58        ItemPosition m_start;
    5859        unsigned m_length;
    5960    };
     
    6263
    6364private:
     65    InlineRun(LayoutUnit logcialLeft, LayoutUnit width, const InlineItem&);
     66    InlineRun(LayoutUnit logcialLeft, LayoutUnit width, ItemPosition, unsigned length, const InlineItem&);
     67
    6468    LayoutUnit m_logicalLeft;
    6569    LayoutUnit m_width;
     
    7175using InlineRuns = Vector<InlineRun>;
    7276
     77inline InlineRun InlineRun::createRun(LayoutUnit logicalLeft, LayoutUnit width, const InlineItem& inlineItem)
     78{
     79    return { logicalLeft, width, inlineItem };
     80}
     81
     82inline InlineRun InlineRun::createTextRun(LayoutUnit logicalLeft, LayoutUnit width, ItemPosition start, unsigned length, const InlineItem& inlineItem)
     83{
     84    return { logicalLeft, width, start, length, inlineItem };
     85}
     86
    7387inline InlineRun::InlineRun(LayoutUnit logicalLeft, LayoutUnit width, const InlineItem& inlineItem)
    7488    : m_logicalLeft(logicalLeft)
     
    7892}
    7993
    80 inline InlineRun::InlineRun(LayoutUnit logicalLeft, LayoutUnit width, ItemPosition position, unsigned length, const InlineItem& inlineItem)
     94inline InlineRun::InlineRun(LayoutUnit logicalLeft, LayoutUnit width, ItemPosition start, unsigned length, const InlineItem& inlineItem)
    8195    : m_logicalLeft(logicalLeft)
    8296    , m_width(width)
    8397    , m_inlineItem(inlineItem)
    84     , m_textContext(TextContext { position, length })
     98    , m_textContext(TextContext { start, length })
    8599{
    86100}
    87101
    88 inline InlineRun::TextContext::TextContext(ItemPosition position, unsigned length)
    89     : m_position(position)
     102inline InlineRun::TextContext::TextContext(ItemPosition start, unsigned length)
     103    : m_start(start)
    90104    , m_length(length)
    91105{
  • trunk/Source/WebCore/layout/inlineformatting/Line.cpp

    r237288 r237323  
    3434namespace Layout {
    3535
    36 InlineFormattingContext::Line::Line(InlineFormattingState& inlineFormattingState)
    37     : m_inlineFormattingState(inlineFormattingState)
     36InlineFormattingContext::Line::Line(InlineFormattingState& formattingState, const Box& formattingRoot)
     37    : m_formattingState(formattingState)
     38    , m_formattingRoot(formattingRoot)
    3839{
    3940}
    4041
    41 void InlineFormattingContext::Line::setConstraints(LayoutUnit lineLogicalLeft, LayoutUnit availableWidth)
     42void InlineFormattingContext::Line::init(LayoutUnit lineLogicalLeft, LayoutUnit availableWidth)
    4243{
    43     m_contentLogicalLeft = lineLogicalLeft;
     44    m_lineLogicalLeft = lineLogicalLeft;
     45    m_lineWidth = availableWidth;
    4446    m_availableWidth = availableWidth;
     47    m_firstRunIndex = { };
     48}
     49
     50static LayoutUnit adjustedLineLogicalLeft(TextAlignMode align, LayoutUnit lineLogicalLeft, LayoutUnit remainingWidth)
     51{
     52    switch (align) {
     53    case TextAlignMode::Left:
     54    case TextAlignMode::WebKitLeft:
     55    case TextAlignMode::Start:
     56        return lineLogicalLeft;
     57    case TextAlignMode::Right:
     58    case TextAlignMode::WebKitRight:
     59    case TextAlignMode::End:
     60        return lineLogicalLeft + std::max(remainingWidth, LayoutUnit());
     61    case TextAlignMode::Center:
     62    case TextAlignMode::WebKitCenter:
     63        return lineLogicalLeft + std::max(remainingWidth / 2, LayoutUnit());
     64    case TextAlignMode::Justify:
     65        ASSERT_NOT_REACHED();
     66        break;
     67    }
     68    ASSERT_NOT_REACHED();
     69    return lineLogicalLeft;
    4570}
    4671
     
    5580}
    5681
     82LayoutUnit InlineFormattingContext::Line::contentLogicalRight()
     83{
     84    if (!m_firstRunIndex.has_value())
     85        return m_lineLogicalLeft;
     86
     87    return m_formattingState.inlineRuns().last().logicalRight();
     88}
     89
    5790void InlineFormattingContext::Line::appendContent(const InlineLineBreaker::Run& run)
    5891{
    5992    auto lastRunWasNotCollapsedText = m_lastRunIsNotCollapsedText;
    60     auto hadContent = hasContent();
    61     auto contentLogicalLeft = m_contentLogicalLeft;
    6293    m_trailingTrimmableContent = { };
     94    m_availableWidth -= run.width;
    6395
    64     auto& inlineRun = run.inlineRun;
    65     m_availableWidth -= run.width;
    66     m_lastRunIsNotCollapsedText = isNonCollapsedText(inlineRun);
    67     m_isEmpty = false;
    68     m_contentLogicalLeft += run.width;
     96    auto& content = run.content;
     97    m_lastRunIsNotCollapsedText = isNonCollapsedText(content);
    6998
    7099    // Append this text run to the end of the last text run, if the last run is continuous.
    71     if (inlineRun.isText()) {
    72         auto textContext = inlineRun.textContext();
     100    std::optional<InlineRun::TextContext> textRun;
     101    if (content.isText()) {
     102        auto textContext = content.textContext();
    73103        auto runLength = textContext->isCollapsed() ? 1 : textContext->length();
    74104
    75         if (isTrimmableContent(inlineRun))
     105        if (isTrimmableContent(content))
    76106            m_trailingTrimmableContent = TrailingTrimmableContent { run.width, runLength };
    77107
    78         if (hadContent && lastRunWasNotCollapsedText) {
    79             auto& inlineRun = m_inlineFormattingState.inlineRuns().last();
     108        if (hasContent() && lastRunWasNotCollapsedText) {
     109            auto& inlineRun = m_formattingState.inlineRuns().last();
    80110            inlineRun.setWidth(inlineRun.width() + run.width);
    81111            inlineRun.textContext()->setLength(inlineRun.textContext()->length() + runLength);
    82112            return;
    83113        }
    84 
    85         return m_inlineFormattingState.appendInlineRun({ contentLogicalLeft, run.width, textContext->start(), runLength, inlineRun.inlineItem()});
     114        textRun = InlineRun::TextContext { textContext->start(), runLength };
    86115    }
    87116
    88     m_inlineFormattingState.appendInlineRun({ contentLogicalLeft, run.width, inlineRun.inlineItem() });
     117    if (textRun)
     118        m_formattingState.appendInlineRun(InlineRun::createTextRun(contentLogicalRight(), run.width, textRun->start(), textRun->length(), content.inlineItem()));
     119    else
     120        m_formattingState.appendInlineRun(InlineRun::createRun(contentLogicalRight(), run.width, content.inlineItem()));
     121    m_firstRunIndex = m_firstRunIndex.value_or(m_formattingState.inlineRuns().size() - 1);
    89122}
    90123
     
    96129            return;
    97130
    98         auto& lastInlineRun = m_inlineFormattingState.inlineRuns().last();
     131        auto& lastInlineRun = m_formattingState.inlineRuns().last();
    99132        lastInlineRun.setWidth(lastInlineRun.width() - m_trailingTrimmableContent->width);
    100133        lastInlineRun.textContext()->setLength(lastInlineRun.textContext()->length() - m_trailingTrimmableContent->length);
    101134
    102         if (!lastInlineRun.textContext()->length())
    103             m_inlineFormattingState.inlineRuns().removeLast();
     135        if (!lastInlineRun.textContext()->length()) {
     136            m_formattingState.inlineRuns().removeLast();
     137            if (m_firstRunIndex.value())
     138                --*m_firstRunIndex;
     139            else
     140                m_firstRunIndex = { };
     141        }
    104142        m_availableWidth += m_trailingTrimmableContent->width;
    105143        m_trailingTrimmableContent = { };
    106144    };
    107145
     146    auto alignRuns = [&]() {
     147
     148        if (!hasContent())
     149            return;
     150
     151        auto adjustedLogicalLeft = adjustedLineLogicalLeft(m_formattingRoot.style().textAlign(), m_lineLogicalLeft, m_availableWidth);
     152        if (m_lineLogicalLeft == adjustedLogicalLeft)
     153            return;
     154
     155        auto& inlineRuns = m_formattingState.inlineRuns();
     156        auto delta = adjustedLogicalLeft - m_lineLogicalLeft;
     157        for (auto runIndex = *m_firstRunIndex; runIndex < inlineRuns.size(); ++runIndex)
     158            inlineRuns[runIndex].setLogicalLeft(inlineRuns[runIndex].logicalLeft() + delta);
     159    };
     160
     161    if (!hasContent())
     162        return;
     163
    108164    trimTrailingContent();
    109     m_isEmpty = true;
     165    alignRuns();
    110166}
    111167
  • trunk/Source/WebCore/layout/layouttree/LayoutTreeBuilder.cpp

    r237321 r237323  
    148148        stream << "run";
    149149        if (inlineRun.textContext())
    150             stream << "(" << inlineRun.textContext()->position() << ", " << inlineRun.textContext()->position() + inlineRun.textContext()->length() << ") ";
     150            stream << "(" << inlineRun.textContext()->start() << ", " << inlineRun.textContext()->start() + inlineRun.textContext()->length() << ") ";
    151151        stream << "(" << inlineRun.logicalLeft() << ", " << inlineRun.logicalRight() << ")";
    152152        stream.nextLine();
Note: See TracChangeset for help on using the changeset viewer.