Home | History | Annotate | Download | only in rendering
      1 /*
      2  * Copyright (C) 2000 Lars Knoll (knoll (at) kde.org)
      3  * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All right reserved.
      4  * Copyright (C) 2010 Google Inc. All rights reserved.
      5  *
      6  * This library is free software; you can redistribute it and/or
      7  * modify it under the terms of the GNU Library General Public
      8  * License as published by the Free Software Foundation; either
      9  * version 2 of the License, or (at your option) any later version.
     10  *
     11  * This library is distributed in the hope that it will be useful,
     12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14  * Library General Public License for more details.
     15  *
     16  * You should have received a copy of the GNU Library General Public License
     17  * along with this library; see the file COPYING.LIB.  If not, write to
     18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     19  * Boston, MA 02110-1301, USA.
     20  *
     21  */
     22 
     23 #include "config.h"
     24 
     25 #include "core/platform/text/BidiResolver.h"
     26 #include "core/rendering/InlineIterator.h"
     27 #include "core/rendering/InlineTextBox.h"
     28 #include "core/rendering/RenderCombineText.h"
     29 #include "core/rendering/RenderCounter.h"
     30 #include "core/rendering/RenderFlowThread.h"
     31 #include "core/rendering/RenderInline.h"
     32 #include "core/rendering/RenderLayer.h"
     33 #include "core/rendering/RenderListMarker.h"
     34 #include "core/rendering/RenderRegion.h"
     35 #include "core/rendering/RenderRubyRun.h"
     36 #include "core/rendering/RenderView.h"
     37 #include "core/rendering/TrailingFloatsRootInlineBox.h"
     38 #include "core/rendering/VerticalPositionCache.h"
     39 #include "core/rendering/break_lines.h"
     40 #include "core/rendering/shapes/ShapeInsideInfo.h"
     41 #include "core/rendering/svg/RenderSVGInlineText.h"
     42 #include "core/rendering/svg/SVGRootInlineBox.h"
     43 #include "wtf/RefCountedLeakCounter.h"
     44 #include "wtf/StdLibExtras.h"
     45 #include "wtf/Vector.h"
     46 #include "wtf/unicode/CharacterNames.h"
     47 
     48 using namespace std;
     49 using namespace WTF;
     50 using namespace Unicode;
     51 
     52 namespace WebCore {
     53 
     54 // We don't let our line box tree for a single line get any deeper than this.
     55 const unsigned cMaxLineDepth = 200;
     56 
     57 static LayoutUnit logicalHeightForLine(const RenderBlock* block, bool isFirstLine, LayoutUnit replacedHeight = 0)
     58 {
     59     if (!block->document()->inNoQuirksMode() && replacedHeight)
     60         return replacedHeight;
     61 
     62     if (!(block->style(isFirstLine)->lineBoxContain() & LineBoxContainBlock))
     63         return 0;
     64 
     65     return max<LayoutUnit>(replacedHeight, block->lineHeight(isFirstLine, block->isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes));
     66 }
     67 
     68 ShapeInsideInfo* RenderBlock::layoutShapeInsideInfo() const
     69 {
     70     ShapeInsideInfo* shapeInsideInfo = view()->layoutState()->shapeInsideInfo();
     71 
     72     if (!shapeInsideInfo && flowThreadContainingBlock() && allowsShapeInsideInfoSharing()) {
     73         // regionAtBlockOffset returns regions like an array first={0,N-1}, second={N,M-1}, ...
     74         LayoutUnit offset = logicalHeight() + logicalHeightForLine(this, false) - LayoutUnit(1);
     75         RenderRegion* region = regionAtBlockOffset(offset);
     76         if (region)
     77             shapeInsideInfo = region->shapeInsideInfo();
     78     }
     79 
     80     return shapeInsideInfo;
     81 }
     82 
     83 enum IndentTextOrNot { DoNotIndentText, IndentText };
     84 
     85 class LineWidth {
     86 public:
     87     LineWidth(RenderBlock* block, bool isFirstLine, IndentTextOrNot shouldIndentText)
     88         : m_block(block)
     89         , m_uncommittedWidth(0)
     90         , m_committedWidth(0)
     91         , m_overhangWidth(0)
     92         , m_left(0)
     93         , m_right(0)
     94         , m_availableWidth(0)
     95         , m_segment(0)
     96         , m_isFirstLine(isFirstLine)
     97         , m_shouldIndentText(shouldIndentText)
     98     {
     99         ASSERT(block);
    100         ShapeInsideInfo* shapeInsideInfo = m_block->layoutShapeInsideInfo();
    101         if (shapeInsideInfo)
    102             m_segment = shapeInsideInfo->currentSegment();
    103         updateAvailableWidth();
    104     }
    105     bool fitsOnLine() const { return currentWidth() <= m_availableWidth; }
    106     bool fitsOnLine(float extra) const { return currentWidth() + extra <= m_availableWidth; }
    107     float currentWidth() const { return m_committedWidth + m_uncommittedWidth; }
    108 
    109     // FIXME: We should eventually replace these three functions by ones that work on a higher abstraction.
    110     float uncommittedWidth() const { return m_uncommittedWidth; }
    111     float committedWidth() const { return m_committedWidth; }
    112     float availableWidth() const { return m_availableWidth; }
    113 
    114     void updateAvailableWidth(LayoutUnit minimumHeight = 0);
    115     void shrinkAvailableWidthForNewFloatIfNeeded(RenderBlock::FloatingObject*);
    116     void addUncommittedWidth(float delta) { m_uncommittedWidth += delta; }
    117     void commit()
    118     {
    119         m_committedWidth += m_uncommittedWidth;
    120         m_uncommittedWidth = 0;
    121     }
    122     void applyOverhang(RenderRubyRun*, RenderObject* startRenderer, RenderObject* endRenderer);
    123     void fitBelowFloats();
    124 
    125     bool shouldIndentText() const { return m_shouldIndentText == IndentText; }
    126 
    127 private:
    128     void computeAvailableWidthFromLeftAndRight()
    129     {
    130         m_availableWidth = max(0.0f, m_right - m_left) + m_overhangWidth;
    131     }
    132 
    133 private:
    134     RenderBlock* m_block;
    135     float m_uncommittedWidth;
    136     float m_committedWidth;
    137     float m_overhangWidth; // The amount by which |m_availableWidth| has been inflated to account for possible contraction due to ruby overhang.
    138     float m_left;
    139     float m_right;
    140     float m_availableWidth;
    141     const LineSegment* m_segment;
    142     bool m_isFirstLine;
    143     IndentTextOrNot m_shouldIndentText;
    144 };
    145 
    146 inline void LineWidth::updateAvailableWidth(LayoutUnit replacedHeight)
    147 {
    148     LayoutUnit height = m_block->logicalHeight();
    149     LayoutUnit logicalHeight = logicalHeightForLine(m_block, m_isFirstLine, replacedHeight);
    150     m_left = m_block->logicalLeftOffsetForLine(height, shouldIndentText(), logicalHeight);
    151     m_right = m_block->logicalRightOffsetForLine(height, shouldIndentText(), logicalHeight);
    152 
    153     if (m_segment) {
    154         m_left = max<float>(m_segment->logicalLeft, m_left);
    155         m_right = min<float>(m_segment->logicalRight, m_right);
    156     }
    157 
    158     computeAvailableWidthFromLeftAndRight();
    159 }
    160 
    161 inline void LineWidth::shrinkAvailableWidthForNewFloatIfNeeded(RenderBlock::FloatingObject* newFloat)
    162 {
    163     LayoutUnit height = m_block->logicalHeight();
    164     if (height < m_block->logicalTopForFloat(newFloat) || height >= m_block->logicalBottomForFloat(newFloat))
    165         return;
    166 
    167     // When floats with shape outside are stacked, the floats are positioned based on the margin box of the float,
    168     // not the shape's contour. Since we computed the width based on the shape contour when we added the float,
    169     // when we add a subsequent float on the same line, we need to undo the shape delta in order to position
    170     // based on the margin box. In order to do this, we need to walk back through the floating object list to find
    171     // the first previous float that is on the same side as our newFloat.
    172     ShapeOutsideInfo* previousShapeOutsideInfo = 0;
    173     const RenderBlock::FloatingObjectSet& floatingObjectSet = m_block->m_floatingObjects->set();
    174     RenderBlock::FloatingObjectSetIterator it = floatingObjectSet.end();
    175     RenderBlock::FloatingObjectSetIterator begin = floatingObjectSet.begin();
    176     while (it != begin) {
    177         --it;
    178         RenderBlock::FloatingObject* previousFloat = *it;
    179         if (previousFloat != newFloat && previousFloat->type() == newFloat->type()) {
    180             previousShapeOutsideInfo = previousFloat->renderer()->shapeOutsideInfo();
    181             if (previousShapeOutsideInfo) {
    182                 previousShapeOutsideInfo->computeSegmentsForContainingBlockLine(m_block->logicalHeight(), m_block->logicalTopForFloat(previousFloat), logicalHeightForLine(m_block, m_isFirstLine));
    183             }
    184             break;
    185         }
    186     }
    187 
    188     ShapeOutsideInfo* shapeOutsideInfo = newFloat->renderer()->shapeOutsideInfo();
    189     if (shapeOutsideInfo)
    190         shapeOutsideInfo->computeSegmentsForContainingBlockLine(m_block->logicalHeight(), m_block->logicalTopForFloat(newFloat), logicalHeightForLine(m_block, m_isFirstLine));
    191 
    192     if (newFloat->type() == RenderBlock::FloatingObject::FloatLeft) {
    193         float newLeft = m_block->logicalRightForFloat(newFloat);
    194         if (previousShapeOutsideInfo)
    195             newLeft -= previousShapeOutsideInfo->rightSegmentMarginBoxDelta();
    196         if (shapeOutsideInfo)
    197             newLeft += shapeOutsideInfo->rightSegmentMarginBoxDelta();
    198 
    199         if (shouldIndentText() && m_block->style()->isLeftToRightDirection())
    200             newLeft += floorToInt(m_block->textIndentOffset());
    201         m_left = max<float>(m_left, newLeft);
    202     } else {
    203         float newRight = m_block->logicalLeftForFloat(newFloat);
    204         if (previousShapeOutsideInfo)
    205             newRight -= previousShapeOutsideInfo->leftSegmentMarginBoxDelta();
    206         if (shapeOutsideInfo)
    207             newRight += shapeOutsideInfo->leftSegmentMarginBoxDelta();
    208 
    209         if (shouldIndentText() && !m_block->style()->isLeftToRightDirection())
    210             newRight -= floorToInt(m_block->textIndentOffset());
    211         m_right = min<float>(m_right, newRight);
    212     }
    213 
    214     computeAvailableWidthFromLeftAndRight();
    215 }
    216 
    217 void LineWidth::applyOverhang(RenderRubyRun* rubyRun, RenderObject* startRenderer, RenderObject* endRenderer)
    218 {
    219     int startOverhang;
    220     int endOverhang;
    221     rubyRun->getOverhang(m_isFirstLine, startRenderer, endRenderer, startOverhang, endOverhang);
    222 
    223     startOverhang = min<int>(startOverhang, m_committedWidth);
    224     m_availableWidth += startOverhang;
    225 
    226     endOverhang = max(min<int>(endOverhang, m_availableWidth - currentWidth()), 0);
    227     m_availableWidth += endOverhang;
    228     m_overhangWidth += startOverhang + endOverhang;
    229 }
    230 
    231 void LineWidth::fitBelowFloats()
    232 {
    233     ASSERT(!m_committedWidth);
    234     ASSERT(!fitsOnLine());
    235 
    236     LayoutUnit floatLogicalBottom;
    237     LayoutUnit lastFloatLogicalBottom = m_block->logicalHeight();
    238     float newLineWidth = m_availableWidth;
    239     float newLineLeft = m_left;
    240     float newLineRight = m_right;
    241     while (true) {
    242         floatLogicalBottom = m_block->nextFloatLogicalBottomBelow(lastFloatLogicalBottom);
    243         if (floatLogicalBottom <= lastFloatLogicalBottom)
    244             break;
    245 
    246         newLineLeft = m_block->logicalLeftOffsetForLine(floatLogicalBottom, shouldIndentText());
    247         newLineRight = m_block->logicalRightOffsetForLine(floatLogicalBottom, shouldIndentText());
    248         newLineWidth = max(0.0f, newLineRight - newLineLeft);
    249         lastFloatLogicalBottom = floatLogicalBottom;
    250         if (newLineWidth >= m_uncommittedWidth)
    251             break;
    252     }
    253 
    254     if (newLineWidth > m_availableWidth) {
    255         m_block->setLogicalHeight(lastFloatLogicalBottom);
    256         m_availableWidth = newLineWidth + m_overhangWidth;
    257         m_left = newLineLeft;
    258         m_right = newLineRight;
    259     }
    260 }
    261 
    262 class LineInfo {
    263 public:
    264     LineInfo()
    265         : m_isFirstLine(true)
    266         , m_isLastLine(false)
    267         , m_isEmpty(true)
    268         , m_previousLineBrokeCleanly(true)
    269         , m_floatPaginationStrut(0)
    270         , m_runsFromLeadingWhitespace(0)
    271     { }
    272 
    273     bool isFirstLine() const { return m_isFirstLine; }
    274     bool isLastLine() const { return m_isLastLine; }
    275     bool isEmpty() const { return m_isEmpty; }
    276     bool previousLineBrokeCleanly() const { return m_previousLineBrokeCleanly; }
    277     LayoutUnit floatPaginationStrut() const { return m_floatPaginationStrut; }
    278     unsigned runsFromLeadingWhitespace() const { return m_runsFromLeadingWhitespace; }
    279     void resetRunsFromLeadingWhitespace() { m_runsFromLeadingWhitespace = 0; }
    280     void incrementRunsFromLeadingWhitespace() { m_runsFromLeadingWhitespace++; }
    281 
    282     void setFirstLine(bool firstLine) { m_isFirstLine = firstLine; }
    283     void setLastLine(bool lastLine) { m_isLastLine = lastLine; }
    284     void setEmpty(bool empty, RenderBlock* block = 0, LineWidth* lineWidth = 0)
    285     {
    286         if (m_isEmpty == empty)
    287             return;
    288         m_isEmpty = empty;
    289         if (!empty && block && floatPaginationStrut()) {
    290             block->setLogicalHeight(block->logicalHeight() + floatPaginationStrut());
    291             setFloatPaginationStrut(0);
    292             lineWidth->updateAvailableWidth();
    293         }
    294     }
    295 
    296     void setPreviousLineBrokeCleanly(bool previousLineBrokeCleanly) { m_previousLineBrokeCleanly = previousLineBrokeCleanly; }
    297     void setFloatPaginationStrut(LayoutUnit strut) { m_floatPaginationStrut = strut; }
    298 
    299 private:
    300     bool m_isFirstLine;
    301     bool m_isLastLine;
    302     bool m_isEmpty;
    303     bool m_previousLineBrokeCleanly;
    304     LayoutUnit m_floatPaginationStrut;
    305     unsigned m_runsFromLeadingWhitespace;
    306 };
    307 
    308 static inline LayoutUnit borderPaddingMarginStart(RenderInline* child)
    309 {
    310     return child->marginStart() + child->paddingStart() + child->borderStart();
    311 }
    312 
    313 static inline LayoutUnit borderPaddingMarginEnd(RenderInline* child)
    314 {
    315     return child->marginEnd() + child->paddingEnd() + child->borderEnd();
    316 }
    317 
    318 static bool shouldAddBorderPaddingMargin(RenderObject* child, bool &checkSide)
    319 {
    320     if (!child || (child->isText() && !toRenderText(child)->textLength()))
    321         return true;
    322     checkSide = false;
    323     return checkSide;
    324 }
    325 
    326 static LayoutUnit inlineLogicalWidth(RenderObject* child, bool start = true, bool end = true)
    327 {
    328     unsigned lineDepth = 1;
    329     LayoutUnit extraWidth = 0;
    330     RenderObject* parent = child->parent();
    331     while (parent->isRenderInline() && lineDepth++ < cMaxLineDepth) {
    332         RenderInline* parentAsRenderInline = toRenderInline(parent);
    333         if (!isEmptyInline(parentAsRenderInline)) {
    334             if (start && shouldAddBorderPaddingMargin(child->previousSibling(), start))
    335                 extraWidth += borderPaddingMarginStart(parentAsRenderInline);
    336             if (end && shouldAddBorderPaddingMargin(child->nextSibling(), end))
    337                 extraWidth += borderPaddingMarginEnd(parentAsRenderInline);
    338             if (!start && !end)
    339                 return extraWidth;
    340         }
    341         child = parent;
    342         parent = child->parent();
    343     }
    344     return extraWidth;
    345 }
    346 
    347 static void determineDirectionality(TextDirection& dir, InlineIterator iter)
    348 {
    349     while (!iter.atEnd()) {
    350         if (iter.atParagraphSeparator())
    351             return;
    352         if (UChar current = iter.current()) {
    353             Direction charDirection = direction(current);
    354             if (charDirection == LeftToRight) {
    355                 dir = LTR;
    356                 return;
    357             }
    358             if (charDirection == RightToLeft || charDirection == RightToLeftArabic) {
    359                 dir = RTL;
    360                 return;
    361             }
    362         }
    363         iter.increment();
    364     }
    365 }
    366 
    367 static void checkMidpoints(LineMidpointState& lineMidpointState, InlineIterator& lBreak)
    368 {
    369     // Check to see if our last midpoint is a start point beyond the line break.  If so,
    370     // shave it off the list, and shave off a trailing space if the previous end point doesn't
    371     // preserve whitespace.
    372     if (lBreak.m_obj && lineMidpointState.numMidpoints && !(lineMidpointState.numMidpoints % 2)) {
    373         InlineIterator* midpoints = lineMidpointState.midpoints.data();
    374         InlineIterator& endpoint = midpoints[lineMidpointState.numMidpoints - 2];
    375         const InlineIterator& startpoint = midpoints[lineMidpointState.numMidpoints - 1];
    376         InlineIterator currpoint = endpoint;
    377         while (!currpoint.atEnd() && currpoint != startpoint && currpoint != lBreak)
    378             currpoint.increment();
    379         if (currpoint == lBreak) {
    380             // We hit the line break before the start point.  Shave off the start point.
    381             lineMidpointState.numMidpoints--;
    382             if (endpoint.m_obj->style()->collapseWhiteSpace())
    383                 endpoint.m_pos--;
    384         }
    385     }
    386 }
    387 
    388 // Don't call this directly. Use one of the descriptive helper functions below.
    389 static void deprecatedAddMidpoint(LineMidpointState& lineMidpointState, const InlineIterator& midpoint)
    390 {
    391     if (lineMidpointState.midpoints.size() <= lineMidpointState.numMidpoints)
    392         lineMidpointState.midpoints.grow(lineMidpointState.numMidpoints + 10);
    393 
    394     InlineIterator* midpoints = lineMidpointState.midpoints.data();
    395     midpoints[lineMidpointState.numMidpoints++] = midpoint;
    396 }
    397 
    398 static inline void startIgnoringSpaces(LineMidpointState& lineMidpointState, const InlineIterator& midpoint)
    399 {
    400     ASSERT(!(lineMidpointState.numMidpoints % 2));
    401     deprecatedAddMidpoint(lineMidpointState, midpoint);
    402 }
    403 
    404 static inline void stopIgnoringSpaces(LineMidpointState& lineMidpointState, const InlineIterator& midpoint)
    405 {
    406     ASSERT(lineMidpointState.numMidpoints % 2);
    407     deprecatedAddMidpoint(lineMidpointState, midpoint);
    408 }
    409 
    410 // When ignoring spaces, this needs to be called for objects that need line boxes such as RenderInlines or
    411 // hard line breaks to ensure that they're not ignored.
    412 static inline void ensureLineBoxInsideIgnoredSpaces(LineMidpointState& lineMidpointState, RenderObject* renderer)
    413 {
    414     InlineIterator midpoint(0, renderer, 0);
    415     stopIgnoringSpaces(lineMidpointState, midpoint);
    416     startIgnoringSpaces(lineMidpointState, midpoint);
    417 }
    418 
    419 // Adding a pair of midpoints before a character will split it out into a new line box.
    420 static inline void ensureCharacterGetsLineBox(LineMidpointState& lineMidpointState, InlineIterator& textParagraphSeparator)
    421 {
    422     InlineIterator midpoint(0, textParagraphSeparator.m_obj, textParagraphSeparator.m_pos);
    423     startIgnoringSpaces(lineMidpointState, InlineIterator(0, textParagraphSeparator.m_obj, textParagraphSeparator.m_pos - 1));
    424     stopIgnoringSpaces(lineMidpointState, InlineIterator(0, textParagraphSeparator.m_obj, textParagraphSeparator.m_pos));
    425 }
    426 
    427 static inline BidiRun* createRun(int start, int end, RenderObject* obj, InlineBidiResolver& resolver)
    428 {
    429     return new BidiRun(start, end, obj, resolver.context(), resolver.dir());
    430 }
    431 
    432 void RenderBlock::appendRunsForObject(BidiRunList<BidiRun>& runs, int start, int end, RenderObject* obj, InlineBidiResolver& resolver)
    433 {
    434     if (start > end || shouldSkipCreatingRunsForObject(obj))
    435         return;
    436 
    437     LineMidpointState& lineMidpointState = resolver.midpointState();
    438     bool haveNextMidpoint = (lineMidpointState.currentMidpoint < lineMidpointState.numMidpoints);
    439     InlineIterator nextMidpoint;
    440     if (haveNextMidpoint)
    441         nextMidpoint = lineMidpointState.midpoints[lineMidpointState.currentMidpoint];
    442     if (lineMidpointState.betweenMidpoints) {
    443         if (!(haveNextMidpoint && nextMidpoint.m_obj == obj))
    444             return;
    445         // This is a new start point. Stop ignoring objects and
    446         // adjust our start.
    447         lineMidpointState.betweenMidpoints = false;
    448         start = nextMidpoint.m_pos;
    449         lineMidpointState.currentMidpoint++;
    450         if (start < end)
    451             return appendRunsForObject(runs, start, end, obj, resolver);
    452     } else {
    453         if (!haveNextMidpoint || (obj != nextMidpoint.m_obj)) {
    454             runs.addRun(createRun(start, end, obj, resolver));
    455             return;
    456         }
    457 
    458         // An end midpoint has been encountered within our object.  We
    459         // need to go ahead and append a run with our endpoint.
    460         if (static_cast<int>(nextMidpoint.m_pos + 1) <= end) {
    461             lineMidpointState.betweenMidpoints = true;
    462             lineMidpointState.currentMidpoint++;
    463             if (nextMidpoint.m_pos != INT_MAX) { // INT_MAX means stop at the object and don't include any of it.
    464                 if (static_cast<int>(nextMidpoint.m_pos + 1) > start)
    465                     runs.addRun(createRun(start, nextMidpoint.m_pos + 1, obj, resolver));
    466                 return appendRunsForObject(runs, nextMidpoint.m_pos + 1, end, obj, resolver);
    467             }
    468         } else
    469            runs.addRun(createRun(start, end, obj, resolver));
    470     }
    471 }
    472 
    473 static inline InlineBox* createInlineBoxForRenderer(RenderObject* obj, bool isRootLineBox, bool isOnlyRun = false)
    474 {
    475     if (isRootLineBox)
    476         return toRenderBlock(obj)->createAndAppendRootInlineBox();
    477 
    478     if (obj->isText()) {
    479         InlineTextBox* textBox = toRenderText(obj)->createInlineTextBox();
    480         // We only treat a box as text for a <br> if we are on a line by ourself or in strict mode
    481         // (Note the use of strict mode.  In "almost strict" mode, we don't treat the box for <br> as text.)
    482         if (obj->isBR())
    483             textBox->setIsText(isOnlyRun || obj->document()->inNoQuirksMode());
    484         return textBox;
    485     }
    486 
    487     if (obj->isBox())
    488         return toRenderBox(obj)->createInlineBox();
    489 
    490     return toRenderInline(obj)->createAndAppendInlineFlowBox();
    491 }
    492 
    493 // FIXME: Don't let counters mark themselves as needing pref width recalcs during layout
    494 // so we don't need this hack.
    495 static inline void updateCounterIfNeeded(RenderText* o)
    496 {
    497     if (!o->preferredLogicalWidthsDirty() || !o->isCounter())
    498         return;
    499     toRenderCounter(o)->updateCounter();
    500 }
    501 
    502 static inline void dirtyLineBoxesForRenderer(RenderObject* o, bool fullLayout)
    503 {
    504     if (o->isText()) {
    505         RenderText* renderText = toRenderText(o);
    506         updateCounterIfNeeded(renderText);
    507         renderText->dirtyLineBoxes(fullLayout);
    508     } else
    509         toRenderInline(o)->dirtyLineBoxes(fullLayout);
    510 }
    511 
    512 static bool parentIsConstructedOrHaveNext(InlineFlowBox* parentBox)
    513 {
    514     do {
    515         if (parentBox->isConstructed() || parentBox->nextOnLine())
    516             return true;
    517         parentBox = parentBox->parent();
    518     } while (parentBox);
    519     return false;
    520 }
    521 
    522 InlineFlowBox* RenderBlock::createLineBoxes(RenderObject* obj, const LineInfo& lineInfo, InlineBox* childBox, bool startNewSegment)
    523 {
    524     // See if we have an unconstructed line box for this object that is also
    525     // the last item on the line.
    526     unsigned lineDepth = 1;
    527     InlineFlowBox* parentBox = 0;
    528     InlineFlowBox* result = 0;
    529     bool hasDefaultLineBoxContain = style()->lineBoxContain() == RenderStyle::initialLineBoxContain();
    530     do {
    531         ASSERT_WITH_SECURITY_IMPLICATION(obj->isRenderInline() || obj == this);
    532 
    533         RenderInline* inlineFlow = (obj != this) ? toRenderInline(obj) : 0;
    534 
    535         // Get the last box we made for this render object.
    536         parentBox = inlineFlow ? inlineFlow->lastLineBox() : toRenderBlock(obj)->lastLineBox();
    537 
    538         // If this box or its ancestor is constructed then it is from a previous line, and we need
    539         // to make a new box for our line.  If this box or its ancestor is unconstructed but it has
    540         // something following it on the line, then we know we have to make a new box
    541         // as well.  In this situation our inline has actually been split in two on
    542         // the same line (this can happen with very fancy language mixtures).
    543         bool constructedNewBox = false;
    544         bool allowedToConstructNewBox = !hasDefaultLineBoxContain || !inlineFlow || inlineFlow->alwaysCreateLineBoxes();
    545         bool mustCreateBoxesToRoot = startNewSegment && !(parentBox && parentBox->isRootInlineBox());
    546         bool canUseExistingParentBox = parentBox && !parentIsConstructedOrHaveNext(parentBox) && !mustCreateBoxesToRoot;
    547         if (allowedToConstructNewBox && !canUseExistingParentBox) {
    548             // We need to make a new box for this render object.  Once
    549             // made, we need to place it at the end of the current line.
    550             InlineBox* newBox = createInlineBoxForRenderer(obj, obj == this);
    551             ASSERT_WITH_SECURITY_IMPLICATION(newBox->isInlineFlowBox());
    552             parentBox = toInlineFlowBox(newBox);
    553             parentBox->setFirstLineStyleBit(lineInfo.isFirstLine());
    554             parentBox->setIsHorizontal(isHorizontalWritingMode());
    555             if (!hasDefaultLineBoxContain)
    556                 parentBox->clearDescendantsHaveSameLineHeightAndBaseline();
    557             constructedNewBox = true;
    558         }
    559 
    560         if (constructedNewBox || canUseExistingParentBox) {
    561             if (!result)
    562                 result = parentBox;
    563 
    564             // If we have hit the block itself, then |box| represents the root
    565             // inline box for the line, and it doesn't have to be appended to any parent
    566             // inline.
    567             if (childBox)
    568                 parentBox->addToLine(childBox);
    569 
    570             if (!constructedNewBox || obj == this)
    571                 break;
    572 
    573             childBox = parentBox;
    574         }
    575 
    576         // If we've exceeded our line depth, then jump straight to the root and skip all the remaining
    577         // intermediate inline flows.
    578         obj = (++lineDepth >= cMaxLineDepth) ? this : obj->parent();
    579 
    580     } while (true);
    581 
    582     return result;
    583 }
    584 
    585 template <typename CharacterType>
    586 static inline bool endsWithASCIISpaces(const CharacterType* characters, unsigned pos, unsigned end)
    587 {
    588     while (isASCIISpace(characters[pos])) {
    589         pos++;
    590         if (pos >= end)
    591             return true;
    592     }
    593     return false;
    594 }
    595 
    596 static bool reachedEndOfTextRenderer(const BidiRunList<BidiRun>& bidiRuns)
    597 {
    598     BidiRun* run = bidiRuns.logicallyLastRun();
    599     if (!run)
    600         return true;
    601     unsigned pos = run->stop();
    602     RenderObject* r = run->m_object;
    603     if (!r->isText() || r->isBR())
    604         return false;
    605     RenderText* renderText = toRenderText(r);
    606     unsigned length = renderText->textLength();
    607     if (pos >= length)
    608         return true;
    609 
    610     if (renderText->is8Bit())
    611         return endsWithASCIISpaces(renderText->characters8(), pos, length);
    612     return endsWithASCIISpaces(renderText->characters16(), pos, length);
    613 }
    614 
    615 RootInlineBox* RenderBlock::constructLine(BidiRunList<BidiRun>& bidiRuns, const LineInfo& lineInfo)
    616 {
    617     ASSERT(bidiRuns.firstRun());
    618 
    619     bool rootHasSelectedChildren = false;
    620     InlineFlowBox* parentBox = 0;
    621     int runCount = bidiRuns.runCount() - lineInfo.runsFromLeadingWhitespace();
    622     for (BidiRun* r = bidiRuns.firstRun(); r; r = r->next()) {
    623         // Create a box for our object.
    624         bool isOnlyRun = (runCount == 1);
    625         if (runCount == 2 && !r->m_object->isListMarker())
    626             isOnlyRun = (!style()->isLeftToRightDirection() ? bidiRuns.lastRun() : bidiRuns.firstRun())->m_object->isListMarker();
    627 
    628         if (lineInfo.isEmpty())
    629             continue;
    630 
    631         InlineBox* box = createInlineBoxForRenderer(r->m_object, false, isOnlyRun);
    632         r->m_box = box;
    633 
    634         ASSERT(box);
    635         if (!box)
    636             continue;
    637 
    638         if (!rootHasSelectedChildren && box->renderer()->selectionState() != RenderObject::SelectionNone)
    639             rootHasSelectedChildren = true;
    640 
    641         // If we have no parent box yet, or if the run is not simply a sibling,
    642         // then we need to construct inline boxes as necessary to properly enclose the
    643         // run's inline box. Segments can only be siblings at the root level, as
    644         // they are positioned separately.
    645         bool runStartsSegment = r->m_startsSegment;
    646 
    647         if (!parentBox || parentBox->renderer() != r->m_object->parent() || runStartsSegment)
    648             // Create new inline boxes all the way back to the appropriate insertion point.
    649             parentBox = createLineBoxes(r->m_object->parent(), lineInfo, box, runStartsSegment);
    650         else {
    651             // Append the inline box to this line.
    652             parentBox->addToLine(box);
    653         }
    654 
    655         bool visuallyOrdered = r->m_object->style()->rtlOrdering() == VisualOrder;
    656         box->setBidiLevel(r->level());
    657 
    658         if (box->isInlineTextBox()) {
    659             InlineTextBox* text = toInlineTextBox(box);
    660             text->setStart(r->m_start);
    661             text->setLen(r->m_stop - r->m_start);
    662             text->setDirOverride(r->dirOverride(visuallyOrdered));
    663             if (r->m_hasHyphen)
    664                 text->setHasHyphen(true);
    665         }
    666     }
    667 
    668     // We should have a root inline box.  It should be unconstructed and
    669     // be the last continuation of our line list.
    670     ASSERT(lastLineBox() && !lastLineBox()->isConstructed());
    671 
    672     // Set the m_selectedChildren flag on the root inline box if one of the leaf inline box
    673     // from the bidi runs walk above has a selection state.
    674     if (rootHasSelectedChildren)
    675         lastLineBox()->root()->setHasSelectedChildren(true);
    676 
    677     // Set bits on our inline flow boxes that indicate which sides should
    678     // paint borders/margins/padding.  This knowledge will ultimately be used when
    679     // we determine the horizontal positions and widths of all the inline boxes on
    680     // the line.
    681     bool isLogicallyLastRunWrapped = bidiRuns.logicallyLastRun()->m_object && bidiRuns.logicallyLastRun()->m_object->isText() ? !reachedEndOfTextRenderer(bidiRuns) : true;
    682     lastLineBox()->determineSpacingForFlowBoxes(lineInfo.isLastLine(), isLogicallyLastRunWrapped, bidiRuns.logicallyLastRun()->m_object);
    683 
    684     // Now mark the line boxes as being constructed.
    685     lastLineBox()->setConstructed();
    686 
    687     // Return the last line.
    688     return lastRootBox();
    689 }
    690 
    691 ETextAlign RenderBlock::textAlignmentForLine(bool endsWithSoftBreak) const
    692 {
    693     ETextAlign alignment = style()->textAlign();
    694     if (!endsWithSoftBreak && alignment == JUSTIFY)
    695         alignment = TASTART;
    696 
    697     return alignment;
    698 }
    699 
    700 static void updateLogicalWidthForLeftAlignedBlock(bool isLeftToRightDirection, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float availableLogicalWidth)
    701 {
    702     // The direction of the block should determine what happens with wide lines.
    703     // In particular with RTL blocks, wide lines should still spill out to the left.
    704     if (isLeftToRightDirection) {
    705         if (totalLogicalWidth > availableLogicalWidth && trailingSpaceRun)
    706             trailingSpaceRun->m_box->setLogicalWidth(max<float>(0, trailingSpaceRun->m_box->logicalWidth() - totalLogicalWidth + availableLogicalWidth));
    707         return;
    708     }
    709 
    710     if (trailingSpaceRun)
    711         trailingSpaceRun->m_box->setLogicalWidth(0);
    712     else if (totalLogicalWidth > availableLogicalWidth)
    713         logicalLeft -= (totalLogicalWidth - availableLogicalWidth);
    714 }
    715 
    716 static void updateLogicalWidthForRightAlignedBlock(bool isLeftToRightDirection, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float availableLogicalWidth)
    717 {
    718     // Wide lines spill out of the block based off direction.
    719     // So even if text-align is right, if direction is LTR, wide lines should overflow out of the right
    720     // side of the block.
    721     if (isLeftToRightDirection) {
    722         if (trailingSpaceRun) {
    723             totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth();
    724             trailingSpaceRun->m_box->setLogicalWidth(0);
    725         }
    726         if (totalLogicalWidth < availableLogicalWidth)
    727             logicalLeft += availableLogicalWidth - totalLogicalWidth;
    728         return;
    729     }
    730 
    731     if (totalLogicalWidth > availableLogicalWidth && trailingSpaceRun) {
    732         trailingSpaceRun->m_box->setLogicalWidth(max<float>(0, trailingSpaceRun->m_box->logicalWidth() - totalLogicalWidth + availableLogicalWidth));
    733         totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth();
    734     } else
    735         logicalLeft += availableLogicalWidth - totalLogicalWidth;
    736 }
    737 
    738 static void updateLogicalWidthForCenterAlignedBlock(bool isLeftToRightDirection, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float availableLogicalWidth)
    739 {
    740     float trailingSpaceWidth = 0;
    741     if (trailingSpaceRun) {
    742         totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth();
    743         trailingSpaceWidth = min(trailingSpaceRun->m_box->logicalWidth(), (availableLogicalWidth - totalLogicalWidth + 1) / 2);
    744         trailingSpaceRun->m_box->setLogicalWidth(max<float>(0, trailingSpaceWidth));
    745     }
    746     if (isLeftToRightDirection)
    747         logicalLeft += max<float>((availableLogicalWidth - totalLogicalWidth) / 2, 0);
    748     else
    749         logicalLeft += totalLogicalWidth > availableLogicalWidth ? (availableLogicalWidth - totalLogicalWidth) : (availableLogicalWidth - totalLogicalWidth) / 2 - trailingSpaceWidth;
    750 }
    751 
    752 void RenderBlock::setMarginsForRubyRun(BidiRun* run, RenderRubyRun* renderer, RenderObject* previousObject, const LineInfo& lineInfo)
    753 {
    754     int startOverhang;
    755     int endOverhang;
    756     RenderObject* nextObject = 0;
    757     for (BidiRun* runWithNextObject = run->next(); runWithNextObject; runWithNextObject = runWithNextObject->next()) {
    758         if (!runWithNextObject->m_object->isOutOfFlowPositioned() && !runWithNextObject->m_box->isLineBreak()) {
    759             nextObject = runWithNextObject->m_object;
    760             break;
    761         }
    762     }
    763     renderer->getOverhang(lineInfo.isFirstLine(), renderer->style()->isLeftToRightDirection() ? previousObject : nextObject, renderer->style()->isLeftToRightDirection() ? nextObject : previousObject, startOverhang, endOverhang);
    764     setMarginStartForChild(renderer, -startOverhang);
    765     setMarginEndForChild(renderer, -endOverhang);
    766 }
    767 
    768 static inline float measureHyphenWidth(RenderText* renderer, const Font& font)
    769 {
    770     RenderStyle* style = renderer->style();
    771     return font.width(RenderBlock::constructTextRun(renderer, font, style->hyphenString().string(), style));
    772 }
    773 
    774 class WordMeasurement {
    775 public:
    776     WordMeasurement()
    777         : renderer(0)
    778         , width(0)
    779         , startOffset(0)
    780         , endOffset(0)
    781     {
    782     }
    783 
    784     RenderText* renderer;
    785     float width;
    786     int startOffset;
    787     int endOffset;
    788     HashSet<const SimpleFontData*> fallbackFonts;
    789 };
    790 
    791 static inline void setLogicalWidthForTextRun(RootInlineBox* lineBox, BidiRun* run, RenderText* renderer, float xPos, const LineInfo& lineInfo,
    792                                              GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache, WordMeasurements& wordMeasurements)
    793 {
    794     HashSet<const SimpleFontData*> fallbackFonts;
    795     GlyphOverflow glyphOverflow;
    796 
    797     const Font& font = renderer->style(lineInfo.isFirstLine())->font();
    798     // Always compute glyph overflow if the block's line-box-contain value is "glyphs".
    799     if (lineBox->fitsToGlyphs()) {
    800         // If we don't stick out of the root line's font box, then don't bother computing our glyph overflow. This optimization
    801         // will keep us from computing glyph bounds in nearly all cases.
    802         bool includeRootLine = lineBox->includesRootLineBoxFontOrLeading();
    803         int baselineShift = lineBox->verticalPositionForBox(run->m_box, verticalPositionCache);
    804         int rootDescent = includeRootLine ? font.fontMetrics().descent() : 0;
    805         int rootAscent = includeRootLine ? font.fontMetrics().ascent() : 0;
    806         int boxAscent = font.fontMetrics().ascent() - baselineShift;
    807         int boxDescent = font.fontMetrics().descent() + baselineShift;
    808         if (boxAscent > rootDescent ||  boxDescent > rootAscent)
    809             glyphOverflow.computeBounds = true;
    810     }
    811 
    812     LayoutUnit hyphenWidth = 0;
    813     if (toInlineTextBox(run->m_box)->hasHyphen()) {
    814         const Font& font = renderer->style(lineInfo.isFirstLine())->font();
    815         hyphenWidth = measureHyphenWidth(renderer, font);
    816     }
    817     float measuredWidth = 0;
    818 
    819     bool kerningIsEnabled = font.typesettingFeatures() & Kerning;
    820 
    821 #if OS(DARWIN)
    822     // FIXME: Having any font feature settings enabled can lead to selection gaps on
    823     // Chromium-mac. https://bugs.webkit.org/show_bug.cgi?id=113418
    824     bool canUseSimpleFontCodePath = renderer->canUseSimpleFontCodePath() && !font.fontDescription().featureSettings();
    825 #else
    826     bool canUseSimpleFontCodePath = renderer->canUseSimpleFontCodePath();
    827 #endif
    828 
    829     // Since we don't cache glyph overflows, we need to re-measure the run if
    830     // the style is linebox-contain: glyph.
    831 
    832     if (!lineBox->fitsToGlyphs() && canUseSimpleFontCodePath) {
    833         int lastEndOffset = run->m_start;
    834         for (size_t i = 0, size = wordMeasurements.size(); i < size && lastEndOffset < run->m_stop; ++i) {
    835             const WordMeasurement& wordMeasurement = wordMeasurements[i];
    836             if (wordMeasurement.width <=0 || wordMeasurement.startOffset == wordMeasurement.endOffset)
    837                 continue;
    838             if (wordMeasurement.renderer != renderer || wordMeasurement.startOffset != lastEndOffset || wordMeasurement.endOffset > run->m_stop)
    839                 continue;
    840 
    841             lastEndOffset = wordMeasurement.endOffset;
    842             if (kerningIsEnabled && lastEndOffset == run->m_stop) {
    843                 int wordLength = lastEndOffset - wordMeasurement.startOffset;
    844                 measuredWidth += renderer->width(wordMeasurement.startOffset, wordLength, xPos, lineInfo.isFirstLine());
    845                 if (i > 0 && wordLength == 1 && renderer->characterAt(wordMeasurement.startOffset) == ' ')
    846                     measuredWidth += renderer->style()->wordSpacing();
    847             } else
    848                 measuredWidth += wordMeasurement.width;
    849             if (!wordMeasurement.fallbackFonts.isEmpty()) {
    850                 HashSet<const SimpleFontData*>::const_iterator end = wordMeasurement.fallbackFonts.end();
    851                 for (HashSet<const SimpleFontData*>::const_iterator it = wordMeasurement.fallbackFonts.begin(); it != end; ++it)
    852                     fallbackFonts.add(*it);
    853             }
    854         }
    855         if (measuredWidth && lastEndOffset != run->m_stop) {
    856             // If we don't have enough cached data, we'll measure the run again.
    857             measuredWidth = 0;
    858             fallbackFonts.clear();
    859         }
    860     }
    861 
    862     if (!measuredWidth)
    863         measuredWidth = renderer->width(run->m_start, run->m_stop - run->m_start, xPos, lineInfo.isFirstLine(), &fallbackFonts, &glyphOverflow);
    864 
    865     run->m_box->setLogicalWidth(measuredWidth + hyphenWidth);
    866     if (!fallbackFonts.isEmpty()) {
    867         ASSERT(run->m_box->isText());
    868         GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.add(toInlineTextBox(run->m_box), make_pair(Vector<const SimpleFontData*>(), GlyphOverflow())).iterator;
    869         ASSERT(it->value.first.isEmpty());
    870         copyToVector(fallbackFonts, it->value.first);
    871         run->m_box->parent()->clearDescendantsHaveSameLineHeightAndBaseline();
    872     }
    873     if ((glyphOverflow.top || glyphOverflow.bottom || glyphOverflow.left || glyphOverflow.right)) {
    874         ASSERT(run->m_box->isText());
    875         GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.add(toInlineTextBox(run->m_box), make_pair(Vector<const SimpleFontData*>(), GlyphOverflow())).iterator;
    876         it->value.second = glyphOverflow;
    877         run->m_box->clearKnownToHaveNoOverflow();
    878     }
    879 }
    880 
    881 static inline void computeExpansionForJustifiedText(BidiRun* firstRun, BidiRun* trailingSpaceRun, Vector<unsigned, 16>& expansionOpportunities, unsigned expansionOpportunityCount, float& totalLogicalWidth, float availableLogicalWidth)
    882 {
    883     if (!expansionOpportunityCount || availableLogicalWidth <= totalLogicalWidth)
    884         return;
    885 
    886     size_t i = 0;
    887     for (BidiRun* r = firstRun; r; r = r->next()) {
    888         // This method is called once per segment, do not move past the current segment.
    889         if (r->m_startsSegment)
    890             break;
    891         if (!r->m_box || r == trailingSpaceRun)
    892             continue;
    893 
    894         if (r->m_object->isText()) {
    895             unsigned opportunitiesInRun = expansionOpportunities[i++];
    896 
    897             ASSERT(opportunitiesInRun <= expansionOpportunityCount);
    898 
    899             // Only justify text if whitespace is collapsed.
    900             if (r->m_object->style()->collapseWhiteSpace()) {
    901                 InlineTextBox* textBox = toInlineTextBox(r->m_box);
    902                 int expansion = (availableLogicalWidth - totalLogicalWidth) * opportunitiesInRun / expansionOpportunityCount;
    903                 textBox->setExpansion(expansion);
    904                 totalLogicalWidth += expansion;
    905             }
    906             expansionOpportunityCount -= opportunitiesInRun;
    907             if (!expansionOpportunityCount)
    908                 break;
    909         }
    910     }
    911 }
    912 
    913 void RenderBlock::updateLogicalWidthForAlignment(const ETextAlign& textAlign, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float& availableLogicalWidth, int expansionOpportunityCount)
    914 {
    915     // Armed with the total width of the line (without justification),
    916     // we now examine our text-align property in order to determine where to position the
    917     // objects horizontally. The total width of the line can be increased if we end up
    918     // justifying text.
    919     switch (textAlign) {
    920     case LEFT:
    921     case WEBKIT_LEFT:
    922         updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
    923         break;
    924     case RIGHT:
    925     case WEBKIT_RIGHT:
    926         updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
    927         break;
    928     case CENTER:
    929     case WEBKIT_CENTER:
    930         updateLogicalWidthForCenterAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
    931         break;
    932     case JUSTIFY:
    933         adjustInlineDirectionLineBounds(expansionOpportunityCount, logicalLeft, availableLogicalWidth);
    934         if (expansionOpportunityCount) {
    935             if (trailingSpaceRun) {
    936                 totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth();
    937                 trailingSpaceRun->m_box->setLogicalWidth(0);
    938             }
    939             break;
    940         }
    941         // Fall through
    942     case TASTART:
    943         if (style()->isLeftToRightDirection())
    944             updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
    945         else
    946             updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
    947         break;
    948     case TAEND:
    949         if (style()->isLeftToRightDirection())
    950             updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
    951         else
    952             updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
    953         break;
    954     }
    955 }
    956 
    957 static IndentTextOrNot requiresIndent(bool isFirstLine, bool isAfterHardLineBreak, RenderStyle* style)
    958 {
    959     if (isFirstLine)
    960         return IndentText;
    961 #if ENABLE(CSS3_TEXT)
    962     if (isAfterHardLineBreak && style->textIndentLine() == TextIndentEachLine)
    963         return IndentText;
    964 #else
    965     UNUSED_PARAM(isAfterHardLineBreak);
    966     UNUSED_PARAM(style);
    967 #endif
    968     return DoNotIndentText;
    969 }
    970 
    971 static void updateLogicalInlinePositions(RenderBlock* block, float& lineLogicalLeft, float& lineLogicalRight, float& availableLogicalWidth, bool firstLine, IndentTextOrNot shouldIndentText, LayoutUnit boxLogicalHeight)
    972 {
    973     LayoutUnit lineLogicalHeight = logicalHeightForLine(block, firstLine, boxLogicalHeight);
    974     lineLogicalLeft = block->pixelSnappedLogicalLeftOffsetForLine(block->logicalHeight(), shouldIndentText == IndentText, lineLogicalHeight);
    975     lineLogicalRight = block->pixelSnappedLogicalRightOffsetForLine(block->logicalHeight(), shouldIndentText == IndentText, lineLogicalHeight);
    976     availableLogicalWidth = lineLogicalRight - lineLogicalLeft;
    977 }
    978 
    979 void RenderBlock::computeInlineDirectionPositionsForLine(RootInlineBox* lineBox, const LineInfo& lineInfo, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd,
    980                                                          GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache, WordMeasurements& wordMeasurements)
    981 {
    982     ETextAlign textAlign = textAlignmentForLine(!reachedEnd && !lineBox->endsWithBreak());
    983 
    984     // CSS 2.1: "'Text-indent' only affects a line if it is the first formatted line of an element. For example, the first line of an anonymous block
    985     // box is only affected if it is the first child of its parent element."
    986     // CSS3 "text-indent", "-webkit-each-line" affects the first line of the block container as well as each line after a forced line break,
    987     // but does not affect lines after a soft wrap break.
    988     bool isFirstLine = lineInfo.isFirstLine() && !(isAnonymousBlock() && parent()->firstChild() != this);
    989     bool isAfterHardLineBreak = lineBox->prevRootBox() && lineBox->prevRootBox()->endsWithBreak();
    990     IndentTextOrNot shouldIndentText = requiresIndent(isFirstLine, isAfterHardLineBreak, style());
    991     float lineLogicalLeft;
    992     float lineLogicalRight;
    993     float availableLogicalWidth;
    994     updateLogicalInlinePositions(this, lineLogicalLeft, lineLogicalRight, availableLogicalWidth, isFirstLine, shouldIndentText, 0);
    995     bool needsWordSpacing;
    996     ShapeInsideInfo* shapeInsideInfo = layoutShapeInsideInfo();
    997     if (shapeInsideInfo && shapeInsideInfo->hasSegments()) {
    998         BidiRun* segmentStart = firstRun;
    999         const SegmentList& segments = shapeInsideInfo->segments();
   1000         float logicalLeft = max<float>(roundToInt(segments[0].logicalLeft), lineLogicalLeft);
   1001         float logicalRight = min<float>(floorToInt(segments[0].logicalRight), lineLogicalRight);
   1002         float startLogicalLeft = logicalLeft;
   1003         float endLogicalRight = logicalLeft;
   1004         float minLogicalLeft = logicalLeft;
   1005         float maxLogicalRight = logicalLeft;
   1006         lineBox->beginPlacingBoxRangesInInlineDirection(logicalLeft);
   1007         for (size_t i = 0; i < segments.size(); i++) {
   1008             if (i) {
   1009                 logicalLeft = max<float>(roundToInt(segments[i].logicalLeft), lineLogicalLeft);
   1010                 logicalRight = min<float>(floorToInt(segments[i].logicalRight), lineLogicalRight);
   1011             }
   1012             availableLogicalWidth = logicalRight - logicalLeft;
   1013             BidiRun* newSegmentStart = computeInlineDirectionPositionsForSegment(lineBox, lineInfo, textAlign, logicalLeft, availableLogicalWidth, segmentStart, trailingSpaceRun, textBoxDataMap, verticalPositionCache, wordMeasurements);
   1014             needsWordSpacing = false;
   1015             endLogicalRight = lineBox->placeBoxRangeInInlineDirection(segmentStart->m_box, newSegmentStart ? newSegmentStart->m_box : 0, logicalLeft, minLogicalLeft, maxLogicalRight, needsWordSpacing, textBoxDataMap);
   1016             if (!newSegmentStart || !newSegmentStart->next())
   1017                 break;
   1018             ASSERT(newSegmentStart->m_startsSegment);
   1019             // Discard the empty segment start marker bidi runs
   1020             segmentStart = newSegmentStart->next();
   1021         }
   1022         lineBox->endPlacingBoxRangesInInlineDirection(startLogicalLeft, endLogicalRight, minLogicalLeft, maxLogicalRight);
   1023         return;
   1024     }
   1025 
   1026     if (firstRun && firstRun->m_object->isReplaced()) {
   1027         RenderBox* renderBox = toRenderBox(firstRun->m_object);
   1028         updateLogicalInlinePositions(this, lineLogicalLeft, lineLogicalRight, availableLogicalWidth, isFirstLine, shouldIndentText, renderBox->logicalHeight());
   1029     }
   1030 
   1031     computeInlineDirectionPositionsForSegment(lineBox, lineInfo, textAlign, lineLogicalLeft, availableLogicalWidth, firstRun, trailingSpaceRun, textBoxDataMap, verticalPositionCache, wordMeasurements);
   1032     // The widths of all runs are now known. We can now place every inline box (and
   1033     // compute accurate widths for the inline flow boxes).
   1034     needsWordSpacing = false;
   1035     lineBox->placeBoxesInInlineDirection(lineLogicalLeft, needsWordSpacing, textBoxDataMap);
   1036 }
   1037 
   1038 BidiRun* RenderBlock::computeInlineDirectionPositionsForSegment(RootInlineBox* lineBox, const LineInfo& lineInfo, ETextAlign textAlign, float& logicalLeft,
   1039     float& availableLogicalWidth, BidiRun* firstRun, BidiRun* trailingSpaceRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache,
   1040     WordMeasurements& wordMeasurements)
   1041 {
   1042     bool needsWordSpacing = false;
   1043     float totalLogicalWidth = lineBox->getFlowSpacingLogicalWidth();
   1044     unsigned expansionOpportunityCount = 0;
   1045     bool isAfterExpansion = true;
   1046     Vector<unsigned, 16> expansionOpportunities;
   1047     RenderObject* previousObject = 0;
   1048 
   1049     BidiRun* r = firstRun;
   1050     for (; r; r = r->next()) {
   1051         // Once we have reached the start of the next segment, we have finished
   1052         // computing the positions for this segment's contents.
   1053         if (r->m_startsSegment)
   1054             break;
   1055         if (!r->m_box || r->m_object->isOutOfFlowPositioned() || r->m_box->isLineBreak())
   1056             continue; // Positioned objects are only participating to figure out their
   1057                       // correct static x position.  They have no effect on the width.
   1058                       // Similarly, line break boxes have no effect on the width.
   1059         if (r->m_object->isText()) {
   1060             RenderText* rt = toRenderText(r->m_object);
   1061             if (textAlign == JUSTIFY && r != trailingSpaceRun) {
   1062                 if (!isAfterExpansion)
   1063                     toInlineTextBox(r->m_box)->setCanHaveLeadingExpansion(true);
   1064                 unsigned opportunitiesInRun;
   1065                 if (rt->is8Bit())
   1066                     opportunitiesInRun = Font::expansionOpportunityCount(rt->characters8() + r->m_start, r->m_stop - r->m_start, r->m_box->direction(), isAfterExpansion);
   1067                 else
   1068                     opportunitiesInRun = Font::expansionOpportunityCount(rt->characters16() + r->m_start, r->m_stop - r->m_start, r->m_box->direction(), isAfterExpansion);
   1069                 expansionOpportunities.append(opportunitiesInRun);
   1070                 expansionOpportunityCount += opportunitiesInRun;
   1071             }
   1072 
   1073             if (int length = rt->textLength()) {
   1074                 if (!r->m_start && needsWordSpacing && isSpaceOrNewline(rt->characterAt(r->m_start)))
   1075                     totalLogicalWidth += rt->style(lineInfo.isFirstLine())->font().wordSpacing();
   1076                 needsWordSpacing = !isSpaceOrNewline(rt->characterAt(r->m_stop - 1)) && r->m_stop == length;
   1077             }
   1078 
   1079             setLogicalWidthForTextRun(lineBox, r, rt, totalLogicalWidth, lineInfo, textBoxDataMap, verticalPositionCache, wordMeasurements);
   1080         } else {
   1081             isAfterExpansion = false;
   1082             if (!r->m_object->isRenderInline()) {
   1083                 RenderBox* renderBox = toRenderBox(r->m_object);
   1084                 if (renderBox->isRubyRun())
   1085                     setMarginsForRubyRun(r, toRenderRubyRun(renderBox), previousObject, lineInfo);
   1086                 r->m_box->setLogicalWidth(logicalWidthForChild(renderBox));
   1087                 totalLogicalWidth += marginStartForChild(renderBox) + marginEndForChild(renderBox);
   1088             }
   1089         }
   1090 
   1091         totalLogicalWidth += r->m_box->logicalWidth();
   1092         previousObject = r->m_object;
   1093     }
   1094 
   1095     if (isAfterExpansion && !expansionOpportunities.isEmpty()) {
   1096         expansionOpportunities.last()--;
   1097         expansionOpportunityCount--;
   1098     }
   1099 
   1100     updateLogicalWidthForAlignment(textAlign, trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth, expansionOpportunityCount);
   1101 
   1102     computeExpansionForJustifiedText(firstRun, trailingSpaceRun, expansionOpportunities, expansionOpportunityCount, totalLogicalWidth, availableLogicalWidth);
   1103 
   1104     return r;
   1105 }
   1106 
   1107 void RenderBlock::computeBlockDirectionPositionsForLine(RootInlineBox* lineBox, BidiRun* firstRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap,
   1108                                                         VerticalPositionCache& verticalPositionCache)
   1109 {
   1110     setLogicalHeight(lineBox->alignBoxesInBlockDirection(logicalHeight(), textBoxDataMap, verticalPositionCache));
   1111 
   1112     // Now make sure we place replaced render objects correctly.
   1113     for (BidiRun* r = firstRun; r; r = r->next()) {
   1114         ASSERT(r->m_box);
   1115         if (!r->m_box)
   1116             continue; // Skip runs with no line boxes.
   1117 
   1118         // Align positioned boxes with the top of the line box.  This is
   1119         // a reasonable approximation of an appropriate y position.
   1120         if (r->m_object->isOutOfFlowPositioned())
   1121             r->m_box->setLogicalTop(logicalHeight());
   1122 
   1123         // Position is used to properly position both replaced elements and
   1124         // to update the static normal flow x/y of positioned elements.
   1125         if (r->m_object->isText())
   1126             toRenderText(r->m_object)->positionLineBox(r->m_box);
   1127         else if (r->m_object->isBox())
   1128             toRenderBox(r->m_object)->positionLineBox(r->m_box);
   1129     }
   1130     // Positioned objects and zero-length text nodes destroy their boxes in
   1131     // position(), which unnecessarily dirties the line.
   1132     lineBox->markDirty(false);
   1133 }
   1134 
   1135 static inline bool isCollapsibleSpace(UChar character, RenderText* renderer)
   1136 {
   1137     if (character == ' ' || character == '\t' || character == softHyphen)
   1138         return true;
   1139     if (character == '\n')
   1140         return !renderer->style()->preserveNewline();
   1141     return false;
   1142 }
   1143 
   1144 
   1145 static void setStaticPositions(RenderBlock* block, RenderBox* child)
   1146 {
   1147     // FIXME: The math here is actually not really right. It's a best-guess approximation that
   1148     // will work for the common cases
   1149     RenderObject* containerBlock = child->container();
   1150     LayoutUnit blockHeight = block->logicalHeight();
   1151     if (containerBlock->isRenderInline()) {
   1152         // A relative positioned inline encloses us. In this case, we also have to determine our
   1153         // position as though we were an inline. Set |staticInlinePosition| and |staticBlockPosition| on the relative positioned
   1154         // inline so that we can obtain the value later.
   1155         toRenderInline(containerBlock)->layer()->setStaticInlinePosition(block->startAlignedOffsetForLine(blockHeight, false));
   1156         toRenderInline(containerBlock)->layer()->setStaticBlockPosition(blockHeight);
   1157     }
   1158     block->updateStaticInlinePositionForChild(child, blockHeight);
   1159     child->layer()->setStaticBlockPosition(blockHeight);
   1160 }
   1161 
   1162 template <typename CharacterType>
   1163 static inline int findFirstTrailingSpace(RenderText* lastText, const CharacterType* characters, int start, int stop)
   1164 {
   1165     int firstSpace = stop;
   1166     while (firstSpace > start) {
   1167         UChar current = characters[firstSpace - 1];
   1168         if (!isCollapsibleSpace(current, lastText))
   1169             break;
   1170         firstSpace--;
   1171     }
   1172 
   1173     return firstSpace;
   1174 }
   1175 
   1176 inline BidiRun* RenderBlock::handleTrailingSpaces(BidiRunList<BidiRun>& bidiRuns, BidiContext* currentContext)
   1177 {
   1178     if (!bidiRuns.runCount()
   1179         || !bidiRuns.logicallyLastRun()->m_object->style()->breakOnlyAfterWhiteSpace()
   1180         || !bidiRuns.logicallyLastRun()->m_object->style()->autoWrap())
   1181         return 0;
   1182 
   1183     BidiRun* trailingSpaceRun = bidiRuns.logicallyLastRun();
   1184     RenderObject* lastObject = trailingSpaceRun->m_object;
   1185     if (!lastObject->isText())
   1186         return 0;
   1187 
   1188     RenderText* lastText = toRenderText(lastObject);
   1189     int firstSpace;
   1190     if (lastText->is8Bit())
   1191         firstSpace = findFirstTrailingSpace(lastText, lastText->characters8(), trailingSpaceRun->start(), trailingSpaceRun->stop());
   1192     else
   1193         firstSpace = findFirstTrailingSpace(lastText, lastText->characters16(), trailingSpaceRun->start(), trailingSpaceRun->stop());
   1194 
   1195     if (firstSpace == trailingSpaceRun->stop())
   1196         return 0;
   1197 
   1198     TextDirection direction = style()->direction();
   1199     bool shouldReorder = trailingSpaceRun != (direction == LTR ? bidiRuns.lastRun() : bidiRuns.firstRun());
   1200     if (firstSpace != trailingSpaceRun->start()) {
   1201         BidiContext* baseContext = currentContext;
   1202         while (BidiContext* parent = baseContext->parent())
   1203             baseContext = parent;
   1204 
   1205         BidiRun* newTrailingRun = new BidiRun(firstSpace, trailingSpaceRun->m_stop, trailingSpaceRun->m_object, baseContext, OtherNeutral);
   1206         trailingSpaceRun->m_stop = firstSpace;
   1207         if (direction == LTR)
   1208             bidiRuns.addRun(newTrailingRun);
   1209         else
   1210             bidiRuns.prependRun(newTrailingRun);
   1211         trailingSpaceRun = newTrailingRun;
   1212         return trailingSpaceRun;
   1213     }
   1214     if (!shouldReorder)
   1215         return trailingSpaceRun;
   1216 
   1217     if (direction == LTR) {
   1218         bidiRuns.moveRunToEnd(trailingSpaceRun);
   1219         trailingSpaceRun->m_level = 0;
   1220     } else {
   1221         bidiRuns.moveRunToBeginning(trailingSpaceRun);
   1222         trailingSpaceRun->m_level = 1;
   1223     }
   1224     return trailingSpaceRun;
   1225 }
   1226 
   1227 void RenderBlock::appendFloatingObjectToLastLine(FloatingObject* floatingObject)
   1228 {
   1229     ASSERT(!floatingObject->m_originatingLine);
   1230     floatingObject->m_originatingLine = lastRootBox();
   1231     lastRootBox()->appendFloat(floatingObject->renderer());
   1232 }
   1233 
   1234 // FIXME: This should be a BidiStatus constructor or create method.
   1235 static inline BidiStatus statusWithDirection(TextDirection textDirection, bool isOverride)
   1236 {
   1237     WTF::Unicode::Direction direction = textDirection == LTR ? LeftToRight : RightToLeft;
   1238     RefPtr<BidiContext> context = BidiContext::create(textDirection == LTR ? 0 : 1, direction, isOverride, FromStyleOrDOM);
   1239 
   1240     // This copies BidiStatus and may churn the ref on BidiContext. I doubt it matters.
   1241     return BidiStatus(direction, direction, direction, context.release());
   1242 }
   1243 
   1244 static inline void setupResolverToResumeInIsolate(InlineBidiResolver& resolver, RenderObject* root, RenderObject* startObject)
   1245 {
   1246     if (root != startObject) {
   1247         RenderObject* parent = startObject->parent();
   1248         setupResolverToResumeInIsolate(resolver, root, parent);
   1249         notifyObserverEnteredObject(&resolver, startObject);
   1250     }
   1251 }
   1252 
   1253 // FIXME: BidiResolver should have this logic.
   1254 static inline void constructBidiRunsForSegment(InlineBidiResolver& topResolver, BidiRunList<BidiRun>& bidiRuns, const InlineIterator& endOfRuns, VisualDirectionOverride override, bool previousLineBrokeCleanly)
   1255 {
   1256     // FIXME: We should pass a BidiRunList into createBidiRunsForLine instead
   1257     // of the resolver owning the runs.
   1258     ASSERT(&topResolver.runs() == &bidiRuns);
   1259     ASSERT(topResolver.position() != endOfRuns);
   1260     RenderObject* currentRoot = topResolver.position().root();
   1261     topResolver.createBidiRunsForLine(endOfRuns, override, previousLineBrokeCleanly);
   1262 
   1263     while (!topResolver.isolatedRuns().isEmpty()) {
   1264         // It does not matter which order we resolve the runs as long as we resolve them all.
   1265         BidiRun* isolatedRun = topResolver.isolatedRuns().last();
   1266         topResolver.isolatedRuns().removeLast();
   1267 
   1268         RenderObject* startObj = isolatedRun->object();
   1269 
   1270         // Only inlines make sense with unicode-bidi: isolate (blocks are already isolated).
   1271         // FIXME: Because enterIsolate is not passed a RenderObject, we have to crawl up the
   1272         // tree to see which parent inline is the isolate. We could change enterIsolate
   1273         // to take a RenderObject and do this logic there, but that would be a layering
   1274         // violation for BidiResolver (which knows nothing about RenderObject).
   1275         RenderInline* isolatedInline = toRenderInline(highestContainingIsolateWithinRoot(startObj, currentRoot));
   1276         ASSERT(isolatedInline);
   1277 
   1278         InlineBidiResolver isolatedResolver;
   1279         EUnicodeBidi unicodeBidi = isolatedInline->style()->unicodeBidi();
   1280         TextDirection direction;
   1281         if (unicodeBidi == Plaintext)
   1282             determineDirectionality(direction, InlineIterator(isolatedInline, isolatedRun->object(), 0));
   1283         else {
   1284             ASSERT(unicodeBidi == Isolate || unicodeBidi == IsolateOverride);
   1285             direction = isolatedInline->style()->direction();
   1286         }
   1287         isolatedResolver.setStatus(statusWithDirection(direction, isOverride(unicodeBidi)));
   1288 
   1289         setupResolverToResumeInIsolate(isolatedResolver, isolatedInline, startObj);
   1290 
   1291         // The starting position is the beginning of the first run within the isolate that was identified
   1292         // during the earlier call to createBidiRunsForLine. This can be but is not necessarily the
   1293         // first run within the isolate.
   1294         InlineIterator iter = InlineIterator(isolatedInline, startObj, isolatedRun->m_start);
   1295         isolatedResolver.setPositionIgnoringNestedIsolates(iter);
   1296 
   1297         // We stop at the next end of line; we may re-enter this isolate in the next call to constructBidiRuns().
   1298         // FIXME: What should end and previousLineBrokeCleanly be?
   1299         // rniwa says previousLineBrokeCleanly is just a WinIE hack and could always be false here?
   1300         isolatedResolver.createBidiRunsForLine(endOfRuns, NoVisualOverride, previousLineBrokeCleanly);
   1301         // Note that we do not delete the runs from the resolver.
   1302         // We're not guaranteed to get any BidiRuns in the previous step. If we don't, we allow the placeholder
   1303         // itself to be turned into an InlineBox. We can't remove it here without potentially losing track of
   1304         // the logically last run.
   1305         if (isolatedResolver.runs().runCount())
   1306             bidiRuns.replaceRunWithRuns(isolatedRun, isolatedResolver.runs());
   1307 
   1308         // If we encountered any nested isolate runs, just move them
   1309         // to the top resolver's list for later processing.
   1310         if (!isolatedResolver.isolatedRuns().isEmpty()) {
   1311             topResolver.isolatedRuns().append(isolatedResolver.isolatedRuns());
   1312             isolatedResolver.isolatedRuns().clear();
   1313             currentRoot = isolatedInline;
   1314         }
   1315     }
   1316 }
   1317 
   1318 static inline bool segmentIsEmpty(const InlineIterator& segmentStart, const InlineIterator& segmentEnd)
   1319 {
   1320     return segmentStart == segmentEnd;
   1321 }
   1322 
   1323 static inline void constructBidiRunsForLine(const RenderBlock* block, InlineBidiResolver& topResolver, BidiRunList<BidiRun>& bidiRuns, const InlineIterator& endOfLine, VisualDirectionOverride override, bool previousLineBrokeCleanly)
   1324 {
   1325     ShapeInsideInfo* shapeInsideInfo = block->layoutShapeInsideInfo();
   1326     if (!shapeInsideInfo || !shapeInsideInfo->hasSegments()) {
   1327         constructBidiRunsForSegment(topResolver, bidiRuns, endOfLine, override, previousLineBrokeCleanly);
   1328         return;
   1329     }
   1330 
   1331     const SegmentRangeList& segmentRanges = shapeInsideInfo->segmentRanges();
   1332     ASSERT(segmentRanges.size());
   1333 
   1334     for (size_t i = 0; i < segmentRanges.size(); i++) {
   1335         LineSegmentIterator iterator = segmentRanges[i].start;
   1336         InlineIterator segmentStart(iterator.root, iterator.object, iterator.offset);
   1337         iterator = segmentRanges[i].end;
   1338         InlineIterator segmentEnd(iterator.root, iterator.object, iterator.offset);
   1339         if (i) {
   1340             ASSERT(segmentStart.m_obj);
   1341             BidiRun* segmentMarker = createRun(segmentStart.m_pos, segmentStart.m_pos, segmentStart.m_obj, topResolver);
   1342             segmentMarker->m_startsSegment = true;
   1343             bidiRuns.addRun(segmentMarker);
   1344             // Do not collapse midpoints between segments
   1345             topResolver.midpointState().betweenMidpoints = false;
   1346         }
   1347         if (!segmentIsEmpty(segmentStart, segmentEnd)) {
   1348             topResolver.setPosition(segmentStart, numberOfIsolateAncestors(segmentStart));
   1349             constructBidiRunsForSegment(topResolver, bidiRuns, segmentEnd, override, previousLineBrokeCleanly);
   1350         }
   1351     }
   1352 }
   1353 
   1354 // This function constructs line boxes for all of the text runs in the resolver and computes their position.
   1355 RootInlineBox* RenderBlock::createLineBoxesFromBidiRuns(BidiRunList<BidiRun>& bidiRuns, const InlineIterator& end, LineInfo& lineInfo, VerticalPositionCache& verticalPositionCache, BidiRun* trailingSpaceRun, WordMeasurements& wordMeasurements)
   1356 {
   1357     if (!bidiRuns.runCount())
   1358         return 0;
   1359 
   1360     // FIXME: Why is this only done when we had runs?
   1361     lineInfo.setLastLine(!end.m_obj);
   1362 
   1363     RootInlineBox* lineBox = constructLine(bidiRuns, lineInfo);
   1364     if (!lineBox)
   1365         return 0;
   1366 
   1367     lineBox->setEndsWithBreak(lineInfo.previousLineBrokeCleanly());
   1368 
   1369     bool isSVGRootInlineBox = lineBox->isSVGRootInlineBox();
   1370 
   1371     GlyphOverflowAndFallbackFontsMap textBoxDataMap;
   1372 
   1373     // Now we position all of our text runs horizontally.
   1374     if (!isSVGRootInlineBox)
   1375         computeInlineDirectionPositionsForLine(lineBox, lineInfo, bidiRuns.firstRun(), trailingSpaceRun, end.atEnd(), textBoxDataMap, verticalPositionCache, wordMeasurements);
   1376 
   1377     // Now position our text runs vertically.
   1378     computeBlockDirectionPositionsForLine(lineBox, bidiRuns.firstRun(), textBoxDataMap, verticalPositionCache);
   1379 
   1380     // SVG text layout code computes vertical & horizontal positions on its own.
   1381     // Note that we still need to execute computeVerticalPositionsForLine() as
   1382     // it calls InlineTextBox::positionLineBox(), which tracks whether the box
   1383     // contains reversed text or not. If we wouldn't do that editing and thus
   1384     // text selection in RTL boxes would not work as expected.
   1385     if (isSVGRootInlineBox) {
   1386         ASSERT(isSVGText());
   1387         static_cast<SVGRootInlineBox*>(lineBox)->computePerCharacterLayoutInformation();
   1388     }
   1389 
   1390     // Compute our overflow now.
   1391     lineBox->computeOverflow(lineBox->lineTop(), lineBox->lineBottom(), textBoxDataMap);
   1392 
   1393     return lineBox;
   1394 }
   1395 
   1396 // Like LayoutState for layout(), LineLayoutState keeps track of global information
   1397 // during an entire linebox tree layout pass (aka layoutInlineChildren).
   1398 class LineLayoutState {
   1399 public:
   1400     LineLayoutState(bool fullLayout, LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom, RenderFlowThread* flowThread)
   1401         : m_lastFloat(0)
   1402         , m_endLine(0)
   1403         , m_floatIndex(0)
   1404         , m_endLineLogicalTop(0)
   1405         , m_endLineMatched(false)
   1406         , m_checkForFloatsFromLastLine(false)
   1407         , m_isFullLayout(fullLayout)
   1408         , m_repaintLogicalTop(repaintLogicalTop)
   1409         , m_repaintLogicalBottom(repaintLogicalBottom)
   1410         , m_adjustedLogicalLineTop(0)
   1411         , m_usesRepaintBounds(false)
   1412         , m_flowThread(flowThread)
   1413     { }
   1414 
   1415     void markForFullLayout() { m_isFullLayout = true; }
   1416     bool isFullLayout() const { return m_isFullLayout; }
   1417 
   1418     bool usesRepaintBounds() const { return m_usesRepaintBounds; }
   1419 
   1420     void setRepaintRange(LayoutUnit logicalHeight)
   1421     {
   1422         m_usesRepaintBounds = true;
   1423         m_repaintLogicalTop = m_repaintLogicalBottom = logicalHeight;
   1424     }
   1425 
   1426     void updateRepaintRangeFromBox(RootInlineBox* box, LayoutUnit paginationDelta = 0)
   1427     {
   1428         m_usesRepaintBounds = true;
   1429         m_repaintLogicalTop = min(m_repaintLogicalTop, box->logicalTopVisualOverflow() + min<LayoutUnit>(paginationDelta, 0));
   1430         m_repaintLogicalBottom = max(m_repaintLogicalBottom, box->logicalBottomVisualOverflow() + max<LayoutUnit>(paginationDelta, 0));
   1431     }
   1432 
   1433     bool endLineMatched() const { return m_endLineMatched; }
   1434     void setEndLineMatched(bool endLineMatched) { m_endLineMatched = endLineMatched; }
   1435 
   1436     bool checkForFloatsFromLastLine() const { return m_checkForFloatsFromLastLine; }
   1437     void setCheckForFloatsFromLastLine(bool check) { m_checkForFloatsFromLastLine = check; }
   1438 
   1439     LineInfo& lineInfo() { return m_lineInfo; }
   1440     const LineInfo& lineInfo() const { return m_lineInfo; }
   1441 
   1442     LayoutUnit endLineLogicalTop() const { return m_endLineLogicalTop; }
   1443     void setEndLineLogicalTop(LayoutUnit logicalTop) { m_endLineLogicalTop = logicalTop; }
   1444 
   1445     RootInlineBox* endLine() const { return m_endLine; }
   1446     void setEndLine(RootInlineBox* line) { m_endLine = line; }
   1447 
   1448     RenderBlock::FloatingObject* lastFloat() const { return m_lastFloat; }
   1449     void setLastFloat(RenderBlock::FloatingObject* lastFloat) { m_lastFloat = lastFloat; }
   1450 
   1451     Vector<RenderBlock::FloatWithRect>& floats() { return m_floats; }
   1452 
   1453     unsigned floatIndex() const { return m_floatIndex; }
   1454     void setFloatIndex(unsigned floatIndex) { m_floatIndex = floatIndex; }
   1455 
   1456     LayoutUnit adjustedLogicalLineTop() const { return m_adjustedLogicalLineTop; }
   1457     void setAdjustedLogicalLineTop(LayoutUnit value) { m_adjustedLogicalLineTop = value; }
   1458 
   1459     RenderFlowThread* flowThread() const { return m_flowThread; }
   1460     void setFlowThread(RenderFlowThread* thread) { m_flowThread = thread; }
   1461 
   1462 private:
   1463     Vector<RenderBlock::FloatWithRect> m_floats;
   1464     RenderBlock::FloatingObject* m_lastFloat;
   1465     RootInlineBox* m_endLine;
   1466     LineInfo m_lineInfo;
   1467     unsigned m_floatIndex;
   1468     LayoutUnit m_endLineLogicalTop;
   1469     bool m_endLineMatched;
   1470     bool m_checkForFloatsFromLastLine;
   1471 
   1472     bool m_isFullLayout;
   1473 
   1474     // FIXME: Should this be a range object instead of two ints?
   1475     LayoutUnit& m_repaintLogicalTop;
   1476     LayoutUnit& m_repaintLogicalBottom;
   1477 
   1478     LayoutUnit m_adjustedLogicalLineTop;
   1479 
   1480     bool m_usesRepaintBounds;
   1481 
   1482     RenderFlowThread* m_flowThread;
   1483 };
   1484 
   1485 static void deleteLineRange(LineLayoutState& layoutState, RootInlineBox* startLine, RootInlineBox* stopLine = 0)
   1486 {
   1487     RootInlineBox* boxToDelete = startLine;
   1488     while (boxToDelete && boxToDelete != stopLine) {
   1489         layoutState.updateRepaintRangeFromBox(boxToDelete);
   1490         // Note: deleteLineRange(firstRootBox()) is not identical to deleteLineBoxTree().
   1491         // deleteLineBoxTree uses nextLineBox() instead of nextRootBox() when traversing.
   1492         RootInlineBox* next = boxToDelete->nextRootBox();
   1493         boxToDelete->deleteLine();
   1494         boxToDelete = next;
   1495     }
   1496 }
   1497 
   1498 void RenderBlock::layoutRunsAndFloats(LineLayoutState& layoutState, bool hasInlineChild)
   1499 {
   1500     // We want to skip ahead to the first dirty line
   1501     InlineBidiResolver resolver;
   1502     RootInlineBox* startLine = determineStartPosition(layoutState, resolver);
   1503 
   1504     unsigned consecutiveHyphenatedLines = 0;
   1505     if (startLine) {
   1506         for (RootInlineBox* line = startLine->prevRootBox(); line && line->isHyphenated(); line = line->prevRootBox())
   1507             consecutiveHyphenatedLines++;
   1508     }
   1509 
   1510     // FIXME: This would make more sense outside of this function, but since
   1511     // determineStartPosition can change the fullLayout flag we have to do this here. Failure to call
   1512     // determineStartPosition first will break fast/repaint/line-flow-with-floats-9.html.
   1513     if (layoutState.isFullLayout() && hasInlineChild && !selfNeedsLayout()) {
   1514         setNeedsLayout(MarkOnlyThis); // Mark as needing a full layout to force us to repaint.
   1515         RenderView* v = view();
   1516         if (v && !v->doingFullRepaint() && hasLayer()) {
   1517             // Because we waited until we were already inside layout to discover
   1518             // that the block really needed a full layout, we missed our chance to repaint the layer
   1519             // before layout started.  Luckily the layer has cached the repaint rect for its original
   1520             // position and size, and so we can use that to make a repaint happen now.
   1521             repaintUsingContainer(containerForRepaint(), pixelSnappedIntRect(layer()->repaintRect()));
   1522         }
   1523     }
   1524 
   1525     if (containsFloats())
   1526         layoutState.setLastFloat(m_floatingObjects->set().last());
   1527 
   1528     // We also find the first clean line and extract these lines.  We will add them back
   1529     // if we determine that we're able to synchronize after handling all our dirty lines.
   1530     InlineIterator cleanLineStart;
   1531     BidiStatus cleanLineBidiStatus;
   1532     if (!layoutState.isFullLayout() && startLine)
   1533         determineEndPosition(layoutState, startLine, cleanLineStart, cleanLineBidiStatus);
   1534 
   1535     if (startLine) {
   1536         if (!layoutState.usesRepaintBounds())
   1537             layoutState.setRepaintRange(logicalHeight());
   1538         deleteLineRange(layoutState, startLine);
   1539     }
   1540 
   1541     if (!layoutState.isFullLayout() && lastRootBox() && lastRootBox()->endsWithBreak()) {
   1542         // If the last line before the start line ends with a line break that clear floats,
   1543         // adjust the height accordingly.
   1544         // A line break can be either the first or the last object on a line, depending on its direction.
   1545         if (InlineBox* lastLeafChild = lastRootBox()->lastLeafChild()) {
   1546             RenderObject* lastObject = lastLeafChild->renderer();
   1547             if (!lastObject->isBR())
   1548                 lastObject = lastRootBox()->firstLeafChild()->renderer();
   1549             if (lastObject->isBR()) {
   1550                 EClear clear = lastObject->style()->clear();
   1551                 if (clear != CNONE)
   1552                     newLine(clear);
   1553             }
   1554         }
   1555     }
   1556 
   1557     layoutRunsAndFloatsInRange(layoutState, resolver, cleanLineStart, cleanLineBidiStatus, consecutiveHyphenatedLines);
   1558     linkToEndLineIfNeeded(layoutState);
   1559     repaintDirtyFloats(layoutState.floats());
   1560 }
   1561 
   1562 RenderBlock::RenderTextInfo::RenderTextInfo()
   1563     : m_text(0)
   1564     , m_font(0)
   1565 {
   1566 }
   1567 
   1568 RenderBlock::RenderTextInfo::~RenderTextInfo()
   1569 {
   1570 }
   1571 
   1572 // Before restarting the layout loop with a new logicalHeight, remove all floats that were added and reset the resolver.
   1573 inline const InlineIterator& RenderBlock::restartLayoutRunsAndFloatsInRange(LayoutUnit oldLogicalHeight, LayoutUnit newLogicalHeight,  FloatingObject* lastFloatFromPreviousLine, InlineBidiResolver& resolver,  const InlineIterator& oldEnd)
   1574 {
   1575     removeFloatingObjectsBelow(lastFloatFromPreviousLine, oldLogicalHeight);
   1576     setLogicalHeight(newLogicalHeight);
   1577     resolver.setPositionIgnoringNestedIsolates(oldEnd);
   1578     return oldEnd;
   1579 }
   1580 
   1581 static inline float firstPositiveWidth(const WordMeasurements& wordMeasurements)
   1582 {
   1583     for (size_t i = 0; i < wordMeasurements.size(); ++i) {
   1584         if (wordMeasurements[i].width > 0)
   1585             return wordMeasurements[i].width;
   1586     }
   1587     return 0;
   1588 }
   1589 
   1590 
   1591 static inline LayoutUnit adjustLogicalLineTop(ShapeInsideInfo* shapeInsideInfo, InlineIterator start, InlineIterator end, const WordMeasurements& wordMeasurements)
   1592 {
   1593     if (!shapeInsideInfo || end != start)
   1594         return 0;
   1595 
   1596     float minWidth = firstPositiveWidth(wordMeasurements);
   1597     ASSERT(minWidth || wordMeasurements.isEmpty());
   1598     if (minWidth > 0 && shapeInsideInfo->adjustLogicalLineTop(minWidth))
   1599         return shapeInsideInfo->logicalLineTop();
   1600 
   1601     return shapeInsideInfo->shapeLogicalBottom();
   1602 }
   1603 
   1604 static inline void pushShapeContentOverflowBelowTheContentBox(RenderBlock* block, ShapeInsideInfo* shapeInsideInfo, LayoutUnit lineTop, LayoutUnit lineHeight)
   1605 {
   1606     ASSERT(shapeInsideInfo);
   1607 
   1608     LayoutUnit logicalLineBottom = lineTop + lineHeight;
   1609     LayoutUnit shapeLogicalBottom = shapeInsideInfo->shapeLogicalBottom();
   1610     LayoutUnit shapeContainingBlockHeight = shapeInsideInfo->shapeContainingBlockHeight();
   1611 
   1612     bool isOverflowPositionedAlready = (shapeContainingBlockHeight - shapeInsideInfo->owner()->borderAndPaddingAfter() + lineHeight) <= lineTop;
   1613 
   1614     // If the last line overlaps with the shape, we don't need the segments anymore
   1615     if (lineTop < shapeLogicalBottom && shapeLogicalBottom < logicalLineBottom)
   1616         shapeInsideInfo->clearSegments();
   1617     if (logicalLineBottom <= shapeLogicalBottom || !shapeContainingBlockHeight || isOverflowPositionedAlready)
   1618         return;
   1619 
   1620     LayoutUnit newLogicalHeight = block->logicalHeight() + (shapeContainingBlockHeight - (lineTop + shapeInsideInfo->owner()->borderAndPaddingAfter()));
   1621     block->setLogicalHeight(newLogicalHeight);
   1622 }
   1623 
   1624 void RenderBlock::updateShapeAndSegmentsForCurrentLine(ShapeInsideInfo*& shapeInsideInfo, LayoutUnit& absoluteLogicalTop, LineLayoutState& layoutState)
   1625 {
   1626     if (layoutState.flowThread())
   1627         return updateShapeAndSegmentsForCurrentLineInFlowThread(shapeInsideInfo, layoutState);
   1628 
   1629     if (!shapeInsideInfo)
   1630         return;
   1631 
   1632     LayoutUnit lineTop = logicalHeight() + absoluteLogicalTop;
   1633     LayoutUnit lineHeight = this->lineHeight(layoutState.lineInfo().isFirstLine(), isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes);
   1634 
   1635     // FIXME: Bug 95361: It is possible for a line to grow beyond lineHeight, in which case these segments may be incorrect.
   1636     shapeInsideInfo->computeSegmentsForLine(lineTop, lineHeight);
   1637 
   1638     pushShapeContentOverflowBelowTheContentBox(this, shapeInsideInfo, lineTop, lineHeight);
   1639 }
   1640 
   1641 void RenderBlock::updateShapeAndSegmentsForCurrentLineInFlowThread(ShapeInsideInfo*& shapeInsideInfo, LineLayoutState& layoutState)
   1642 {
   1643     ASSERT(layoutState.flowThread());
   1644 
   1645     LayoutUnit lineHeight = this->lineHeight(layoutState.lineInfo().isFirstLine(), isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes);
   1646 
   1647     RenderRegion* currentRegion = regionAtBlockOffset(logicalHeight());
   1648     if (!currentRegion)
   1649         return;
   1650 
   1651     shapeInsideInfo = currentRegion->shapeInsideInfo();
   1652 
   1653     LayoutUnit logicalLineTopInFlowThread = logicalHeight() + offsetFromLogicalTopOfFirstPage();
   1654     LayoutUnit logicalLineBottomInFlowThread = logicalLineTopInFlowThread + lineHeight;
   1655     LayoutUnit logicalRegionTopInFlowThread = currentRegion->logicalTopForFlowThreadContent();
   1656     LayoutUnit logicalRegionBottomInFlowThread = logicalRegionTopInFlowThread + currentRegion->logicalHeight() - currentRegion->borderAndPaddingBefore() - currentRegion->borderAndPaddingAfter();
   1657 
   1658     // We only want to deal regions with shapes, so we look up for the next region whether it has a shape
   1659     if (!shapeInsideInfo && !currentRegion->isLastRegion()) {
   1660         LayoutUnit deltaToNextRegion = logicalHeight() + logicalRegionBottomInFlowThread - logicalLineTopInFlowThread;
   1661         RenderRegion* lookupForNextRegion = regionAtBlockOffset(logicalHeight() + deltaToNextRegion);
   1662         if (!lookupForNextRegion->shapeInsideInfo())
   1663             return;
   1664     }
   1665 
   1666     LayoutUnit shapeBottomInFlowThread = LayoutUnit::max();
   1667     if (shapeInsideInfo)
   1668         shapeBottomInFlowThread = shapeInsideInfo->shapeLogicalBottom() + currentRegion->logicalTopForFlowThreadContent();
   1669 
   1670     // If the line is between two shapes/regions we position the line to the top of the next shape/region
   1671     RenderRegion* nextRegion = regionAtBlockOffset(logicalHeight() + lineHeight);
   1672     if ((currentRegion != nextRegion && (logicalLineBottomInFlowThread > logicalRegionBottomInFlowThread)) || (!currentRegion->isLastRegion() && shapeBottomInFlowThread < logicalLineBottomInFlowThread)) {
   1673         LayoutUnit deltaToNextRegion = logicalRegionBottomInFlowThread - logicalLineTopInFlowThread;
   1674         nextRegion = regionAtBlockOffset(logicalHeight() + deltaToNextRegion);
   1675 
   1676         ASSERT(currentRegion != nextRegion);
   1677 
   1678         shapeInsideInfo = nextRegion->shapeInsideInfo();
   1679         setLogicalHeight(logicalHeight() + deltaToNextRegion);
   1680 
   1681         currentRegion = nextRegion;
   1682 
   1683         logicalLineTopInFlowThread = logicalHeight() + offsetFromLogicalTopOfFirstPage();
   1684         logicalLineBottomInFlowThread = logicalLineTopInFlowThread + lineHeight;
   1685         logicalRegionTopInFlowThread = currentRegion->logicalTopForFlowThreadContent();
   1686         logicalRegionBottomInFlowThread = logicalRegionTopInFlowThread + currentRegion->logicalHeight() - currentRegion->borderAndPaddingBefore() - currentRegion->borderAndPaddingAfter();
   1687     }
   1688 
   1689     if (!shapeInsideInfo)
   1690         return;
   1691 
   1692     // We position the first line to the top of the shape in the region or to the previously adjusted position in the shape
   1693     if (logicalLineBottomInFlowThread <= (logicalRegionTopInFlowThread + lineHeight) || (logicalLineTopInFlowThread - logicalRegionTopInFlowThread) < (layoutState.adjustedLogicalLineTop() - currentRegion->borderAndPaddingBefore())) {
   1694         LayoutUnit shapeTopOffset = layoutState.adjustedLogicalLineTop();
   1695         if (!shapeTopOffset)
   1696             shapeTopOffset = shapeInsideInfo->shapeLogicalTop();
   1697 
   1698         LayoutUnit shapePositionInFlowThread = currentRegion->logicalTopForFlowThreadContent() + shapeTopOffset;
   1699         LayoutUnit shapeTopLineTopDelta = shapePositionInFlowThread - logicalLineTopInFlowThread - currentRegion->borderAndPaddingBefore();
   1700 
   1701         setLogicalHeight(logicalHeight() + shapeTopLineTopDelta);
   1702         logicalLineTopInFlowThread += shapeTopLineTopDelta;
   1703         layoutState.setAdjustedLogicalLineTop(0);
   1704     }
   1705 
   1706     LayoutUnit lineTop = logicalLineTopInFlowThread - currentRegion->logicalTopForFlowThreadContent() + currentRegion->borderAndPaddingBefore();
   1707     shapeInsideInfo->computeSegmentsForLine(lineTop, lineHeight);
   1708 
   1709     if (currentRegion->isLastRegion())
   1710         pushShapeContentOverflowBelowTheContentBox(this, shapeInsideInfo, lineTop, lineHeight);
   1711 }
   1712 
   1713 bool RenderBlock::adjustLogicalLineTopAndLogicalHeightIfNeeded(ShapeInsideInfo* shapeInsideInfo, LayoutUnit absoluteLogicalTop, LineLayoutState& layoutState, InlineBidiResolver& resolver, FloatingObject* lastFloatFromPreviousLine, InlineIterator& end, WordMeasurements& wordMeasurements)
   1714 {
   1715     LayoutUnit adjustedLogicalLineTop = adjustLogicalLineTop(shapeInsideInfo, resolver.position(), end, wordMeasurements);
   1716     if (!adjustedLogicalLineTop)
   1717         return false;
   1718 
   1719     LayoutUnit newLogicalHeight = adjustedLogicalLineTop - absoluteLogicalTop;
   1720 
   1721     if (layoutState.flowThread()) {
   1722         layoutState.setAdjustedLogicalLineTop(adjustedLogicalLineTop);
   1723         newLogicalHeight = logicalHeight();
   1724     }
   1725 
   1726 
   1727     end = restartLayoutRunsAndFloatsInRange(logicalHeight(), newLogicalHeight, lastFloatFromPreviousLine, resolver, end);
   1728     return true;
   1729 }
   1730 
   1731 void RenderBlock::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, InlineBidiResolver& resolver, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines)
   1732 {
   1733     RenderStyle* styleToUse = style();
   1734     bool paginated = view()->layoutState() && view()->layoutState()->isPaginated();
   1735     LineMidpointState& lineMidpointState = resolver.midpointState();
   1736     InlineIterator end = resolver.position();
   1737     bool checkForEndLineMatch = layoutState.endLine();
   1738     RenderTextInfo renderTextInfo;
   1739     VerticalPositionCache verticalPositionCache;
   1740 
   1741     LineBreaker lineBreaker(this);
   1742 
   1743     LayoutUnit absoluteLogicalTop;
   1744     ShapeInsideInfo* shapeInsideInfo = layoutShapeInsideInfo();
   1745     if (shapeInsideInfo) {
   1746         ASSERT(shapeInsideInfo->owner() == this || allowsShapeInsideInfoSharing());
   1747         if (shapeInsideInfo != this->shapeInsideInfo()) {
   1748             // FIXME Bug 100284: If subsequent LayoutStates are pushed, we will have to add
   1749             // their offsets from the original shape-inside container.
   1750             absoluteLogicalTop = logicalTop();
   1751         }
   1752         // Begin layout at the logical top of our shape inside.
   1753         if (logicalHeight() + absoluteLogicalTop < shapeInsideInfo->shapeLogicalTop()) {
   1754             LayoutUnit logicalHeight = shapeInsideInfo->shapeLogicalTop() - absoluteLogicalTop;
   1755             if (layoutState.flowThread())
   1756                 logicalHeight -= shapeInsideInfo->owner()->borderAndPaddingBefore();
   1757             setLogicalHeight(logicalHeight);
   1758         }
   1759     }
   1760 
   1761     while (!end.atEnd()) {
   1762         // FIXME: Is this check necessary before the first iteration or can it be moved to the end?
   1763         if (checkForEndLineMatch) {
   1764             layoutState.setEndLineMatched(matchedEndLine(layoutState, resolver, cleanLineStart, cleanLineBidiStatus));
   1765             if (layoutState.endLineMatched()) {
   1766                 resolver.setPosition(InlineIterator(resolver.position().root(), 0, 0), 0);
   1767                 break;
   1768             }
   1769         }
   1770 
   1771         lineMidpointState.reset();
   1772 
   1773         layoutState.lineInfo().setEmpty(true);
   1774         layoutState.lineInfo().resetRunsFromLeadingWhitespace();
   1775 
   1776         const InlineIterator oldEnd = end;
   1777         bool isNewUBAParagraph = layoutState.lineInfo().previousLineBrokeCleanly();
   1778         FloatingObject* lastFloatFromPreviousLine = (containsFloats()) ? m_floatingObjects->set().last() : 0;
   1779 
   1780         updateShapeAndSegmentsForCurrentLine(shapeInsideInfo, absoluteLogicalTop, layoutState);
   1781 
   1782         WordMeasurements wordMeasurements;
   1783         end = lineBreaker.nextLineBreak(resolver, layoutState.lineInfo(), renderTextInfo, lastFloatFromPreviousLine, consecutiveHyphenatedLines, wordMeasurements);
   1784         renderTextInfo.m_lineBreakIterator.resetPriorContext();
   1785         if (resolver.position().atEnd()) {
   1786             // FIXME: We shouldn't be creating any runs in nextLineBreak to begin with!
   1787             // Once BidiRunList is separated from BidiResolver this will not be needed.
   1788             resolver.runs().deleteRuns();
   1789             resolver.markCurrentRunEmpty(); // FIXME: This can probably be replaced by an ASSERT (or just removed).
   1790             layoutState.setCheckForFloatsFromLastLine(true);
   1791             resolver.setPosition(InlineIterator(resolver.position().root(), 0, 0), 0);
   1792             break;
   1793         }
   1794 
   1795         if (adjustLogicalLineTopAndLogicalHeightIfNeeded(shapeInsideInfo, absoluteLogicalTop, layoutState, resolver, lastFloatFromPreviousLine, end, wordMeasurements))
   1796             continue;
   1797 
   1798         ASSERT(end != resolver.position());
   1799 
   1800         // This is a short-cut for empty lines.
   1801         if (layoutState.lineInfo().isEmpty()) {
   1802             if (lastRootBox())
   1803                 lastRootBox()->setLineBreakInfo(end.m_obj, end.m_pos, resolver.status());
   1804         } else {
   1805             VisualDirectionOverride override = (styleToUse->rtlOrdering() == VisualOrder ? (styleToUse->direction() == LTR ? VisualLeftToRightOverride : VisualRightToLeftOverride) : NoVisualOverride);
   1806 
   1807             if (isNewUBAParagraph && styleToUse->unicodeBidi() == Plaintext && !resolver.context()->parent()) {
   1808                 TextDirection direction = styleToUse->direction();
   1809                 determineDirectionality(direction, resolver.position());
   1810                 resolver.setStatus(BidiStatus(direction, isOverride(styleToUse->unicodeBidi())));
   1811             }
   1812             // FIXME: This ownership is reversed. We should own the BidiRunList and pass it to createBidiRunsForLine.
   1813             BidiRunList<BidiRun>& bidiRuns = resolver.runs();
   1814             constructBidiRunsForLine(this, resolver, bidiRuns, end, override, layoutState.lineInfo().previousLineBrokeCleanly());
   1815             ASSERT(resolver.position() == end);
   1816 
   1817             BidiRun* trailingSpaceRun = !layoutState.lineInfo().previousLineBrokeCleanly() ? handleTrailingSpaces(bidiRuns, resolver.context()) : 0;
   1818 
   1819             if (bidiRuns.runCount() && lineBreaker.lineWasHyphenated()) {
   1820                 bidiRuns.logicallyLastRun()->m_hasHyphen = true;
   1821                 consecutiveHyphenatedLines++;
   1822             } else
   1823                 consecutiveHyphenatedLines = 0;
   1824 
   1825             // Now that the runs have been ordered, we create the line boxes.
   1826             // At the same time we figure out where border/padding/margin should be applied for
   1827             // inline flow boxes.
   1828 
   1829             LayoutUnit oldLogicalHeight = logicalHeight();
   1830             RootInlineBox* lineBox = createLineBoxesFromBidiRuns(bidiRuns, end, layoutState.lineInfo(), verticalPositionCache, trailingSpaceRun, wordMeasurements);
   1831 
   1832             bidiRuns.deleteRuns();
   1833             resolver.markCurrentRunEmpty(); // FIXME: This can probably be replaced by an ASSERT (or just removed).
   1834 
   1835             if (lineBox) {
   1836                 lineBox->setLineBreakInfo(end.m_obj, end.m_pos, resolver.status());
   1837                 if (layoutState.usesRepaintBounds())
   1838                     layoutState.updateRepaintRangeFromBox(lineBox);
   1839 
   1840                 if (paginated) {
   1841                     LayoutUnit adjustment = 0;
   1842                     adjustLinePositionForPagination(lineBox, adjustment, layoutState.flowThread());
   1843                     if (adjustment) {
   1844                         LayoutUnit oldLineWidth = availableLogicalWidthForLine(oldLogicalHeight, layoutState.lineInfo().isFirstLine());
   1845                         lineBox->adjustBlockDirectionPosition(adjustment);
   1846                         if (layoutState.usesRepaintBounds())
   1847                             layoutState.updateRepaintRangeFromBox(lineBox);
   1848 
   1849                         if (availableLogicalWidthForLine(oldLogicalHeight + adjustment, layoutState.lineInfo().isFirstLine()) != oldLineWidth) {
   1850                             // We have to delete this line, remove all floats that got added, and let line layout re-run.
   1851                             lineBox->deleteLine();
   1852                             end = restartLayoutRunsAndFloatsInRange(oldLogicalHeight, oldLogicalHeight + adjustment, lastFloatFromPreviousLine, resolver, oldEnd);
   1853                             continue;
   1854                         }
   1855 
   1856                         setLogicalHeight(lineBox->lineBottomWithLeading());
   1857                     }
   1858 
   1859                     if (layoutState.flowThread())
   1860                         lineBox->setContainingRegion(regionAtBlockOffset(lineBox->lineTopWithLeading()));
   1861                 }
   1862             }
   1863         }
   1864 
   1865         for (size_t i = 0; i < lineBreaker.positionedObjects().size(); ++i)
   1866             setStaticPositions(this, lineBreaker.positionedObjects()[i]);
   1867 
   1868         if (!layoutState.lineInfo().isEmpty()) {
   1869             layoutState.lineInfo().setFirstLine(false);
   1870             newLine(lineBreaker.clear());
   1871         }
   1872 
   1873         if (m_floatingObjects && lastRootBox()) {
   1874             const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
   1875             FloatingObjectSetIterator it = floatingObjectSet.begin();
   1876             FloatingObjectSetIterator end = floatingObjectSet.end();
   1877             if (layoutState.lastFloat()) {
   1878                 FloatingObjectSetIterator lastFloatIterator = floatingObjectSet.find(layoutState.lastFloat());
   1879                 ASSERT(lastFloatIterator != end);
   1880                 ++lastFloatIterator;
   1881                 it = lastFloatIterator;
   1882             }
   1883             for (; it != end; ++it) {
   1884                 FloatingObject* f = *it;
   1885                 appendFloatingObjectToLastLine(f);
   1886                 ASSERT(f->m_renderer == layoutState.floats()[layoutState.floatIndex()].object);
   1887                 // If a float's geometry has changed, give up on syncing with clean lines.
   1888                 if (layoutState.floats()[layoutState.floatIndex()].rect != f->frameRect())
   1889                     checkForEndLineMatch = false;
   1890                 layoutState.setFloatIndex(layoutState.floatIndex() + 1);
   1891             }
   1892             layoutState.setLastFloat(!floatingObjectSet.isEmpty() ? floatingObjectSet.last() : 0);
   1893         }
   1894 
   1895         lineMidpointState.reset();
   1896         resolver.setPosition(end, numberOfIsolateAncestors(end));
   1897     }
   1898 
   1899     if (paginated && !style()->hasAutoWidows()) {
   1900         // Check the line boxes to make sure we didn't create unacceptable widows.
   1901         // However, we'll prioritize orphans - so nothing we do here should create
   1902         // a new orphan.
   1903 
   1904         RootInlineBox* lineBox = lastRootBox();
   1905 
   1906         // Count from the end of the block backwards, to see how many hanging
   1907         // lines we have.
   1908         RootInlineBox* firstLineInBlock = firstRootBox();
   1909         int numLinesHanging = 1;
   1910         while (lineBox && lineBox != firstLineInBlock && !lineBox->isFirstAfterPageBreak()) {
   1911             ++numLinesHanging;
   1912             lineBox = lineBox->prevRootBox();
   1913         }
   1914 
   1915         // If there were no breaks in the block, we didn't create any widows.
   1916         if (!lineBox || !lineBox->isFirstAfterPageBreak() || lineBox == firstLineInBlock)
   1917             return;
   1918 
   1919         if (numLinesHanging < style()->widows()) {
   1920             // We have detected a widow. Now we need to work out how many
   1921             // lines there are on the previous page, and how many we need
   1922             // to steal.
   1923             int numLinesNeeded = style()->widows() - numLinesHanging;
   1924             RootInlineBox* currentFirstLineOfNewPage = lineBox;
   1925 
   1926             // Count the number of lines in the previous page.
   1927             lineBox = lineBox->prevRootBox();
   1928             int numLinesInPreviousPage = 1;
   1929             while (lineBox && lineBox != firstLineInBlock && !lineBox->isFirstAfterPageBreak()) {
   1930                 ++numLinesInPreviousPage;
   1931                 lineBox = lineBox->prevRootBox();
   1932             }
   1933 
   1934             // If there was an explicit value for orphans, respect that. If not, we still
   1935             // shouldn't create a situation where we make an orphan bigger than the initial value.
   1936             // This means that setting widows implies we also care about orphans, but given
   1937             // the specification says the initial orphan value is non-zero, this is ok. The
   1938             // author is always free to set orphans explicitly as well.
   1939             int orphans = style()->hasAutoOrphans() ? style()->initialOrphans() : style()->orphans();
   1940             int numLinesAvailable = numLinesInPreviousPage - orphans;
   1941             if (numLinesAvailable <= 0)
   1942                 return;
   1943 
   1944             int numLinesToTake = min(numLinesAvailable, numLinesNeeded);
   1945             // Wind back from our first widowed line.
   1946             lineBox = currentFirstLineOfNewPage;
   1947             for (int i = 0; i < numLinesToTake; ++i)
   1948                 lineBox = lineBox->prevRootBox();
   1949 
   1950             // We now want to break at this line. Remember for next layout and trigger relayout.
   1951             setBreakAtLineToAvoidWidow(lineBox);
   1952             markLinesDirtyInBlockRange(lastRootBox()->lineBottomWithLeading(), lineBox->lineBottomWithLeading(), lineBox);
   1953         }
   1954     }
   1955 }
   1956 
   1957 void RenderBlock::linkToEndLineIfNeeded(LineLayoutState& layoutState)
   1958 {
   1959     if (layoutState.endLine()) {
   1960         if (layoutState.endLineMatched()) {
   1961             bool paginated = view()->layoutState() && view()->layoutState()->isPaginated();
   1962             // Attach all the remaining lines, and then adjust their y-positions as needed.
   1963             LayoutUnit delta = logicalHeight() - layoutState.endLineLogicalTop();
   1964             for (RootInlineBox* line = layoutState.endLine(); line; line = line->nextRootBox()) {
   1965                 line->attachLine();
   1966                 if (paginated) {
   1967                     delta -= line->paginationStrut();
   1968                     adjustLinePositionForPagination(line, delta, layoutState.flowThread());
   1969                 }
   1970                 if (delta) {
   1971                     layoutState.updateRepaintRangeFromBox(line, delta);
   1972                     line->adjustBlockDirectionPosition(delta);
   1973                 }
   1974                 if (layoutState.flowThread())
   1975                     line->setContainingRegion(regionAtBlockOffset(line->lineTopWithLeading()));
   1976                 if (Vector<RenderBox*>* cleanLineFloats = line->floatsPtr()) {
   1977                     Vector<RenderBox*>::iterator end = cleanLineFloats->end();
   1978                     for (Vector<RenderBox*>::iterator f = cleanLineFloats->begin(); f != end; ++f) {
   1979                         FloatingObject* floatingObject = insertFloatingObject(*f);
   1980                         ASSERT(!floatingObject->m_originatingLine);
   1981                         floatingObject->m_originatingLine = line;
   1982                         setLogicalHeight(logicalTopForChild(*f) - marginBeforeForChild(*f) + delta);
   1983                         positionNewFloats();
   1984                     }
   1985                 }
   1986             }
   1987             setLogicalHeight(lastRootBox()->lineBottomWithLeading());
   1988         } else {
   1989             // Delete all the remaining lines.
   1990             deleteLineRange(layoutState, layoutState.endLine());
   1991         }
   1992     }
   1993 
   1994     if (m_floatingObjects && (layoutState.checkForFloatsFromLastLine() || positionNewFloats()) && lastRootBox()) {
   1995         // In case we have a float on the last line, it might not be positioned up to now.
   1996         // This has to be done before adding in the bottom border/padding, or the float will
   1997         // include the padding incorrectly. -dwh
   1998         if (layoutState.checkForFloatsFromLastLine()) {
   1999             LayoutUnit bottomVisualOverflow = lastRootBox()->logicalBottomVisualOverflow();
   2000             LayoutUnit bottomLayoutOverflow = lastRootBox()->logicalBottomLayoutOverflow();
   2001             TrailingFloatsRootInlineBox* trailingFloatsLineBox = new TrailingFloatsRootInlineBox(this);
   2002             m_lineBoxes.appendLineBox(trailingFloatsLineBox);
   2003             trailingFloatsLineBox->setConstructed();
   2004             GlyphOverflowAndFallbackFontsMap textBoxDataMap;
   2005             VerticalPositionCache verticalPositionCache;
   2006             LayoutUnit blockLogicalHeight = logicalHeight();
   2007             trailingFloatsLineBox->alignBoxesInBlockDirection(blockLogicalHeight, textBoxDataMap, verticalPositionCache);
   2008             trailingFloatsLineBox->setLineTopBottomPositions(blockLogicalHeight, blockLogicalHeight, blockLogicalHeight, blockLogicalHeight);
   2009             trailingFloatsLineBox->setPaginatedLineWidth(availableLogicalWidthForContent(blockLogicalHeight));
   2010             LayoutRect logicalLayoutOverflow(0, blockLogicalHeight, 1, bottomLayoutOverflow - blockLogicalHeight);
   2011             LayoutRect logicalVisualOverflow(0, blockLogicalHeight, 1, bottomVisualOverflow - blockLogicalHeight);
   2012             trailingFloatsLineBox->setOverflowFromLogicalRects(logicalLayoutOverflow, logicalVisualOverflow, trailingFloatsLineBox->lineTop(), trailingFloatsLineBox->lineBottom());
   2013             if (layoutState.flowThread())
   2014                 trailingFloatsLineBox->setContainingRegion(regionAtBlockOffset(trailingFloatsLineBox->lineTopWithLeading()));
   2015         }
   2016 
   2017         const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
   2018         FloatingObjectSetIterator it = floatingObjectSet.begin();
   2019         FloatingObjectSetIterator end = floatingObjectSet.end();
   2020         if (layoutState.lastFloat()) {
   2021             FloatingObjectSetIterator lastFloatIterator = floatingObjectSet.find(layoutState.lastFloat());
   2022             ASSERT(lastFloatIterator != end);
   2023             ++lastFloatIterator;
   2024             it = lastFloatIterator;
   2025         }
   2026         for (; it != end; ++it)
   2027             appendFloatingObjectToLastLine(*it);
   2028         layoutState.setLastFloat(!floatingObjectSet.isEmpty() ? floatingObjectSet.last() : 0);
   2029     }
   2030 }
   2031 
   2032 void RenderBlock::repaintDirtyFloats(Vector<FloatWithRect>& floats)
   2033 {
   2034     size_t floatCount = floats.size();
   2035     // Floats that did not have layout did not repaint when we laid them out. They would have
   2036     // painted by now if they had moved, but if they stayed at (0, 0), they still need to be
   2037     // painted.
   2038     for (size_t i = 0; i < floatCount; ++i) {
   2039         if (!floats[i].everHadLayout) {
   2040             RenderBox* f = floats[i].object;
   2041             if (!f->x() && !f->y() && f->checkForRepaintDuringLayout())
   2042                 f->repaint();
   2043         }
   2044     }
   2045 }
   2046 
   2047 void RenderBlock::layoutInlineChildren(bool relayoutChildren, LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom)
   2048 {
   2049     setLogicalHeight(borderBefore() + paddingBefore());
   2050 
   2051     // Lay out our hypothetical grid line as though it occurs at the top of the block.
   2052     if (view()->layoutState() && view()->layoutState()->lineGrid() == this)
   2053         layoutLineGridBox();
   2054 
   2055     RenderFlowThread* flowThread = flowThreadContainingBlock();
   2056     bool clearLinesForPagination = firstLineBox() && flowThread && !flowThread->hasRegions();
   2057 
   2058     // Figure out if we should clear out our line boxes.
   2059     // FIXME: Handle resize eventually!
   2060     bool isFullLayout = !firstLineBox() || selfNeedsLayout() || relayoutChildren || clearLinesForPagination;
   2061     LineLayoutState layoutState(isFullLayout, repaintLogicalTop, repaintLogicalBottom, flowThread);
   2062 
   2063     if (isFullLayout)
   2064         lineBoxes()->deleteLineBoxes();
   2065 
   2066     // Text truncation kicks in in two cases:
   2067     //     1) If your overflow isn't visible and your text-overflow-mode isn't clip.
   2068     //     2) If you're an anonymous block with a block parent that satisfies #1.
   2069     // FIXME: CSS3 says that descendants that are clipped must also know how to truncate.  This is insanely
   2070     // difficult to figure out in general (especially in the middle of doing layout), so we only handle the
   2071     // simple case of an anonymous block truncating when it's parent is clipped.
   2072     bool hasTextOverflow = (style()->textOverflow() && hasOverflowClip())
   2073         || (isAnonymousBlock() && parent() && parent()->isRenderBlock() && parent()->style()->textOverflow() && parent()->hasOverflowClip());
   2074 
   2075     // Walk all the lines and delete our ellipsis line boxes if they exist.
   2076     if (hasTextOverflow)
   2077          deleteEllipsisLineBoxes();
   2078 
   2079     if (firstChild()) {
   2080         // In full layout mode, clear the line boxes of children upfront. Otherwise,
   2081         // siblings can run into stale root lineboxes during layout. Then layout
   2082         // the replaced elements later. In partial layout mode, line boxes are not
   2083         // deleted and only dirtied. In that case, we can layout the replaced
   2084         // elements at the same time.
   2085         bool hasInlineChild = false;
   2086         Vector<RenderBox*> replacedChildren;
   2087         for (InlineWalker walker(this); !walker.atEnd(); walker.advance()) {
   2088             RenderObject* o = walker.current();
   2089             if (!hasInlineChild && o->isInline())
   2090                 hasInlineChild = true;
   2091 
   2092             if (o->isReplaced() || o->isFloating() || o->isOutOfFlowPositioned()) {
   2093                 RenderBox* box = toRenderBox(o);
   2094 
   2095                 if (relayoutChildren || box->hasRelativeDimensions())
   2096                     o->setChildNeedsLayout(MarkOnlyThis);
   2097 
   2098                 // If relayoutChildren is set and the child has percentage padding or an embedded content box, we also need to invalidate the childs pref widths.
   2099                 if (relayoutChildren && box->needsPreferredWidthsRecalculation())
   2100                     o->setPreferredLogicalWidthsDirty(true, MarkOnlyThis);
   2101 
   2102                 if (o->isOutOfFlowPositioned())
   2103                     o->containingBlock()->insertPositionedObject(box);
   2104                 else if (o->isFloating())
   2105                     layoutState.floats().append(FloatWithRect(box));
   2106                 else if (isFullLayout || o->needsLayout()) {
   2107                     // Replaced element.
   2108                     box->dirtyLineBoxes(isFullLayout);
   2109                     if (isFullLayout)
   2110                         replacedChildren.append(box);
   2111                     else
   2112                         o->layoutIfNeeded();
   2113                 }
   2114             } else if (o->isText() || (o->isRenderInline() && !walker.atEndOfInline())) {
   2115                 if (!o->isText())
   2116                     toRenderInline(o)->updateAlwaysCreateLineBoxes(layoutState.isFullLayout());
   2117                 if (layoutState.isFullLayout() || o->selfNeedsLayout())
   2118                     dirtyLineBoxesForRenderer(o, layoutState.isFullLayout());
   2119                 o->clearNeedsLayout();
   2120             }
   2121         }
   2122 
   2123         for (size_t i = 0; i < replacedChildren.size(); i++)
   2124              replacedChildren[i]->layoutIfNeeded();
   2125 
   2126         layoutRunsAndFloats(layoutState, hasInlineChild);
   2127     }
   2128 
   2129     // Expand the last line to accommodate Ruby and emphasis marks.
   2130     int lastLineAnnotationsAdjustment = 0;
   2131     if (lastRootBox()) {
   2132         LayoutUnit lowestAllowedPosition = max(lastRootBox()->lineBottom(), logicalHeight() + paddingAfter());
   2133         if (!style()->isFlippedLinesWritingMode())
   2134             lastLineAnnotationsAdjustment = lastRootBox()->computeUnderAnnotationAdjustment(lowestAllowedPosition);
   2135         else
   2136             lastLineAnnotationsAdjustment = lastRootBox()->computeOverAnnotationAdjustment(lowestAllowedPosition);
   2137     }
   2138 
   2139     // Now add in the bottom border/padding.
   2140     setLogicalHeight(logicalHeight() + lastLineAnnotationsAdjustment + borderAfter() + paddingAfter() + scrollbarLogicalHeight());
   2141 
   2142     if (!firstLineBox() && hasLineIfEmpty())
   2143         setLogicalHeight(logicalHeight() + lineHeight(true, isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes));
   2144 
   2145     // See if we have any lines that spill out of our block.  If we do, then we will possibly need to
   2146     // truncate text.
   2147     if (hasTextOverflow)
   2148         checkLinesForTextOverflow();
   2149 }
   2150 
   2151 void RenderBlock::checkFloatsInCleanLine(RootInlineBox* line, Vector<FloatWithRect>& floats, size_t& floatIndex, bool& encounteredNewFloat, bool& dirtiedByFloat)
   2152 {
   2153     Vector<RenderBox*>* cleanLineFloats = line->floatsPtr();
   2154     if (!cleanLineFloats)
   2155         return;
   2156 
   2157     Vector<RenderBox*>::iterator end = cleanLineFloats->end();
   2158     for (Vector<RenderBox*>::iterator it = cleanLineFloats->begin(); it != end; ++it) {
   2159         RenderBox* floatingBox = *it;
   2160         floatingBox->layoutIfNeeded();
   2161         LayoutSize newSize(floatingBox->width() + floatingBox->marginWidth(), floatingBox->height() + floatingBox->marginHeight());
   2162         if (floats[floatIndex].object != floatingBox) {
   2163             encounteredNewFloat = true;
   2164             return;
   2165         }
   2166 
   2167         if (floats[floatIndex].rect.size() != newSize) {
   2168             LayoutUnit floatTop = isHorizontalWritingMode() ? floats[floatIndex].rect.y() : floats[floatIndex].rect.x();
   2169             LayoutUnit floatHeight = isHorizontalWritingMode() ? max(floats[floatIndex].rect.height(), newSize.height())
   2170                                                                  : max(floats[floatIndex].rect.width(), newSize.width());
   2171             floatHeight = min(floatHeight, LayoutUnit::max() - floatTop);
   2172             line->markDirty();
   2173             markLinesDirtyInBlockRange(line->lineBottomWithLeading(), floatTop + floatHeight, line);
   2174             floats[floatIndex].rect.setSize(newSize);
   2175             dirtiedByFloat = true;
   2176         }
   2177         floatIndex++;
   2178     }
   2179 }
   2180 
   2181 RootInlineBox* RenderBlock::determineStartPosition(LineLayoutState& layoutState, InlineBidiResolver& resolver)
   2182 {
   2183     RootInlineBox* curr = 0;
   2184     RootInlineBox* last = 0;
   2185 
   2186     // FIXME: This entire float-checking block needs to be broken into a new function.
   2187     bool dirtiedByFloat = false;
   2188     if (!layoutState.isFullLayout()) {
   2189         // Paginate all of the clean lines.
   2190         bool paginated = view()->layoutState() && view()->layoutState()->isPaginated();
   2191         LayoutUnit paginationDelta = 0;
   2192         size_t floatIndex = 0;
   2193         for (curr = firstRootBox(); curr && !curr->isDirty(); curr = curr->nextRootBox()) {
   2194             if (paginated) {
   2195                 if (lineWidthForPaginatedLineChanged(curr, 0, layoutState.flowThread())) {
   2196                     curr->markDirty();
   2197                     break;
   2198                 }
   2199                 paginationDelta -= curr->paginationStrut();
   2200                 adjustLinePositionForPagination(curr, paginationDelta, layoutState.flowThread());
   2201                 if (paginationDelta) {
   2202                     if (containsFloats() || !layoutState.floats().isEmpty()) {
   2203                         // FIXME: Do better eventually.  For now if we ever shift because of pagination and floats are present just go to a full layout.
   2204                         layoutState.markForFullLayout();
   2205                         break;
   2206                     }
   2207 
   2208                     layoutState.updateRepaintRangeFromBox(curr, paginationDelta);
   2209                     curr->adjustBlockDirectionPosition(paginationDelta);
   2210                 }
   2211                 if (layoutState.flowThread())
   2212                     curr->setContainingRegion(regionAtBlockOffset(curr->lineTopWithLeading()));
   2213             }
   2214 
   2215             // If a new float has been inserted before this line or before its last known float, just do a full layout.
   2216             bool encounteredNewFloat = false;
   2217             checkFloatsInCleanLine(curr, layoutState.floats(), floatIndex, encounteredNewFloat, dirtiedByFloat);
   2218             if (encounteredNewFloat)
   2219                 layoutState.markForFullLayout();
   2220 
   2221             if (dirtiedByFloat || layoutState.isFullLayout())
   2222                 break;
   2223         }
   2224         // Check if a new float has been inserted after the last known float.
   2225         if (!curr && floatIndex < layoutState.floats().size())
   2226             layoutState.markForFullLayout();
   2227     }
   2228 
   2229     if (layoutState.isFullLayout()) {
   2230         // FIXME: This should just call deleteLineBoxTree, but that causes
   2231         // crashes for fast/repaint tests.
   2232         curr = firstRootBox();
   2233         while (curr) {
   2234             // Note: This uses nextRootBox() insted of nextLineBox() like deleteLineBoxTree does.
   2235             RootInlineBox* next = curr->nextRootBox();
   2236             curr->deleteLine();
   2237             curr = next;
   2238         }
   2239         ASSERT(!firstLineBox() && !lastLineBox());
   2240     } else {
   2241         if (curr) {
   2242             // We have a dirty line.
   2243             if (RootInlineBox* prevRootBox = curr->prevRootBox()) {
   2244                 // We have a previous line.
   2245                 if (!dirtiedByFloat && (!prevRootBox->endsWithBreak() || !prevRootBox->lineBreakObj() || (prevRootBox->lineBreakObj()->isText() && prevRootBox->lineBreakPos() >= toRenderText(prevRootBox->lineBreakObj())->textLength())))
   2246                     // The previous line didn't break cleanly or broke at a newline
   2247                     // that has been deleted, so treat it as dirty too.
   2248                     curr = prevRootBox;
   2249             }
   2250         } else {
   2251             // No dirty lines were found.
   2252             // If the last line didn't break cleanly, treat it as dirty.
   2253             if (lastRootBox() && !lastRootBox()->endsWithBreak())
   2254                 curr = lastRootBox();
   2255         }
   2256 
   2257         // If we have no dirty lines, then last is just the last root box.
   2258         last = curr ? curr->prevRootBox() : lastRootBox();
   2259     }
   2260 
   2261     unsigned numCleanFloats = 0;
   2262     if (!layoutState.floats().isEmpty()) {
   2263         LayoutUnit savedLogicalHeight = logicalHeight();
   2264         // Restore floats from clean lines.
   2265         RootInlineBox* line = firstRootBox();
   2266         while (line != curr) {
   2267             if (Vector<RenderBox*>* cleanLineFloats = line->floatsPtr()) {
   2268                 Vector<RenderBox*>::iterator end = cleanLineFloats->end();
   2269                 for (Vector<RenderBox*>::iterator f = cleanLineFloats->begin(); f != end; ++f) {
   2270                     FloatingObject* floatingObject = insertFloatingObject(*f);
   2271                     ASSERT(!floatingObject->m_originatingLine);
   2272                     floatingObject->m_originatingLine = line;
   2273                     setLogicalHeight(logicalTopForChild(*f) - marginBeforeForChild(*f));
   2274                     positionNewFloats();
   2275                     ASSERT(layoutState.floats()[numCleanFloats].object == *f);
   2276                     numCleanFloats++;
   2277                 }
   2278             }
   2279             line = line->nextRootBox();
   2280         }
   2281         setLogicalHeight(savedLogicalHeight);
   2282     }
   2283     layoutState.setFloatIndex(numCleanFloats);
   2284 
   2285     layoutState.lineInfo().setFirstLine(!last);
   2286     layoutState.lineInfo().setPreviousLineBrokeCleanly(!last || last->endsWithBreak());
   2287 
   2288     if (last) {
   2289         setLogicalHeight(last->lineBottomWithLeading());
   2290         InlineIterator iter = InlineIterator(this, last->lineBreakObj(), last->lineBreakPos());
   2291         resolver.setPosition(iter, numberOfIsolateAncestors(iter));
   2292         resolver.setStatus(last->lineBreakBidiStatus());
   2293     } else {
   2294         TextDirection direction = style()->direction();
   2295         if (style()->unicodeBidi() == Plaintext)
   2296             determineDirectionality(direction, InlineIterator(this, bidiFirstSkippingEmptyInlines(this), 0));
   2297         resolver.setStatus(BidiStatus(direction, isOverride(style()->unicodeBidi())));
   2298         InlineIterator iter = InlineIterator(this, bidiFirstSkippingEmptyInlines(this, &resolver), 0);
   2299         resolver.setPosition(iter, numberOfIsolateAncestors(iter));
   2300     }
   2301     return curr;
   2302 }
   2303 
   2304 void RenderBlock::determineEndPosition(LineLayoutState& layoutState, RootInlineBox* startLine, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus)
   2305 {
   2306     ASSERT(!layoutState.endLine());
   2307     size_t floatIndex = layoutState.floatIndex();
   2308     RootInlineBox* last = 0;
   2309     for (RootInlineBox* curr = startLine->nextRootBox(); curr; curr = curr->nextRootBox()) {
   2310         if (!curr->isDirty()) {
   2311             bool encounteredNewFloat = false;
   2312             bool dirtiedByFloat = false;
   2313             checkFloatsInCleanLine(curr, layoutState.floats(), floatIndex, encounteredNewFloat, dirtiedByFloat);
   2314             if (encounteredNewFloat)
   2315                 return;
   2316         }
   2317         if (curr->isDirty())
   2318             last = 0;
   2319         else if (!last)
   2320             last = curr;
   2321     }
   2322 
   2323     if (!last)
   2324         return;
   2325 
   2326     // At this point, |last| is the first line in a run of clean lines that ends with the last line
   2327     // in the block.
   2328 
   2329     RootInlineBox* prev = last->prevRootBox();
   2330     cleanLineStart = InlineIterator(this, prev->lineBreakObj(), prev->lineBreakPos());
   2331     cleanLineBidiStatus = prev->lineBreakBidiStatus();
   2332     layoutState.setEndLineLogicalTop(prev->lineBottomWithLeading());
   2333 
   2334     for (RootInlineBox* line = last; line; line = line->nextRootBox())
   2335         line->extractLine(); // Disconnect all line boxes from their render objects while preserving
   2336                              // their connections to one another.
   2337 
   2338     layoutState.setEndLine(last);
   2339 }
   2340 
   2341 bool RenderBlock::checkPaginationAndFloatsAtEndLine(LineLayoutState& layoutState)
   2342 {
   2343     LayoutUnit lineDelta = logicalHeight() - layoutState.endLineLogicalTop();
   2344 
   2345     bool paginated = view()->layoutState() && view()->layoutState()->isPaginated();
   2346     if (paginated && layoutState.flowThread()) {
   2347         // Check all lines from here to the end, and see if the hypothetical new position for the lines will result
   2348         // in a different available line width.
   2349         for (RootInlineBox* lineBox = layoutState.endLine(); lineBox; lineBox = lineBox->nextRootBox()) {
   2350             if (paginated) {
   2351                 // This isn't the real move we're going to do, so don't update the line box's pagination
   2352                 // strut yet.
   2353                 LayoutUnit oldPaginationStrut = lineBox->paginationStrut();
   2354                 lineDelta -= oldPaginationStrut;
   2355                 adjustLinePositionForPagination(lineBox, lineDelta, layoutState.flowThread());
   2356                 lineBox->setPaginationStrut(oldPaginationStrut);
   2357             }
   2358             if (lineWidthForPaginatedLineChanged(lineBox, lineDelta, layoutState.flowThread()))
   2359                 return false;
   2360         }
   2361     }
   2362 
   2363     if (!lineDelta || !m_floatingObjects)
   2364         return true;
   2365 
   2366     // See if any floats end in the range along which we want to shift the lines vertically.
   2367     LayoutUnit logicalTop = min(logicalHeight(), layoutState.endLineLogicalTop());
   2368 
   2369     RootInlineBox* lastLine = layoutState.endLine();
   2370     while (RootInlineBox* nextLine = lastLine->nextRootBox())
   2371         lastLine = nextLine;
   2372 
   2373     LayoutUnit logicalBottom = lastLine->lineBottomWithLeading() + absoluteValue(lineDelta);
   2374 
   2375     const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
   2376     FloatingObjectSetIterator end = floatingObjectSet.end();
   2377     for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
   2378         FloatingObject* f = *it;
   2379         if (logicalBottomForFloat(f) >= logicalTop && logicalBottomForFloat(f) < logicalBottom)
   2380             return false;
   2381     }
   2382 
   2383     return true;
   2384 }
   2385 
   2386 bool RenderBlock::matchedEndLine(LineLayoutState& layoutState, const InlineBidiResolver& resolver, const InlineIterator& endLineStart, const BidiStatus& endLineStatus)
   2387 {
   2388     if (resolver.position() == endLineStart) {
   2389         if (resolver.status() != endLineStatus)
   2390             return false;
   2391         return checkPaginationAndFloatsAtEndLine(layoutState);
   2392     }
   2393 
   2394     // The first clean line doesn't match, but we can check a handful of following lines to try
   2395     // to match back up.
   2396     static int numLines = 8; // The # of lines we're willing to match against.
   2397     RootInlineBox* originalEndLine = layoutState.endLine();
   2398     RootInlineBox* line = originalEndLine;
   2399     for (int i = 0; i < numLines && line; i++, line = line->nextRootBox()) {
   2400         if (line->lineBreakObj() == resolver.position().m_obj && line->lineBreakPos() == resolver.position().m_pos) {
   2401             // We have a match.
   2402             if (line->lineBreakBidiStatus() != resolver.status())
   2403                 return false; // ...but the bidi state doesn't match.
   2404 
   2405             bool matched = false;
   2406             RootInlineBox* result = line->nextRootBox();
   2407             layoutState.setEndLine(result);
   2408             if (result) {
   2409                 layoutState.setEndLineLogicalTop(line->lineBottomWithLeading());
   2410                 matched = checkPaginationAndFloatsAtEndLine(layoutState);
   2411             }
   2412 
   2413             // Now delete the lines that we failed to sync.
   2414             deleteLineRange(layoutState, originalEndLine, result);
   2415             return matched;
   2416         }
   2417     }
   2418 
   2419     return false;
   2420 }
   2421 
   2422 enum WhitespacePosition { LeadingWhitespace, TrailingWhitespace };
   2423 static inline bool shouldCollapseWhiteSpace(const RenderStyle* style, const LineInfo& lineInfo, WhitespacePosition whitespacePosition)
   2424 {
   2425     // CSS2 16.6.1
   2426     // If a space (U+0020) at the beginning of a line has 'white-space' set to 'normal', 'nowrap', or 'pre-line', it is removed.
   2427     // If a space (U+0020) at the end of a line has 'white-space' set to 'normal', 'nowrap', or 'pre-line', it is also removed.
   2428     // If spaces (U+0020) or tabs (U+0009) at the end of a line have 'white-space' set to 'pre-wrap', UAs may visually collapse them.
   2429     return style->collapseWhiteSpace()
   2430         || (whitespacePosition == TrailingWhitespace && style->whiteSpace() == PRE_WRAP && (!lineInfo.isEmpty() || !lineInfo.previousLineBrokeCleanly()));
   2431 }
   2432 
   2433 static bool requiresLineBoxForContent(RenderInline* flow, const LineInfo& lineInfo)
   2434 {
   2435     RenderObject* parent = flow->parent();
   2436     if (flow->document()->inNoQuirksMode()
   2437         && (flow->style(lineInfo.isFirstLine())->lineHeight() != parent->style(lineInfo.isFirstLine())->lineHeight()
   2438         || flow->style()->verticalAlign() != parent->style()->verticalAlign()
   2439         || !parent->style()->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(flow->style()->font().fontMetrics())))
   2440         return true;
   2441     return false;
   2442 }
   2443 
   2444 static bool alwaysRequiresLineBox(RenderObject* flow)
   2445 {
   2446     // FIXME: Right now, we only allow line boxes for inlines that are truly empty.
   2447     // We need to fix this, though, because at the very least, inlines containing only
   2448     // ignorable whitespace should should also have line boxes.
   2449     return isEmptyInline(flow) && toRenderInline(flow)->hasInlineDirectionBordersPaddingOrMargin();
   2450 }
   2451 
   2452 static bool requiresLineBox(const InlineIterator& it, const LineInfo& lineInfo = LineInfo(), WhitespacePosition whitespacePosition = LeadingWhitespace)
   2453 {
   2454     if (it.m_obj->isFloatingOrOutOfFlowPositioned())
   2455         return false;
   2456 
   2457     if (it.m_obj->isRenderInline() && !alwaysRequiresLineBox(it.m_obj) && !requiresLineBoxForContent(toRenderInline(it.m_obj), lineInfo))
   2458         return false;
   2459 
   2460     if (!shouldCollapseWhiteSpace(it.m_obj->style(), lineInfo, whitespacePosition) || it.m_obj->isBR())
   2461         return true;
   2462 
   2463     UChar current = it.current();
   2464     bool notJustWhitespace = current != ' ' && current != '\t' && current != softHyphen && (current != '\n' || it.m_obj->preservesNewline());
   2465     return notJustWhitespace || isEmptyInline(it.m_obj);
   2466 }
   2467 
   2468 bool RenderBlock::generatesLineBoxesForInlineChild(RenderObject* inlineObj)
   2469 {
   2470     ASSERT(inlineObj->parent() == this);
   2471 
   2472     InlineIterator it(this, inlineObj, 0);
   2473     // FIXME: We should pass correct value for WhitespacePosition.
   2474     while (!it.atEnd() && !requiresLineBox(it))
   2475         it.increment();
   2476 
   2477     return !it.atEnd();
   2478 }
   2479 
   2480 // FIXME: The entire concept of the skipTrailingWhitespace function is flawed, since we really need to be building
   2481 // line boxes even for containers that may ultimately collapse away. Otherwise we'll never get positioned
   2482 // elements quite right. In other words, we need to build this function's work into the normal line
   2483 // object iteration process.
   2484 // NB. this function will insert any floating elements that would otherwise
   2485 // be skipped but it will not position them.
   2486 void RenderBlock::LineBreaker::skipTrailingWhitespace(InlineIterator& iterator, const LineInfo& lineInfo)
   2487 {
   2488     while (!iterator.atEnd() && !requiresLineBox(iterator, lineInfo, TrailingWhitespace)) {
   2489         RenderObject* object = iterator.m_obj;
   2490         if (object->isOutOfFlowPositioned())
   2491             setStaticPositions(m_block, toRenderBox(object));
   2492         else if (object->isFloating())
   2493             m_block->insertFloatingObject(toRenderBox(object));
   2494         iterator.increment();
   2495     }
   2496 }
   2497 
   2498 void RenderBlock::LineBreaker::skipLeadingWhitespace(InlineBidiResolver& resolver, LineInfo& lineInfo,
   2499                                                      FloatingObject* lastFloatFromPreviousLine, LineWidth& width)
   2500 {
   2501     while (!resolver.position().atEnd() && !requiresLineBox(resolver.position(), lineInfo, LeadingWhitespace)) {
   2502         RenderObject* object = resolver.position().m_obj;
   2503         if (object->isOutOfFlowPositioned()) {
   2504             setStaticPositions(m_block, toRenderBox(object));
   2505             if (object->style()->isOriginalDisplayInlineType()) {
   2506                 resolver.runs().addRun(createRun(0, 1, object, resolver));
   2507                 lineInfo.incrementRunsFromLeadingWhitespace();
   2508             }
   2509         } else if (object->isFloating()) {
   2510             // The top margin edge of a self-collapsing block that clears a float intrudes up into it by the height of the margin,
   2511             // so in order to place this first child float at the top content edge of the self-collapsing block add the margin back in before placement.
   2512             LayoutUnit marginOffset = (!object->previousSibling() && m_block->isSelfCollapsingBlock() && m_block->style()->clear() && m_block->getClearDelta(m_block, LayoutUnit())) ? m_block->collapsedMarginBeforeForChild(m_block) : LayoutUnit();
   2513             LayoutUnit oldLogicalHeight = m_block->logicalHeight();
   2514             m_block->setLogicalHeight(oldLogicalHeight + marginOffset);
   2515             m_block->positionNewFloatOnLine(m_block->insertFloatingObject(toRenderBox(object)), lastFloatFromPreviousLine, lineInfo, width);
   2516             m_block->setLogicalHeight(oldLogicalHeight);
   2517         } else if (object->isText() && object->style()->hasTextCombine() && object->isCombineText() && !toRenderCombineText(object)->isCombined()) {
   2518             toRenderCombineText(object)->combineText();
   2519             if (toRenderCombineText(object)->isCombined())
   2520                 continue;
   2521         }
   2522         resolver.increment();
   2523     }
   2524     resolver.commitExplicitEmbedding();
   2525 }
   2526 
   2527 // This is currently just used for list markers and inline flows that have line boxes. Neither should
   2528 // have an effect on whitespace at the start of the line.
   2529 static bool shouldSkipWhitespaceAfterStartObject(RenderBlock* block, RenderObject* o, LineMidpointState& lineMidpointState)
   2530 {
   2531     RenderObject* next = bidiNextSkippingEmptyInlines(block, o);
   2532     while (next && next->isFloatingOrOutOfFlowPositioned())
   2533         next = bidiNextSkippingEmptyInlines(block, next);
   2534 
   2535     if (next && !next->isBR() && next->isText() && toRenderText(next)->textLength() > 0) {
   2536         RenderText* nextText = toRenderText(next);
   2537         UChar nextChar = nextText->characterAt(0);
   2538         if (nextText->style()->isCollapsibleWhiteSpace(nextChar)) {
   2539             startIgnoringSpaces(lineMidpointState, InlineIterator(0, o, 0));
   2540             return true;
   2541         }
   2542     }
   2543 
   2544     return false;
   2545 }
   2546 
   2547 static ALWAYS_INLINE float textWidth(RenderText* text, unsigned from, unsigned len, const Font& font, float xPos, bool isFixedPitch, bool collapseWhiteSpace, HashSet<const SimpleFontData*>* fallbackFonts = 0, TextLayout* layout = 0)
   2548 {
   2549     GlyphOverflow glyphOverflow;
   2550     if (isFixedPitch || (!from && len == text->textLength()) || text->style()->hasTextCombine())
   2551         return text->width(from, len, font, xPos, fallbackFonts, &glyphOverflow);
   2552 
   2553     if (layout)
   2554         return Font::width(*layout, from, len, fallbackFonts);
   2555 
   2556     TextRun run = RenderBlock::constructTextRun(text, font, text, from, len, text->style());
   2557     run.setCharactersLength(text->textLength() - from);
   2558     ASSERT(run.charactersLength() >= run.length());
   2559 
   2560     run.setCharacterScanForCodePath(!text->canUseSimpleFontCodePath());
   2561     run.setTabSize(!collapseWhiteSpace, text->style()->tabSize());
   2562     run.setXPos(xPos);
   2563     return font.width(run, fallbackFonts, &glyphOverflow);
   2564 }
   2565 
   2566 class TrailingObjects {
   2567 public:
   2568     TrailingObjects();
   2569     void setTrailingWhitespace(RenderText*);
   2570     void clear();
   2571     void appendBoxIfNeeded(RenderBox*);
   2572 
   2573     enum CollapseFirstSpaceOrNot { DoNotCollapseFirstSpace, CollapseFirstSpace };
   2574 
   2575     void updateMidpointsForTrailingBoxes(LineMidpointState&, const InlineIterator& lBreak, CollapseFirstSpaceOrNot);
   2576 
   2577 private:
   2578     RenderText* m_whitespace;
   2579     Vector<RenderBox*, 4> m_boxes;
   2580 };
   2581 
   2582 TrailingObjects::TrailingObjects()
   2583     : m_whitespace(0)
   2584 {
   2585 }
   2586 
   2587 inline void TrailingObjects::setTrailingWhitespace(RenderText* whitespace)
   2588 {
   2589     ASSERT(whitespace);
   2590     m_whitespace = whitespace;
   2591 }
   2592 
   2593 inline void TrailingObjects::clear()
   2594 {
   2595     m_whitespace = 0;
   2596     // Using resize(0) rather than clear() here saves 2% on
   2597     // PerformanceTests/Layout/line-layout.html because we avoid freeing and
   2598     // re-allocating the underlying buffer repeatedly.
   2599     m_boxes.resize(0);
   2600 }
   2601 
   2602 inline void TrailingObjects::appendBoxIfNeeded(RenderBox* box)
   2603 {
   2604     if (m_whitespace)
   2605         m_boxes.append(box);
   2606 }
   2607 
   2608 void TrailingObjects::updateMidpointsForTrailingBoxes(LineMidpointState& lineMidpointState, const InlineIterator& lBreak, CollapseFirstSpaceOrNot collapseFirstSpace)
   2609 {
   2610     if (!m_whitespace)
   2611         return;
   2612 
   2613     // This object is either going to be part of the last midpoint, or it is going to be the actual endpoint.
   2614     // In both cases we just decrease our pos by 1 level to exclude the space, allowing it to - in effect - collapse into the newline.
   2615     if (lineMidpointState.numMidpoints % 2) {
   2616         // Find the trailing space object's midpoint.
   2617         int trailingSpaceMidpoint = lineMidpointState.numMidpoints - 1;
   2618         for ( ; trailingSpaceMidpoint > 0 && lineMidpointState.midpoints[trailingSpaceMidpoint].m_obj != m_whitespace; --trailingSpaceMidpoint) { }
   2619         ASSERT(trailingSpaceMidpoint >= 0);
   2620         if (collapseFirstSpace == CollapseFirstSpace)
   2621             lineMidpointState.midpoints[trailingSpaceMidpoint].m_pos--;
   2622 
   2623         // Now make sure every single trailingPositionedBox following the trailingSpaceMidpoint properly stops and starts
   2624         // ignoring spaces.
   2625         size_t currentMidpoint = trailingSpaceMidpoint + 1;
   2626         for (size_t i = 0; i < m_boxes.size(); ++i) {
   2627             if (currentMidpoint >= lineMidpointState.numMidpoints) {
   2628                 // We don't have a midpoint for this box yet.
   2629                 ensureLineBoxInsideIgnoredSpaces(lineMidpointState, m_boxes[i]);
   2630             } else {
   2631                 ASSERT(lineMidpointState.midpoints[currentMidpoint].m_obj == m_boxes[i]);
   2632                 ASSERT(lineMidpointState.midpoints[currentMidpoint + 1].m_obj == m_boxes[i]);
   2633             }
   2634             currentMidpoint += 2;
   2635         }
   2636     } else if (!lBreak.m_obj) {
   2637         ASSERT(m_whitespace->isText());
   2638         ASSERT(collapseFirstSpace == CollapseFirstSpace);
   2639         // Add a new end midpoint that stops right at the very end.
   2640         unsigned length = m_whitespace->textLength();
   2641         unsigned pos = length >= 2 ? length - 2 : INT_MAX;
   2642         InlineIterator endMid(0, m_whitespace, pos);
   2643         startIgnoringSpaces(lineMidpointState, endMid);
   2644         for (size_t i = 0; i < m_boxes.size(); ++i) {
   2645             ensureLineBoxInsideIgnoredSpaces(lineMidpointState, m_boxes[i]);
   2646         }
   2647     }
   2648 }
   2649 
   2650 void RenderBlock::LineBreaker::reset()
   2651 {
   2652     m_positionedObjects.clear();
   2653     m_hyphenated = false;
   2654     m_clear = CNONE;
   2655 }
   2656 
   2657 InlineIterator RenderBlock::LineBreaker::nextLineBreak(InlineBidiResolver& resolver, LineInfo& lineInfo, RenderTextInfo& renderTextInfo, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines, WordMeasurements& wordMeasurements)
   2658 {
   2659     ShapeInsideInfo* shapeInsideInfo = m_block->layoutShapeInsideInfo();
   2660 
   2661     if (!shapeInsideInfo || !shapeInsideInfo->lineOverlapsShapeBounds())
   2662         return nextSegmentBreak(resolver, lineInfo, renderTextInfo, lastFloatFromPreviousLine, consecutiveHyphenatedLines, wordMeasurements);
   2663 
   2664     InlineIterator end = resolver.position();
   2665     InlineIterator oldEnd = end;
   2666 
   2667     if (!shapeInsideInfo->hasSegments()) {
   2668         end = nextSegmentBreak(resolver, lineInfo, renderTextInfo, lastFloatFromPreviousLine, consecutiveHyphenatedLines, wordMeasurements);
   2669         resolver.setPositionIgnoringNestedIsolates(oldEnd);
   2670         return oldEnd;
   2671     }
   2672 
   2673     const SegmentList& segments = shapeInsideInfo->segments();
   2674     SegmentRangeList& segmentRanges = shapeInsideInfo->segmentRanges();
   2675 
   2676     for (unsigned i = 0; i < segments.size() && !end.atEnd(); i++) {
   2677         InlineIterator segmentStart = resolver.position();
   2678         end = nextSegmentBreak(resolver, lineInfo, renderTextInfo, lastFloatFromPreviousLine, consecutiveHyphenatedLines, wordMeasurements);
   2679 
   2680         ASSERT(segmentRanges.size() == i);
   2681         if (resolver.position().atEnd()) {
   2682             segmentRanges.append(LineSegmentRange(segmentStart, end));
   2683             break;
   2684         }
   2685         if (resolver.position() == end) {
   2686             // Nothing fit this segment
   2687             end = segmentStart;
   2688             segmentRanges.append(LineSegmentRange(segmentStart, segmentStart));
   2689             resolver.setPositionIgnoringNestedIsolates(segmentStart);
   2690         } else {
   2691             // Note that resolver.position is already skipping some of the white space at the beginning of the line,
   2692             // so that's why segmentStart might be different than resolver.position().
   2693             LineSegmentRange range(resolver.position(), end);
   2694             segmentRanges.append(range);
   2695             resolver.setPosition(end, numberOfIsolateAncestors(end));
   2696 
   2697             if (lineInfo.previousLineBrokeCleanly()) {
   2698                 // If we hit a new line break, just stop adding anything to this line.
   2699                 break;
   2700             }
   2701         }
   2702     }
   2703     resolver.setPositionIgnoringNestedIsolates(oldEnd);
   2704     return end;
   2705 }
   2706 
   2707 static inline bool iteratorIsBeyondEndOfRenderCombineText(const InlineIterator& iter, RenderCombineText* renderer)
   2708 {
   2709     return iter.m_obj == renderer && iter.m_pos >= renderer->textLength();
   2710 }
   2711 
   2712 InlineIterator RenderBlock::LineBreaker::nextSegmentBreak(InlineBidiResolver& resolver, LineInfo& lineInfo, RenderTextInfo& renderTextInfo, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines, WordMeasurements& wordMeasurements)
   2713 {
   2714     reset();
   2715 
   2716     ASSERT(resolver.position().root() == m_block);
   2717 
   2718     bool appliedStartWidth = resolver.position().m_pos > 0;
   2719     bool includeEndWidth = true;
   2720     LineMidpointState& lineMidpointState = resolver.midpointState();
   2721 
   2722     LineWidth width(m_block, lineInfo.isFirstLine(), requiresIndent(lineInfo.isFirstLine(), lineInfo.previousLineBrokeCleanly(), m_block->style()));
   2723 
   2724     skipLeadingWhitespace(resolver, lineInfo, lastFloatFromPreviousLine, width);
   2725 
   2726     if (resolver.position().atEnd())
   2727         return resolver.position();
   2728 
   2729     // This variable is used only if whitespace isn't set to PRE, and it tells us whether
   2730     // or not we are currently ignoring whitespace.
   2731     bool ignoringSpaces = false;
   2732     InlineIterator ignoreStart;
   2733 
   2734     // This variable tracks whether the very last character we saw was a space.  We use
   2735     // this to detect when we encounter a second space so we know we have to terminate
   2736     // a run.
   2737     bool currentCharacterIsSpace = false;
   2738     bool currentCharacterShouldCollapseIfPreWap = false;
   2739     TrailingObjects trailingObjects;
   2740 
   2741     InlineIterator lBreak = resolver.position();
   2742 
   2743     // FIXME: It is error-prone to split the position object out like this.
   2744     // Teach this code to work with objects instead of this split tuple.
   2745     InlineIterator current = resolver.position();
   2746     RenderObject* last = current.m_obj;
   2747     bool atStart = true;
   2748 
   2749     bool startingNewParagraph = lineInfo.previousLineBrokeCleanly();
   2750     lineInfo.setPreviousLineBrokeCleanly(false);
   2751 
   2752     bool autoWrapWasEverTrueOnLine = false;
   2753     bool floatsFitOnLine = true;
   2754 
   2755     // Firefox and Opera will allow a table cell to grow to fit an image inside it under
   2756     // very specific circumstances (in order to match common WinIE renderings).
   2757     // Not supporting the quirk has caused us to mis-render some real sites. (See Bugzilla 10517.)
   2758     RenderStyle* blockStyle = m_block->style();
   2759     bool allowImagesToBreak = !m_block->document()->inQuirksMode() || !m_block->isTableCell() || !blockStyle->logicalWidth().isIntrinsicOrAuto();
   2760 
   2761     EWhiteSpace currWS = blockStyle->whiteSpace();
   2762     EWhiteSpace lastWS = currWS;
   2763     while (current.m_obj) {
   2764         RenderStyle* currentStyle = current.m_obj->style();
   2765         RenderObject* next = bidiNextSkippingEmptyInlines(m_block, current.m_obj);
   2766         if (next && next->parent() && !next->parent()->isDescendantOf(current.m_obj->parent()))
   2767             includeEndWidth = true;
   2768 
   2769         currWS = current.m_obj->isReplaced() ? current.m_obj->parent()->style()->whiteSpace() : currentStyle->whiteSpace();
   2770         lastWS = last->isReplaced() ? last->parent()->style()->whiteSpace() : last->style()->whiteSpace();
   2771 
   2772         bool autoWrap = RenderStyle::autoWrap(currWS);
   2773         autoWrapWasEverTrueOnLine = autoWrapWasEverTrueOnLine || autoWrap;
   2774 
   2775         bool preserveNewline = current.m_obj->isSVGInlineText() ? false : RenderStyle::preserveNewline(currWS);
   2776 
   2777         bool collapseWhiteSpace = RenderStyle::collapseWhiteSpace(currWS);
   2778 
   2779         if (current.m_obj->isBR()) {
   2780             if (width.fitsOnLine()) {
   2781                 lBreak.moveToStartOf(current.m_obj);
   2782                 lBreak.increment();
   2783 
   2784                 // A <br> always breaks a line, so don't let the line be collapsed
   2785                 // away. Also, the space at the end of a line with a <br> does not
   2786                 // get collapsed away.  It only does this if the previous line broke
   2787                 // cleanly.  Otherwise the <br> has no effect on whether the line is
   2788                 // empty or not.
   2789                 if (startingNewParagraph)
   2790                     lineInfo.setEmpty(false, m_block, &width);
   2791                 trailingObjects.clear();
   2792                 lineInfo.setPreviousLineBrokeCleanly(true);
   2793 
   2794                 // A <br> with clearance always needs a linebox in case the lines below it get dirtied later and
   2795                 // need to check for floats to clear - so if we're ignoring spaces, stop ignoring them and add a
   2796                 // run for this object.
   2797                 if (ignoringSpaces && currentStyle->clear() != CNONE)
   2798                     ensureLineBoxInsideIgnoredSpaces(lineMidpointState, current.m_obj);
   2799 
   2800                 if (!lineInfo.isEmpty())
   2801                     m_clear = currentStyle->clear();
   2802             }
   2803             goto end;
   2804         }
   2805 
   2806         if (current.m_obj->isOutOfFlowPositioned()) {
   2807             // If our original display wasn't an inline type, then we can
   2808             // go ahead and determine our static inline position now.
   2809             RenderBox* box = toRenderBox(current.m_obj);
   2810             bool isInlineType = box->style()->isOriginalDisplayInlineType();
   2811             if (!isInlineType)
   2812                 m_block->setStaticInlinePositionForChild(box, m_block->logicalHeight(), m_block->startOffsetForContent(m_block->logicalHeight()));
   2813             else  {
   2814                 // If our original display was an INLINE type, then we can go ahead
   2815                 // and determine our static y position now.
   2816                 box->layer()->setStaticBlockPosition(m_block->logicalHeight());
   2817             }
   2818 
   2819             // If we're ignoring spaces, we have to stop and include this object and
   2820             // then start ignoring spaces again.
   2821             if (isInlineType || current.m_obj->container()->isRenderInline()) {
   2822                 if (ignoringSpaces)
   2823                     ensureLineBoxInsideIgnoredSpaces(lineMidpointState, current.m_obj);
   2824                 trailingObjects.appendBoxIfNeeded(box);
   2825             } else
   2826                 m_positionedObjects.append(box);
   2827             width.addUncommittedWidth(inlineLogicalWidth(current.m_obj));
   2828             // Reset prior line break context characters.
   2829             renderTextInfo.m_lineBreakIterator.resetPriorContext();
   2830         } else if (current.m_obj->isFloating()) {
   2831             RenderBox* floatBox = toRenderBox(current.m_obj);
   2832             FloatingObject* f = m_block->insertFloatingObject(floatBox);
   2833             // check if it fits in the current line.
   2834             // If it does, position it now, otherwise, position
   2835             // it after moving to next line (in newLine() func)
   2836             // FIXME: Bug 110372: Properly position multiple stacked floats with non-rectangular shape outside.
   2837             if (floatsFitOnLine && width.fitsOnLine(m_block->logicalWidthForFloat(f))) {
   2838                 m_block->positionNewFloatOnLine(f, lastFloatFromPreviousLine, lineInfo, width);
   2839                 if (lBreak.m_obj == current.m_obj) {
   2840                     ASSERT(!lBreak.m_pos);
   2841                     lBreak.increment();
   2842                 }
   2843             } else
   2844                 floatsFitOnLine = false;
   2845             // Update prior line break context characters, using U+FFFD (OBJECT REPLACEMENT CHARACTER) for floating element.
   2846             renderTextInfo.m_lineBreakIterator.updatePriorContext(replacementCharacter);
   2847         } else if (current.m_obj->isRenderInline()) {
   2848             // Right now, we should only encounter empty inlines here.
   2849             ASSERT(isEmptyInline(current.m_obj));
   2850 
   2851             RenderInline* flowBox = toRenderInline(current.m_obj);
   2852 
   2853             // Now that some inline flows have line boxes, if we are already ignoring spaces, we need
   2854             // to make sure that we stop to include this object and then start ignoring spaces again.
   2855             // If this object is at the start of the line, we need to behave like list markers and
   2856             // start ignoring spaces.
   2857             bool requiresLineBox = alwaysRequiresLineBox(current.m_obj);
   2858             if (requiresLineBox || requiresLineBoxForContent(flowBox, lineInfo)) {
   2859                 // An empty inline that only has line-height, vertical-align or font-metrics will only get a
   2860                 // line box to affect the height of the line if the rest of the line is not empty.
   2861                 if (requiresLineBox)
   2862                     lineInfo.setEmpty(false, m_block, &width);
   2863                 if (ignoringSpaces) {
   2864                     trailingObjects.clear();
   2865                     ensureLineBoxInsideIgnoredSpaces(lineMidpointState, current.m_obj);
   2866                 } else if (blockStyle->collapseWhiteSpace() && resolver.position().m_obj == current.m_obj
   2867                     && shouldSkipWhitespaceAfterStartObject(m_block, current.m_obj, lineMidpointState)) {
   2868                     // Like with list markers, we start ignoring spaces to make sure that any
   2869                     // additional spaces we see will be discarded.
   2870                     currentCharacterShouldCollapseIfPreWap = currentCharacterIsSpace = true;
   2871                     ignoringSpaces = true;
   2872                 }
   2873             }
   2874 
   2875             width.addUncommittedWidth(inlineLogicalWidth(current.m_obj) + borderPaddingMarginStart(flowBox) + borderPaddingMarginEnd(flowBox));
   2876         } else if (current.m_obj->isReplaced()) {
   2877             RenderBox* replacedBox = toRenderBox(current.m_obj);
   2878 
   2879             if (atStart)
   2880                 width.updateAvailableWidth(replacedBox->logicalHeight());
   2881 
   2882             // Break on replaced elements if either has normal white-space.
   2883             if ((autoWrap || RenderStyle::autoWrap(lastWS)) && (!current.m_obj->isImage() || allowImagesToBreak)) {
   2884                 width.commit();
   2885                 lBreak.moveToStartOf(current.m_obj);
   2886             }
   2887 
   2888             if (ignoringSpaces)
   2889                 stopIgnoringSpaces(lineMidpointState, InlineIterator(0, current.m_obj, 0));
   2890 
   2891             lineInfo.setEmpty(false, m_block, &width);
   2892             ignoringSpaces = false;
   2893             currentCharacterShouldCollapseIfPreWap = currentCharacterIsSpace = false;
   2894             trailingObjects.clear();
   2895 
   2896             // Optimize for a common case. If we can't find whitespace after the list
   2897             // item, then this is all moot.
   2898             LayoutUnit replacedLogicalWidth = m_block->logicalWidthForChild(replacedBox) + m_block->marginStartForChild(replacedBox) + m_block->marginEndForChild(replacedBox) + inlineLogicalWidth(current.m_obj);
   2899             if (current.m_obj->isListMarker()) {
   2900                 if (blockStyle->collapseWhiteSpace() && shouldSkipWhitespaceAfterStartObject(m_block, current.m_obj, lineMidpointState)) {
   2901                     // Like with inline flows, we start ignoring spaces to make sure that any
   2902                     // additional spaces we see will be discarded.
   2903                     currentCharacterShouldCollapseIfPreWap = currentCharacterIsSpace = true;
   2904                     ignoringSpaces = true;
   2905                 }
   2906                 if (toRenderListMarker(current.m_obj)->isInside())
   2907                     width.addUncommittedWidth(replacedLogicalWidth);
   2908             } else
   2909                 width.addUncommittedWidth(replacedLogicalWidth);
   2910             if (current.m_obj->isRubyRun())
   2911                 width.applyOverhang(toRenderRubyRun(current.m_obj), last, next);
   2912             // Update prior line break context characters, using U+FFFD (OBJECT REPLACEMENT CHARACTER) for replaced element.
   2913             renderTextInfo.m_lineBreakIterator.updatePriorContext(replacementCharacter);
   2914         } else if (current.m_obj->isText()) {
   2915             if (!current.m_pos)
   2916                 appliedStartWidth = false;
   2917 
   2918             RenderText* t = toRenderText(current.m_obj);
   2919 
   2920             bool isSVGText = t->isSVGInlineText();
   2921 
   2922             if (t->style()->hasTextCombine() && current.m_obj->isCombineText() && !toRenderCombineText(current.m_obj)->isCombined()) {
   2923                 RenderCombineText* combineRenderer = toRenderCombineText(current.m_obj);
   2924                 combineRenderer->combineText();
   2925                 // The length of the renderer's text may have changed. Increment stale iterator positions
   2926                 if (iteratorIsBeyondEndOfRenderCombineText(lBreak, combineRenderer)) {
   2927                     ASSERT(iteratorIsBeyondEndOfRenderCombineText(resolver.position(), combineRenderer));
   2928                     lBreak.increment();
   2929                     resolver.increment();
   2930                 }
   2931             }
   2932 
   2933             RenderStyle* style = t->style(lineInfo.isFirstLine());
   2934             const Font& f = style->font();
   2935             bool isFixedPitch = f.isFixedPitch();
   2936 
   2937             unsigned lastSpace = current.m_pos;
   2938             float wordSpacing = currentStyle->wordSpacing();
   2939             float lastSpaceWordSpacing = 0;
   2940             float wordSpacingForWordMeasurement = 0;
   2941 
   2942             float wrapW = width.uncommittedWidth() + inlineLogicalWidth(current.m_obj, !appliedStartWidth, true);
   2943             float charWidth = 0;
   2944             // Auto-wrapping text should wrap in the middle of a word only if it could not wrap before the word,
   2945             // which is only possible if the word is the first thing on the line, that is, if |w| is zero.
   2946             bool breakWords = currentStyle->breakWords() && ((autoWrap && !width.committedWidth()) || currWS == PRE);
   2947             bool midWordBreak = false;
   2948             bool breakAll = currentStyle->wordBreak() == BreakAllWordBreak && autoWrap;
   2949             float hyphenWidth = 0;
   2950 
   2951             if (isSVGText) {
   2952                 breakWords = false;
   2953                 breakAll = false;
   2954             }
   2955 
   2956             if (t->isWordBreak()) {
   2957                 width.commit();
   2958                 lBreak.moveToStartOf(current.m_obj);
   2959                 ASSERT(current.m_pos == t->textLength());
   2960             }
   2961 
   2962             if (renderTextInfo.m_text != t) {
   2963                 updateCounterIfNeeded(t);
   2964                 renderTextInfo.m_text = t;
   2965                 renderTextInfo.m_font = &f;
   2966                 renderTextInfo.m_layout = f.createLayout(t, width.currentWidth(), collapseWhiteSpace);
   2967                 renderTextInfo.m_lineBreakIterator.resetStringAndReleaseIterator(t->text(), style->locale());
   2968             } else if (renderTextInfo.m_layout && renderTextInfo.m_font != &f) {
   2969                 renderTextInfo.m_font = &f;
   2970                 renderTextInfo.m_layout = f.createLayout(t, width.currentWidth(), collapseWhiteSpace);
   2971             }
   2972 
   2973             TextLayout* textLayout = renderTextInfo.m_layout.get();
   2974 
   2975             // Non-zero only when kerning is enabled and TextLayout isn't used, in which case we measure
   2976             // words with their trailing space, then subtract its width.
   2977             float wordTrailingSpaceWidth = (f.typesettingFeatures() & Kerning) && !textLayout ? f.width(constructTextRun(t, f, &space, 1, style)) + wordSpacing : 0;
   2978 
   2979             UChar lastCharacter = renderTextInfo.m_lineBreakIterator.lastCharacter();
   2980             UChar secondToLastCharacter = renderTextInfo.m_lineBreakIterator.secondToLastCharacter();
   2981             for (; current.m_pos < t->textLength(); current.fastIncrementInTextNode()) {
   2982                 bool previousCharacterIsSpace = currentCharacterIsSpace;
   2983                 bool previousCharacterShouldCollapseIfPreWap = currentCharacterShouldCollapseIfPreWap;
   2984                 UChar c = current.current();
   2985                 currentCharacterShouldCollapseIfPreWap = currentCharacterIsSpace = c == ' ' || c == '\t' || (!preserveNewline && (c == '\n'));
   2986 
   2987                 if (!collapseWhiteSpace || !currentCharacterIsSpace)
   2988                     lineInfo.setEmpty(false, m_block, &width);
   2989 
   2990                 if (c == softHyphen && autoWrap && !hyphenWidth) {
   2991                     hyphenWidth = measureHyphenWidth(t, f);
   2992                     width.addUncommittedWidth(hyphenWidth);
   2993                 }
   2994 
   2995                 bool applyWordSpacing = false;
   2996 
   2997                 if ((breakAll || breakWords) && !midWordBreak) {
   2998                     wrapW += charWidth;
   2999                     bool midWordBreakIsBeforeSurrogatePair = U16_IS_LEAD(c) && current.m_pos + 1 < t->textLength() && U16_IS_TRAIL((*t)[current.m_pos + 1]);
   3000                     charWidth = textWidth(t, current.m_pos, midWordBreakIsBeforeSurrogatePair ? 2 : 1, f, width.committedWidth() + wrapW, isFixedPitch, collapseWhiteSpace, 0, textLayout);
   3001                     midWordBreak = width.committedWidth() + wrapW + charWidth > width.availableWidth();
   3002                 }
   3003 
   3004                 bool betweenWords = c == '\n' || (currWS != PRE && !atStart && isBreakable(renderTextInfo.m_lineBreakIterator, current.m_pos, current.m_nextBreakablePosition));
   3005 
   3006                 if (betweenWords || midWordBreak) {
   3007                     bool stoppedIgnoringSpaces = false;
   3008                     if (ignoringSpaces) {
   3009                         lastSpaceWordSpacing = 0;
   3010                         if (!currentCharacterIsSpace) {
   3011                             // Stop ignoring spaces and begin at this
   3012                             // new point.
   3013                             ignoringSpaces = false;
   3014                             wordSpacingForWordMeasurement = 0;
   3015                             lastSpace = current.m_pos; // e.g., "Foo    goo", don't add in any of the ignored spaces.
   3016                             stopIgnoringSpaces(lineMidpointState, InlineIterator(0, current.m_obj, current.m_pos));
   3017                             stoppedIgnoringSpaces = true;
   3018                         } else {
   3019                             // Just keep ignoring these spaces.
   3020                             goto nextCharacter;
   3021                         }
   3022                     }
   3023 
   3024                     wordMeasurements.grow(wordMeasurements.size() + 1);
   3025                     WordMeasurement& wordMeasurement = wordMeasurements.last();
   3026 
   3027                     wordMeasurement.renderer = t;
   3028                     wordMeasurement.endOffset = current.m_pos;
   3029                     wordMeasurement.startOffset = lastSpace;
   3030 
   3031                     float additionalTmpW;
   3032                     if (wordTrailingSpaceWidth && c == ' ')
   3033                         additionalTmpW = textWidth(t, lastSpace, current.m_pos + 1 - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace, &wordMeasurement.fallbackFonts, textLayout) - wordTrailingSpaceWidth;
   3034                     else
   3035                         additionalTmpW = textWidth(t, lastSpace, current.m_pos - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace, &wordMeasurement.fallbackFonts, textLayout);
   3036 
   3037                     wordMeasurement.width = additionalTmpW + wordSpacingForWordMeasurement;
   3038                     additionalTmpW += lastSpaceWordSpacing;
   3039                     width.addUncommittedWidth(additionalTmpW);
   3040                     if (!appliedStartWidth) {
   3041                         width.addUncommittedWidth(inlineLogicalWidth(current.m_obj, true, false));
   3042                         appliedStartWidth = true;
   3043                     }
   3044 
   3045                     applyWordSpacing = wordSpacing && currentCharacterIsSpace;
   3046 
   3047                     if (!width.committedWidth() && autoWrap && !width.fitsOnLine())
   3048                         width.fitBelowFloats();
   3049 
   3050                     if (autoWrap || breakWords) {
   3051                         // If we break only after white-space, consider the current character
   3052                         // as candidate width for this line.
   3053                         bool lineWasTooWide = false;
   3054                         if (width.fitsOnLine() && currentCharacterIsSpace && currentStyle->breakOnlyAfterWhiteSpace() && !midWordBreak) {
   3055                             float charWidth = textWidth(t, current.m_pos, 1, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace, &wordMeasurement.fallbackFonts, textLayout) + (applyWordSpacing ? wordSpacing : 0);
   3056                             // Check if line is too big even without the extra space
   3057                             // at the end of the line. If it is not, do nothing.
   3058                             // If the line needs the extra whitespace to be too long,
   3059                             // then move the line break to the space and skip all
   3060                             // additional whitespace.
   3061                             if (!width.fitsOnLine(charWidth)) {
   3062                                 lineWasTooWide = true;
   3063                                 lBreak.moveTo(current.m_obj, current.m_pos, current.m_nextBreakablePosition);
   3064                                 skipTrailingWhitespace(lBreak, lineInfo);
   3065                             }
   3066                         }
   3067                         if (lineWasTooWide || !width.fitsOnLine()) {
   3068                             if (lBreak.atTextParagraphSeparator()) {
   3069                                 if (!stoppedIgnoringSpaces && current.m_pos > 0)
   3070                                     ensureCharacterGetsLineBox(lineMidpointState, current);
   3071                                 lBreak.increment();
   3072                                 lineInfo.setPreviousLineBrokeCleanly(true);
   3073                                 wordMeasurement.endOffset = lBreak.m_pos;
   3074                             }
   3075                             if (lBreak.m_obj && lBreak.m_pos && lBreak.m_obj->isText() && toRenderText(lBreak.m_obj)->textLength() && toRenderText(lBreak.m_obj)->characterAt(lBreak.m_pos - 1) == softHyphen)
   3076                                 m_hyphenated = true;
   3077                             if (lBreak.m_pos && lBreak.m_pos != (unsigned)wordMeasurement.endOffset && !wordMeasurement.width) {
   3078                                 if (charWidth) {
   3079                                     wordMeasurement.endOffset = lBreak.m_pos;
   3080                                     wordMeasurement.width = charWidth;
   3081                                 }
   3082                             }
   3083                             // Didn't fit. Jump to the end unless there's still an opportunity to collapse whitespace.
   3084                             if (ignoringSpaces || !collapseWhiteSpace || !currentCharacterIsSpace || !previousCharacterIsSpace)
   3085                                 goto end;
   3086                         } else {
   3087                             if (!betweenWords || (midWordBreak && !autoWrap))
   3088                                 width.addUncommittedWidth(-additionalTmpW);
   3089                             if (hyphenWidth) {
   3090                                 // Subtract the width of the soft hyphen out since we fit on a line.
   3091                                 width.addUncommittedWidth(-hyphenWidth);
   3092                                 hyphenWidth = 0;
   3093                             }
   3094                         }
   3095                     }
   3096 
   3097                     if (c == '\n' && preserveNewline) {
   3098                         if (!stoppedIgnoringSpaces && current.m_pos > 0)
   3099                             ensureCharacterGetsLineBox(lineMidpointState, current);
   3100                         lBreak.moveTo(current.m_obj, current.m_pos, current.m_nextBreakablePosition);
   3101                         lBreak.increment();
   3102                         lineInfo.setPreviousLineBrokeCleanly(true);
   3103                         return lBreak;
   3104                     }
   3105 
   3106                     if (autoWrap && betweenWords) {
   3107                         width.commit();
   3108                         wrapW = 0;
   3109                         lBreak.moveTo(current.m_obj, current.m_pos, current.m_nextBreakablePosition);
   3110                         // Auto-wrapping text should not wrap in the middle of a word once it has had an
   3111                         // opportunity to break after a word.
   3112                         breakWords = false;
   3113                     }
   3114 
   3115                     if (midWordBreak && !U16_IS_TRAIL(c) && !(category(c) & (Mark_NonSpacing | Mark_Enclosing | Mark_SpacingCombining))) {
   3116                         // Remember this as a breakable position in case
   3117                         // adding the end width forces a break.
   3118                         lBreak.moveTo(current.m_obj, current.m_pos, current.m_nextBreakablePosition);
   3119                         midWordBreak &= (breakWords || breakAll);
   3120                     }
   3121 
   3122                     if (betweenWords) {
   3123                         lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0;
   3124                         wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasurement.width) ? wordSpacing : 0;
   3125                         lastSpace = current.m_pos;
   3126                     }
   3127 
   3128                     if (!ignoringSpaces && currentStyle->collapseWhiteSpace()) {
   3129                         // If we encounter a newline, or if we encounter a
   3130                         // second space, we need to go ahead and break up this
   3131                         // run and enter a mode where we start collapsing spaces.
   3132                         if (currentCharacterIsSpace && previousCharacterIsSpace) {
   3133                             ignoringSpaces = true;
   3134 
   3135                             // We just entered a mode where we are ignoring
   3136                             // spaces. Create a midpoint to terminate the run
   3137                             // before the second space.
   3138                             startIgnoringSpaces(lineMidpointState, ignoreStart);
   3139                             trailingObjects.updateMidpointsForTrailingBoxes(lineMidpointState, InlineIterator(), TrailingObjects::DoNotCollapseFirstSpace);
   3140                         }
   3141                     }
   3142                 } else if (ignoringSpaces) {
   3143                     // Stop ignoring spaces and begin at this
   3144                     // new point.
   3145                     ignoringSpaces = false;
   3146                     lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0;
   3147                     wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasurements.last().width) ? wordSpacing : 0;
   3148                     lastSpace = current.m_pos; // e.g., "Foo    goo", don't add in any of the ignored spaces.
   3149                     stopIgnoringSpaces(lineMidpointState, InlineIterator(0, current.m_obj, current.m_pos));
   3150                 }
   3151 
   3152                 if (isSVGText && current.m_pos > 0) {
   3153                     // Force creation of new InlineBoxes for each absolute positioned character (those that start new text chunks).
   3154                     if (toRenderSVGInlineText(t)->characterStartsNewTextChunk(current.m_pos))
   3155                         ensureCharacterGetsLineBox(lineMidpointState, current);
   3156                 }
   3157 
   3158                 if (currentCharacterIsSpace && !previousCharacterIsSpace) {
   3159                     ignoreStart.m_obj = current.m_obj;
   3160                     ignoreStart.m_pos = current.m_pos;
   3161                 }
   3162 
   3163                 if (!currentCharacterIsSpace && previousCharacterShouldCollapseIfPreWap) {
   3164                     if (autoWrap && currentStyle->breakOnlyAfterWhiteSpace())
   3165                         lBreak.moveTo(current.m_obj, current.m_pos, current.m_nextBreakablePosition);
   3166                 }
   3167 
   3168                 if (collapseWhiteSpace && currentCharacterIsSpace && !ignoringSpaces)
   3169                     trailingObjects.setTrailingWhitespace(toRenderText(current.m_obj));
   3170                 else if (!currentStyle->collapseWhiteSpace() || !currentCharacterIsSpace)
   3171                     trailingObjects.clear();
   3172 
   3173                 atStart = false;
   3174             nextCharacter:
   3175                 secondToLastCharacter = lastCharacter;
   3176                 lastCharacter = c;
   3177             }
   3178 
   3179             renderTextInfo.m_lineBreakIterator.setPriorContext(lastCharacter, secondToLastCharacter);
   3180 
   3181             wordMeasurements.grow(wordMeasurements.size() + 1);
   3182             WordMeasurement& wordMeasurement = wordMeasurements.last();
   3183             wordMeasurement.renderer = t;
   3184 
   3185             // IMPORTANT: current.m_pos is > length here!
   3186             float additionalTmpW = ignoringSpaces ? 0 : textWidth(t, lastSpace, current.m_pos - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace, &wordMeasurement.fallbackFonts, textLayout);
   3187             wordMeasurement.startOffset = lastSpace;
   3188             wordMeasurement.endOffset = current.m_pos;
   3189             wordMeasurement.width = ignoringSpaces ? 0 : additionalTmpW + wordSpacingForWordMeasurement;
   3190             additionalTmpW += lastSpaceWordSpacing;
   3191             width.addUncommittedWidth(additionalTmpW + inlineLogicalWidth(current.m_obj, !appliedStartWidth, includeEndWidth));
   3192             includeEndWidth = false;
   3193 
   3194             if (!width.fitsOnLine()) {
   3195                 if (!m_hyphenated && lBreak.previousInSameNode() == softHyphen)
   3196                     m_hyphenated = true;
   3197 
   3198                 if (m_hyphenated)
   3199                     goto end;
   3200             }
   3201         } else
   3202             ASSERT_NOT_REACHED();
   3203 
   3204         bool checkForBreak = autoWrap;
   3205         if (width.committedWidth() && !width.fitsOnLine() && lBreak.m_obj && currWS == NOWRAP)
   3206             checkForBreak = true;
   3207         else if (next && current.m_obj->isText() && next->isText() && !next->isBR() && (autoWrap || next->style()->autoWrap())) {
   3208             if (autoWrap && currentCharacterIsSpace)
   3209                 checkForBreak = true;
   3210             else {
   3211                 RenderText* nextText = toRenderText(next);
   3212                 if (nextText->textLength()) {
   3213                     UChar c = nextText->characterAt(0);
   3214                     // If the next item on the line is text, and if we did not end with
   3215                     // a space, then the next text run continues our word (and so it needs to
   3216                     // keep adding to the uncommitted width. Just update and continue.
   3217                     checkForBreak = !currentCharacterIsSpace && (c == ' ' || c == '\t' || (c == '\n' && !next->preservesNewline()));
   3218                 } else if (nextText->isWordBreak())
   3219                     checkForBreak = true;
   3220 
   3221                 if (!width.fitsOnLine() && !width.committedWidth())
   3222                     width.fitBelowFloats();
   3223 
   3224                 bool canPlaceOnLine = width.fitsOnLine() || !autoWrapWasEverTrueOnLine;
   3225                 if (canPlaceOnLine && checkForBreak) {
   3226                     width.commit();
   3227                     lBreak.moveToStartOf(next);
   3228                 }
   3229             }
   3230         }
   3231 
   3232         if (checkForBreak && !width.fitsOnLine()) {
   3233             // if we have floats, try to get below them.
   3234             if (currentCharacterIsSpace && !ignoringSpaces && currentStyle->collapseWhiteSpace())
   3235                 trailingObjects.clear();
   3236 
   3237             if (width.committedWidth())
   3238                 goto end;
   3239 
   3240             width.fitBelowFloats();
   3241 
   3242             // |width| may have been adjusted because we got shoved down past a float (thus
   3243             // giving us more room), so we need to retest, and only jump to
   3244             // the end label if we still don't fit on the line. -dwh
   3245             if (!width.fitsOnLine())
   3246                 goto end;
   3247         } else if (blockStyle->autoWrap() && !width.fitsOnLine() && !width.committedWidth()) {
   3248             // If the container autowraps but the current child does not then we still need to ensure that it
   3249             // wraps and moves below any floats.
   3250             width.fitBelowFloats();
   3251         }
   3252 
   3253         if (!current.m_obj->isFloatingOrOutOfFlowPositioned()) {
   3254             last = current.m_obj;
   3255             if (last->isReplaced() && autoWrap && (!last->isImage() || allowImagesToBreak) && (!last->isListMarker() || toRenderListMarker(last)->isInside())) {
   3256                 width.commit();
   3257                 lBreak.moveToStartOf(next);
   3258             }
   3259         }
   3260 
   3261         // Clear out our character space bool, since inline <pre>s don't collapse whitespace
   3262         // with adjacent inline normal/nowrap spans.
   3263         if (!collapseWhiteSpace)
   3264             currentCharacterIsSpace = false;
   3265 
   3266         current.moveToStartOf(next);
   3267         atStart = false;
   3268     }
   3269 
   3270     if (width.fitsOnLine() || lastWS == NOWRAP)
   3271         lBreak.clear();
   3272 
   3273  end:
   3274     ShapeInsideInfo* shapeInfo = m_block->layoutShapeInsideInfo();
   3275     bool segmentAllowsOverflow = !shapeInfo || !shapeInfo->hasSegments();
   3276 
   3277     if (lBreak == resolver.position() && (!lBreak.m_obj || !lBreak.m_obj->isBR()) && segmentAllowsOverflow) {
   3278         // we just add as much as possible
   3279         if (blockStyle->whiteSpace() == PRE && !current.m_pos) {
   3280             lBreak.moveTo(last, last->isText() ? last->length() : 0);
   3281         } else if (lBreak.m_obj) {
   3282             // Don't ever break in the middle of a word if we can help it.
   3283             // There's no room at all. We just have to be on this line,
   3284             // even though we'll spill out.
   3285             lBreak.moveTo(current.m_obj, current.m_pos);
   3286         }
   3287     }
   3288 
   3289     // FIXME Bug 100049: We do not need to consume input in a multi-segment line
   3290     // unless no segment will.
   3291     // make sure we consume at least one char/object.
   3292     if (lBreak == resolver.position() && segmentAllowsOverflow)
   3293         lBreak.increment();
   3294 
   3295     // Sanity check our midpoints.
   3296     checkMidpoints(lineMidpointState, lBreak);
   3297 
   3298     trailingObjects.updateMidpointsForTrailingBoxes(lineMidpointState, lBreak, TrailingObjects::CollapseFirstSpace);
   3299 
   3300     // We might have made lBreak an iterator that points past the end
   3301     // of the object. Do this adjustment to make it point to the start
   3302     // of the next object instead to avoid confusing the rest of the
   3303     // code.
   3304     if (lBreak.m_pos > 0) {
   3305         lBreak.m_pos--;
   3306         lBreak.increment();
   3307     }
   3308 
   3309     return lBreak;
   3310 }
   3311 
   3312 void RenderBlock::addOverflowFromInlineChildren()
   3313 {
   3314     LayoutUnit endPadding = hasOverflowClip() ? paddingEnd() : LayoutUnit();
   3315     // FIXME: Need to find another way to do this, since scrollbars could show when we don't want them to.
   3316     if (hasOverflowClip() && !endPadding && node() && node()->isRootEditableElement() && style()->isLeftToRightDirection())
   3317         endPadding = 1;
   3318     for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
   3319         addLayoutOverflow(curr->paddedLayoutOverflowRect(endPadding));
   3320         LayoutRect visualOverflow = curr->visualOverflowRect(curr->lineTop(), curr->lineBottom());
   3321         addContentsVisualOverflow(visualOverflow);
   3322     }
   3323 }
   3324 
   3325 void RenderBlock::deleteEllipsisLineBoxes()
   3326 {
   3327     ETextAlign textAlign = style()->textAlign();
   3328     bool ltr = style()->isLeftToRightDirection();
   3329     bool firstLine = true;
   3330     for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
   3331         if (curr->hasEllipsisBox()) {
   3332             curr->clearTruncation();
   3333 
   3334             // Shift the line back where it belongs if we cannot accomodate an ellipsis.
   3335             float logicalLeft = pixelSnappedLogicalLeftOffsetForLine(curr->lineTop(), firstLine);
   3336             float availableLogicalWidth = logicalRightOffsetForLine(curr->lineTop(), false) - logicalLeft;
   3337             float totalLogicalWidth = curr->logicalWidth();
   3338             updateLogicalWidthForAlignment(textAlign, 0, logicalLeft, totalLogicalWidth, availableLogicalWidth, 0);
   3339 
   3340             if (ltr)
   3341                 curr->adjustLogicalPosition((logicalLeft - curr->logicalLeft()), 0);
   3342             else
   3343                 curr->adjustLogicalPosition(-(curr->logicalLeft() - logicalLeft), 0);
   3344         }
   3345         firstLine = false;
   3346     }
   3347 }
   3348 
   3349 void RenderBlock::checkLinesForTextOverflow()
   3350 {
   3351     // Determine the width of the ellipsis using the current font.
   3352     // FIXME: CSS3 says this is configurable, also need to use 0x002E (FULL STOP) if horizontal ellipsis is "not renderable"
   3353     const Font& font = style()->font();
   3354     DEFINE_STATIC_LOCAL(AtomicString, ellipsisStr, (&horizontalEllipsis, 1));
   3355     const Font& firstLineFont = firstLineStyle()->font();
   3356     int firstLineEllipsisWidth = firstLineFont.width(constructTextRun(this, firstLineFont, &horizontalEllipsis, 1, firstLineStyle()));
   3357     int ellipsisWidth = (font == firstLineFont) ? firstLineEllipsisWidth : font.width(constructTextRun(this, font, &horizontalEllipsis, 1, style()));
   3358 
   3359     // For LTR text truncation, we want to get the right edge of our padding box, and then we want to see
   3360     // if the right edge of a line box exceeds that.  For RTL, we use the left edge of the padding box and
   3361     // check the left edge of the line box to see if it is less
   3362     // Include the scrollbar for overflow blocks, which means we want to use "contentWidth()"
   3363     bool ltr = style()->isLeftToRightDirection();
   3364     ETextAlign textAlign = style()->textAlign();
   3365     bool firstLine = true;
   3366     for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
   3367         // FIXME: Use pixelSnappedLogicalRightOffsetForLine instead of snapping it ourselves once the column workaround in said method has been fixed.
   3368         // https://bugs.webkit.org/show_bug.cgi?id=105461
   3369         int blockRightEdge = snapSizeToPixel(logicalRightOffsetForLine(curr->lineTop(), firstLine), curr->x());
   3370         int blockLeftEdge = pixelSnappedLogicalLeftOffsetForLine(curr->lineTop(), firstLine);
   3371         int lineBoxEdge = ltr ? snapSizeToPixel(curr->x() + curr->logicalWidth(), curr->x()) : snapSizeToPixel(curr->x(), 0);
   3372         if ((ltr && lineBoxEdge > blockRightEdge) || (!ltr && lineBoxEdge < blockLeftEdge)) {
   3373             // This line spills out of our box in the appropriate direction.  Now we need to see if the line
   3374             // can be truncated.  In order for truncation to be possible, the line must have sufficient space to
   3375             // accommodate our truncation string, and no replaced elements (images, tables) can overlap the ellipsis
   3376             // space.
   3377 
   3378             LayoutUnit width = firstLine ? firstLineEllipsisWidth : ellipsisWidth;
   3379             LayoutUnit blockEdge = ltr ? blockRightEdge : blockLeftEdge;
   3380             if (curr->lineCanAccommodateEllipsis(ltr, blockEdge, lineBoxEdge, width)) {
   3381                 float totalLogicalWidth = curr->placeEllipsis(ellipsisStr, ltr, blockLeftEdge, blockRightEdge, width);
   3382 
   3383                 float logicalLeft = 0; // We are only intersted in the delta from the base position.
   3384                 float truncatedWidth = pixelSnappedLogicalRightOffsetForLine(curr->lineTop(), firstLine);
   3385                 updateLogicalWidthForAlignment(textAlign, 0, logicalLeft, totalLogicalWidth, truncatedWidth, 0);
   3386                 if (ltr)
   3387                     curr->adjustLogicalPosition(logicalLeft, 0);
   3388                 else
   3389                     curr->adjustLogicalPosition(-(truncatedWidth - (logicalLeft + totalLogicalWidth)), 0);
   3390             }
   3391         }
   3392         firstLine = false;
   3393     }
   3394 }
   3395 
   3396 bool RenderBlock::positionNewFloatOnLine(FloatingObject* newFloat, FloatingObject* lastFloatFromPreviousLine, LineInfo& lineInfo, LineWidth& width)
   3397 {
   3398     if (!positionNewFloats())
   3399         return false;
   3400 
   3401     width.shrinkAvailableWidthForNewFloatIfNeeded(newFloat);
   3402 
   3403     // We only connect floats to lines for pagination purposes if the floats occur at the start of
   3404     // the line and the previous line had a hard break (so this line is either the first in the block
   3405     // or follows a <br>).
   3406     if (!newFloat->m_paginationStrut || !lineInfo.previousLineBrokeCleanly() || !lineInfo.isEmpty())
   3407         return true;
   3408 
   3409     const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
   3410     ASSERT(floatingObjectSet.last() == newFloat);
   3411 
   3412     LayoutUnit floatLogicalTop = logicalTopForFloat(newFloat);
   3413     int paginationStrut = newFloat->m_paginationStrut;
   3414 
   3415     if (floatLogicalTop - paginationStrut != logicalHeight() + lineInfo.floatPaginationStrut())
   3416         return true;
   3417 
   3418     FloatingObjectSetIterator it = floatingObjectSet.end();
   3419     --it; // Last float is newFloat, skip that one.
   3420     FloatingObjectSetIterator begin = floatingObjectSet.begin();
   3421     while (it != begin) {
   3422         --it;
   3423         FloatingObject* f = *it;
   3424         if (f == lastFloatFromPreviousLine)
   3425             break;
   3426         if (logicalTopForFloat(f) == logicalHeight() + lineInfo.floatPaginationStrut()) {
   3427             f->m_paginationStrut += paginationStrut;
   3428             RenderBox* o = f->m_renderer;
   3429             setLogicalTopForChild(o, logicalTopForChild(o) + marginBeforeForChild(o) + paginationStrut);
   3430             if (o->isRenderBlock())
   3431                 toRenderBlock(o)->setChildNeedsLayout(MarkOnlyThis);
   3432             o->layoutIfNeeded();
   3433             // Save the old logical top before calling removePlacedObject which will set
   3434             // isPlaced to false. Otherwise it will trigger an assert in logicalTopForFloat.
   3435             LayoutUnit oldLogicalTop = logicalTopForFloat(f);
   3436             m_floatingObjects->removePlacedObject(f);
   3437             setLogicalTopForFloat(f, oldLogicalTop + paginationStrut);
   3438             m_floatingObjects->addPlacedObject(f);
   3439         }
   3440     }
   3441 
   3442     // Just update the line info's pagination strut without altering our logical height yet. If the line ends up containing
   3443     // no content, then we don't want to improperly grow the height of the block.
   3444     lineInfo.setFloatPaginationStrut(lineInfo.floatPaginationStrut() + paginationStrut);
   3445     return true;
   3446 }
   3447 
   3448 LayoutUnit RenderBlock::startAlignedOffsetForLine(LayoutUnit position, bool firstLine)
   3449 {
   3450     ETextAlign textAlign = style()->textAlign();
   3451 
   3452     if (textAlign == TASTART) // FIXME: Handle TAEND here
   3453         return startOffsetForLine(position, firstLine);
   3454 
   3455     // updateLogicalWidthForAlignment() handles the direction of the block so no need to consider it here
   3456     float totalLogicalWidth = 0;
   3457     float logicalLeft = logicalLeftOffsetForLine(logicalHeight(), false);
   3458     float availableLogicalWidth = logicalRightOffsetForLine(logicalHeight(), false) - logicalLeft;
   3459     updateLogicalWidthForAlignment(textAlign, 0, logicalLeft, totalLogicalWidth, availableLogicalWidth, 0);
   3460 
   3461     if (!style()->isLeftToRightDirection())
   3462         return logicalWidth() - logicalLeft;
   3463     return logicalLeft;
   3464 }
   3465 
   3466 
   3467 void RenderBlock::layoutLineGridBox()
   3468 {
   3469     if (style()->lineGrid() == RenderStyle::initialLineGrid()) {
   3470         setLineGridBox(0);
   3471         return;
   3472     }
   3473 
   3474     setLineGridBox(0);
   3475 
   3476     RootInlineBox* lineGridBox = new RootInlineBox(this);
   3477     lineGridBox->setHasTextChildren(); // Needed to make the line ascent/descent actually be honored in quirks mode.
   3478     lineGridBox->setConstructed();
   3479     GlyphOverflowAndFallbackFontsMap textBoxDataMap;
   3480     VerticalPositionCache verticalPositionCache;
   3481     lineGridBox->alignBoxesInBlockDirection(logicalHeight(), textBoxDataMap, verticalPositionCache);
   3482 
   3483     setLineGridBox(lineGridBox);
   3484 
   3485     // FIXME: If any of the characteristics of the box change compared to the old one, then we need to do a deep dirtying
   3486     // (similar to what happens when the page height changes). Ideally, though, we only do this if someone is actually snapping
   3487     // to this grid.
   3488 }
   3489 
   3490 }
   3491