Changeset 241023 in webkit


Ignore:
Timestamp:
Feb 6, 2019 9:04:44 AM (5 years ago)
Author:
Alan Bujtas
Message:

[LFC][IFC] Move line layout code to a dedicated file
https://bugs.webkit.org/show_bug.cgi?id=194328

Reviewed by Antti Koivisto.

  • Sources.txt:
  • WebCore.xcodeproj/project.pbxproj:
  • layout/inlineformatting/InlineFormattingContext.cpp:

(WebCore::Layout::InlineFormattingContext::layout const):
(WebCore::Layout::isTrimmableContent): Deleted.
(WebCore::Layout::InlineFormattingContext::initializeNewLine const): Deleted.
(WebCore::Layout::InlineFormattingContext::splitInlineRunIfNeeded const): Deleted.
(WebCore::Layout::InlineFormattingContext::createFinalRuns const): Deleted.
(WebCore::Layout::InlineFormattingContext::postProcessInlineRuns const): Deleted.
(WebCore::Layout::InlineFormattingContext::closeLine const): Deleted.
(WebCore::Layout::InlineFormattingContext::appendContentToLine const): Deleted.
(WebCore::Layout::InlineFormattingContext::layoutInlineContent const): Deleted.
(WebCore::Layout::InlineFormattingContext::computeFloatPosition const): Deleted.
(WebCore::Layout::InlineFormattingContext::placeInFlowPositionedChildren const): Deleted.

  • layout/inlineformatting/InlineFormattingContext.h:

(WebCore::Layout::InlineFormattingContext::LineLayout::Line::hasContent const):
(WebCore::Layout::InlineFormattingContext::LineLayout::Line::isClosed const):
(WebCore::Layout::InlineFormattingContext::LineLayout::Line::isFirstLine const):
(WebCore::Layout::InlineFormattingContext::LineLayout::Line::runs):
(WebCore::Layout::InlineFormattingContext::LineLayout::Line::contentLogicalLeft const):
(WebCore::Layout::InlineFormattingContext::LineLayout::Line::availableWidth const):
(WebCore::Layout::InlineFormattingContext::LineLayout::Line::lastRunType const):
(WebCore::Layout::InlineFormattingContext::LineLayout::Line::logicalTop const):
(WebCore::Layout::InlineFormattingContext::LineLayout::Line::logicalBottom const):
(WebCore::Layout::InlineFormattingContext::LineLayout::Line::logicalHeight const):
(WebCore::Layout::InlineFormattingContext::Line::hasContent const): Deleted.
(WebCore::Layout::InlineFormattingContext::Line::isClosed const): Deleted.
(WebCore::Layout::InlineFormattingContext::Line::isFirstLine const): Deleted.
(WebCore::Layout::InlineFormattingContext::Line::runs): Deleted.
(WebCore::Layout::InlineFormattingContext::Line::contentLogicalLeft const): Deleted.
(WebCore::Layout::InlineFormattingContext::Line::availableWidth const): Deleted.
(WebCore::Layout::InlineFormattingContext::Line::lastRunType const): Deleted.
(WebCore::Layout::InlineFormattingContext::Line::logicalTop const): Deleted.
(WebCore::Layout::InlineFormattingContext::Line::logicalBottom const): Deleted.
(WebCore::Layout::InlineFormattingContext::Line::logicalHeight const): Deleted.

  • layout/inlineformatting/InlineFormattingContextGeometry.cpp:

(WebCore::Layout::adjustedLineLogicalLeft): Deleted.
(WebCore::Layout::InlineFormattingContext::Geometry::justifyRuns): Deleted.
(WebCore::Layout::InlineFormattingContext::Geometry::computeExpansionOpportunities): Deleted.
(WebCore::Layout::InlineFormattingContext::Geometry::alignRuns): Deleted.
(WebCore::Layout::InlineFormattingContext::Geometry::runWidth): Deleted.

  • layout/inlineformatting/Line.cpp:

(WebCore::Layout::InlineFormattingContext::LineLayout::Line::init):
(WebCore::Layout::InlineFormattingContext::LineLayout::Line::adjustLogicalLeft):
(WebCore::Layout::InlineFormattingContext::LineLayout::Line::adjustLogicalRight):
(WebCore::Layout::InlineFormattingContext::LineLayout::Line::contentLogicalRight const):
(WebCore::Layout::InlineFormattingContext::LineLayout::Line::appendContent):
(WebCore::Layout::InlineFormattingContext::LineLayout::Line::close):
(WebCore::Layout::InlineFormattingContext::Line::init): Deleted.
(WebCore::Layout::InlineFormattingContext::Line::adjustLogicalLeft): Deleted.
(WebCore::Layout::InlineFormattingContext::Line::adjustLogicalRight): Deleted.
(WebCore::Layout::InlineFormattingContext::Line::contentLogicalRight const): Deleted.
(WebCore::Layout::InlineFormattingContext::Line::appendContent): Deleted.
(WebCore::Layout::InlineFormattingContext::Line::close): Deleted.

