⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 238460 in webkit


Ignore:
Timestamp:
Nov 23, 2018, 9:05:43 AM (8 years ago)
Author:
Alan Bujtas
Message:

[LFC][IFC] Add support for variable height runs.
https://bugs.webkit.org/show_bug.cgi?id=191925

Reviewed by Antti Koivisto.

Source/WebCore:

https://www.w3.org/TR/CSS22/visudet.html#inline-box-height

10.8 Line height calculations: the 'line-height' and 'vertical-align' properties

The height of each inline-level box in the line box is calculated. For replaced elements, inline-block elements,
and inline-table elements, this is the height of their margin box; for inline boxes, this is their 'line-height'.

The line box height is the distance between the uppermost box top and the lowermost box bottom.

The minimum height consists of a minimum height above the baseline and a minimum depth below it,
exactly as if each line box starts with a zero-width inline box with the element's font and line height properties.
We call that imaginary box a "strut." (The name is inspired by TeX.).

Test: fast/inline/inline-content-with-image-simple.html

  • layout/Verification.cpp:

(WebCore::Layout::checkForMatchingNonTextRuns):
(WebCore::Layout::checkForMatchingTextRuns):
(WebCore::Layout::outputMismatchingComplexLineInformationIfNeeded):

  • layout/inlineformatting/InlineFormattingContext.cpp:

(WebCore::Layout::InlineFormattingContext::initializeNewLine const):
(WebCore::Layout::InlineFormattingContext::splitInlineRunIfNeeded const):
(WebCore::Layout::InlineFormattingContext::createFinalRuns const):
(WebCore::Layout::InlineFormattingContext::appendContentToLine const):
(WebCore::Layout::InlineFormattingContext::layoutInlineContent const):

  • layout/inlineformatting/InlineFormattingContext.h:

(WebCore::Layout::InlineFormattingContext::Line::logicalHeight const):

  • layout/inlineformatting/InlineFormattingContextGeometry.cpp:

(WebCore::Layout::InlineFormattingContext::Geometry::justifyRuns):

  • layout/inlineformatting/InlineRun.h:

(WebCore::Layout::InlineRun::logicalWidth const):
(WebCore::Layout::InlineRun::logicalHeight const):
(WebCore::Layout::InlineRun::setLogicalWidth):
(WebCore::Layout::InlineRun::width const): Deleted.
(WebCore::Layout::InlineRun::height const): Deleted.
(WebCore::Layout::InlineRun::setWidth): Deleted.

  • layout/inlineformatting/Line.cpp:

(WebCore::Layout::InlineFormattingContext::Line::init):
(WebCore::Layout::InlineFormattingContext::Line::appendContent):
(WebCore::Layout::InlineFormattingContext::Line::close):

  • layout/layouttree/LayoutTreeBuilder.cpp:

(WebCore::Layout::outputInlineRuns):

Tools:

  • LayoutReloaded/misc/LFC-passing-tests.txt:

LayoutTests:

  • fast/inline/inline-content-with-image-simple-expected.txt: Added.
  • fast/inline/inline-content-with-image-simple.html: Added.
