1/*
2 * Copyright (C) 2000 Lars Knoll (knoll@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/accessibility/AXObjectCache.h"
26#include "core/rendering/BidiRunForLine.h"
27#include "core/rendering/RenderCounter.h"
28#include "core/rendering/RenderFlowThread.h"
29#include "core/rendering/RenderLayer.h"
30#include "core/rendering/RenderListMarker.h"
31#include "core/rendering/RenderObjectInlines.h"
32#include "core/rendering/RenderRegion.h"
33#include "core/rendering/RenderRubyRun.h"
34#include "core/rendering/RenderView.h"
35#include "core/rendering/TextRunConstructor.h"
36#include "core/rendering/TrailingFloatsRootInlineBox.h"
37#include "core/rendering/VerticalPositionCache.h"
38#include "core/rendering/line/BreakingContextInlineHeaders.h"
39#include "core/rendering/line/LineLayoutState.h"
40#include "core/rendering/line/LineWidth.h"
41#include "core/rendering/line/RenderTextInfo.h"
42#include "core/rendering/line/WordMeasurement.h"
43#include "core/rendering/svg/SVGRootInlineBox.h"
44#include "platform/fonts/Character.h"
45#include "platform/text/BidiResolver.h"
46#include "wtf/RefCountedLeakCounter.h"
47#include "wtf/StdLibExtras.h"
48#include "wtf/Vector.h"
49#include "wtf/unicode/CharacterNames.h"
50
51namespace blink {
52
53using namespace WTF::Unicode;
54
55static inline InlineBox* createInlineBoxForRenderer(RenderObject* obj, bool isRootLineBox, bool isOnlyRun = false)
56{
57    if (isRootLineBox)
58        return toRenderBlockFlow(obj)->createAndAppendRootInlineBox();
59
60    if (obj->isText()) {
61        InlineTextBox* textBox = toRenderText(obj)->createInlineTextBox();
62        // We only treat a box as text for a <br> if we are on a line by ourself or in strict mode
63        // (Note the use of strict mode.  In "almost strict" mode, we don't treat the box for <br> as text.)
64        if (obj->isBR())
65            textBox->setIsText(isOnlyRun || obj->document().inNoQuirksMode());
66        return textBox;
67    }
68
69    if (obj->isBox())
70        return toRenderBox(obj)->createInlineBox();
71
72    return toRenderInline(obj)->createAndAppendInlineFlowBox();
73}
74
75static inline void dirtyLineBoxesForRenderer(RenderObject* o, bool fullLayout)
76{
77    if (o->isText()) {
78        RenderText* renderText = toRenderText(o);
79        renderText->dirtyLineBoxes(fullLayout);
80    } else
81        toRenderInline(o)->dirtyLineBoxes(fullLayout);
82}
83
84static bool parentIsConstructedOrHaveNext(InlineFlowBox* parentBox)
85{
86    do {
87        if (parentBox->isConstructed() || parentBox->nextOnLine())
88            return true;
89        parentBox = parentBox->parent();
90    } while (parentBox);
91    return false;
92}
93
94InlineFlowBox* RenderBlockFlow::createLineBoxes(RenderObject* obj, const LineInfo& lineInfo, InlineBox* childBox)
95{
96    // See if we have an unconstructed line box for this object that is also
97    // the last item on the line.
98    unsigned lineDepth = 1;
99    InlineFlowBox* parentBox = 0;
100    InlineFlowBox* result = 0;
101    bool hasDefaultLineBoxContain = style()->lineBoxContain() == RenderStyle::initialLineBoxContain();
102    do {
103        ASSERT_WITH_SECURITY_IMPLICATION(obj->isRenderInline() || obj == this);
104
105        RenderInline* inlineFlow = (obj != this) ? toRenderInline(obj) : 0;
106
107        // Get the last box we made for this render object.
108        parentBox = inlineFlow ? inlineFlow->lastLineBox() : toRenderBlock(obj)->lastLineBox();
109
110        // If this box or its ancestor is constructed then it is from a previous line, and we need
111        // to make a new box for our line.  If this box or its ancestor is unconstructed but it has
112        // something following it on the line, then we know we have to make a new box
113        // as well.  In this situation our inline has actually been split in two on
114        // the same line (this can happen with very fancy language mixtures).
115        bool constructedNewBox = false;
116        bool allowedToConstructNewBox = !hasDefaultLineBoxContain || !inlineFlow || inlineFlow->alwaysCreateLineBoxes();
117        bool canUseExistingParentBox = parentBox && !parentIsConstructedOrHaveNext(parentBox);
118        if (allowedToConstructNewBox && !canUseExistingParentBox) {
119            // We need to make a new box for this render object.  Once
120            // made, we need to place it at the end of the current line.
121            InlineBox* newBox = createInlineBoxForRenderer(obj, obj == this);
122            ASSERT_WITH_SECURITY_IMPLICATION(newBox->isInlineFlowBox());
123            parentBox = toInlineFlowBox(newBox);
124            parentBox->setFirstLineStyleBit(lineInfo.isFirstLine());
125            parentBox->setIsHorizontal(isHorizontalWritingMode());
126            if (!hasDefaultLineBoxContain)
127                parentBox->clearDescendantsHaveSameLineHeightAndBaseline();
128            constructedNewBox = true;
129        }
130
131        if (constructedNewBox || canUseExistingParentBox) {
132            if (!result)
133                result = parentBox;
134
135            // If we have hit the block itself, then |box| represents the root
136            // inline box for the line, and it doesn't have to be appended to any parent
137            // inline.
138            if (childBox)
139                parentBox->addToLine(childBox);
140
141            if (!constructedNewBox || obj == this)
142                break;
143
144            childBox = parentBox;
145        }
146
147        // If we've exceeded our line depth, then jump straight to the root and skip all the remaining
148        // intermediate inline flows.
149        obj = (++lineDepth >= cMaxLineDepth) ? this : obj->parent();
150
151    } while (true);
152
153    return result;
154}
155
156template <typename CharacterType>
157static inline bool endsWithASCIISpaces(const CharacterType* characters, unsigned pos, unsigned end)
158{
159    while (isASCIISpace(characters[pos])) {
160        pos++;
161        if (pos >= end)
162            return true;
163    }
164    return false;
165}
166
167static bool reachedEndOfTextRenderer(const BidiRunList<BidiRun>& bidiRuns)
168{
169    BidiRun* run = bidiRuns.logicallyLastRun();
170    if (!run)
171        return true;
172    unsigned pos = run->stop();
173    RenderObject* r = run->m_object;
174    if (!r->isText() || r->isBR())
175        return false;
176    RenderText* renderText = toRenderText(r);
177    unsigned length = renderText->textLength();
178    if (pos >= length)
179        return true;
180
181    if (renderText->is8Bit())
182        return endsWithASCIISpaces(renderText->characters8(), pos, length);
183    return endsWithASCIISpaces(renderText->characters16(), pos, length);
184}
185
186RootInlineBox* RenderBlockFlow::constructLine(BidiRunList<BidiRun>& bidiRuns, const LineInfo& lineInfo)
187{
188    ASSERT(bidiRuns.firstRun());
189
190    bool rootHasSelectedChildren = false;
191    InlineFlowBox* parentBox = 0;
192    int runCount = bidiRuns.runCount() - lineInfo.runsFromLeadingWhitespace();
193    for (BidiRun* r = bidiRuns.firstRun(); r; r = r->next()) {
194        // Create a box for our object.
195        bool isOnlyRun = (runCount == 1);
196        if (runCount == 2 && !r->m_object->isListMarker())
197            isOnlyRun = (!style()->isLeftToRightDirection() ? bidiRuns.lastRun() : bidiRuns.firstRun())->m_object->isListMarker();
198
199        if (lineInfo.isEmpty())
200            continue;
201
202        InlineBox* box = createInlineBoxForRenderer(r->m_object, false, isOnlyRun);
203        r->m_box = box;
204
205        ASSERT(box);
206        if (!box)
207            continue;
208
209        if (!rootHasSelectedChildren && box->renderer().selectionState() != RenderObject::SelectionNone)
210            rootHasSelectedChildren = true;
211
212        // If we have no parent box yet, or if the run is not simply a sibling,
213        // then we need to construct inline boxes as necessary to properly enclose the
214        // run's inline box. Segments can only be siblings at the root level, as
215        // they are positioned separately.
216        if (!parentBox || parentBox->renderer() != r->m_object->parent()) {
217            // Create new inline boxes all the way back to the appropriate insertion point.
218            parentBox = createLineBoxes(r->m_object->parent(), lineInfo, box);
219        } else {
220            // Append the inline box to this line.
221            parentBox->addToLine(box);
222        }
223
224        bool visuallyOrdered = r->m_object->style()->rtlOrdering() == VisualOrder;
225        box->setBidiLevel(r->level());
226
227        if (box->isInlineTextBox()) {
228            InlineTextBox* text = toInlineTextBox(box);
229            text->setStart(r->m_start);
230            text->setLen(r->m_stop - r->m_start);
231            text->setDirOverride(r->dirOverride(visuallyOrdered));
232            if (r->m_hasHyphen)
233                text->setHasHyphen(true);
234
235            if (AXObjectCache* cache = document().existingAXObjectCache())
236                cache->inlineTextBoxesUpdated(r->m_object);
237        }
238    }
239
240    // We should have a root inline box.  It should be unconstructed and
241    // be the last continuation of our line list.
242    ASSERT(lastLineBox() && !lastLineBox()->isConstructed());
243
244    // Set the m_selectedChildren flag on the root inline box if one of the leaf inline box
245    // from the bidi runs walk above has a selection state.
246    if (rootHasSelectedChildren)
247        lastLineBox()->root().setHasSelectedChildren(true);
248
249    // Set bits on our inline flow boxes that indicate which sides should
250    // paint borders/margins/padding.  This knowledge will ultimately be used when
251    // we determine the horizontal positions and widths of all the inline boxes on
252    // the line.
253    bool isLogicallyLastRunWrapped = bidiRuns.logicallyLastRun()->m_object && bidiRuns.logicallyLastRun()->m_object->isText() ? !reachedEndOfTextRenderer(bidiRuns) : true;
254    lastLineBox()->determineSpacingForFlowBoxes(lineInfo.isLastLine(), isLogicallyLastRunWrapped, bidiRuns.logicallyLastRun()->m_object);
255
256    // Now mark the line boxes as being constructed.
257    lastLineBox()->setConstructed();
258
259    // Return the last line.
260    return lastRootBox();
261}
262
263ETextAlign RenderBlockFlow::textAlignmentForLine(bool endsWithSoftBreak) const
264{
265    ETextAlign alignment = style()->textAlign();
266    if (endsWithSoftBreak)
267        return alignment;
268
269    if (!RuntimeEnabledFeatures::css3TextEnabled())
270        return (alignment == JUSTIFY) ? TASTART : alignment;
271
272    if (alignment != JUSTIFY)
273        return alignment;
274
275    TextAlignLast alignmentLast = style()->textAlignLast();
276    switch (alignmentLast) {
277    case TextAlignLastStart:
278        return TASTART;
279    case TextAlignLastEnd:
280        return TAEND;
281    case TextAlignLastLeft:
282        return LEFT;
283    case TextAlignLastRight:
284        return RIGHT;
285    case TextAlignLastCenter:
286        return CENTER;
287    case TextAlignLastJustify:
288        return JUSTIFY;
289    case TextAlignLastAuto:
290        if (style()->textJustify() == TextJustifyDistribute)
291            return JUSTIFY;
292        return TASTART;
293    }
294
295    return alignment;
296}
297
298static void updateLogicalWidthForLeftAlignedBlock(bool isLeftToRightDirection, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float availableLogicalWidth)
299{
300    // The direction of the block should determine what happens with wide lines.
301    // In particular with RTL blocks, wide lines should still spill out to the left.
302    if (isLeftToRightDirection) {
303        if (totalLogicalWidth > availableLogicalWidth && trailingSpaceRun)
304            trailingSpaceRun->m_box->setLogicalWidth(std::max<float>(0, trailingSpaceRun->m_box->logicalWidth() - totalLogicalWidth + availableLogicalWidth));
305        return;
306    }
307
308    if (trailingSpaceRun)
309        trailingSpaceRun->m_box->setLogicalWidth(0);
310    else if (totalLogicalWidth > availableLogicalWidth)
311        logicalLeft -= (totalLogicalWidth - availableLogicalWidth);
312}
313
314static void updateLogicalWidthForRightAlignedBlock(bool isLeftToRightDirection, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float availableLogicalWidth)
315{
316    // Wide lines spill out of the block based off direction.
317    // So even if text-align is right, if direction is LTR, wide lines should overflow out of the right
318    // side of the block.
319    if (isLeftToRightDirection) {
320        if (trailingSpaceRun) {
321            totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth();
322            trailingSpaceRun->m_box->setLogicalWidth(0);
323        }
324        if (totalLogicalWidth < availableLogicalWidth)
325            logicalLeft += availableLogicalWidth - totalLogicalWidth;
326        return;
327    }
328
329    if (totalLogicalWidth > availableLogicalWidth && trailingSpaceRun) {
330        trailingSpaceRun->m_box->setLogicalWidth(std::max<float>(0, trailingSpaceRun->m_box->logicalWidth() - totalLogicalWidth + availableLogicalWidth));
331        totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth();
332    } else
333        logicalLeft += availableLogicalWidth - totalLogicalWidth;
334}
335
336static void updateLogicalWidthForCenterAlignedBlock(bool isLeftToRightDirection, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float availableLogicalWidth)
337{
338    float trailingSpaceWidth = 0;
339    if (trailingSpaceRun) {
340        totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth();
341        trailingSpaceWidth = std::min(trailingSpaceRun->m_box->logicalWidth(), (availableLogicalWidth - totalLogicalWidth + 1) / 2);
342        trailingSpaceRun->m_box->setLogicalWidth(std::max<float>(0, trailingSpaceWidth));
343    }
344    if (isLeftToRightDirection)
345        logicalLeft += std::max<float>((availableLogicalWidth - totalLogicalWidth) / 2, 0);
346    else
347        logicalLeft += totalLogicalWidth > availableLogicalWidth ? (availableLogicalWidth - totalLogicalWidth) : (availableLogicalWidth - totalLogicalWidth) / 2 - trailingSpaceWidth;
348}
349
350void RenderBlockFlow::setMarginsForRubyRun(BidiRun* run, RenderRubyRun* renderer, RenderObject* previousObject, const LineInfo& lineInfo)
351{
352    int startOverhang;
353    int endOverhang;
354    RenderObject* nextObject = 0;
355    for (BidiRun* runWithNextObject = run->next(); runWithNextObject; runWithNextObject = runWithNextObject->next()) {
356        if (!runWithNextObject->m_object->isOutOfFlowPositioned() && !runWithNextObject->m_box->isLineBreak()) {
357            nextObject = runWithNextObject->m_object;
358            break;
359        }
360    }
361    renderer->getOverhang(lineInfo.isFirstLine(), renderer->style()->isLeftToRightDirection() ? previousObject : nextObject, renderer->style()->isLeftToRightDirection() ? nextObject : previousObject, startOverhang, endOverhang);
362    setMarginStartForChild(renderer, -startOverhang);
363    setMarginEndForChild(renderer, -endOverhang);
364}
365
366static inline void setLogicalWidthForTextRun(RootInlineBox* lineBox, BidiRun* run, RenderText* renderer, float xPos, const LineInfo& lineInfo,
367                                             GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache, WordMeasurements& wordMeasurements)
368{
369    HashSet<const SimpleFontData*> fallbackFonts;
370    GlyphOverflow glyphOverflow;
371
372    const Font& font = renderer->style(lineInfo.isFirstLine())->font();
373    // Always compute glyph overflow if the block's line-box-contain value is "glyphs".
374    if (lineBox->fitsToGlyphs()) {
375        // If we don't stick out of the root line's font box, then don't bother computing our glyph overflow. This optimization
376        // will keep us from computing glyph bounds in nearly all cases.
377        bool includeRootLine = lineBox->includesRootLineBoxFontOrLeading();
378        int baselineShift = lineBox->verticalPositionForBox(run->m_box, verticalPositionCache);
379        int rootDescent = includeRootLine ? font.fontMetrics().descent() : 0;
380        int rootAscent = includeRootLine ? font.fontMetrics().ascent() : 0;
381        int boxAscent = font.fontMetrics().ascent() - baselineShift;
382        int boxDescent = font.fontMetrics().descent() + baselineShift;
383        if (boxAscent > rootDescent ||  boxDescent > rootAscent)
384            glyphOverflow.computeBounds = true;
385    }
386
387    LayoutUnit hyphenWidth = 0;
388    if (toInlineTextBox(run->m_box)->hasHyphen()) {
389        const Font& font = renderer->style(lineInfo.isFirstLine())->font();
390        hyphenWidth = measureHyphenWidth(renderer, font, run->direction());
391    }
392    float measuredWidth = 0;
393
394    bool kerningIsEnabled = font.fontDescription().typesettingFeatures() & Kerning;
395
396#if OS(MACOSX)
397    // FIXME: Having any font feature settings enabled can lead to selection gaps on
398    // Chromium-mac. https://bugs.webkit.org/show_bug.cgi?id=113418
399    bool canUseSimpleFontCodePath = renderer->canUseSimpleFontCodePath() && !font.fontDescription().featureSettings();
400#else
401    bool canUseSimpleFontCodePath = renderer->canUseSimpleFontCodePath();
402#endif
403
404    // Since we don't cache glyph overflows, we need to re-measure the run if
405    // the style is linebox-contain: glyph.
406
407    if (!lineBox->fitsToGlyphs() && canUseSimpleFontCodePath) {
408        int lastEndOffset = run->m_start;
409        for (size_t i = 0, size = wordMeasurements.size(); i < size && lastEndOffset < run->m_stop; ++i) {
410            const WordMeasurement& wordMeasurement = wordMeasurements[i];
411            if (wordMeasurement.width <=0 || wordMeasurement.startOffset == wordMeasurement.endOffset)
412                continue;
413            if (wordMeasurement.renderer != renderer || wordMeasurement.startOffset != lastEndOffset || wordMeasurement.endOffset > run->m_stop)
414                continue;
415
416            lastEndOffset = wordMeasurement.endOffset;
417            if (kerningIsEnabled && lastEndOffset == run->m_stop) {
418                int wordLength = lastEndOffset - wordMeasurement.startOffset;
419                measuredWidth += renderer->width(wordMeasurement.startOffset, wordLength, xPos, run->direction(), lineInfo.isFirstLine());
420                if (i > 0 && wordLength == 1 && renderer->characterAt(wordMeasurement.startOffset) == ' ')
421                    measuredWidth += renderer->style()->wordSpacing();
422            } else
423                measuredWidth += wordMeasurement.width;
424            if (!wordMeasurement.fallbackFonts.isEmpty()) {
425                HashSet<const SimpleFontData*>::const_iterator end = wordMeasurement.fallbackFonts.end();
426                for (HashSet<const SimpleFontData*>::const_iterator it = wordMeasurement.fallbackFonts.begin(); it != end; ++it)
427                    fallbackFonts.add(*it);
428            }
429        }
430        if (measuredWidth && lastEndOffset != run->m_stop) {
431            // If we don't have enough cached data, we'll measure the run again.
432            measuredWidth = 0;
433            fallbackFonts.clear();
434        }
435    }
436
437    if (!measuredWidth)
438        measuredWidth = renderer->width(run->m_start, run->m_stop - run->m_start, xPos, run->direction(), lineInfo.isFirstLine(), &fallbackFonts, &glyphOverflow);
439
440    run->m_box->setLogicalWidth(measuredWidth + hyphenWidth);
441    if (!fallbackFonts.isEmpty()) {
442        ASSERT(run->m_box->isText());
443        GlyphOverflowAndFallbackFontsMap::ValueType* it = textBoxDataMap.add(toInlineTextBox(run->m_box), std::make_pair(Vector<const SimpleFontData*>(), GlyphOverflow())).storedValue;
444        ASSERT(it->value.first.isEmpty());
445        copyToVector(fallbackFonts, it->value.first);
446        run->m_box->parent()->clearDescendantsHaveSameLineHeightAndBaseline();
447    }
448    if (!glyphOverflow.isZero()) {
449        ASSERT(run->m_box->isText());
450        GlyphOverflowAndFallbackFontsMap::ValueType* it = textBoxDataMap.add(toInlineTextBox(run->m_box), std::make_pair(Vector<const SimpleFontData*>(), GlyphOverflow())).storedValue;
451        it->value.second = glyphOverflow;
452        run->m_box->clearKnownToHaveNoOverflow();
453    }
454}
455
456static inline void computeExpansionForJustifiedText(BidiRun* firstRun, BidiRun* trailingSpaceRun, Vector<unsigned, 16>& expansionOpportunities, unsigned expansionOpportunityCount, float& totalLogicalWidth, float availableLogicalWidth)
457{
458    if (!expansionOpportunityCount || availableLogicalWidth <= totalLogicalWidth)
459        return;
460
461    size_t i = 0;
462    for (BidiRun* r = firstRun; r; r = r->next()) {
463        if (!r->m_box || r == trailingSpaceRun)
464            continue;
465
466        if (r->m_object->isText()) {
467            unsigned opportunitiesInRun = expansionOpportunities[i++];
468
469            ASSERT(opportunitiesInRun <= expansionOpportunityCount);
470
471            // Don't justify for white-space: pre.
472            if (r->m_object->style()->whiteSpace() != PRE) {
473                InlineTextBox* textBox = toInlineTextBox(r->m_box);
474                int expansion = (availableLogicalWidth - totalLogicalWidth) * opportunitiesInRun / expansionOpportunityCount;
475                textBox->setExpansion(expansion);
476                totalLogicalWidth += expansion;
477            }
478            expansionOpportunityCount -= opportunitiesInRun;
479            if (!expansionOpportunityCount)
480                break;
481        }
482    }
483}
484
485void RenderBlockFlow::updateLogicalWidthForAlignment(const ETextAlign& textAlign, const RootInlineBox* rootInlineBox, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float& availableLogicalWidth, unsigned expansionOpportunityCount)
486{
487    TextDirection direction;
488    if (rootInlineBox && rootInlineBox->renderer().style()->unicodeBidi() == Plaintext)
489        direction = rootInlineBox->direction();
490    else
491        direction = style()->direction();
492
493    // Armed with the total width of the line (without justification),
494    // we now examine our text-align property in order to determine where to position the
495    // objects horizontally. The total width of the line can be increased if we end up
496    // justifying text.
497    switch (textAlign) {
498    case LEFT:
499    case WEBKIT_LEFT:
500        updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
501        break;
502    case RIGHT:
503    case WEBKIT_RIGHT:
504        updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
505        break;
506    case CENTER:
507    case WEBKIT_CENTER:
508        updateLogicalWidthForCenterAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
509        break;
510    case JUSTIFY:
511        adjustInlineDirectionLineBounds(expansionOpportunityCount, logicalLeft, availableLogicalWidth);
512        if (expansionOpportunityCount) {
513            if (trailingSpaceRun) {
514                totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth();
515                trailingSpaceRun->m_box->setLogicalWidth(0);
516            }
517            break;
518        }
519        // Fall through
520    case TASTART:
521        if (direction == LTR)
522            updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
523        else
524            updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
525        break;
526    case TAEND:
527        if (direction == LTR)
528            updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
529        else
530            updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
531        break;
532    }
533    if (style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
534        logicalLeft += verticalScrollbarWidth();
535}
536
537static void updateLogicalInlinePositions(RenderBlockFlow* block, float& lineLogicalLeft, float& lineLogicalRight, float& availableLogicalWidth, bool firstLine, IndentTextOrNot shouldIndentText, LayoutUnit boxLogicalHeight)
538{
539    LayoutUnit lineLogicalHeight = block->minLineHeightForReplacedRenderer(firstLine, boxLogicalHeight);
540    lineLogicalLeft = block->logicalLeftOffsetForLine(block->logicalHeight(), shouldIndentText == IndentText, lineLogicalHeight).toFloat();
541    lineLogicalRight = block->logicalRightOffsetForLine(block->logicalHeight(), shouldIndentText == IndentText, lineLogicalHeight).toFloat();
542    availableLogicalWidth = lineLogicalRight - lineLogicalLeft;
543}
544
545void RenderBlockFlow::computeInlineDirectionPositionsForLine(RootInlineBox* lineBox, const LineInfo& lineInfo, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd,
546                                                         GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache, WordMeasurements& wordMeasurements)
547{
548    ETextAlign textAlign = textAlignmentForLine(!reachedEnd && !lineBox->endsWithBreak());
549
550    // 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
551    // box is only affected if it is the first child of its parent element."
552    // CSS3 "text-indent", "each-line" affects the first line of the block container as well as each line after a forced line break,
553    // but does not affect lines after a soft wrap break.
554    bool isFirstLine = lineInfo.isFirstLine() && !(isAnonymousBlock() && parent()->slowFirstChild() != this);
555    bool isAfterHardLineBreak = lineBox->prevRootBox() && lineBox->prevRootBox()->endsWithBreak();
556    IndentTextOrNot shouldIndentText = requiresIndent(isFirstLine, isAfterHardLineBreak, style());
557    float lineLogicalLeft;
558    float lineLogicalRight;
559    float availableLogicalWidth;
560    updateLogicalInlinePositions(this, lineLogicalLeft, lineLogicalRight, availableLogicalWidth, isFirstLine, shouldIndentText, 0);
561    bool needsWordSpacing;
562
563    if (firstRun && firstRun->m_object->isReplaced()) {
564        RenderBox* renderBox = toRenderBox(firstRun->m_object);
565        updateLogicalInlinePositions(this, lineLogicalLeft, lineLogicalRight, availableLogicalWidth, isFirstLine, shouldIndentText, renderBox->logicalHeight());
566    }
567
568    computeInlineDirectionPositionsForSegment(lineBox, lineInfo, textAlign, lineLogicalLeft, availableLogicalWidth, firstRun, trailingSpaceRun, textBoxDataMap, verticalPositionCache, wordMeasurements);
569    // The widths of all runs are now known. We can now place every inline box (and
570    // compute accurate widths for the inline flow boxes).
571    needsWordSpacing = lineBox->isLeftToRightDirection() ? false: true;
572    lineBox->placeBoxesInInlineDirection(lineLogicalLeft, needsWordSpacing);
573}
574
575BidiRun* RenderBlockFlow::computeInlineDirectionPositionsForSegment(RootInlineBox* lineBox, const LineInfo& lineInfo, ETextAlign textAlign, float& logicalLeft,
576    float& availableLogicalWidth, BidiRun* firstRun, BidiRun* trailingSpaceRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache,
577    WordMeasurements& wordMeasurements)
578{
579    bool needsWordSpacing = true;
580    float totalLogicalWidth = lineBox->getFlowSpacingLogicalWidth().toFloat();
581    unsigned expansionOpportunityCount = 0;
582    bool isAfterExpansion = true;
583    Vector<unsigned, 16> expansionOpportunities;
584    RenderObject* previousObject = 0;
585    TextJustify textJustify = style()->textJustify();
586
587    BidiRun* r = firstRun;
588    for (; r; r = r->next()) {
589        if (!r->m_box || r->m_object->isOutOfFlowPositioned() || r->m_box->isLineBreak())
590            continue; // Positioned objects are only participating to figure out their
591                      // correct static x position.  They have no effect on the width.
592                      // Similarly, line break boxes have no effect on the width.
593        if (r->m_object->isText()) {
594            RenderText* rt = toRenderText(r->m_object);
595            if (textAlign == JUSTIFY && r != trailingSpaceRun && textJustify != TextJustifyNone) {
596                if (!isAfterExpansion)
597                    toInlineTextBox(r->m_box)->setCanHaveLeadingExpansion(true);
598                unsigned opportunitiesInRun;
599                if (rt->is8Bit())
600                    opportunitiesInRun = Character::expansionOpportunityCount(rt->characters8() + r->m_start, r->m_stop - r->m_start, r->m_box->direction(), isAfterExpansion);
601                else
602                    opportunitiesInRun = Character::expansionOpportunityCount(rt->characters16() + r->m_start, r->m_stop - r->m_start, r->m_box->direction(), isAfterExpansion);
603                expansionOpportunities.append(opportunitiesInRun);
604                expansionOpportunityCount += opportunitiesInRun;
605            }
606
607            if (rt->textLength()) {
608                if (!r->m_start && needsWordSpacing && isSpaceOrNewline(rt->characterAt(r->m_start)))
609                    totalLogicalWidth += rt->style(lineInfo.isFirstLine())->font().fontDescription().wordSpacing();
610                needsWordSpacing = !isSpaceOrNewline(rt->characterAt(r->m_stop - 1));
611            }
612
613            setLogicalWidthForTextRun(lineBox, r, rt, totalLogicalWidth, lineInfo, textBoxDataMap, verticalPositionCache, wordMeasurements);
614        } else {
615            isAfterExpansion = false;
616            if (!r->m_object->isRenderInline()) {
617                RenderBox* renderBox = toRenderBox(r->m_object);
618                if (renderBox->isRubyRun())
619                    setMarginsForRubyRun(r, toRenderRubyRun(renderBox), previousObject, lineInfo);
620                r->m_box->setLogicalWidth(logicalWidthForChild(renderBox).toFloat());
621                totalLogicalWidth += marginStartForChild(renderBox) + marginEndForChild(renderBox);
622            }
623        }
624
625        totalLogicalWidth += r->m_box->logicalWidth();
626        previousObject = r->m_object;
627    }
628
629    if (isAfterExpansion && !expansionOpportunities.isEmpty()) {
630        expansionOpportunities.last()--;
631        expansionOpportunityCount--;
632    }
633
634    updateLogicalWidthForAlignment(textAlign, lineBox, trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth, expansionOpportunityCount);
635
636    computeExpansionForJustifiedText(firstRun, trailingSpaceRun, expansionOpportunities, expansionOpportunityCount, totalLogicalWidth, availableLogicalWidth);
637
638    return r;
639}
640
641void RenderBlockFlow::computeBlockDirectionPositionsForLine(RootInlineBox* lineBox, BidiRun* firstRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap,
642                                                        VerticalPositionCache& verticalPositionCache)
643{
644    setLogicalHeight(lineBox->alignBoxesInBlockDirection(logicalHeight(), textBoxDataMap, verticalPositionCache));
645
646    // Now make sure we place replaced render objects correctly.
647    for (BidiRun* r = firstRun; r; r = r->next()) {
648        ASSERT(r->m_box);
649        if (!r->m_box)
650            continue; // Skip runs with no line boxes.
651
652        // Align positioned boxes with the top of the line box.  This is
653        // a reasonable approximation of an appropriate y position.
654        if (r->m_object->isOutOfFlowPositioned())
655            r->m_box->setLogicalTop(logicalHeight().toFloat());
656
657        // Position is used to properly position both replaced elements and
658        // to update the static normal flow x/y of positioned elements.
659        if (r->m_object->isText())
660            toRenderText(r->m_object)->positionLineBox(r->m_box);
661        else if (r->m_object->isBox())
662            toRenderBox(r->m_object)->positionLineBox(r->m_box);
663    }
664}
665
666void RenderBlockFlow::appendFloatingObjectToLastLine(FloatingObject* floatingObject)
667{
668    ASSERT(!floatingObject->originatingLine());
669    floatingObject->setOriginatingLine(lastRootBox());
670    lastRootBox()->appendFloat(floatingObject->renderer());
671}
672
673// This function constructs line boxes for all of the text runs in the resolver and computes their position.
674RootInlineBox* RenderBlockFlow::createLineBoxesFromBidiRuns(unsigned bidiLevel, BidiRunList<BidiRun>& bidiRuns, const InlineIterator& end, LineInfo& lineInfo, VerticalPositionCache& verticalPositionCache, BidiRun* trailingSpaceRun, WordMeasurements& wordMeasurements)
675{
676    if (!bidiRuns.runCount())
677        return 0;
678
679    // FIXME: Why is this only done when we had runs?
680    lineInfo.setLastLine(!end.object());
681
682    RootInlineBox* lineBox = constructLine(bidiRuns, lineInfo);
683    if (!lineBox)
684        return 0;
685
686    lineBox->setBidiLevel(bidiLevel);
687    lineBox->setEndsWithBreak(lineInfo.previousLineBrokeCleanly());
688
689    bool isSVGRootInlineBox = lineBox->isSVGRootInlineBox();
690
691    GlyphOverflowAndFallbackFontsMap textBoxDataMap;
692
693    // Now we position all of our text runs horizontally.
694    if (!isSVGRootInlineBox)
695        computeInlineDirectionPositionsForLine(lineBox, lineInfo, bidiRuns.firstRun(), trailingSpaceRun, end.atEnd(), textBoxDataMap, verticalPositionCache, wordMeasurements);
696
697    // Now position our text runs vertically.
698    computeBlockDirectionPositionsForLine(lineBox, bidiRuns.firstRun(), textBoxDataMap, verticalPositionCache);
699
700    // SVG text layout code computes vertical & horizontal positions on its own.
701    // Note that we still need to execute computeVerticalPositionsForLine() as
702    // it calls InlineTextBox::positionLineBox(), which tracks whether the box
703    // contains reversed text or not. If we wouldn't do that editing and thus
704    // text selection in RTL boxes would not work as expected.
705    if (isSVGRootInlineBox) {
706        ASSERT(isSVGText());
707        toSVGRootInlineBox(lineBox)->computePerCharacterLayoutInformation();
708    }
709
710    // Compute our overflow now.
711    lineBox->computeOverflow(lineBox->lineTop(), lineBox->lineBottom(), textBoxDataMap);
712
713    return lineBox;
714}
715
716static void deleteLineRange(LineLayoutState& layoutState, RootInlineBox* startLine, RootInlineBox* stopLine = 0)
717{
718    RootInlineBox* boxToDelete = startLine;
719    while (boxToDelete && boxToDelete != stopLine) {
720        layoutState.updatePaintInvalidationRangeFromBox(boxToDelete);
721        // Note: deleteLineRange(firstRootBox()) is not identical to deleteLineBoxTree().
722        // deleteLineBoxTree uses nextLineBox() instead of nextRootBox() when traversing.
723        RootInlineBox* next = boxToDelete->nextRootBox();
724        boxToDelete->deleteLine();
725        boxToDelete = next;
726    }
727}
728
729void RenderBlockFlow::layoutRunsAndFloats(LineLayoutState& layoutState)
730{
731    // We want to skip ahead to the first dirty line
732    InlineBidiResolver resolver;
733    RootInlineBox* startLine = determineStartPosition(layoutState, resolver);
734
735    if (containsFloats())
736        layoutState.setLastFloat(m_floatingObjects->set().last().get());
737
738    // We also find the first clean line and extract these lines.  We will add them back
739    // if we determine that we're able to synchronize after handling all our dirty lines.
740    InlineIterator cleanLineStart;
741    BidiStatus cleanLineBidiStatus;
742    if (!layoutState.isFullLayout() && startLine)
743        determineEndPosition(layoutState, startLine, cleanLineStart, cleanLineBidiStatus);
744
745    if (startLine) {
746        if (!layoutState.usesPaintInvalidationBounds())
747            layoutState.setPaintInvalidationRange(logicalHeight());
748        deleteLineRange(layoutState, startLine);
749    }
750
751    if (!layoutState.isFullLayout() && lastRootBox() && lastRootBox()->endsWithBreak()) {
752        // If the last line before the start line ends with a line break that clear floats,
753        // adjust the height accordingly.
754        // A line break can be either the first or the last object on a line, depending on its direction.
755        if (InlineBox* lastLeafChild = lastRootBox()->lastLeafChild()) {
756            RenderObject* lastObject = &lastLeafChild->renderer();
757            if (!lastObject->isBR())
758                lastObject = &lastRootBox()->firstLeafChild()->renderer();
759            if (lastObject->isBR()) {
760                EClear clear = lastObject->style()->clear();
761                if (clear != CNONE)
762                    clearFloats(clear);
763            }
764        }
765    }
766
767    layoutRunsAndFloatsInRange(layoutState, resolver, cleanLineStart, cleanLineBidiStatus);
768    linkToEndLineIfNeeded(layoutState);
769    markDirtyFloatsForPaintInvalidation(layoutState.floats());
770}
771
772// Before restarting the layout loop with a new logicalHeight, remove all floats that were added and reset the resolver.
773inline const InlineIterator& RenderBlockFlow::restartLayoutRunsAndFloatsInRange(LayoutUnit oldLogicalHeight, LayoutUnit newLogicalHeight,  FloatingObject* lastFloatFromPreviousLine, InlineBidiResolver& resolver,  const InlineIterator& oldEnd)
774{
775    removeFloatingObjectsBelow(lastFloatFromPreviousLine, oldLogicalHeight);
776    setLogicalHeight(newLogicalHeight);
777    resolver.setPositionIgnoringNestedIsolates(oldEnd);
778    return oldEnd;
779}
780
781void RenderBlockFlow::layoutRunsAndFloatsInRange(LineLayoutState& layoutState,
782    InlineBidiResolver& resolver, const InlineIterator& cleanLineStart,
783    const BidiStatus& cleanLineBidiStatus)
784{
785    RenderStyle* styleToUse = style();
786    bool paginated = view()->layoutState() && view()->layoutState()->isPaginated();
787    LineMidpointState& lineMidpointState = resolver.midpointState();
788    InlineIterator endOfLine = resolver.position();
789    bool checkForEndLineMatch = layoutState.endLine();
790    RenderTextInfo renderTextInfo;
791    VerticalPositionCache verticalPositionCache;
792
793    LineBreaker lineBreaker(this);
794
795    while (!endOfLine.atEnd()) {
796        // FIXME: Is this check necessary before the first iteration or can it be moved to the end?
797        if (checkForEndLineMatch) {
798            layoutState.setEndLineMatched(matchedEndLine(layoutState, resolver, cleanLineStart, cleanLineBidiStatus));
799            if (layoutState.endLineMatched()) {
800                resolver.setPosition(InlineIterator(resolver.position().root(), 0, 0), 0);
801                break;
802            }
803        }
804
805        lineMidpointState.reset();
806
807        layoutState.lineInfo().setEmpty(true);
808        layoutState.lineInfo().resetRunsFromLeadingWhitespace();
809
810        const InlineIterator previousEndofLine = endOfLine;
811        bool isNewUBAParagraph = layoutState.lineInfo().previousLineBrokeCleanly();
812        FloatingObject* lastFloatFromPreviousLine = (containsFloats()) ? m_floatingObjects->set().last().get() : 0;
813
814        WordMeasurements wordMeasurements;
815        endOfLine = lineBreaker.nextLineBreak(resolver, layoutState.lineInfo(), renderTextInfo,
816            lastFloatFromPreviousLine, wordMeasurements);
817        renderTextInfo.m_lineBreakIterator.resetPriorContext();
818        if (resolver.position().atEnd()) {
819            // FIXME: We shouldn't be creating any runs in nextLineBreak to begin with!
820            // Once BidiRunList is separated from BidiResolver this will not be needed.
821            resolver.runs().deleteRuns();
822            resolver.markCurrentRunEmpty(); // FIXME: This can probably be replaced by an ASSERT (or just removed).
823            layoutState.setCheckForFloatsFromLastLine(true);
824            resolver.setPosition(InlineIterator(resolver.position().root(), 0, 0), 0);
825            break;
826        }
827
828        ASSERT(endOfLine != resolver.position());
829
830        // This is a short-cut for empty lines.
831        if (layoutState.lineInfo().isEmpty()) {
832            if (lastRootBox())
833                lastRootBox()->setLineBreakInfo(endOfLine.object(), endOfLine.offset(), resolver.status());
834        } else {
835            VisualDirectionOverride override = (styleToUse->rtlOrdering() == VisualOrder ? (styleToUse->direction() == LTR ? VisualLeftToRightOverride : VisualRightToLeftOverride) : NoVisualOverride);
836            if (isNewUBAParagraph && styleToUse->unicodeBidi() == Plaintext && !resolver.context()->parent()) {
837                TextDirection direction = determinePlaintextDirectionality(resolver.position().root(), resolver.position().object(), resolver.position().offset());
838                resolver.setStatus(BidiStatus(direction, isOverride(styleToUse->unicodeBidi())));
839            }
840            // FIXME: This ownership is reversed. We should own the BidiRunList and pass it to createBidiRunsForLine.
841            BidiRunList<BidiRun>& bidiRuns = resolver.runs();
842            constructBidiRunsForLine(resolver, bidiRuns, endOfLine, override, layoutState.lineInfo().previousLineBrokeCleanly(), isNewUBAParagraph);
843            ASSERT(resolver.position() == endOfLine);
844
845            BidiRun* trailingSpaceRun = resolver.trailingSpaceRun();
846
847            if (bidiRuns.runCount() && lineBreaker.lineWasHyphenated())
848                bidiRuns.logicallyLastRun()->m_hasHyphen = true;
849
850            // Now that the runs have been ordered, we create the line boxes.
851            // At the same time we figure out where border/padding/margin should be applied for
852            // inline flow boxes.
853
854            LayoutUnit oldLogicalHeight = logicalHeight();
855            RootInlineBox* lineBox = createLineBoxesFromBidiRuns(resolver.status().context->level(), bidiRuns, endOfLine, layoutState.lineInfo(), verticalPositionCache, trailingSpaceRun, wordMeasurements);
856
857            bidiRuns.deleteRuns();
858            resolver.markCurrentRunEmpty(); // FIXME: This can probably be replaced by an ASSERT (or just removed).
859
860            if (lineBox) {
861                lineBox->setLineBreakInfo(endOfLine.object(), endOfLine.offset(), resolver.status());
862                if (layoutState.usesPaintInvalidationBounds())
863                    layoutState.updatePaintInvalidationRangeFromBox(lineBox);
864
865                if (paginated) {
866                    LayoutUnit adjustment = 0;
867                    adjustLinePositionForPagination(lineBox, adjustment, layoutState.flowThread());
868                    if (adjustment) {
869                        LayoutUnit oldLineWidth = availableLogicalWidthForLine(oldLogicalHeight, layoutState.lineInfo().isFirstLine());
870                        lineBox->adjustBlockDirectionPosition(adjustment.toFloat());
871                        if (layoutState.usesPaintInvalidationBounds())
872                            layoutState.updatePaintInvalidationRangeFromBox(lineBox);
873
874                        if (availableLogicalWidthForLine(oldLogicalHeight + adjustment, layoutState.lineInfo().isFirstLine()) != oldLineWidth) {
875                            // We have to delete this line, remove all floats that got added, and let line layout re-run.
876                            lineBox->deleteLine();
877                            endOfLine = restartLayoutRunsAndFloatsInRange(oldLogicalHeight, oldLogicalHeight + adjustment, lastFloatFromPreviousLine, resolver, previousEndofLine);
878                            continue;
879                        }
880
881                        setLogicalHeight(lineBox->lineBottomWithLeading());
882                    }
883                }
884            }
885        }
886
887        for (size_t i = 0; i < lineBreaker.positionedObjects().size(); ++i)
888            setStaticPositions(this, lineBreaker.positionedObjects()[i]);
889
890        if (!layoutState.lineInfo().isEmpty()) {
891            layoutState.lineInfo().setFirstLine(false);
892            clearFloats(lineBreaker.clear());
893        }
894
895        if (m_floatingObjects && lastRootBox()) {
896            const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
897            FloatingObjectSetIterator it = floatingObjectSet.begin();
898            FloatingObjectSetIterator end = floatingObjectSet.end();
899            if (layoutState.lastFloat()) {
900                FloatingObjectSetIterator lastFloatIterator = floatingObjectSet.find(layoutState.lastFloat());
901                ASSERT(lastFloatIterator != end);
902                ++lastFloatIterator;
903                it = lastFloatIterator;
904            }
905            for (; it != end; ++it) {
906                FloatingObject* f = it->get();
907                appendFloatingObjectToLastLine(f);
908                ASSERT(f->renderer() == layoutState.floats()[layoutState.floatIndex()].object);
909                // If a float's geometry has changed, give up on syncing with clean lines.
910                if (layoutState.floats()[layoutState.floatIndex()].rect != f->frameRect())
911                    checkForEndLineMatch = false;
912                layoutState.setFloatIndex(layoutState.floatIndex() + 1);
913            }
914            layoutState.setLastFloat(!floatingObjectSet.isEmpty() ? floatingObjectSet.last().get() : 0);
915        }
916
917        lineMidpointState.reset();
918        resolver.setPosition(endOfLine, numberOfIsolateAncestors(endOfLine));
919    }
920
921    // In case we already adjusted the line positions during this layout to avoid widows
922    // then we need to ignore the possibility of having a new widows situation.
923    // Otherwise, we risk leaving empty containers which is against the block fragmentation principles.
924    if (paginated && !style()->hasAutoWidows() && !didBreakAtLineToAvoidWidow()) {
925        // Check the line boxes to make sure we didn't create unacceptable widows.
926        // However, we'll prioritize orphans - so nothing we do here should create
927        // a new orphan.
928
929        RootInlineBox* lineBox = lastRootBox();
930
931        // Count from the end of the block backwards, to see how many hanging
932        // lines we have.
933        RootInlineBox* firstLineInBlock = firstRootBox();
934        int numLinesHanging = 1;
935        while (lineBox && lineBox != firstLineInBlock && !lineBox->isFirstAfterPageBreak()) {
936            ++numLinesHanging;
937            lineBox = lineBox->prevRootBox();
938        }
939
940        // If there were no breaks in the block, we didn't create any widows.
941        if (!lineBox || !lineBox->isFirstAfterPageBreak() || lineBox == firstLineInBlock)
942            return;
943
944        if (numLinesHanging < style()->widows()) {
945            // We have detected a widow. Now we need to work out how many
946            // lines there are on the previous page, and how many we need
947            // to steal.
948            int numLinesNeeded = style()->widows() - numLinesHanging;
949            RootInlineBox* currentFirstLineOfNewPage = lineBox;
950
951            // Count the number of lines in the previous page.
952            lineBox = lineBox->prevRootBox();
953            int numLinesInPreviousPage = 1;
954            while (lineBox && lineBox != firstLineInBlock && !lineBox->isFirstAfterPageBreak()) {
955                ++numLinesInPreviousPage;
956                lineBox = lineBox->prevRootBox();
957            }
958
959            // If there was an explicit value for orphans, respect that. If not, we still
960            // shouldn't create a situation where we make an orphan bigger than the initial value.
961            // This means that setting widows implies we also care about orphans, but given
962            // the specification says the initial orphan value is non-zero, this is ok. The
963            // author is always free to set orphans explicitly as well.
964            int orphans = style()->hasAutoOrphans() ? style()->initialOrphans() : style()->orphans();
965            int numLinesAvailable = numLinesInPreviousPage - orphans;
966            if (numLinesAvailable <= 0)
967                return;
968
969            int numLinesToTake = std::min(numLinesAvailable, numLinesNeeded);
970            // Wind back from our first widowed line.
971            lineBox = currentFirstLineOfNewPage;
972            for (int i = 0; i < numLinesToTake; ++i)
973                lineBox = lineBox->prevRootBox();
974
975            // We now want to break at this line. Remember for next layout and trigger relayout.
976            setBreakAtLineToAvoidWidow(lineCount(lineBox));
977            markLinesDirtyInBlockRange(lastRootBox()->lineBottomWithLeading(), lineBox->lineBottomWithLeading(), lineBox);
978        }
979    }
980
981    clearDidBreakAtLineToAvoidWidow();
982}
983
984void RenderBlockFlow::linkToEndLineIfNeeded(LineLayoutState& layoutState)
985{
986    if (layoutState.endLine()) {
987        if (layoutState.endLineMatched()) {
988            bool paginated = view()->layoutState() && view()->layoutState()->isPaginated();
989            // Attach all the remaining lines, and then adjust their y-positions as needed.
990            LayoutUnit delta = logicalHeight() - layoutState.endLineLogicalTop();
991            for (RootInlineBox* line = layoutState.endLine(); line; line = line->nextRootBox()) {
992                line->attachLine();
993                if (paginated) {
994                    delta -= line->paginationStrut();
995                    adjustLinePositionForPagination(line, delta, layoutState.flowThread());
996                }
997                if (delta) {
998                    layoutState.updatePaintInvalidationRangeFromBox(line, delta);
999                    line->adjustBlockDirectionPosition(delta.toFloat());
1000                }
1001                if (Vector<RenderBox*>* cleanLineFloats = line->floatsPtr()) {
1002                    Vector<RenderBox*>::iterator end = cleanLineFloats->end();
1003                    for (Vector<RenderBox*>::iterator f = cleanLineFloats->begin(); f != end; ++f) {
1004                        FloatingObject* floatingObject = insertFloatingObject(*f);
1005                        ASSERT(!floatingObject->originatingLine());
1006                        floatingObject->setOriginatingLine(line);
1007                        setLogicalHeight(logicalTopForChild(*f) - marginBeforeForChild(*f) + delta);
1008                        positionNewFloats();
1009                    }
1010                }
1011            }
1012            setLogicalHeight(lastRootBox()->lineBottomWithLeading());
1013        } else {
1014            // Delete all the remaining lines.
1015            deleteLineRange(layoutState, layoutState.endLine());
1016        }
1017    }
1018
1019    if (m_floatingObjects && (layoutState.checkForFloatsFromLastLine() || positionNewFloats()) && lastRootBox()) {
1020        // In case we have a float on the last line, it might not be positioned up to now.
1021        // This has to be done before adding in the bottom border/padding, or the float will
1022        // include the padding incorrectly. -dwh
1023        const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
1024        FloatingObjectSetIterator it = floatingObjectSet.begin();
1025        FloatingObjectSetIterator end = floatingObjectSet.end();
1026        if (layoutState.lastFloat()) {
1027            FloatingObjectSetIterator lastFloatIterator = floatingObjectSet.find(layoutState.lastFloat());
1028            ASSERT(lastFloatIterator != end);
1029            ++lastFloatIterator;
1030            it = lastFloatIterator;
1031        }
1032        layoutState.setLastFloat(!floatingObjectSet.isEmpty() ? floatingObjectSet.last().get() : 0);
1033
1034        if (it == end)
1035            return;
1036
1037        if (layoutState.checkForFloatsFromLastLine()) {
1038            LayoutUnit bottomVisualOverflow = lastRootBox()->logicalBottomVisualOverflow();
1039            LayoutUnit bottomLayoutOverflow = lastRootBox()->logicalBottomLayoutOverflow();
1040            TrailingFloatsRootInlineBox* trailingFloatsLineBox = new TrailingFloatsRootInlineBox(*this);
1041            m_lineBoxes.appendLineBox(trailingFloatsLineBox);
1042            trailingFloatsLineBox->setConstructed();
1043            GlyphOverflowAndFallbackFontsMap textBoxDataMap;
1044            VerticalPositionCache verticalPositionCache;
1045            LayoutUnit blockLogicalHeight = logicalHeight();
1046            trailingFloatsLineBox->alignBoxesInBlockDirection(blockLogicalHeight, textBoxDataMap, verticalPositionCache);
1047            trailingFloatsLineBox->setLineTopBottomPositions(blockLogicalHeight, blockLogicalHeight, blockLogicalHeight, blockLogicalHeight);
1048            trailingFloatsLineBox->setPaginatedLineWidth(availableLogicalWidthForContent());
1049            LayoutRect logicalLayoutOverflow(0, blockLogicalHeight, 1, bottomLayoutOverflow - blockLogicalHeight);
1050            LayoutRect logicalVisualOverflow(0, blockLogicalHeight, 1, bottomVisualOverflow - blockLogicalHeight);
1051            trailingFloatsLineBox->setOverflowFromLogicalRects(logicalLayoutOverflow, logicalVisualOverflow, trailingFloatsLineBox->lineTop(), trailingFloatsLineBox->lineBottom());
1052        }
1053
1054        for (; it != end; ++it)
1055            appendFloatingObjectToLastLine(it->get());
1056    }
1057}
1058
1059void RenderBlockFlow::markDirtyFloatsForPaintInvalidation(Vector<FloatWithRect>& floats)
1060{
1061    size_t floatCount = floats.size();
1062    // Floats that did not have layout did not paint invalidations when we laid them out. They would have
1063    // painted by now if they had moved, but if they stayed at (0, 0), they still need to be
1064    // painted.
1065    for (size_t i = 0; i < floatCount; ++i) {
1066        if (!floats[i].everHadLayout) {
1067            RenderBox* f = floats[i].object;
1068            if (!f->x() && !f->y() && f->checkForPaintInvalidation()) {
1069                f->setShouldDoFullPaintInvalidation(true);
1070            }
1071        }
1072    }
1073}
1074
1075struct InlineMinMaxIterator {
1076/* InlineMinMaxIterator is a class that will iterate over all render objects that contribute to
1077   inline min/max width calculations.  Note the following about the way it walks:
1078   (1) Positioned content is skipped (since it does not contribute to min/max width of a block)
1079   (2) We do not drill into the children of floats or replaced elements, since you can't break
1080       in the middle of such an element.
1081   (3) Inline flows (e.g., <a>, <span>, <i>) are walked twice, since each side can have
1082       distinct borders/margin/padding that contribute to the min/max width.
1083*/
1084    RenderObject* parent;
1085    RenderObject* current;
1086    bool endOfInline;
1087
1088    InlineMinMaxIterator(RenderObject* p, bool end = false)
1089        : parent(p), current(p), endOfInline(end)
1090    {
1091
1092    }
1093
1094    RenderObject* next();
1095};
1096
1097RenderObject* InlineMinMaxIterator::next()
1098{
1099    RenderObject* result = 0;
1100    bool oldEndOfInline = endOfInline;
1101    endOfInline = false;
1102    while (current || current == parent) {
1103        if (!oldEndOfInline && (current == parent || (!current->isFloating() && !current->isReplaced() && !current->isOutOfFlowPositioned())))
1104            result = current->slowFirstChild();
1105
1106        if (!result) {
1107            // We hit the end of our inline. (It was empty, e.g., <span></span>.)
1108            if (!oldEndOfInline && current->isRenderInline()) {
1109                result = current;
1110                endOfInline = true;
1111                break;
1112            }
1113
1114            while (current && current != parent) {
1115                result = current->nextSibling();
1116                if (result)
1117                    break;
1118                current = current->parent();
1119                if (current && current != parent && current->isRenderInline()) {
1120                    result = current;
1121                    endOfInline = true;
1122                    break;
1123                }
1124            }
1125        }
1126
1127        if (!result)
1128            break;
1129
1130        if (!result->isOutOfFlowPositioned() && (result->isText() || result->isFloating() || result->isReplaced() || result->isRenderInline()))
1131            break;
1132
1133        current = result;
1134        result = 0;
1135    }
1136
1137    // Update our position.
1138    current = result;
1139    return current;
1140}
1141
1142static LayoutUnit getBPMWidth(LayoutUnit childValue, Length cssUnit)
1143{
1144    if (cssUnit.type() != Auto)
1145        return (cssUnit.isFixed() ? static_cast<LayoutUnit>(cssUnit.value()) : childValue);
1146    return 0;
1147}
1148
1149static LayoutUnit getBorderPaddingMargin(RenderBoxModelObject* child, bool endOfInline)
1150{
1151    RenderStyle* childStyle = child->style();
1152    if (endOfInline) {
1153        return getBPMWidth(child->marginEnd(), childStyle->marginEnd()) +
1154            getBPMWidth(child->paddingEnd(), childStyle->paddingEnd()) +
1155            child->borderEnd();
1156    }
1157    return getBPMWidth(child->marginStart(), childStyle->marginStart()) +
1158        getBPMWidth(child->paddingStart(), childStyle->paddingStart()) +
1159        child->borderStart();
1160}
1161
1162static inline void stripTrailingSpace(float& inlineMax, float& inlineMin, RenderObject* trailingSpaceChild)
1163{
1164    if (trailingSpaceChild && trailingSpaceChild->isText()) {
1165        // Collapse away the trailing space at the end of a block.
1166        RenderText* t = toRenderText(trailingSpaceChild);
1167        const UChar space = ' ';
1168        const Font& font = t->style()->font(); // FIXME: This ignores first-line.
1169        float spaceWidth = font.width(constructTextRun(t, font, &space, 1, t->style(), LTR));
1170        inlineMax -= spaceWidth + font.fontDescription().wordSpacing();
1171        if (inlineMin > inlineMax)
1172            inlineMin = inlineMax;
1173    }
1174}
1175
1176static inline void updatePreferredWidth(LayoutUnit& preferredWidth, float& result)
1177{
1178    LayoutUnit snappedResult = LayoutUnit::fromFloatCeil(result);
1179    preferredWidth = std::max(snappedResult, preferredWidth);
1180}
1181
1182// When converting between floating point and LayoutUnits we risk losing precision
1183// with each conversion. When this occurs while accumulating our preferred widths,
1184// we can wind up with a line width that's larger than our maxPreferredWidth due to
1185// pure float accumulation.
1186static inline LayoutUnit adjustFloatForSubPixelLayout(float value)
1187{
1188    return LayoutUnit::fromFloatCeil(value);
1189}
1190
1191// FIXME: This function should be broken into something less monolithic.
1192// FIXME: The main loop here is very similar to LineBreaker::nextSegmentBreak. They can probably reuse code.
1193void RenderBlockFlow::computeInlinePreferredLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth)
1194{
1195    float inlineMax = 0;
1196    float inlineMin = 0;
1197
1198    RenderStyle* styleToUse = style();
1199    RenderBlock* containingBlock = this->containingBlock();
1200    LayoutUnit cw = containingBlock ? containingBlock->contentLogicalWidth() : LayoutUnit();
1201
1202    // If we are at the start of a line, we want to ignore all white-space.
1203    // Also strip spaces if we previously had text that ended in a trailing space.
1204    bool stripFrontSpaces = true;
1205    RenderObject* trailingSpaceChild = 0;
1206
1207    // Firefox and Opera will allow a table cell to grow to fit an image inside it under
1208    // very specific cirucumstances (in order to match common WinIE renderings).
1209    // Not supporting the quirk has caused us to mis-render some real sites. (See Bugzilla 10517.)
1210    bool allowImagesToBreak = !document().inQuirksMode() || !isTableCell() || !styleToUse->logicalWidth().isIntrinsicOrAuto();
1211
1212    bool autoWrap, oldAutoWrap;
1213    autoWrap = oldAutoWrap = styleToUse->autoWrap();
1214
1215    InlineMinMaxIterator childIterator(this);
1216
1217    // Only gets added to the max preffered width once.
1218    bool addedTextIndent = false;
1219    // Signals the text indent was more negative than the min preferred width
1220    bool hasRemainingNegativeTextIndent = false;
1221
1222    LayoutUnit textIndent = minimumValueForLength(styleToUse->textIndent(), cw);
1223    RenderObject* prevFloat = 0;
1224    bool isPrevChildInlineFlow = false;
1225    bool shouldBreakLineAfterText = false;
1226    while (RenderObject* child = childIterator.next()) {
1227        autoWrap = child->isReplaced() ? child->parent()->style()->autoWrap() :
1228            child->style()->autoWrap();
1229
1230        if (!child->isBR()) {
1231            // Step One: determine whether or not we need to go ahead and
1232            // terminate our current line. Each discrete chunk can become
1233            // the new min-width, if it is the widest chunk seen so far, and
1234            // it can also become the max-width.
1235
1236            // Children fall into three categories:
1237            // (1) An inline flow object. These objects always have a min/max of 0,
1238            // and are included in the iteration solely so that their margins can
1239            // be added in.
1240            //
1241            // (2) An inline non-text non-flow object, e.g., an inline replaced element.
1242            // These objects can always be on a line by themselves, so in this situation
1243            // we need to go ahead and break the current line, and then add in our own
1244            // margins and min/max width on its own line, and then terminate the line.
1245            //
1246            // (3) A text object. Text runs can have breakable characters at the start,
1247            // the middle or the end. They may also lose whitespace off the front if
1248            // we're already ignoring whitespace. In order to compute accurate min-width
1249            // information, we need three pieces of information.
1250            // (a) the min-width of the first non-breakable run. Should be 0 if the text string
1251            // starts with whitespace.
1252            // (b) the min-width of the last non-breakable run. Should be 0 if the text string
1253            // ends with whitespace.
1254            // (c) the min/max width of the string (trimmed for whitespace).
1255            //
1256            // If the text string starts with whitespace, then we need to go ahead and
1257            // terminate our current line (unless we're already in a whitespace stripping
1258            // mode.
1259            //
1260            // If the text string has a breakable character in the middle, but didn't start
1261            // with whitespace, then we add the width of the first non-breakable run and
1262            // then end the current line. We then need to use the intermediate min/max width
1263            // values (if any of them are larger than our current min/max). We then look at
1264            // the width of the last non-breakable run and use that to start a new line
1265            // (unless we end in whitespace).
1266            RenderStyle* childStyle = child->style();
1267            float childMin = 0;
1268            float childMax = 0;
1269
1270            if (!child->isText()) {
1271                // Case (1) and (2). Inline replaced and inline flow elements.
1272                if (child->isRenderInline()) {
1273                    // Add in padding/border/margin from the appropriate side of
1274                    // the element.
1275                    float bpm = getBorderPaddingMargin(toRenderInline(child), childIterator.endOfInline).toFloat();
1276                    childMin += bpm;
1277                    childMax += bpm;
1278
1279                    inlineMin += childMin;
1280                    inlineMax += childMax;
1281
1282                    child->clearPreferredLogicalWidthsDirty();
1283                } else {
1284                    // Inline replaced elts add in their margins to their min/max values.
1285                    LayoutUnit margins = 0;
1286                    Length startMargin = childStyle->marginStart();
1287                    Length endMargin = childStyle->marginEnd();
1288                    if (startMargin.isFixed())
1289                        margins += adjustFloatForSubPixelLayout(startMargin.value());
1290                    if (endMargin.isFixed())
1291                        margins += adjustFloatForSubPixelLayout(endMargin.value());
1292                    childMin += margins.ceilToFloat();
1293                    childMax += margins.ceilToFloat();
1294                }
1295            }
1296
1297            if (!child->isRenderInline() && !child->isText()) {
1298                // Case (2). Inline replaced elements and floats.
1299                // Go ahead and terminate the current line as far as
1300                // minwidth is concerned.
1301                LayoutUnit childMinPreferredLogicalWidth, childMaxPreferredLogicalWidth;
1302                if (child->isBox() && child->isHorizontalWritingMode() != isHorizontalWritingMode()) {
1303                    RenderBox* childBox = toRenderBox(child);
1304                    LogicalExtentComputedValues computedValues;
1305                    childBox->computeLogicalHeight(childBox->borderAndPaddingLogicalHeight(), 0, computedValues);
1306                    childMinPreferredLogicalWidth = childMaxPreferredLogicalWidth = computedValues.m_extent;
1307                } else {
1308                    childMinPreferredLogicalWidth = child->minPreferredLogicalWidth();
1309                    childMaxPreferredLogicalWidth = child->maxPreferredLogicalWidth();
1310                }
1311                childMin += childMinPreferredLogicalWidth.ceilToFloat();
1312                childMax += childMaxPreferredLogicalWidth.ceilToFloat();
1313
1314                bool clearPreviousFloat;
1315                if (child->isFloating()) {
1316                    clearPreviousFloat = (prevFloat
1317                        && ((prevFloat->style()->floating() == LeftFloat && (childStyle->clear() & CLEFT))
1318                            || (prevFloat->style()->floating() == RightFloat && (childStyle->clear() & CRIGHT))));
1319                    prevFloat = child;
1320                } else {
1321                    clearPreviousFloat = false;
1322                }
1323
1324                bool canBreakReplacedElement = !child->isImage() || allowImagesToBreak;
1325                if ((canBreakReplacedElement && (autoWrap || oldAutoWrap) && (!isPrevChildInlineFlow || shouldBreakLineAfterText)) || clearPreviousFloat) {
1326                    updatePreferredWidth(minLogicalWidth, inlineMin);
1327                    inlineMin = 0;
1328                }
1329
1330                // If we're supposed to clear the previous float, then terminate maxwidth as well.
1331                if (clearPreviousFloat) {
1332                    updatePreferredWidth(maxLogicalWidth, inlineMax);
1333                    inlineMax = 0;
1334                }
1335
1336                // Add in text-indent. This is added in only once.
1337                if (!addedTextIndent && !child->isFloating()) {
1338                    float ceiledTextIndent = textIndent.ceilToFloat();
1339                    childMin += ceiledTextIndent;
1340                    childMax += ceiledTextIndent;
1341
1342                    if (childMin < 0)
1343                        textIndent = adjustFloatForSubPixelLayout(childMin);
1344                    else
1345                        addedTextIndent = true;
1346                }
1347
1348                // Add our width to the max.
1349                inlineMax += std::max<float>(0, childMax);
1350
1351                if (!autoWrap || !canBreakReplacedElement || (isPrevChildInlineFlow && !shouldBreakLineAfterText)) {
1352                    if (child->isFloating())
1353                        updatePreferredWidth(minLogicalWidth, childMin);
1354                    else
1355                        inlineMin += childMin;
1356                } else {
1357                    // Now check our line.
1358                    updatePreferredWidth(minLogicalWidth, childMin);
1359
1360                    // Now start a new line.
1361                    inlineMin = 0;
1362                }
1363
1364                if (autoWrap && canBreakReplacedElement && isPrevChildInlineFlow) {
1365                    updatePreferredWidth(minLogicalWidth, inlineMin);
1366                    inlineMin = 0;
1367                }
1368
1369                // We are no longer stripping whitespace at the start of
1370                // a line.
1371                if (!child->isFloating()) {
1372                    stripFrontSpaces = false;
1373                    trailingSpaceChild = 0;
1374                }
1375            } else if (child->isText()) {
1376                // Case (3). Text.
1377                RenderText* t = toRenderText(child);
1378
1379                if (t->isWordBreak()) {
1380                    updatePreferredWidth(minLogicalWidth, inlineMin);
1381                    inlineMin = 0;
1382                    continue;
1383                }
1384
1385                if (t->style()->hasTextCombine() && t->isCombineText())
1386                    toRenderCombineText(t)->combineText();
1387
1388                // Determine if we have a breakable character. Pass in
1389                // whether or not we should ignore any spaces at the front
1390                // of the string. If those are going to be stripped out,
1391                // then they shouldn't be considered in the breakable char
1392                // check.
1393                bool hasBreakableChar, hasBreak;
1394                float firstLineMinWidth, lastLineMinWidth;
1395                bool hasBreakableStart, hasBreakableEnd;
1396                float firstLineMaxWidth, lastLineMaxWidth;
1397                t->trimmedPrefWidths(inlineMax,
1398                    firstLineMinWidth, hasBreakableStart, lastLineMinWidth, hasBreakableEnd,
1399                    hasBreakableChar, hasBreak, firstLineMaxWidth, lastLineMaxWidth,
1400                    childMin, childMax, stripFrontSpaces, styleToUse->direction());
1401
1402                // This text object will not be rendered, but it may still provide a breaking opportunity.
1403                if (!hasBreak && !childMax) {
1404                    if (autoWrap && (hasBreakableStart || hasBreakableEnd)) {
1405                        updatePreferredWidth(minLogicalWidth, inlineMin);
1406                        inlineMin = 0;
1407                    }
1408                    continue;
1409                }
1410
1411                if (stripFrontSpaces)
1412                    trailingSpaceChild = child;
1413                else
1414                    trailingSpaceChild = 0;
1415
1416                // Add in text-indent. This is added in only once.
1417                float ti = 0;
1418                if (!addedTextIndent || hasRemainingNegativeTextIndent) {
1419                    ti = textIndent.ceilToFloat();
1420                    childMin += ti;
1421                    firstLineMinWidth += ti;
1422
1423                    // It the text indent negative and larger than the child minimum, we re-use the remainder
1424                    // in future minimum calculations, but using the negative value again on the maximum
1425                    // will lead to under-counting the max pref width.
1426                    if (!addedTextIndent) {
1427                        childMax += ti;
1428                        firstLineMaxWidth += ti;
1429                        addedTextIndent = true;
1430                    }
1431
1432                    if (childMin < 0) {
1433                        textIndent = childMin;
1434                        hasRemainingNegativeTextIndent = true;
1435                    }
1436                }
1437
1438                // If we have no breakable characters at all,
1439                // then this is the easy case. We add ourselves to the current
1440                // min and max and continue.
1441                if (!hasBreakableChar) {
1442                    inlineMin += childMin;
1443                } else {
1444                    if (hasBreakableStart) {
1445                        updatePreferredWidth(minLogicalWidth, inlineMin);
1446                    } else {
1447                        inlineMin += firstLineMinWidth;
1448                        updatePreferredWidth(minLogicalWidth, inlineMin);
1449                        childMin -= ti;
1450                    }
1451
1452                    inlineMin = childMin;
1453
1454                    if (hasBreakableEnd) {
1455                        updatePreferredWidth(minLogicalWidth, inlineMin);
1456                        inlineMin = 0;
1457                        shouldBreakLineAfterText = false;
1458                    } else {
1459                        updatePreferredWidth(minLogicalWidth, inlineMin);
1460                        inlineMin = lastLineMinWidth;
1461                        shouldBreakLineAfterText = true;
1462                    }
1463                }
1464
1465                if (hasBreak) {
1466                    inlineMax += firstLineMaxWidth;
1467                    updatePreferredWidth(maxLogicalWidth, inlineMax);
1468                    updatePreferredWidth(maxLogicalWidth, childMax);
1469                    inlineMax = lastLineMaxWidth;
1470                    addedTextIndent = true;
1471                } else {
1472                    inlineMax += std::max<float>(0, childMax);
1473                }
1474            }
1475
1476            // Ignore spaces after a list marker.
1477            if (child->isListMarker())
1478                stripFrontSpaces = true;
1479        } else {
1480            updatePreferredWidth(minLogicalWidth, inlineMin);
1481            updatePreferredWidth(maxLogicalWidth, inlineMax);
1482            inlineMin = inlineMax = 0;
1483            stripFrontSpaces = true;
1484            trailingSpaceChild = 0;
1485            addedTextIndent = true;
1486        }
1487
1488        if (!child->isText() && child->isRenderInline())
1489            isPrevChildInlineFlow = true;
1490        else
1491            isPrevChildInlineFlow = false;
1492
1493        oldAutoWrap = autoWrap;
1494    }
1495
1496    if (styleToUse->collapseWhiteSpace())
1497        stripTrailingSpace(inlineMax, inlineMin, trailingSpaceChild);
1498
1499    updatePreferredWidth(minLogicalWidth, inlineMin);
1500    updatePreferredWidth(maxLogicalWidth, inlineMax);
1501}
1502
1503void RenderBlockFlow::layoutInlineChildren(bool relayoutChildren, LayoutUnit& paintInvalidationLogicalTop, LayoutUnit& paintInvalidationLogicalBottom, LayoutUnit afterEdge)
1504{
1505    RenderFlowThread* flowThread = flowThreadContainingBlock();
1506    bool clearLinesForPagination = firstLineBox() && flowThread && !flowThread->hasRegions();
1507
1508    // Figure out if we should clear out our line boxes.
1509    // FIXME: Handle resize eventually!
1510    bool isFullLayout = !firstLineBox() || selfNeedsLayout() || relayoutChildren || clearLinesForPagination;
1511    LineLayoutState layoutState(isFullLayout, paintInvalidationLogicalTop, paintInvalidationLogicalBottom, flowThread);
1512
1513    if (isFullLayout) {
1514        // Ensure the old line boxes will be erased.
1515        if (firstLineBox())
1516            setShouldDoFullPaintInvalidation(true);
1517        lineBoxes()->deleteLineBoxes();
1518    }
1519
1520    // Text truncation kicks in in two cases:
1521    //     1) If your overflow isn't visible and your text-overflow-mode isn't clip.
1522    //     2) If you're an anonymous block with a block parent that satisfies #1 that was created
1523    //        to accomodate a block that has inline and block children. This excludes parents where
1524    //        canCollapseAnonymousBlockChild is false, notabley flex items and grid items.
1525    // FIXME: CSS3 says that descendants that are clipped must also know how to truncate.  This is insanely
1526    // difficult to figure out in general (especially in the middle of doing layout), so we only handle the
1527    // simple case of an anonymous block truncating when it's parent is clipped.
1528    bool hasTextOverflow = (style()->textOverflow() && hasOverflowClip())
1529        || (isAnonymousBlock() && parent() && parent()->isRenderBlock() && toRenderBlock(parent())->canCollapseAnonymousBlockChild()
1530            && parent()->style()->textOverflow() && parent()->hasOverflowClip());
1531
1532    // Walk all the lines and delete our ellipsis line boxes if they exist.
1533    if (hasTextOverflow)
1534         deleteEllipsisLineBoxes();
1535
1536    if (firstChild()) {
1537        // In full layout mode, clear the line boxes of children upfront. Otherwise,
1538        // siblings can run into stale root lineboxes during layout. Then layout
1539        // the replaced elements later. In partial layout mode, line boxes are not
1540        // deleted and only dirtied. In that case, we can layout the replaced
1541        // elements at the same time.
1542        Vector<RenderBox*> replacedChildren;
1543        for (InlineWalker walker(this); !walker.atEnd(); walker.advance()) {
1544            RenderObject* o = walker.current();
1545
1546            if (!layoutState.hasInlineChild() && o->isInline())
1547                layoutState.setHasInlineChild(true);
1548
1549            if (o->isReplaced() || o->isFloating() || o->isOutOfFlowPositioned()) {
1550                RenderBox* box = toRenderBox(o);
1551
1552                updateBlockChildDirtyBitsBeforeLayout(relayoutChildren, box);
1553
1554                if (o->isOutOfFlowPositioned())
1555                    o->containingBlock()->insertPositionedObject(box);
1556                else if (o->isFloating())
1557                    layoutState.floats().append(FloatWithRect(box));
1558                else if (isFullLayout || o->needsLayout()) {
1559                    // Replaced element.
1560                    box->dirtyLineBoxes(isFullLayout);
1561                    if (isFullLayout)
1562                        replacedChildren.append(box);
1563                    else
1564                        o->layoutIfNeeded();
1565                }
1566            } else if (o->isText() || (o->isRenderInline() && !walker.atEndOfInline())) {
1567                if (!o->isText())
1568                    toRenderInline(o)->updateAlwaysCreateLineBoxes(layoutState.isFullLayout());
1569                if (layoutState.isFullLayout() || o->selfNeedsLayout())
1570                    dirtyLineBoxesForRenderer(o, layoutState.isFullLayout());
1571                o->clearNeedsLayout();
1572            }
1573        }
1574
1575        for (size_t i = 0; i < replacedChildren.size(); i++)
1576            replacedChildren[i]->layoutIfNeeded();
1577
1578        layoutRunsAndFloats(layoutState);
1579    }
1580
1581    // Expand the last line to accommodate Ruby and emphasis marks.
1582    int lastLineAnnotationsAdjustment = 0;
1583    if (lastRootBox()) {
1584        LayoutUnit lowestAllowedPosition = std::max(lastRootBox()->lineBottom(), logicalHeight() + paddingAfter());
1585        if (!style()->isFlippedLinesWritingMode())
1586            lastLineAnnotationsAdjustment = lastRootBox()->computeUnderAnnotationAdjustment(lowestAllowedPosition);
1587        else
1588            lastLineAnnotationsAdjustment = lastRootBox()->computeOverAnnotationAdjustment(lowestAllowedPosition);
1589    }
1590
1591    // Now add in the bottom border/padding.
1592    setLogicalHeight(logicalHeight() + lastLineAnnotationsAdjustment + afterEdge);
1593
1594    if (!firstLineBox() && hasLineIfEmpty())
1595        setLogicalHeight(logicalHeight() + lineHeight(true, isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes));
1596
1597    // See if we have any lines that spill out of our block.  If we do, then we will possibly need to
1598    // truncate text.
1599    if (hasTextOverflow)
1600        checkLinesForTextOverflow();
1601
1602    // Ensure the new line boxes will be painted.
1603    if (isFullLayout && firstLineBox())
1604        setShouldDoFullPaintInvalidation(true);
1605}
1606
1607void RenderBlockFlow::checkFloatsInCleanLine(RootInlineBox* line, Vector<FloatWithRect>& floats, size_t& floatIndex, bool& encounteredNewFloat, bool& dirtiedByFloat)
1608{
1609    Vector<RenderBox*>* cleanLineFloats = line->floatsPtr();
1610    if (!cleanLineFloats)
1611        return;
1612
1613    Vector<RenderBox*>::iterator end = cleanLineFloats->end();
1614    for (Vector<RenderBox*>::iterator it = cleanLineFloats->begin(); it != end; ++it) {
1615        RenderBox* floatingBox = *it;
1616        floatingBox->layoutIfNeeded();
1617        LayoutSize newSize(floatingBox->width() + floatingBox->marginWidth(), floatingBox->height() + floatingBox->marginHeight());
1618        if (floats[floatIndex].object != floatingBox) {
1619            encounteredNewFloat = true;
1620            return;
1621        }
1622
1623        if (floats[floatIndex].rect.size() != newSize) {
1624            LayoutUnit floatTop = isHorizontalWritingMode() ? floats[floatIndex].rect.y() : floats[floatIndex].rect.x();
1625            LayoutUnit floatHeight = isHorizontalWritingMode() ? std::max(floats[floatIndex].rect.height(), newSize.height())
1626                : std::max(floats[floatIndex].rect.width(), newSize.width());
1627            floatHeight = std::min(floatHeight, LayoutUnit::max() - floatTop);
1628            line->markDirty();
1629            markLinesDirtyInBlockRange(line->lineBottomWithLeading(), floatTop + floatHeight, line);
1630            floats[floatIndex].rect.setSize(newSize);
1631            dirtiedByFloat = true;
1632        }
1633        floatIndex++;
1634    }
1635}
1636
1637RootInlineBox* RenderBlockFlow::determineStartPosition(LineLayoutState& layoutState, InlineBidiResolver& resolver)
1638{
1639    RootInlineBox* curr = 0;
1640    RootInlineBox* last = 0;
1641
1642    // FIXME: This entire float-checking block needs to be broken into a new function.
1643    bool dirtiedByFloat = false;
1644    if (!layoutState.isFullLayout()) {
1645        // Paginate all of the clean lines.
1646        bool paginated = view()->layoutState() && view()->layoutState()->isPaginated();
1647        LayoutUnit paginationDelta = 0;
1648        size_t floatIndex = 0;
1649        for (curr = firstRootBox(); curr && !curr->isDirty(); curr = curr->nextRootBox()) {
1650            if (paginated) {
1651                paginationDelta -= curr->paginationStrut();
1652                adjustLinePositionForPagination(curr, paginationDelta, layoutState.flowThread());
1653                if (paginationDelta) {
1654                    if (containsFloats() || !layoutState.floats().isEmpty()) {
1655                        // FIXME: Do better eventually.  For now if we ever shift because of pagination and floats are present just go to a full layout.
1656                        layoutState.markForFullLayout();
1657                        break;
1658                    }
1659
1660                    layoutState.updatePaintInvalidationRangeFromBox(curr, paginationDelta);
1661                    curr->adjustBlockDirectionPosition(paginationDelta.toFloat());
1662                }
1663            }
1664
1665            // If a new float has been inserted before this line or before its last known float, just do a full layout.
1666            bool encounteredNewFloat = false;
1667            checkFloatsInCleanLine(curr, layoutState.floats(), floatIndex, encounteredNewFloat, dirtiedByFloat);
1668            if (encounteredNewFloat)
1669                layoutState.markForFullLayout();
1670
1671            if (dirtiedByFloat || layoutState.isFullLayout())
1672                break;
1673        }
1674        // Check if a new float has been inserted after the last known float.
1675        if (!curr && floatIndex < layoutState.floats().size())
1676            layoutState.markForFullLayout();
1677    }
1678
1679    if (layoutState.isFullLayout()) {
1680        // If we encountered a new float and have inline children, mark ourself to force us to issue paint invalidations.
1681        if (layoutState.hasInlineChild() && !selfNeedsLayout()) {
1682            setNeedsLayoutAndFullPaintInvalidation(MarkOnlyThis);
1683            setShouldDoFullPaintInvalidation(true);
1684        }
1685
1686        // FIXME: This should just call deleteLineBoxTree, but that causes
1687        // crashes for fast/repaint tests.
1688        curr = firstRootBox();
1689        while (curr) {
1690            // Note: This uses nextRootBox() insted of nextLineBox() like deleteLineBoxTree does.
1691            RootInlineBox* next = curr->nextRootBox();
1692            curr->deleteLine();
1693            curr = next;
1694        }
1695        ASSERT(!firstLineBox() && !lastLineBox());
1696    } else {
1697        if (curr) {
1698            // We have a dirty line.
1699            if (RootInlineBox* prevRootBox = curr->prevRootBox()) {
1700                // We have a previous line.
1701                if (!dirtiedByFloat && (!prevRootBox->endsWithBreak() || !prevRootBox->lineBreakObj() || (prevRootBox->lineBreakObj()->isText() && prevRootBox->lineBreakPos() >= toRenderText(prevRootBox->lineBreakObj())->textLength())))
1702                    // The previous line didn't break cleanly or broke at a newline
1703                    // that has been deleted, so treat it as dirty too.
1704                    curr = prevRootBox;
1705            }
1706        } else {
1707            // No dirty lines were found.
1708            // If the last line didn't break cleanly, treat it as dirty.
1709            if (lastRootBox() && !lastRootBox()->endsWithBreak())
1710                curr = lastRootBox();
1711        }
1712
1713        // If we have no dirty lines, then last is just the last root box.
1714        last = curr ? curr->prevRootBox() : lastRootBox();
1715    }
1716
1717    unsigned numCleanFloats = 0;
1718    if (!layoutState.floats().isEmpty()) {
1719        LayoutUnit savedLogicalHeight = logicalHeight();
1720        // Restore floats from clean lines.
1721        RootInlineBox* line = firstRootBox();
1722        while (line != curr) {
1723            if (Vector<RenderBox*>* cleanLineFloats = line->floatsPtr()) {
1724                Vector<RenderBox*>::iterator end = cleanLineFloats->end();
1725                for (Vector<RenderBox*>::iterator f = cleanLineFloats->begin(); f != end; ++f) {
1726                    FloatingObject* floatingObject = insertFloatingObject(*f);
1727                    ASSERT(!floatingObject->originatingLine());
1728                    floatingObject->setOriginatingLine(line);
1729                    setLogicalHeight(logicalTopForChild(*f) - marginBeforeForChild(*f));
1730                    positionNewFloats();
1731                    ASSERT(layoutState.floats()[numCleanFloats].object == *f);
1732                    numCleanFloats++;
1733                }
1734            }
1735            line = line->nextRootBox();
1736        }
1737        setLogicalHeight(savedLogicalHeight);
1738    }
1739    layoutState.setFloatIndex(numCleanFloats);
1740
1741    layoutState.lineInfo().setFirstLine(!last);
1742    layoutState.lineInfo().setPreviousLineBrokeCleanly(!last || last->endsWithBreak());
1743
1744    if (last) {
1745        setLogicalHeight(last->lineBottomWithLeading());
1746        InlineIterator iter = InlineIterator(this, last->lineBreakObj(), last->lineBreakPos());
1747        resolver.setPosition(iter, numberOfIsolateAncestors(iter));
1748        resolver.setStatus(last->lineBreakBidiStatus());
1749    } else {
1750        TextDirection direction = style()->direction();
1751        if (style()->unicodeBidi() == Plaintext)
1752            direction = determinePlaintextDirectionality(this);
1753        resolver.setStatus(BidiStatus(direction, isOverride(style()->unicodeBidi())));
1754        InlineIterator iter = InlineIterator(this, bidiFirstSkippingEmptyInlines(this, resolver.runs(), &resolver), 0);
1755        resolver.setPosition(iter, numberOfIsolateAncestors(iter));
1756    }
1757    return curr;
1758}
1759
1760void RenderBlockFlow::determineEndPosition(LineLayoutState& layoutState, RootInlineBox* startLine, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus)
1761{
1762    ASSERT(!layoutState.endLine());
1763    size_t floatIndex = layoutState.floatIndex();
1764    RootInlineBox* last = 0;
1765    for (RootInlineBox* curr = startLine->nextRootBox(); curr; curr = curr->nextRootBox()) {
1766        if (!curr->isDirty()) {
1767            bool encounteredNewFloat = false;
1768            bool dirtiedByFloat = false;
1769            checkFloatsInCleanLine(curr, layoutState.floats(), floatIndex, encounteredNewFloat, dirtiedByFloat);
1770            if (encounteredNewFloat)
1771                return;
1772        }
1773        if (curr->isDirty())
1774            last = 0;
1775        else if (!last)
1776            last = curr;
1777    }
1778
1779    if (!last)
1780        return;
1781
1782    // At this point, |last| is the first line in a run of clean lines that ends with the last line
1783    // in the block.
1784
1785    RootInlineBox* prev = last->prevRootBox();
1786    cleanLineStart = InlineIterator(this, prev->lineBreakObj(), prev->lineBreakPos());
1787    cleanLineBidiStatus = prev->lineBreakBidiStatus();
1788    layoutState.setEndLineLogicalTop(prev->lineBottomWithLeading());
1789
1790    for (RootInlineBox* line = last; line; line = line->nextRootBox())
1791        line->extractLine(); // Disconnect all line boxes from their render objects while preserving
1792                             // their connections to one another.
1793
1794    layoutState.setEndLine(last);
1795}
1796
1797bool RenderBlockFlow::checkPaginationAndFloatsAtEndLine(LineLayoutState& layoutState)
1798{
1799    LayoutUnit lineDelta = logicalHeight() - layoutState.endLineLogicalTop();
1800
1801    bool paginated = view()->layoutState() && view()->layoutState()->isPaginated();
1802    if (paginated && layoutState.flowThread()) {
1803        // Check all lines from here to the end, and see if the hypothetical new position for the lines will result
1804        // in a different available line width.
1805        for (RootInlineBox* lineBox = layoutState.endLine(); lineBox; lineBox = lineBox->nextRootBox()) {
1806            if (paginated) {
1807                // This isn't the real move we're going to do, so don't update the line box's pagination
1808                // strut yet.
1809                LayoutUnit oldPaginationStrut = lineBox->paginationStrut();
1810                lineDelta -= oldPaginationStrut;
1811                adjustLinePositionForPagination(lineBox, lineDelta, layoutState.flowThread());
1812                lineBox->setPaginationStrut(oldPaginationStrut);
1813            }
1814        }
1815    }
1816
1817    if (!lineDelta || !m_floatingObjects)
1818        return true;
1819
1820    // See if any floats end in the range along which we want to shift the lines vertically.
1821    LayoutUnit logicalTop = std::min(logicalHeight(), layoutState.endLineLogicalTop());
1822
1823    RootInlineBox* lastLine = layoutState.endLine();
1824    while (RootInlineBox* nextLine = lastLine->nextRootBox())
1825        lastLine = nextLine;
1826
1827    LayoutUnit logicalBottom = lastLine->lineBottomWithLeading() + absoluteValue(lineDelta);
1828
1829    const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
1830    FloatingObjectSetIterator end = floatingObjectSet.end();
1831    for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
1832        FloatingObject* floatingObject = it->get();
1833        if (logicalBottomForFloat(floatingObject) >= logicalTop && logicalBottomForFloat(floatingObject) < logicalBottom)
1834            return false;
1835    }
1836
1837    return true;
1838}
1839
1840bool RenderBlockFlow::matchedEndLine(LineLayoutState& layoutState, const InlineBidiResolver& resolver, const InlineIterator& endLineStart, const BidiStatus& endLineStatus)
1841{
1842    if (resolver.position() == endLineStart) {
1843        if (resolver.status() != endLineStatus)
1844            return false;
1845        return checkPaginationAndFloatsAtEndLine(layoutState);
1846    }
1847
1848    // The first clean line doesn't match, but we can check a handful of following lines to try
1849    // to match back up.
1850    static int numLines = 8; // The # of lines we're willing to match against.
1851    RootInlineBox* originalEndLine = layoutState.endLine();
1852    RootInlineBox* line = originalEndLine;
1853    for (int i = 0; i < numLines && line; i++, line = line->nextRootBox()) {
1854        if (line->lineBreakObj() == resolver.position().object() && line->lineBreakPos() == resolver.position().offset()) {
1855            // We have a match.
1856            if (line->lineBreakBidiStatus() != resolver.status())
1857                return false; // ...but the bidi state doesn't match.
1858
1859            bool matched = false;
1860            RootInlineBox* result = line->nextRootBox();
1861            layoutState.setEndLine(result);
1862            if (result) {
1863                layoutState.setEndLineLogicalTop(line->lineBottomWithLeading());
1864                matched = checkPaginationAndFloatsAtEndLine(layoutState);
1865            }
1866
1867            // Now delete the lines that we failed to sync.
1868            deleteLineRange(layoutState, originalEndLine, result);
1869            return matched;
1870        }
1871    }
1872
1873    return false;
1874}
1875
1876bool RenderBlockFlow::generatesLineBoxesForInlineChild(RenderObject* inlineObj)
1877
1878{
1879    ASSERT(inlineObj->parent() == this);
1880
1881    InlineIterator it(this, inlineObj, 0);
1882    // FIXME: We should pass correct value for WhitespacePosition.
1883    while (!it.atEnd() && !requiresLineBox(it))
1884        it.increment();
1885
1886    return !it.atEnd();
1887}
1888
1889
1890void RenderBlockFlow::addOverflowFromInlineChildren()
1891{
1892    LayoutUnit endPadding = hasOverflowClip() ? paddingEnd() : LayoutUnit();
1893    // FIXME: Need to find another way to do this, since scrollbars could show when we don't want them to.
1894    if (hasOverflowClip() && !endPadding && node() && node()->isRootEditableElement() && style()->isLeftToRightDirection())
1895        endPadding = 1;
1896    for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
1897        addLayoutOverflow(curr->paddedLayoutOverflowRect(endPadding));
1898        LayoutRect visualOverflow = curr->visualOverflowRect(curr->lineTop(), curr->lineBottom());
1899        addContentsVisualOverflow(visualOverflow);
1900    }
1901}
1902
1903void RenderBlockFlow::deleteEllipsisLineBoxes()
1904{
1905    ETextAlign textAlign = style()->textAlign();
1906    bool ltr = style()->isLeftToRightDirection();
1907    bool firstLine = true;
1908    for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
1909        if (curr->hasEllipsisBox()) {
1910            curr->clearTruncation();
1911
1912            // Shift the line back where it belongs if we cannot accomodate an ellipsis.
1913            float logicalLeft = logicalLeftOffsetForLine(curr->lineTop(), firstLine).toFloat();
1914            float availableLogicalWidth = logicalRightOffsetForLine(curr->lineTop(), false) - logicalLeft;
1915            float totalLogicalWidth = curr->logicalWidth();
1916            updateLogicalWidthForAlignment(textAlign, curr, 0, logicalLeft, totalLogicalWidth, availableLogicalWidth, 0);
1917
1918            if (ltr)
1919                curr->adjustLogicalPosition((logicalLeft - curr->logicalLeft()), 0);
1920            else
1921                curr->adjustLogicalPosition(-(curr->logicalLeft() - logicalLeft), 0);
1922        }
1923        firstLine = false;
1924    }
1925}
1926
1927void RenderBlockFlow::checkLinesForTextOverflow()
1928{
1929    // Determine the width of the ellipsis using the current font.
1930    // FIXME: CSS3 says this is configurable, also need to use 0x002E (FULL STOP) if horizontal ellipsis is "not renderable"
1931    const Font& font = style()->font();
1932    DEFINE_STATIC_LOCAL(AtomicString, ellipsisStr, (&horizontalEllipsis, 1));
1933    const Font& firstLineFont = firstLineStyle()->font();
1934    // FIXME: We should probably not hard-code the direction here. https://crbug.com/333004
1935    TextDirection ellipsisDirection = LTR;
1936    float firstLineEllipsisWidth = firstLineFont.width(constructTextRun(this, firstLineFont, &horizontalEllipsis, 1, firstLineStyle(), ellipsisDirection));
1937    float ellipsisWidth = (font == firstLineFont) ? firstLineEllipsisWidth : font.width(constructTextRun(this, font, &horizontalEllipsis, 1, style(), ellipsisDirection));
1938
1939    // For LTR text truncation, we want to get the right edge of our padding box, and then we want to see
1940    // if the right edge of a line box exceeds that.  For RTL, we use the left edge of the padding box and
1941    // check the left edge of the line box to see if it is less
1942    // Include the scrollbar for overflow blocks, which means we want to use "contentWidth()"
1943    bool ltr = style()->isLeftToRightDirection();
1944    ETextAlign textAlign = style()->textAlign();
1945    bool firstLine = true;
1946    for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
1947        float currLogicalLeft = curr->logicalLeft();
1948        LayoutUnit blockRightEdge = logicalRightOffsetForLine(curr->lineTop(), firstLine);
1949        LayoutUnit blockLeftEdge = logicalLeftOffsetForLine(curr->lineTop(), firstLine);
1950        LayoutUnit lineBoxEdge = ltr ? currLogicalLeft + curr->logicalWidth() : currLogicalLeft;
1951        if ((ltr && lineBoxEdge > blockRightEdge) || (!ltr && lineBoxEdge < blockLeftEdge)) {
1952            // This line spills out of our box in the appropriate direction.  Now we need to see if the line
1953            // can be truncated.  In order for truncation to be possible, the line must have sufficient space to
1954            // accommodate our truncation string, and no replaced elements (images, tables) can overlap the ellipsis
1955            // space.
1956
1957            LayoutUnit width = firstLine ? firstLineEllipsisWidth : ellipsisWidth;
1958            LayoutUnit blockEdge = ltr ? blockRightEdge : blockLeftEdge;
1959            if (curr->lineCanAccommodateEllipsis(ltr, blockEdge, lineBoxEdge, width)) {
1960                float totalLogicalWidth = curr->placeEllipsis(ellipsisStr, ltr, blockLeftEdge.toFloat(), blockRightEdge.toFloat(), width.toFloat());
1961
1962                float logicalLeft = 0; // We are only intersted in the delta from the base position.
1963                float availableLogicalWidth = (blockRightEdge - blockLeftEdge).toFloat();
1964                updateLogicalWidthForAlignment(textAlign, curr, 0, logicalLeft, totalLogicalWidth, availableLogicalWidth, 0);
1965                if (ltr)
1966                    curr->adjustLogicalPosition(logicalLeft, 0);
1967                else
1968                    curr->adjustLogicalPosition(logicalLeft - (availableLogicalWidth - totalLogicalWidth), 0);
1969            }
1970        }
1971        firstLine = false;
1972    }
1973}
1974
1975bool RenderBlockFlow::positionNewFloatOnLine(FloatingObject* newFloat, FloatingObject* lastFloatFromPreviousLine, LineInfo& lineInfo, LineWidth& width)
1976{
1977    if (!positionNewFloats())
1978        return false;
1979
1980    width.shrinkAvailableWidthForNewFloatIfNeeded(newFloat);
1981
1982    // We only connect floats to lines for pagination purposes if the floats occur at the start of
1983    // the line and the previous line had a hard break (so this line is either the first in the block
1984    // or follows a <br>).
1985    if (!newFloat->paginationStrut() || !lineInfo.previousLineBrokeCleanly() || !lineInfo.isEmpty())
1986        return true;
1987
1988    const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
1989    ASSERT(floatingObjectSet.last() == newFloat);
1990
1991    LayoutUnit floatLogicalTop = logicalTopForFloat(newFloat);
1992    int paginationStrut = newFloat->paginationStrut();
1993
1994    if (floatLogicalTop - paginationStrut != logicalHeight() + lineInfo.floatPaginationStrut())
1995        return true;
1996
1997    FloatingObjectSetIterator it = floatingObjectSet.end();
1998    --it; // Last float is newFloat, skip that one.
1999    FloatingObjectSetIterator begin = floatingObjectSet.begin();
2000    while (it != begin) {
2001        --it;
2002        FloatingObject* floatingObject = it->get();
2003        if (floatingObject == lastFloatFromPreviousLine)
2004            break;
2005        if (logicalTopForFloat(floatingObject) == logicalHeight() + lineInfo.floatPaginationStrut()) {
2006            floatingObject->setPaginationStrut(paginationStrut + floatingObject->paginationStrut());
2007            RenderBox* floatBox = floatingObject->renderer();
2008            setLogicalTopForChild(floatBox, logicalTopForChild(floatBox) + marginBeforeForChild(floatBox) + paginationStrut);
2009            if (floatBox->isRenderBlock())
2010                floatBox->forceChildLayout();
2011            else
2012                floatBox->layoutIfNeeded();
2013            // Save the old logical top before calling removePlacedObject which will set
2014            // isPlaced to false. Otherwise it will trigger an assert in logicalTopForFloat.
2015            LayoutUnit oldLogicalTop = logicalTopForFloat(floatingObject);
2016            m_floatingObjects->removePlacedObject(floatingObject);
2017            setLogicalTopForFloat(floatingObject, oldLogicalTop + paginationStrut);
2018            m_floatingObjects->addPlacedObject(floatingObject);
2019        }
2020    }
2021
2022    // Just update the line info's pagination strut without altering our logical height yet. If the line ends up containing
2023    // no content, then we don't want to improperly grow the height of the block.
2024    lineInfo.setFloatPaginationStrut(lineInfo.floatPaginationStrut() + paginationStrut);
2025    return true;
2026}
2027
2028LayoutUnit RenderBlockFlow::startAlignedOffsetForLine(LayoutUnit position, bool firstLine)
2029{
2030    ETextAlign textAlign = style()->textAlign();
2031
2032    if (textAlign == TASTART) // FIXME: Handle TAEND here
2033        return startOffsetForLine(position, firstLine);
2034
2035    // updateLogicalWidthForAlignment() handles the direction of the block so no need to consider it here
2036    float totalLogicalWidth = 0;
2037    float logicalLeft = logicalLeftOffsetForLine(logicalHeight(), false).toFloat();
2038    float availableLogicalWidth = logicalRightOffsetForLine(logicalHeight(), false) - logicalLeft;
2039    updateLogicalWidthForAlignment(textAlign, 0, 0, logicalLeft, totalLogicalWidth, availableLogicalWidth, 0);
2040
2041    if (!style()->isLeftToRightDirection())
2042        return logicalWidth() - logicalLeft;
2043    return logicalLeft;
2044}
2045
2046}
2047