Location:
trunk/Source/WebCore
Files:
1 added
1 deleted
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r241022 r241023  
     12019-02-06  Zalan Bujtas  <zalan@apple.com>
     2
     3        [LFC][IFC] Move line layout code to a dedicated file
     4        https://bugs.webkit.org/show_bug.cgi?id=194328
     5
     6        Reviewed by Antti Koivisto.
     7
     8        * Sources.txt:
     9        * WebCore.xcodeproj/project.pbxproj:
     10        * layout/inlineformatting/InlineFormattingContext.cpp:
     11        (WebCore::Layout::InlineFormattingContext::layout const):
     12        (WebCore::Layout::isTrimmableContent): Deleted.
     13        (WebCore::Layout::InlineFormattingContext::initializeNewLine const): Deleted.
     14        (WebCore::Layout::InlineFormattingContext::splitInlineRunIfNeeded const): Deleted.
     15        (WebCore::Layout::InlineFormattingContext::createFinalRuns const): Deleted.
     16        (WebCore::Layout::InlineFormattingContext::postProcessInlineRuns const): Deleted.
     17        (WebCore::Layout::InlineFormattingContext::closeLine const): Deleted.
     18        (WebCore::Layout::InlineFormattingContext::appendContentToLine const): Deleted.
     19        (WebCore::Layout::InlineFormattingContext::layoutInlineContent const): Deleted.
     20        (WebCore::Layout::InlineFormattingContext::computeFloatPosition const): Deleted.
     21        (WebCore::Layout::InlineFormattingContext::placeInFlowPositionedChildren const): Deleted.
     22        * layout/inlineformatting/InlineFormattingContext.h:
     23        (WebCore::Layout::InlineFormattingContext::LineLayout::Line::hasContent const):
     24        (WebCore::Layout::InlineFormattingContext::LineLayout::Line::isClosed const):
     25        (WebCore::Layout::InlineFormattingContext::LineLayout::Line::isFirstLine const):
     26        (WebCore::Layout::InlineFormattingContext::LineLayout::Line::runs):
     27        (WebCore::Layout::InlineFormattingContext::LineLayout::Line::contentLogicalLeft const):
     28        (WebCore::Layout::InlineFormattingContext::LineLayout::Line::availableWidth const):
     29        (WebCore::Layout::InlineFormattingContext::LineLayout::Line::lastRunType const):
     30        (WebCore::Layout::InlineFormattingContext::LineLayout::Line::logicalTop const):
     31        (WebCore::Layout::InlineFormattingContext::LineLayout::Line::logicalBottom const):
     32        (WebCore::Layout::InlineFormattingContext::LineLayout::Line::logicalHeight const):
     33        (WebCore::Layout::InlineFormattingContext::Line::hasContent const): Deleted.
     34        (WebCore::Layout::InlineFormattingContext::Line::isClosed const): Deleted.
     35        (WebCore::Layout::InlineFormattingContext::Line::isFirstLine const): Deleted.
     36        (WebCore::Layout::InlineFormattingContext::Line::runs): Deleted.
     37        (WebCore::Layout::InlineFormattingContext::Line::contentLogicalLeft const): Deleted.
     38        (WebCore::Layout::InlineFormattingContext::Line::availableWidth const): Deleted.
     39        (WebCore::Layout::InlineFormattingContext::Line::lastRunType const): Deleted.
     40        (WebCore::Layout::InlineFormattingContext::Line::logicalTop const): Deleted.
     41        (WebCore::Layout::InlineFormattingContext::Line::logicalBottom const): Deleted.
     42        (WebCore::Layout::InlineFormattingContext::Line::logicalHeight const): Deleted.
     43        * layout/inlineformatting/InlineFormattingContextGeometry.cpp:
     44        (WebCore::Layout::adjustedLineLogicalLeft): Deleted.
     45        (WebCore::Layout::InlineFormattingContext::Geometry::justifyRuns): Deleted.
     46        (WebCore::Layout::InlineFormattingContext::Geometry::computeExpansionOpportunities): Deleted.
     47        (WebCore::Layout::InlineFormattingContext::Geometry::alignRuns): Deleted.
     48        (WebCore::Layout::InlineFormattingContext::Geometry::runWidth): Deleted.
     49        * layout/inlineformatting/Line.cpp:
     50        (WebCore::Layout::InlineFormattingContext::LineLayout::Line::init):
     51        (WebCore::Layout::InlineFormattingContext::LineLayout::Line::adjustLogicalLeft):
     52        (WebCore::Layout::InlineFormattingContext::LineLayout::Line::adjustLogicalRight):
     53        (WebCore::Layout::InlineFormattingContext::LineLayout::Line::contentLogicalRight const):
     54        (WebCore::Layout::InlineFormattingContext::LineLayout::Line::appendContent):
     55        (WebCore::Layout::InlineFormattingContext::LineLayout::Line::close):
     56        (WebCore::Layout::InlineFormattingContext::Line::init): Deleted.
     57        (WebCore::Layout::InlineFormattingContext::Line::adjustLogicalLeft): Deleted.
     58        (WebCore::Layout::InlineFormattingContext::Line::adjustLogicalRight): Deleted.
     59        (WebCore::Layout::InlineFormattingContext::Line::contentLogicalRight const): Deleted.
     60        (WebCore::Layout::InlineFormattingContext::Line::appendContent): Deleted.
     61        (WebCore::Layout::InlineFormattingContext::Line::close): Deleted.
     62
    1632019-02-06  Youenn Fablet  <youenn@apple.com>
    264
  • trunk/Source/WebCore/Sources.txt

    r240898 r241023  
    13411341layout/inlineformatting/InlineFormattingContext.cpp
    13421342layout/inlineformatting/InlineFormattingContextGeometry.cpp
     1343layout/inlineformatting/InlineFormattingContextLineLayout.cpp
    13431344layout/inlineformatting/InlineFormattingState.cpp
    13441345layout/inlineformatting/InlineInvalidation.cpp
    13451346layout/inlineformatting/InlineLineBreaker.cpp
    13461347layout/inlineformatting/InlineRunProvider.cpp
    1347 layout/inlineformatting/Line.cpp
    13481348layout/inlineformatting/text/TextUtil.cpp
    13491349layout/layouttree/LayoutBlockContainer.cpp
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r240994 r241023  
    91979197                6F0830DF20B46951008A945B /* BlockFormattingContextGeometry.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = BlockFormattingContextGeometry.cpp; sourceTree = "<group>"; };
    91989198                6F219D742178D37100BB033C /* InlineRun.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InlineRun.h; sourceTree = "<group>"; };
    9199                 6F219D762178D37100BB033C /* Line.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Line.cpp; sourceTree = "<group>"; };
    92009199                6F222B741AB52D640094651A /* WebGLVertexArrayObjectBase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebGLVertexArrayObjectBase.h; sourceTree = "<group>"; };
    92019200                6F222B751AB52D8A0094651A /* WebGLVertexArrayObjectBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebGLVertexArrayObjectBase.cpp; sourceTree = "<group>"; };
     9201                6F25B200220A85AB0000011B /* InlineFormattingContextLineLayout.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = InlineFormattingContextLineLayout.cpp; sourceTree = "<group>"; };
    92029202                6F35EFAF2187CBD50044E0F4 /* InlineFormattingContextGeometry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InlineFormattingContextGeometry.cpp; sourceTree = "<group>"; };
    92039203                6F3E1F5F2136141700A65A08 /* FloatBox.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FloatBox.cpp; sourceTree = "<group>"; };
     
    1645716457                                6F7CA3C8208C2B2E002F29AB /* InlineFormattingContext.h */,
    1645816458                                6F35EFAF2187CBD50044E0F4 /* InlineFormattingContextGeometry.cpp */,
     16459                                6F25B200220A85AB0000011B /* InlineFormattingContextLineLayout.cpp */,
    1645916460                                115CFA7D208B8E10001E6991 /* InlineFormattingState.cpp */,
    1646016461                                115CFA7C208B8E10001E6991 /* InlineFormattingState.h */,
     
    1646716468                                6F5217C62177F5A6006583BB /* InlineRunProvider.cpp */,
    1646816469                                6F5217C42177F5A6006583BB /* InlineRunProvider.h */,
    16469                                 6F219D762178D37100BB033C /* Line.cpp */,
    1647016470                        );
    1647116471                        path = inlineformatting;
  • trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp

    r240975 r241023  
    2929#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
    3030
    31 #include "FloatingContext.h"
    32 #include "FloatingState.h"
    3331#include "InlineFormattingState.h"
    3432#include "InlineLineBreaker.h"
     
    8886    InlineRunProvider inlineRunProvider;
    8987    collectInlineContent(inlineRunProvider);
    90     layoutInlineContent(inlineRunProvider);
     88    LineLayout(*this).layout(inlineRunProvider);
    9189    LOG_WITH_STREAM(FormattingContextLayout, stream << "[End] -> inline formatting context -> formatting root(" << &root << ")");
    92 }
    93 
    94 static bool isTrimmableContent(const InlineLineBreaker::Run& run)
    95 {
    96     return run.content.isWhitespace() && run.content.style().collapseWhiteSpace();
    97 }
    98 
    99 void InlineFormattingContext::initializeNewLine(Line& line) const
    100 {
    101     auto& formattingRoot = downcast<Container>(root());
    102     auto& formattingRootDisplayBox = layoutState().displayBoxForLayoutBox(formattingRoot);
    103 
    104     auto lineLogicalLeft = formattingRootDisplayBox.contentBoxLeft();
    105     auto lineLogicalTop = line.isFirstLine() ? formattingRootDisplayBox.contentBoxTop() : line.logicalBottom();
    106     auto availableWidth = formattingRootDisplayBox.contentBoxWidth();
    107 
    108     // Check for intruding floats and adjust logical left/available width for this line accordingly.
    109     auto& floatingState = formattingState().floatingState();
    110     if (!floatingState.isEmpty()) {
    111         auto floatConstraints = floatingState.constraints({ lineLogicalTop }, formattingRoot);
    112         // Check if these constraints actually put limitation on the line.
    113         if (floatConstraints.left && *floatConstraints.left <= formattingRootDisplayBox.contentBoxLeft())
    114             floatConstraints.left = { };
    115 
    116         if (floatConstraints.right && *floatConstraints.right >= formattingRootDisplayBox.contentBoxRight())
    117             floatConstraints.right = { };
    118 
    119         if (floatConstraints.left && floatConstraints.right) {
    120             ASSERT(*floatConstraints.left < *floatConstraints.right);
    121             availableWidth = *floatConstraints.right - *floatConstraints.left;
    122             lineLogicalLeft = *floatConstraints.left;
    123         } else if (floatConstraints.left) {
    124             ASSERT(*floatConstraints.left > lineLogicalLeft);
    125             availableWidth -= (*floatConstraints.left - lineLogicalLeft);
    126             lineLogicalLeft = *floatConstraints.left;
    127         } else if (floatConstraints.right) {
    128             ASSERT(*floatConstraints.right > lineLogicalLeft);
    129             availableWidth = *floatConstraints.right - lineLogicalLeft;
    130         }
    131     }
    132 
    133     line.init({ lineLogicalLeft, lineLogicalTop }, availableWidth, formattingRoot.style().computedLineHeight());
    134 }
    135 
    136 void InlineFormattingContext::splitInlineRunIfNeeded(const InlineRun& inlineRun, InlineRuns& splitRuns) const
    137 {
    138     ASSERT(inlineRun.textContext());
    139     ASSERT(inlineRun.overlapsMultipleInlineItems());
    140     // In certain cases, a run can overlap multiple inline elements like this:
    141     // <span>normal text content</span><span style="position: relative; left: 10px;">but this one needs a dedicated run</span><span>end of text</span>
    142     // The content above generates one long run <normal text contentbut this one needs dedicated runend of text>
    143     // However, since the middle run is positioned, it needs to be moved independently from the rest of the content, hence it needs a dedicated inline run.
    144 
    145     // 1. Start with the first inline item (element) and travers the list until
    146     // 2. either find an inline item that needs a dedicated run or we reach the end of the run
    147     // 3. Create dedicate inline runs.
    148     auto& inlineContent = formattingState().inlineContent();
    149     auto contentStart = inlineRun.logicalLeft();
    150     auto startPosition = inlineRun.textContext()->start();
    151     auto remaningLength = inlineRun.textContext()->length();
    152 
    153     struct Uncommitted {
    154         const InlineItem* firstInlineItem { nullptr };
    155         const InlineItem* lastInlineItem { nullptr };
    156         unsigned length { 0 };
    157     };
    158     Optional<Uncommitted> uncommitted;
    159 
    160     auto commit = [&] {
    161         if (!uncommitted)
    162             return;
    163 
    164         contentStart += uncommitted->firstInlineItem->nonBreakableStart();
    165 
    166         auto runWidth = Geometry::runWidth(inlineContent, *uncommitted->firstInlineItem, startPosition, uncommitted->length, contentStart);
    167         auto run = InlineRun { { inlineRun.logicalTop(), contentStart, runWidth, inlineRun.logicalHeight() }, *uncommitted->firstInlineItem };
    168         run.setTextContext({ startPosition, uncommitted->length });
    169         splitRuns.append(run);
    170 
    171         contentStart += runWidth + uncommitted->lastInlineItem->nonBreakableEnd();
    172 
    173         startPosition = 0;
    174         uncommitted = { };
    175     };
    176 
    177     for (auto iterator = inlineContent.find(const_cast<InlineItem*>(&inlineRun.inlineItem())); iterator != inlineContent.end() && remaningLength > 0; ++iterator) {
    178         auto& inlineItem = **iterator;
    179 
    180         // Skip all non-inflow boxes (floats, out-of-flow positioned elements). They don't participate in the inline run context.
    181         if (!inlineItem.layoutBox().isInFlow())
    182             continue;
    183 
    184         auto currentLength = [&] {
    185             return std::min(remaningLength, inlineItem.textContent().length() - startPosition);
    186         };
    187 
    188         // 1. Break before/after -> requires dedicated run -> commit what we've got so far and also commit the current inline element as a separate inline run.
    189         // 2. Break at the beginning of the inline element -> commit what we've got so far. Current element becomes the first uncommitted.
    190         // 3. Break at the end of the inline element -> commit what we've got so far including the current element.
    191         // 4. Inline element does not require run breaking -> add current inline element to uncommitted. Jump to the next element.
    192         auto detachingRules = inlineItem.detachingRules();
    193 
    194         // #1
    195         if (detachingRules.containsAll({ InlineItem::DetachingRule::BreakAtStart, InlineItem::DetachingRule::BreakAtEnd })) {
    196             commit();
    197             auto contentLength = currentLength();
    198             uncommitted = Uncommitted { &inlineItem, &inlineItem, contentLength };
    199             remaningLength -= contentLength;
    200             commit();
    201             continue;
    202         }
    203 
    204         // #2
    205         if (detachingRules.contains(InlineItem::DetachingRule::BreakAtStart))
    206             commit();
    207 
    208         // Add current inline item to uncommitted.
    209         // #3 and #4
    210         auto contentLength = currentLength();
    211         if (!uncommitted)
    212             uncommitted = Uncommitted { &inlineItem, &inlineItem, 0 };
    213         uncommitted->length += contentLength;
    214         uncommitted->lastInlineItem = &inlineItem;
    215         remaningLength -= contentLength;
    216 
    217         // #3
    218         if (detachingRules.contains(InlineItem::DetachingRule::BreakAtEnd))
    219             commit();
    220     }
    221     // Either all inline elements needed dedicated runs or neither of them.
    222     if (!remaningLength || remaningLength == inlineRun.textContext()->length())
    223         return;
    224 
    225     commit();
    226 }
    227 
    228 void InlineFormattingContext::createFinalRuns(Line& line) const
    229 {
    230     auto& inlineFormattingState = formattingState();
    231     for (auto& inlineRun : line.runs()) {
    232         if (inlineRun.overlapsMultipleInlineItems()) {
    233             InlineRuns splitRuns;
    234             splitInlineRunIfNeeded(inlineRun, splitRuns);
    235             for (auto& splitRun : splitRuns)
    236                 inlineFormattingState.appendInlineRun(splitRun);
    237 
    238             if (!splitRuns.isEmpty())
    239                 continue;
    240         }
    241 
    242         auto finalRun = [&] {
    243             auto& inlineItem = inlineRun.inlineItem();
    244             if (inlineItem.detachingRules().isEmpty())
    245                 return inlineRun;
    246 
    247             InlineRun adjustedRun = inlineRun;
    248             auto width = inlineRun.logicalWidth() - inlineItem.nonBreakableStart() - inlineItem.nonBreakableEnd();
    249             adjustedRun.setLogicalLeft(inlineRun.logicalLeft() + inlineItem.nonBreakableStart());
    250             adjustedRun.setLogicalWidth(width);
    251             return adjustedRun;
    252         };
    253 
    254         inlineFormattingState.appendInlineRun(finalRun());
    255     }
    256 }
    257 
    258 void InlineFormattingContext::postProcessInlineRuns(Line& line, IsLastLine isLastLine) const
    259 {
    260     Geometry::alignRuns(root().style().textAlign(), line, isLastLine);
    261     auto firstRunIndex = formattingState().inlineRuns().size();
    262     createFinalRuns(line);
    263 
    264     placeInFlowPositionedChildren(firstRunIndex);
    265 }
    266 
    267 void InlineFormattingContext::closeLine(Line& line, IsLastLine isLastLine) const
    268 {
    269     line.close();
    270     if (!line.hasContent())
    271         return;
    272 
    273     postProcessInlineRuns(line, isLastLine);
    274 }
    275 
    276 void InlineFormattingContext::appendContentToLine(Line& line, const InlineRunProvider::Run& run, const LayoutSize& runSize) const
    277 {
    278     auto lastRunType = line.lastRunType();
    279     line.appendContent(run, runSize);
    280 
    281     if (root().style().textAlign() == TextAlignMode::Justify)
    282         Geometry::computeExpansionOpportunities(line, run, lastRunType.valueOr(InlineRunProvider::Run::Type::NonWhitespace));
    283 }
    284 
    285 void InlineFormattingContext::layoutInlineContent(const InlineRunProvider& inlineRunProvider) const
    286 {
    287     auto& layoutState = this->layoutState();
    288     auto& inlineFormattingState = formattingState();
    289     auto floatingContext = FloatingContext { inlineFormattingState.floatingState() };
    290 
    291     Line line;
    292     initializeNewLine(line);
    293 
    294     InlineLineBreaker lineBreaker(layoutState, inlineFormattingState.inlineContent(), inlineRunProvider.runs());
    295     while (auto run = lineBreaker.nextRun(line.contentLogicalRight(), line.availableWidth(), !line.hasContent())) {
    296         auto isFirstRun = run->position == InlineLineBreaker::Run::Position::LineBegin;
    297         auto isLastRun = run->position == InlineLineBreaker::Run::Position::LineEnd;
    298         auto generatesInlineRun = true;
    299 
    300         // Position float and adjust the runs on line.
    301         if (run->content.isFloat()) {
    302             auto& floatBox = run->content.inlineItem().layoutBox();
    303             computeFloatPosition(floatingContext, line, floatBox);
    304             inlineFormattingState.floatingState().append(floatBox);
    305 
    306             auto floatBoxWidth = layoutState.displayBoxForLayoutBox(floatBox).marginBox().width();
    307             // Shrink availble space for current line and move existing inline runs.
    308             floatBox.isLeftFloatingPositioned() ? line.adjustLogicalLeft(floatBoxWidth) : line.adjustLogicalRight(floatBoxWidth);
    309 
    310             generatesInlineRun = false;
    311         }
    312 
    313         // 1. Initialize new line if needed.
    314         // 2. Append inline run unless it is skipped.
    315         // 3. Close current line if needed.
    316         if (isFirstRun) {
    317             // When the first run does not generate an actual inline run, the next run comes in first-run as well.
    318             // No need to spend time on closing/initializing.
    319             // Skip leading whitespace.
    320             if (!generatesInlineRun || isTrimmableContent(*run))
    321                 continue;
    322 
    323             if (line.hasContent()) {
    324                 // Previous run ended up being at the line end. Adjust the line accordingly.
    325                 if (!line.isClosed())
    326                     closeLine(line, IsLastLine::No);
    327                 initializeNewLine(line);
    328             }
    329          }
    330 
    331         if (generatesInlineRun) {
    332             auto width = run->width;
    333             auto height = run->content.isText() ? LayoutUnit(root().style().computedLineHeight()) : layoutState.displayBoxForLayoutBox(run->content.inlineItem().layoutBox()).height();
    334             appendContentToLine(line, run->content, { width, height });
    335         }
    336 
    337         if (isLastRun)
    338             closeLine(line, IsLastLine::No);
    339     }
    340 
    341     closeLine(line, IsLastLine::Yes);
    34290}
    34391
     
    418166    computeWidthAndMargin(layoutBox);
    419167    computeHeightAndMargin(layoutBox);
    420 }
    421 
    422 void InlineFormattingContext::computeFloatPosition(const FloatingContext& floatingContext, Line& line, const Box& floatBox) const
    423 {
    424     auto& layoutState = this->layoutState();
    425     ASSERT(layoutState.hasDisplayBox(floatBox));
    426     auto& displayBox = layoutState.displayBoxForLayoutBox(floatBox);
    427 
    428     // Set static position first.
    429     displayBox.setTopLeft({ line.contentLogicalRight(), line.logicalTop() });
    430     // Float it.
    431     displayBox.setTopLeft(floatingContext.positionForFloat(floatBox));
    432 }
    433 
    434 void InlineFormattingContext::placeInFlowPositionedChildren(unsigned fistRunIndex) const
    435 {
    436     auto& inlineRuns = formattingState().inlineRuns();
    437     for (auto runIndex = fistRunIndex; runIndex < inlineRuns.size(); ++runIndex) {
    438         auto& inlineRun = inlineRuns[runIndex];
    439 
    440         auto positionOffset = [&](auto& layoutBox) {
    441             // FIXME: Need to figure out whether in-flow offset should stick. This might very well be temporary.
    442             Optional<LayoutSize> offset;
    443             for (auto* box = &layoutBox; box != &root(); box = box->parent()) {
    444                 if (!box->isInFlowPositioned())
    445                     continue;
    446                 offset = offset.valueOr(LayoutSize()) + Geometry::inFlowPositionedPositionOffset(layoutState(), *box);
    447             }
    448             return offset;
    449         };
    450 
    451         if (auto offset = positionOffset(inlineRun.inlineItem().layoutBox())) {
    452             inlineRun.moveVertically(offset->height());
    453             inlineRun.moveHorizontally(offset->width());
    454         }
    455     }
    456168}
    457169
  • trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h

    r240975 r241023  
    3030#include "DisplayBox.h"
    3131#include "FormattingContext.h"
     32#include "InlineFormattingState.h"
    3233#include "InlineRun.h"
    3334#include <wtf/IsoMalloc.h>
     
    3637namespace Layout {
    3738
     39class FloatingState;
    3840class InlineContainer;
    39 class InlineFormattingState;
    4041class InlineRunProvider;
     42class Line;
    4143
    4244// This class implements the layout logic for inline formatting contexts.
     
    4648public:
    4749    InlineFormattingContext(const Box& formattingContextRoot, InlineFormattingState&);
    48 
    4950    void layout() const override;
    5051
    5152private:
    52     class Line {
     53    class LineLayout {
    5354    public:
    54         void init(const LayoutPoint& topLeft, LayoutUnit availableWidth, LayoutUnit minimalHeight);
    55         void close();
    56 
    57         void appendContent(const InlineRunProvider::Run&, const LayoutSize&);
    58 
    59         void adjustLogicalLeft(LayoutUnit delta);
    60         void adjustLogicalRight(LayoutUnit delta);
    61 
    62         bool hasContent() const { return !m_inlineRuns.isEmpty(); }
    63         bool isClosed() const { return m_closed; }
    64         bool isFirstLine() const { return m_isFirstLine; }
    65         Vector<InlineRun>& runs() { return m_inlineRuns; }
    66 
    67         LayoutUnit contentLogicalRight() const;
    68         LayoutUnit contentLogicalLeft() const { return m_logicalRect.left(); }
    69         LayoutUnit availableWidth() const { return m_availableWidth; }
    70         Optional<InlineRunProvider::Run::Type> lastRunType() const { return m_lastRunType; }
    71 
    72         LayoutUnit logicalTop() const { return m_logicalRect.top(); }
    73         LayoutUnit logicalBottom() const { return m_logicalRect.bottom(); }
    74         LayoutUnit logicalHeight() const { return logicalBottom() - logicalTop(); }
     55        LineLayout(const InlineFormattingContext&);
     56        void layout(const InlineRunProvider&) const;
    7557
    7658    private:
    77         struct TrailingTrimmableContent {
    78             LayoutUnit width;
    79             unsigned length;
    80         };
    81         Optional<TrailingTrimmableContent> m_trailingTrimmableContent;
    82         Optional<InlineRunProvider::Run::Type> m_lastRunType;
    83         bool m_lastRunCanExpand { false };
     59        enum class IsLastLine { No, Yes };
     60        void initializeNewLine(Line&) const;
     61        void closeLine(Line&, IsLastLine) const;
     62        void appendContentToLine(Line&, const InlineRunProvider::Run&, const LayoutSize&) const;
     63        void postProcessInlineRuns(Line&, IsLastLine) const;
     64        void createFinalRuns(Line&) const;
     65        void splitInlineRunIfNeeded(const InlineRun&, InlineRuns& splitRuns) const;
     66        void computeFloatPosition(const FloatingContext&, Line&, const Box&) const;
     67        void placeInFlowPositionedChildren(unsigned firstRunIndex) const;
     68        void alignRuns(TextAlignMode, Line&, IsLastLine) const;
     69        void computeExpansionOpportunities(Line&, const InlineRunProvider::Run&, InlineRunProvider::Run::Type lastRunType) const;
     70        LayoutUnit runWidth(const InlineContent&, const InlineItem&, ItemPosition from, unsigned length, LayoutUnit contentLogicalLeft) const;
    8471
    85         Display::Box::Rect m_logicalRect;
    86         LayoutUnit m_availableWidth;
     72    private:
     73        static void justifyRuns(Line&);
    8774
    88         Vector<InlineRun> m_inlineRuns;
    89         bool m_isFirstLine { true };
    90         bool m_closed { true };
     75    private:
     76        const InlineFormattingContext& m_formattingContext;
     77        InlineFormattingState& m_formattingState;
     78        FloatingState& m_floatingState;
     79        const Container& m_formattingRoot;
    9180    };
    92     enum class IsLastLine { No, Yes };
    9381
    9482    class Geometry : public FormattingContext::Geometry {
     
    9684        static HeightAndMargin inlineBlockHeightAndMargin(const LayoutState&, const Box&);
    9785        static WidthAndMargin inlineBlockWidthAndMargin(LayoutState&, const Box&);
    98         static void alignRuns(TextAlignMode, Line&, IsLastLine);
    99         static void computeExpansionOpportunities(Line&, const InlineRunProvider::Run&, InlineRunProvider::Run::Type lastRunType);
    100         static LayoutUnit runWidth(const InlineContent&, const InlineItem&, ItemPosition from, unsigned length, LayoutUnit contentLogicalLeft);
    101 
    102     private:
    103         static void justifyRuns(Line&);
    10486    };
    105 
    106     void layoutInlineContent(const InlineRunProvider&) const;
    107     void initializeNewLine(Line&) const;
    108     void closeLine(Line&, IsLastLine) const;
    109     void appendContentToLine(Line&, const InlineRunProvider::Run&, const LayoutSize&) const;
    110     void postProcessInlineRuns(Line&, IsLastLine) const;
    111     void createFinalRuns(Line&) const;
    112     void splitInlineRunIfNeeded(const InlineRun&, InlineRuns& splitRuns) const;
    11387
    11488    void layoutFormattingContextRoot(const Box&) const;
     
    11791    void computeHeightAndMargin(const Box&) const;
    11892    void computeWidthAndMargin(const Box&) const;
    119     void computeFloatPosition(const FloatingContext&, Line&, const Box&) const;
    120     void placeInFlowPositionedChildren(unsigned firstRunIndex) const;
    12193
    12294    void collectInlineContent(InlineRunProvider&) const;
  • trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContextGeometry.cpp

    r239609 r241023  
    7979}
    8080
    81 static LayoutUnit adjustedLineLogicalLeft(TextAlignMode align, LayoutUnit lineLogicalLeft, LayoutUnit remainingWidth)
    82 {
    83     switch (align) {
    84     case TextAlignMode::Left:
    85     case TextAlignMode::WebKitLeft:
    86     case TextAlignMode::Start:
    87         return lineLogicalLeft;
    88     case TextAlignMode::Right:
    89     case TextAlignMode::WebKitRight:
    90     case TextAlignMode::End:
    91         return lineLogicalLeft + std::max(remainingWidth, 0_lu);
    92     case TextAlignMode::Center:
    93     case TextAlignMode::WebKitCenter:
    94         return lineLogicalLeft + std::max(remainingWidth / 2, 0_lu);
    95     case TextAlignMode::Justify:
    96         ASSERT_NOT_REACHED();
    97         break;
    98     }
    99     ASSERT_NOT_REACHED();
    100     return lineLogicalLeft;
    101 }
    102 
    103 void InlineFormattingContext::Geometry::justifyRuns(Line& line)
    104 {
    105     auto& inlineRuns = line.runs();
    106     auto& lastInlineRun = inlineRuns.last();
    107 
    108     // Adjust (forbid) trailing expansion for the last text run on line.
    109     auto expansionBehavior = lastInlineRun.expansionOpportunity().behavior;
    110     // Remove allow and add forbid.
    111     expansionBehavior ^= AllowTrailingExpansion;
    112     expansionBehavior |= ForbidTrailingExpansion;
    113     lastInlineRun.expansionOpportunity().behavior = expansionBehavior;
    114 
    115     // Collect expansion opportunities and justify the runs.
    116     auto widthToDistribute = line.availableWidth();
    117     if (widthToDistribute <= 0)
    118         return;
    119 
    120     auto expansionOpportunities = 0;
    121     for (auto& inlineRun : inlineRuns)
    122         expansionOpportunities += inlineRun.expansionOpportunity().count;
    123 
    124     if (!expansionOpportunities)
    125         return;
    126 
    127     float expansion = widthToDistribute.toFloat() / expansionOpportunities;
    128     LayoutUnit accumulatedExpansion;
    129     for (auto& inlineRun : inlineRuns) {
    130         auto expansionForRun = inlineRun.expansionOpportunity().count * expansion;
    131 
    132         inlineRun.expansionOpportunity().expansion = expansionForRun;
    133         inlineRun.setLogicalLeft(inlineRun.logicalLeft() + accumulatedExpansion);
    134         inlineRun.setLogicalWidth(inlineRun.logicalWidth() + expansionForRun);
    135         accumulatedExpansion += expansionForRun;
    136     }
    137 }
    138 
    139 void InlineFormattingContext::Geometry::computeExpansionOpportunities(Line& line, const InlineRunProvider::Run& run, InlineRunProvider::Run::Type lastRunType)
    140 {
    141     auto isExpansionOpportunity = [](auto currentRunIsWhitespace, auto lastRunIsWhitespace) {
    142         return currentRunIsWhitespace || (!currentRunIsWhitespace && !lastRunIsWhitespace);
    143     };
    144 
    145     auto expansionBehavior = [](auto isAtExpansionOpportunity) {
    146         ExpansionBehavior expansionBehavior = AllowTrailingExpansion;
    147         expansionBehavior |= isAtExpansionOpportunity ? ForbidLeadingExpansion : AllowLeadingExpansion;
    148         return expansionBehavior;
    149     };
    150 
    151     auto isAtExpansionOpportunity = isExpansionOpportunity(run.isWhitespace(), lastRunType == InlineRunProvider::Run::Type::Whitespace);
    152 
    153     auto& currentInlineRun = line.runs().last();
    154     auto& expansionOpportunity = currentInlineRun.expansionOpportunity();
    155     if (isAtExpansionOpportunity)
    156         ++expansionOpportunity.count;
    157 
    158     expansionOpportunity.behavior = expansionBehavior(isAtExpansionOpportunity);
    159 }
    160 
    161 void InlineFormattingContext::Geometry::alignRuns(TextAlignMode textAlign, Line& line,  IsLastLine isLastLine)
    162 {
    163     auto adjutedTextAlignment = textAlign != TextAlignMode::Justify ? textAlign : isLastLine == IsLastLine::No ? TextAlignMode::Justify : TextAlignMode::Left;
    164     if (adjutedTextAlignment == TextAlignMode::Justify) {
    165         justifyRuns(line);
    166         return;
    167     }
    168 
    169     auto lineLogicalLeft = line.contentLogicalLeft();
    170     auto adjustedLogicalLeft = adjustedLineLogicalLeft(adjutedTextAlignment, lineLogicalLeft, line.availableWidth());
    171     if (adjustedLogicalLeft == lineLogicalLeft)
    172         return;
    173 
    174     auto delta = adjustedLogicalLeft - lineLogicalLeft;
    175     for (auto& inlineRun : line.runs())
    176         inlineRun.setLogicalLeft(inlineRun.logicalLeft() + delta);
    177 }
    178 
    179 LayoutUnit InlineFormattingContext::Geometry::runWidth(const InlineContent& inlineContent, const InlineItem& inlineItem, ItemPosition from, unsigned length, LayoutUnit contentLogicalLeft)
    180 {
    181     LayoutUnit width;
    182     auto startPosition = from;
    183     auto iterator = inlineContent.find(const_cast<InlineItem*>(&inlineItem));
    184 #if !ASSERT_DISABLED
    185     auto inlineItemEnd = inlineContent.end();
    186 #endif
    187     while (length) {
    188         ASSERT(iterator != inlineItemEnd);
    189         auto& currentInlineItem = **iterator;
    190         auto endPosition = std::min<ItemPosition>(startPosition + length, currentInlineItem.textContent().length());
    191         auto textWidth = TextUtil::width(currentInlineItem, startPosition, endPosition, contentLogicalLeft);
    192 
    193         contentLogicalLeft += textWidth;
    194         width += textWidth;
    195         length -= (endPosition - startPosition);
    196 
    197         startPosition = 0;
    198         ++iterator;
    199     }
    200     return width;
    201 }
    202 
    20381}
    20482}
Note: See TracChangeset for help on using the changeset viewer.