Location:
trunk
Files:
2 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r238457 r238460  
     12018-11-23  Zalan Bujtas  <zalan@apple.com>
     2
     3        [LFC][IFC] Add support for variable height runs.
     4        https://bugs.webkit.org/show_bug.cgi?id=191925
     5
     6        Reviewed by Antti Koivisto.
     7
     8        * fast/inline/inline-content-with-image-simple-expected.txt: Added.
     9        * fast/inline/inline-content-with-image-simple.html: Added.
     10
    1112018-11-23  Javier Fernandez  <jfernandez@igalia.com>
    212
  • trunk/Source/WebCore/ChangeLog

    r238459 r238460  
     12018-11-23  Zalan Butjas  <zalan@apple.com>
     2
     3        [LFC][IFC] Add support for variable height runs.
     4        https://bugs.webkit.org/show_bug.cgi?id=191925
     5
     6        Reviewed by Antti Koivisto.
     7
     8        https://www.w3.org/TR/CSS22/visudet.html#inline-box-height
     9
     10        10.8 Line height calculations: the 'line-height' and 'vertical-align' properties
     11
     12        The height of each inline-level box in the line box is calculated. For replaced elements, inline-block elements,
     13        and inline-table elements, this is the height of their margin box; for inline boxes, this is their 'line-height'.
     14
     15        The line box height is the distance between the uppermost box top and the lowermost box bottom.
     16
     17        The minimum height consists of a minimum height above the baseline and a minimum depth below it,
     18        exactly as if each line box starts with a zero-width inline box with the element's font and line height properties.
     19        We call that imaginary box a "strut." (The name is inspired by TeX.).
     20
     21        Test: fast/inline/inline-content-with-image-simple.html
     22
     23        * layout/Verification.cpp:
     24        (WebCore::Layout::checkForMatchingNonTextRuns):
     25        (WebCore::Layout::checkForMatchingTextRuns):
     26        (WebCore::Layout::outputMismatchingComplexLineInformationIfNeeded):
     27        * layout/inlineformatting/InlineFormattingContext.cpp:
     28        (WebCore::Layout::InlineFormattingContext::initializeNewLine const):
     29        (WebCore::Layout::InlineFormattingContext::splitInlineRunIfNeeded const):
     30        (WebCore::Layout::InlineFormattingContext::createFinalRuns const):
     31        (WebCore::Layout::InlineFormattingContext::appendContentToLine const):
     32        (WebCore::Layout::InlineFormattingContext::layoutInlineContent const):
     33        * layout/inlineformatting/InlineFormattingContext.h:
     34        (WebCore::Layout::InlineFormattingContext::Line::logicalHeight const):
     35        * layout/inlineformatting/InlineFormattingContextGeometry.cpp:
     36        (WebCore::Layout::InlineFormattingContext::Geometry::justifyRuns):
     37        * layout/inlineformatting/InlineRun.h:
     38        (WebCore::Layout::InlineRun::logicalWidth const):
     39        (WebCore::Layout::InlineRun::logicalHeight const):
     40        (WebCore::Layout::InlineRun::setLogicalWidth):
     41        (WebCore::Layout::InlineRun::width const): Deleted.
     42        (WebCore::Layout::InlineRun::height const): Deleted.
     43        (WebCore::Layout::InlineRun::setWidth): Deleted.
     44        * layout/inlineformatting/Line.cpp:
     45        (WebCore::Layout::InlineFormattingContext::Line::init):
     46        (WebCore::Layout::InlineFormattingContext::Line::appendContent):
     47        (WebCore::Layout::InlineFormattingContext::Line::close):
     48        * layout/layouttree/LayoutTreeBuilder.cpp:
     49        (WebCore::Layout::outputInlineRuns):
     50
    1512018-11-23  Antti Koivisto  <antti@apple.com>
    252
  • trunk/Source/WebCore/layout/Verification.cpp

    r238431 r238460  
    8888static bool checkForMatchingNonTextRuns(const InlineRun& inlineRun, const WebCore::InlineBox& inlineBox)
    8989{
    90     return areEssentiallyEqual(inlineBox.logicalLeft(), inlineRun.logicalLeft()) && areEssentiallyEqual(inlineBox.logicalRight(), inlineRun.logicalRight());
    91 }
    92 
    93 static bool checkForMatchingTextRuns(const InlineRun& inlineRun, float logicalLeft, float logicalRight, unsigned start, unsigned end)
    94 {
    95     return areEssentiallyEqual(logicalLeft, inlineRun.logicalLeft()) && areEssentiallyEqual(logicalRight, inlineRun.logicalRight()) && start == inlineRun.textContext()->start() && (end == (inlineRun.textContext()->start() + inlineRun.textContext()->length()));
     90    return areEssentiallyEqual(inlineBox.logicalLeft(), inlineRun.logicalLeft())
     91        && areEssentiallyEqual(inlineBox.logicalRight(), inlineRun.logicalRight())
     92        && areEssentiallyEqual(inlineBox.logicalHeight(), inlineRun.logicalHeight());
     93}
     94
     95static bool checkForMatchingTextRuns(const InlineRun& inlineRun, float logicalLeft, float logicalRight, unsigned start, unsigned end, float logicalHeight)
     96{
     97    return areEssentiallyEqual(logicalLeft, inlineRun.logicalLeft())
     98        && areEssentiallyEqual(logicalRight, inlineRun.logicalRight())
     99        && start == inlineRun.textContext()->start()
     100        && (end == (inlineRun.textContext()->start() + inlineRun.textContext()->length()))
     101        && areEssentiallyEqual(logicalHeight, inlineRun.logicalHeight());
    96102}
    97103
     
    160166        if (inlineTextBox) {
    161167            auto xOffset = resolveForRelativePositionIfNeeded(*inlineTextBox);
    162             matchingRuns = checkForMatchingTextRuns(inlineRun, inlineTextBox->logicalLeft() + xOffset, inlineTextBox->logicalRight() + xOffset, inlineTextBox->start(), inlineTextBox->end() + 1);
     168            matchingRuns = checkForMatchingTextRuns(inlineRun, inlineTextBox->logicalLeft() + xOffset,
     169                inlineTextBox->logicalRight() + xOffset,
     170                inlineTextBox->start(),
     171                inlineTextBox->end() + 1,
     172                inlineTextBox->logicalHeight());
    163173
    164174            // <span>foobar</span>foobar generates 2 inline text boxes while we only generate one inline run.
     
    183193                    logicalRight = inlineTextBox->logicalRight() + xOffset;
    184194                    end += (inlineTextBox->end() + 1);
    185                     if (checkForMatchingTextRuns(inlineRun, logicalLeft, logicalRight, start, end)) {
     195                    if (checkForMatchingTextRuns(inlineRun, logicalLeft, logicalRight, start, end, inlineTextBox->logicalHeight())) {
    186196                        matchingRuns = true;
    187197                        inlineBoxIndex = index;
     
    203213            if (inlineTextBox)
    204214                stream << "(" << inlineTextBox->start() << ", " << inlineTextBox->end() + 1 << ")";
    205             stream << " (" << inlineBox->logicalLeft() << ", " << inlineBox->logicalRight() << ") ";
     215            stream << " (" << inlineBox->logicalLeft() << ", " << inlineBox->logicalRight() << ") (" << inlineBox->logicalWidth() << "x" << inlineBox->logicalHeight() << ")";
    206216
    207217            stream << "inline run ";
    208218            if (inlineRun.textContext())
    209219                stream << "(" << inlineRun.textContext()->start() << ", " << inlineRun.textContext()->start() + inlineRun.textContext()->length() << ") ";
    210             stream << "(" << inlineRun.logicalLeft() << ", " << inlineRun.logicalRight() << ")";
     220            stream << "(" << inlineRun.logicalLeft() << ", " << inlineRun.logicalRight() << ") (" << inlineRun.logicalWidth() << "x" << inlineRun.logicalHeight() << ")";
    211221            stream.nextLine();
    212222            mismatched = true;
  • trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp

    r238449 r238460  
    118118    }
    119119
    120     Display::Box::Rect logicalRect;
    121     logicalRect.setTop(lineLogicalTop);
    122     logicalRect.setLeft(lineLogicalLeft);
    123     logicalRect.setWidth(availableWidth);
    124     logicalRect.setHeight(formattingRoot.style().computedLineHeight());
    125 
    126     line.init(logicalRect);
     120    line.init({ lineLogicalLeft, lineLogicalTop }, availableWidth, formattingRoot.style().computedLineHeight());
    127121}
    128122
     
    158152
    159153        auto runWidth = Geometry::runWidth(inlineContent, *uncommitted->firstInlineItem, startPosition, uncommitted->length, contentStart);
    160         auto run = InlineRun { { inlineRun.logicalTop(), contentStart, runWidth, inlineRun.height() }, *uncommitted->firstInlineItem };
     154        auto run = InlineRun { { inlineRun.logicalTop(), contentStart, runWidth, inlineRun.logicalHeight() }, *uncommitted->firstInlineItem };
    161155        run.setTextContext({ startPosition, uncommitted->length });
    162156        splitRuns.append(run);
     
    236230
    237231            InlineRun adjustedRun = inlineRun;
    238             auto width = inlineRun.width() - inlineItem.nonBreakableStart() - inlineItem.nonBreakableEnd();
     232            auto width = inlineRun.logicalWidth() - inlineItem.nonBreakableStart() - inlineItem.nonBreakableEnd();
    239233            adjustedRun.setLogicalLeft(inlineRun.logicalLeft() + inlineItem.nonBreakableStart());
    240             adjustedRun.setWidth(width);
     234            adjustedRun.setLogicalWidth(width);
    241235            return adjustedRun;
    242236        };
     
    264258}
    265259
    266 void InlineFormattingContext::appendContentToLine(Line& line, const InlineLineBreaker::Run& run) const
     260void InlineFormattingContext::appendContentToLine(Line& line, const InlineRunProvider::Run& run, const LayoutSize& runSize) const
    267261{
    268262    auto lastRunType = line.lastRunType();
    269     line.appendContent(run);
     263    line.appendContent(run, runSize);
    270264
    271265    if (root().style().textAlign() == TextAlignMode::Justify)
    272         Geometry::computeExpansionOpportunities(line, run.content, lastRunType.value_or(InlineRunProvider::Run::Type::NonWhitespace));
     266        Geometry::computeExpansionOpportunities(line, run, lastRunType.value_or(InlineRunProvider::Run::Type::NonWhitespace));
    273267}
    274268
     
    319313         }
    320314
    321         if (generatesInlineRun)
    322             appendContentToLine(line, *run);
     315        if (generatesInlineRun) {
     316            auto width = run->width;
     317            auto height = run->content.isText() ? LayoutUnit(root().style().computedLineHeight()) : layoutState.displayBoxForLayoutBox(run->content.inlineItem().layoutBox()).height();
     318            appendContentToLine(line, run->content, { width, height });
     319        }
    323320
    324321        if (isLastRun)
  • trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h

    r238403 r238460  
    3030#include "DisplayBox.h"
    3131#include "FormattingContext.h"
    32 #include "InlineLineBreaker.h"
    3332#include "InlineRun.h"
    3433#include <wtf/IsoMalloc.h>
     
    5251    class Line {
    5352    public:
    54         void init(const Display::Box::Rect&);
     53        void init(const LayoutPoint& topLeft, LayoutUnit availableWidth, LayoutUnit minimalHeight);
    5554        void close();
    5655
    57         void appendContent(const InlineLineBreaker::Run&);
     56        void appendContent(const InlineRunProvider::Run&, const LayoutSize&);
    5857
    5958        void adjustLogicalLeft(LayoutUnit delta);
     
    7271        LayoutUnit logicalTop() const { return m_logicalRect.top(); }
    7372        LayoutUnit logicalBottom() const { return m_logicalRect.bottom(); }
     73        LayoutUnit logicalHeight() const { return logicalBottom() - logicalTop(); }
    7474
    7575    private:
     
    106106    void initializeNewLine(Line&) const;
    107107    void closeLine(Line&, IsLastLine) const;
    108     void appendContentToLine(Line&, const InlineLineBreaker::Run&) const;
     108    void appendContentToLine(Line&, const InlineRunProvider::Run&, const LayoutSize&) const;
    109109    void postProcessInlineRuns(Line&, IsLastLine) const;
    110110    void createFinalRuns(Line&) const;
  • trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContextGeometry.cpp

    r238403 r238460  
    132132        inlineRun.expansionOpportunity().expansion = expansionForRun;
    133133        inlineRun.setLogicalLeft(inlineRun.logicalLeft() + accumulatedExpansion);
    134         inlineRun.setWidth(inlineRun.width() + expansionForRun);
     134        inlineRun.setLogicalWidth(inlineRun.logicalWidth() + expansionForRun);
    135135        accumulatedExpansion += expansionForRun;
    136136    }
  • trunk/Source/WebCore/layout/inlineformatting/InlineRun.h

    r238225 r238460  
    4242    LayoutUnit logicalBottom() const { return m_logicalRect.bottom(); }
    4343
    44     LayoutUnit width() const { return m_logicalRect.width(); }
    45     LayoutUnit height() const { return m_logicalRect.height(); }
     44    LayoutUnit logicalWidth() const { return m_logicalRect.width(); }
     45    LayoutUnit logicalHeight() const { return m_logicalRect.height(); }
    4646    bool overlapsMultipleInlineItems() const;
    4747
    48     void setWidth(LayoutUnit width) { m_logicalRect.setWidth(width); }
     48    void setLogicalWidth(LayoutUnit width) { m_logicalRect.setWidth(width); }
    4949    void setLogicalLeft(LayoutUnit logicalLeft) { m_logicalRect.setLeft(logicalLeft); }
    5050    void setLogicalRight(LayoutUnit logicalRight) { m_logicalRect.shiftRightTo(logicalRight); }
  • trunk/Source/WebCore/layout/inlineformatting/Line.cpp

    r238402 r238460  
    3333namespace Layout {
    3434
    35 void InlineFormattingContext::Line::init(const Display::Box::Rect& logicalRect)
     35void InlineFormattingContext::Line::init(const LayoutPoint& topLeft, LayoutUnit availableWidth, LayoutUnit minimalHeight)
    3636{
    37     m_logicalRect = logicalRect;
    38     m_availableWidth = logicalRect.width();
     37    m_logicalRect.setTopLeft(topLeft);
     38    m_logicalRect.setWidth(availableWidth);
     39    m_logicalRect.setHeight(minimalHeight);
     40    m_availableWidth = availableWidth;
    3941
    4042    m_inlineRuns.clear();
     
    7779}
    7880
    79 void InlineFormattingContext::Line::appendContent(const InlineLineBreaker::Run& run)
     81void InlineFormattingContext::Line::appendContent(const InlineRunProvider::Run& run, const LayoutSize& runSize)
    8082{
    8183    ASSERT(!isClosed());
    8284
    83     auto& content = run.content;
    84 
    8585    // Append this text run to the end of the last text run, if the last run is continuous.
    8686    std::optional<InlineRun::TextContext> textRun;
    87     if (content.isText()) {
    88         auto textContext = content.textContext();
     87    if (run.isText()) {
     88        auto textContext = run.textContext();
    8989        auto runLength = textContext->isCollapsed() ? 1 : textContext->length();
    9090        textRun = InlineRun::TextContext { textContext->start(), runLength };
    9191    }
    9292
    93     auto requiresNewInlineRun = !hasContent() || !content.isText() || !m_lastRunCanExpand;
     93    auto requiresNewInlineRun = !hasContent() || !run.isText() || !m_lastRunCanExpand;
    9494    if (requiresNewInlineRun) {
    9595        // FIXME: This needs proper baseline handling
    96         auto inlineRun = InlineRun { { logicalTop(), contentLogicalRight(), run.width, logicalBottom() - logicalTop() }, content.inlineItem() };
     96        auto inlineRun = InlineRun { { logicalTop(), contentLogicalRight(), runSize.width(), runSize.height() }, run.inlineItem() };
    9797        if (textRun)
    9898            inlineRun.setTextContext({ textRun->start(), textRun->length() });
    9999        m_inlineRuns.append(inlineRun);
     100        m_logicalRect.setHeight(std::max(runSize.height(), m_logicalRect.height()));
    100101    } else {
    101102        // Non-text runs always require new inline run.
    102103        ASSERT(textRun);
    103104        auto& inlineRun = m_inlineRuns.last();
    104         inlineRun.setWidth(inlineRun.width() + run.width);
     105        ASSERT(runSize.height() == inlineRun.logicalHeight());
     106        inlineRun.setLogicalWidth(inlineRun.logicalWidth() + runSize.width());
    105107        inlineRun.textContext()->setLength(inlineRun.textContext()->length() + textRun->length());
    106108    }
    107109
    108     m_availableWidth -= run.width;
    109     m_lastRunType = content.type();
    110     m_lastRunCanExpand = content.isText() && !content.textContext()->isCollapsed();
     110    m_availableWidth -= runSize.width();
     111    m_lastRunType = run.type();
     112    m_lastRunCanExpand = run.isText() && !run.textContext()->isCollapsed();
    111113    m_trailingTrimmableContent = { };
    112     if (isTrimmableContent(content))
    113         m_trailingTrimmableContent = TrailingTrimmableContent { run.width, textRun->length() };
     114    if (isTrimmableContent(run))
     115        m_trailingTrimmableContent = TrailingTrimmableContent { runSize.width(), textRun->length() };
    114116}
    115117
     
    122124
    123125        auto& lastInlineRun = m_inlineRuns.last();
    124         lastInlineRun.setWidth(lastInlineRun.width() - m_trailingTrimmableContent->width);
     126        lastInlineRun.setLogicalWidth(lastInlineRun.logicalWidth() - m_trailingTrimmableContent->width);
    125127        lastInlineRun.textContext()->setLength(lastInlineRun.textContext()->length() - m_trailingTrimmableContent->length);
    126128
  • trunk/Source/WebCore/layout/layouttree/LayoutTreeBuilder.cpp

    r238279 r238460  
    152152        else
    153153            stream << "(x, x) ";
    154         stream << "at [" << inlineRun.logicalLeft() << ", " << inlineRun.logicalTop() << "] size [" << inlineRun.width() << " " << inlineRun.height() << "]";
     154        stream << "at [" << inlineRun.logicalLeft() << ", " << inlineRun.logicalTop() << "] size [" << inlineRun.logicalWidth() << " " << inlineRun.logicalHeight() << "]";
    155155        stream.nextLine();
    156156    }
  • trunk/Tools/ChangeLog

    r238458 r238460  
     12018-11-23  Zalan Bujtas  <zalan@apple.com>
     2
     3        [LFC][IFC] Add support for variable height runs.
     4        https://bugs.webkit.org/show_bug.cgi?id=191925
     5
     6        Reviewed by Antti Koivisto.
     7
     8        * LayoutReloaded/misc/LFC-passing-tests.txt:
     9
    1102018-11-23  Alberto Garcia  <berto@igalia.com>
    211
  • trunk/Tools/LayoutReloaded/misc/LFC-passing-tests.txt

    r238448 r238460  
    7777fast/inline/inline-content-with-margin-left-right.html
    7878fast/inline/inline-content-and-nested-formatting-root-with-margin-left-right.html
     79fast/inline/inline-content-with-image-simple.html
    7980fast/block/basic/height-percentage-simple.html
    8081fast/block/basic/child-block-level-box-with-height-percent.html
Note: See TracChangeset for help on using the changeset viewer.