18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
32fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All right reserved.
4d0825bca7fe65beaee391d30da42e937db621564Steve Block * Copyright (C) 2010 Google Inc. All rights reserved.
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is free software; you can redistribute it and/or
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modify it under the terms of the GNU Library General Public
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * License as published by the Free Software Foundation; either
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * version 2 of the License, or (at your option) any later version.
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is distributed in the hope that it will be useful,
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Library General Public License for more details.
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * You should have received a copy of the GNU Library General Public License
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * along with this library; see the file COPYING.LIB.  If not, write to
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Boston, MA 02110-1301, USA.
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "BidiResolver.h"
2606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen#include "Hyphenation.h"
278a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#include "InlineIterator.h"
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "InlineTextBox.h"
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Logging.h"
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RenderArena.h"
312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "RenderCombineText.h"
328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "RenderInline.h"
33545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch#include "RenderLayer.h"
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RenderListMarker.h"
352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "RenderRubyRun.h"
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RenderView.h"
3768513a70bcd92384395513322f1b801e7bf9c729Steve Block#include "Settings.h"
3881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#include "TextBreakIterator.h"
39ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch#include "TextRun.h"
40d0825bca7fe65beaee391d30da42e937db621564Steve Block#include "TrailingFloatsRootInlineBox.h"
416b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "VerticalPositionCache.h"
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "break_lines.h"
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/AlwaysInline.h>
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/RefCountedLeakCounter.h>
45635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include <wtf/StdLibExtras.h>
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/Vector.h>
4709b60ab8488b362c96df8f268613aafaeebfcfa1Steve Block#include <wtf/unicode/CharacterNames.h>
4809b60ab8488b362c96df8f268613aafaeebfcfa1Steve Block
4909b60ab8488b362c96df8f268613aafaeebfcfa1Steve Block#if ENABLE(SVG)
5009b60ab8488b362c96df8f268613aafaeebfcfa1Steve Block#include "RenderSVGInlineText.h"
5109b60ab8488b362c96df8f268613aafaeebfcfa1Steve Block#include "SVGRootInlineBox.h"
5209b60ab8488b362c96df8f268613aafaeebfcfa1Steve Block#endif
5309b60ab8488b362c96df8f268613aafaeebfcfa1Steve Block
547cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba#ifdef ANDROID_LAYOUT
557cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba#include "Frame.h"
567cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba#include "FrameTree.h"
577cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba#include "Settings.h"
587cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba#include "Text.h"
597cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba#include "HTMLNames.h"
607cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba#endif // ANDROID_LAYOUT
6106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace std;
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace WTF;
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace Unicode;
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// We don't let our line box tree for a single line get any deeper than this.
698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectconst unsigned cMaxLineDepth = 200;
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic inline int borderPaddingMarginStart(RenderInline* child)
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
73a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    return child->marginStart() + child->paddingStart() + child->borderStart();
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic inline int borderPaddingMarginEnd(RenderInline* child)
772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return child->marginEnd() + child->paddingEnd() + child->borderEnd();
792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
81a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochstatic int inlineLogicalWidth(RenderObject* child, bool start = true, bool end = true)
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    unsigned lineDepth = 1;
848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int extraWidth = 0;
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RenderObject* parent = child->parent();
862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    while (parent->isRenderInline() && lineDepth++ < cMaxLineDepth) {
872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        RenderInline* parentAsRenderInline = toRenderInline(parent);
888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        if (start && !child->previousSibling())
892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            extraWidth += borderPaddingMarginStart(parentAsRenderInline);
908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        if (end && !child->nextSibling())
912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            extraWidth += borderPaddingMarginEnd(parentAsRenderInline);
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        child = parent;
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        parent = child->parent();
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return extraWidth;
968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic void checkMidpoints(LineMidpointState& lineMidpointState, InlineIterator& lBreak)
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Check to see if our last midpoint is a start point beyond the line break.  If so,
1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // shave it off the list, and shave off a trailing space if the previous end point doesn't
1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // preserve whitespace.
1032bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (lBreak.m_obj && lineMidpointState.numMidpoints && !(lineMidpointState.numMidpoints % 2)) {
1040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        InlineIterator* midpoints = lineMidpointState.midpoints.data();
1050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        InlineIterator& endpoint = midpoints[lineMidpointState.numMidpoints - 2];
1060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        const InlineIterator& startpoint = midpoints[lineMidpointState.numMidpoints - 1];
1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        InlineIterator currpoint = endpoint;
1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        while (!currpoint.atEnd() && currpoint != startpoint && currpoint != lBreak)
1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            currpoint.increment();
1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (currpoint == lBreak) {
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // We hit the line break before the start point.  Shave off the start point.
1120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            lineMidpointState.numMidpoints--;
1132bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (endpoint.m_obj->style()->collapseWhiteSpace())
1142bde8e466a4451c7319e3a072d118917957d6554Steve Block                endpoint.m_pos--;
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic void addMidpoint(LineMidpointState& lineMidpointState, const InlineIterator& midpoint)
1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (lineMidpointState.midpoints.size() <= lineMidpointState.numMidpoints)
1220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        lineMidpointState.midpoints.grow(lineMidpointState.numMidpoints + 10);
1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    InlineIterator* midpoints = lineMidpointState.midpoints.data();
1250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    midpoints[lineMidpointState.numMidpoints++] = midpoint;
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic inline BidiRun* createRun(int start, int end, RenderObject* obj, InlineBidiResolver& resolver)
1292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
1302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return new (obj->renderArena()) BidiRun(start, end, obj, resolver.context(), resolver.dir());
1312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
1322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid RenderBlock::appendRunsForObject(BidiRunList<BidiRun>& runs, int start, int end, RenderObject* obj, InlineBidiResolver& resolver)
1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (start > end || obj->isFloating() ||
1362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        (obj->isPositioned() && !obj->style()->isOriginalDisplayInlineType() && !obj->container()->isRenderInline()))
1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    LineMidpointState& lineMidpointState = resolver.midpointState();
1400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    bool haveNextMidpoint = (lineMidpointState.currentMidpoint < lineMidpointState.numMidpoints);
1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    InlineIterator nextMidpoint;
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (haveNextMidpoint)
1430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        nextMidpoint = lineMidpointState.midpoints[lineMidpointState.currentMidpoint];
1440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (lineMidpointState.betweenMidpoints) {
1452bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (!(haveNextMidpoint && nextMidpoint.m_obj == obj))
1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // This is a new start point. Stop ignoring objects and
1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // adjust our start.
1490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        lineMidpointState.betweenMidpoints = false;
1502bde8e466a4451c7319e3a072d118917957d6554Steve Block        start = nextMidpoint.m_pos;
1510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        lineMidpointState.currentMidpoint++;
1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (start < end)
1532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return appendRunsForObject(runs, start, end, obj, resolver);
1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else {
1552bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (!haveNextMidpoint || (obj != nextMidpoint.m_obj)) {
1562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            runs.addRun(createRun(start, end, obj, resolver));
1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // An end midpoint has been encountered within our object.  We
1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // need to go ahead and append a run with our endpoint.
1622bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (static_cast<int>(nextMidpoint.m_pos + 1) <= end) {
1630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            lineMidpointState.betweenMidpoints = true;
1640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            lineMidpointState.currentMidpoint++;
1652bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (nextMidpoint.m_pos != UINT_MAX) { // UINT_MAX means stop at the object and don't include any of it.
1662bde8e466a4451c7319e3a072d118917957d6554Steve Block                if (static_cast<int>(nextMidpoint.m_pos + 1) > start)
1672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    runs.addRun(createRun(start, nextMidpoint.m_pos + 1, obj, resolver));
1682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                return appendRunsForObject(runs, nextMidpoint.m_pos + 1, end, obj, resolver);
1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
1708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else
1712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch           runs.addRun(createRun(start, end, obj, resolver));
1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic inline InlineBox* createInlineBoxForRenderer(RenderObject* obj, bool isRootLineBox, bool isOnlyRun = false)
1768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
1778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (isRootLineBox)
1780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return toRenderBlock(obj)->createAndAppendRootInlineBox();
1798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (obj->isText()) {
1818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        InlineTextBox* textBox = toRenderText(obj)->createInlineTextBox();
1828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // We only treat a box as text for a <br> if we are on a line by ourself or in strict mode
1838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // (Note the use of strict mode.  In "almost strict" mode, we don't treat the box for <br> as text.)
1848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        if (obj->isBR())
1855ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            textBox->setIsText(isOnlyRun || obj->document()->inNoQuirksMode());
1868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return textBox;
1878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
1888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (obj->isBox())
1908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return toRenderBox(obj)->createInlineBox();
1918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return toRenderInline(obj)->createAndAppendInlineFlowBox();
1938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
1948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic inline void dirtyLineBoxesForRenderer(RenderObject* o, bool fullLayout)
1968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
1978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (o->isText()) {
19881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (o->preferredLogicalWidthsDirty() && (o->isCounter() || o->isQuote()))
199bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen            toRenderText(o)->computePreferredLogicalWidths(0); // FIXME: Counters depend on this hack. No clue why. Should be investigated and removed.
2008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        toRenderText(o)->dirtyLineBoxes(fullLayout);
2018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    } else
2028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        toRenderInline(o)->dirtyLineBoxes(fullLayout);
2038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
2048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2052fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockstatic bool parentIsConstructedOrHaveNext(InlineFlowBox* parentBox)
2062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
2072fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    do {
2082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        if (parentBox->isConstructed() || parentBox->nextOnLine())
2092fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            return true;
2102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        parentBox = parentBox->parent();
2112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    } while (parentBox);
2122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return false;
2132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
2142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2152bde8e466a4451c7319e3a072d118917957d6554Steve BlockInlineFlowBox* RenderBlock::createLineBoxes(RenderObject* obj, bool firstLine, InlineBox* childBox)
2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // See if we have an unconstructed line box for this object that is also
2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // the last item on the line.
2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    unsigned lineDepth = 1;
2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    InlineFlowBox* parentBox = 0;
2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    InlineFlowBox* result = 0;
2222bde8e466a4451c7319e3a072d118917957d6554Steve Block    bool hasDefaultLineBoxContain = style()->lineBoxContain() == RenderStyle::initialLineBoxContain();
2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    do {
224635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        ASSERT(obj->isRenderInline() || obj == this);
2258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        RenderInline* inlineFlow = (obj != this) ? toRenderInline(obj) : 0;
2272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Get the last box we made for this render object.
2292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        parentBox = inlineFlow ? inlineFlow->lastLineBox() : toRenderBlock(obj)->lastLineBox();
2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        // If this box or its ancestor is constructed then it is from a previous line, and we need
2322fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        // to make a new box for our line.  If this box or its ancestor is unconstructed but it has
2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // something following it on the line, then we know we have to make a new box
2348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // as well.  In this situation our inline has actually been split in two on
2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // the same line (this can happen with very fancy language mixtures).
2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        bool constructedNewBox = false;
2372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        bool allowedToConstructNewBox = !hasDefaultLineBoxContain || !inlineFlow || inlineFlow->alwaysCreateLineBoxes();
2382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        bool canUseExistingParentBox = parentBox && !parentIsConstructedOrHaveNext(parentBox);
2392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (allowedToConstructNewBox && !canUseExistingParentBox) {
2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // We need to make a new box for this render object.  Once
2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // made, we need to place it at the end of the current line.
2428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            InlineBox* newBox = createInlineBoxForRenderer(obj, obj == this);
2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            ASSERT(newBox->isInlineFlowBox());
2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            parentBox = static_cast<InlineFlowBox*>(newBox);
2458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            parentBox->setFirstLineStyleBit(firstLine);
2462bde8e466a4451c7319e3a072d118917957d6554Steve Block            parentBox->setIsHorizontal(isHorizontalWritingMode());
2472bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (!hasDefaultLineBoxContain)
2482bde8e466a4451c7319e3a072d118917957d6554Steve Block                parentBox->clearDescendantsHaveSameLineHeightAndBaseline();
2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            constructedNewBox = true;
2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (constructedNewBox || canUseExistingParentBox) {
2532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            if (!result)
2542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                result = parentBox;
2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            // If we have hit the block itself, then |box| represents the root
2572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            // inline box for the line, and it doesn't have to be appended to any parent
2582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            // inline.
2592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            if (childBox)
2602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                parentBox->addToLine(childBox);
2618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            if (!constructedNewBox || obj == this)
2632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                break;
2648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            childBox = parentBox;
2662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
2678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // If we've exceeded our line depth, then jump straight to the root and skip all the remaining
2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // intermediate inline flows.
2708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        obj = (++lineDepth >= cMaxLineDepth) ? this : obj->parent();
2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } while (true);
2738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return result;
2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic bool reachedEndOfTextRenderer(const BidiRunList<BidiRun>& bidiRuns)
2782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
2792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    BidiRun* run = bidiRuns.logicallyLastRun();
2802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!run)
2812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return true;
2822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    unsigned int pos = run->stop();
2832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RenderObject* r = run->m_object;
2842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!r->isText() || r->isBR())
2852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
2862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RenderText* renderText = toRenderText(r);
2872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (pos >= renderText->textLength())
2882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return true;
2892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    while (isASCIISpace(renderText->characters()[pos])) {
2912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        pos++;
2922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (pos >= renderText->textLength())
2932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return true;
2942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
2952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return false;
2962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
2972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochRootInlineBox* RenderBlock::constructLine(BidiRunList<BidiRun>& bidiRuns, bool firstLine, bool lastLine)
2998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(bidiRuns.firstRun());
3018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
302a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    bool rootHasSelectedChildren = false;
3038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    InlineFlowBox* parentBox = 0;
3042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    for (BidiRun* r = bidiRuns.firstRun(); r; r = r->next()) {
3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Create a box for our object.
3062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        bool isOnlyRun = (bidiRuns.runCount() == 1);
3072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (bidiRuns.runCount() == 2 && !r->m_object->isListMarker())
3082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            isOnlyRun = (!style()->isLeftToRightDirection() ? bidiRuns.lastRun() : bidiRuns.firstRun())->m_object->isListMarker();
3098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        InlineBox* box = createInlineBoxForRenderer(r->m_object, false, isOnlyRun);
3118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        r->m_box = box;
3128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(box);
3145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (!box)
3155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            continue;
3165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
317a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (!rootHasSelectedChildren && box->renderer()->selectionState() != RenderObject::SelectionNone)
318a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            rootHasSelectedChildren = true;
319a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
3205f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // If we have no parent box yet, or if the run is not simply a sibling,
3215f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // then we need to construct inline boxes as necessary to properly enclose the
3225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // run's inline box.
3235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (!parentBox || parentBox->renderer() != r->m_object->parent())
3245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            // Create new inline boxes all the way back to the appropriate insertion point.
3252bde8e466a4451c7319e3a072d118917957d6554Steve Block            parentBox = createLineBoxes(r->m_object->parent(), firstLine, box);
3262bde8e466a4451c7319e3a072d118917957d6554Steve Block        else {
3272bde8e466a4451c7319e3a072d118917957d6554Steve Block            // Append the inline box to this line.
3282bde8e466a4451c7319e3a072d118917957d6554Steve Block            parentBox->addToLine(box);
3292bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
3305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
3315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        bool visuallyOrdered = r->m_object->style()->visuallyOrdered();
33281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        box->setBidiLevel(r->level());
3335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
3345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (box->isInlineTextBox()) {
3355f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            InlineTextBox* text = static_cast<InlineTextBox*>(box);
3365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            text->setStart(r->m_start);
3375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            text->setLen(r->m_stop - r->m_start);
3385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            text->m_dirOverride = r->dirOverride(visuallyOrdered);
33906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen            if (r->m_hasHyphen)
34006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                text->setHasHyphen(true);
3418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
3428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // We should have a root inline box.  It should be unconstructed and
3458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // be the last continuation of our line list.
3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(lastLineBox() && !lastLineBox()->isConstructed());
3478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
348a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // Set the m_selectedChildren flag on the root inline box if one of the leaf inline box
349a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // from the bidi runs walk above has a selection state.
350a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (rootHasSelectedChildren)
351a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        lastLineBox()->root()->setHasSelectedChildren(true);
352a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Set bits on our inline flow boxes that indicate which sides should
3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // paint borders/margins/padding.  This knowledge will ultimately be used when
3558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // we determine the horizontal positions and widths of all the inline boxes on
3568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // the line.
3572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool isLogicallyLastRunWrapped = bidiRuns.logicallyLastRun()->m_object && bidiRuns.logicallyLastRun()->m_object->isText() ? !reachedEndOfTextRenderer(bidiRuns) : true;
3582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    lastLineBox()->determineSpacingForFlowBoxes(lastLine, isLogicallyLastRunWrapped, bidiRuns.logicallyLastRun()->m_object);
3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Now mark the line boxes as being constructed.
3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    lastLineBox()->setConstructed();
3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Return the last line.
3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return lastRootBox();
3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
36781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen MurdochETextAlign RenderBlock::textAlignmentForLine(bool endsWithSoftBreak) const
36881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
36981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ETextAlign alignment = style()->textAlign();
37081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (!endsWithSoftBreak && alignment == JUSTIFY)
37181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        alignment = TAAUTO;
37281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
37381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return alignment;
37481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
37581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
3762bde8e466a4451c7319e3a072d118917957d6554Steve Blockstatic void updateLogicalWidthForLeftAlignedBlock(bool isLeftToRightDirection, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float availableLogicalWidth)
3772bde8e466a4451c7319e3a072d118917957d6554Steve Block{
3782bde8e466a4451c7319e3a072d118917957d6554Steve Block    // The direction of the block should determine what happens with wide lines.
3792bde8e466a4451c7319e3a072d118917957d6554Steve Block    // In particular with RTL blocks, wide lines should still spill out to the left.
3802bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (isLeftToRightDirection) {
3812bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (totalLogicalWidth > availableLogicalWidth && trailingSpaceRun)
3822bde8e466a4451c7319e3a072d118917957d6554Steve Block            trailingSpaceRun->m_box->setLogicalWidth(max<float>(0, trailingSpaceRun->m_box->logicalWidth() - totalLogicalWidth + availableLogicalWidth));
3832bde8e466a4451c7319e3a072d118917957d6554Steve Block        return;
3842bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
3852bde8e466a4451c7319e3a072d118917957d6554Steve Block
3862bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (trailingSpaceRun)
3872bde8e466a4451c7319e3a072d118917957d6554Steve Block        trailingSpaceRun->m_box->setLogicalWidth(0);
3882bde8e466a4451c7319e3a072d118917957d6554Steve Block    else if (totalLogicalWidth > availableLogicalWidth)
3892bde8e466a4451c7319e3a072d118917957d6554Steve Block        logicalLeft -= (totalLogicalWidth - availableLogicalWidth);
3902bde8e466a4451c7319e3a072d118917957d6554Steve Block}
3912bde8e466a4451c7319e3a072d118917957d6554Steve Block
3922bde8e466a4451c7319e3a072d118917957d6554Steve Blockstatic void updateLogicalWidthForRightAlignedBlock(bool isLeftToRightDirection, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float availableLogicalWidth)
3932bde8e466a4451c7319e3a072d118917957d6554Steve Block{
3942bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Wide lines spill out of the block based off direction.
3952bde8e466a4451c7319e3a072d118917957d6554Steve Block    // So even if text-align is right, if direction is LTR, wide lines should overflow out of the right
3962bde8e466a4451c7319e3a072d118917957d6554Steve Block    // side of the block.
3972bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (isLeftToRightDirection) {
3982bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (trailingSpaceRun) {
3992bde8e466a4451c7319e3a072d118917957d6554Steve Block            totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth();
4002bde8e466a4451c7319e3a072d118917957d6554Steve Block            trailingSpaceRun->m_box->setLogicalWidth(0);
4012bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
4022bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (totalLogicalWidth < availableLogicalWidth)
4032bde8e466a4451c7319e3a072d118917957d6554Steve Block            logicalLeft += availableLogicalWidth - totalLogicalWidth;
4042bde8e466a4451c7319e3a072d118917957d6554Steve Block        return;
4052bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
4062bde8e466a4451c7319e3a072d118917957d6554Steve Block
4072bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (totalLogicalWidth > availableLogicalWidth && trailingSpaceRun) {
4082bde8e466a4451c7319e3a072d118917957d6554Steve Block        trailingSpaceRun->m_box->setLogicalWidth(max<float>(0, trailingSpaceRun->m_box->logicalWidth() - totalLogicalWidth + availableLogicalWidth));
4092bde8e466a4451c7319e3a072d118917957d6554Steve Block        totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth();
4102bde8e466a4451c7319e3a072d118917957d6554Steve Block    } else
4112bde8e466a4451c7319e3a072d118917957d6554Steve Block        logicalLeft += availableLogicalWidth - totalLogicalWidth;
4122bde8e466a4451c7319e3a072d118917957d6554Steve Block}
4132bde8e466a4451c7319e3a072d118917957d6554Steve Block
4142bde8e466a4451c7319e3a072d118917957d6554Steve Blockstatic void updateLogicalWidthForCenterAlignedBlock(bool isLeftToRightDirection, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float availableLogicalWidth)
4152bde8e466a4451c7319e3a072d118917957d6554Steve Block{
4162bde8e466a4451c7319e3a072d118917957d6554Steve Block    float trailingSpaceWidth = 0;
4172bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (trailingSpaceRun) {
4182bde8e466a4451c7319e3a072d118917957d6554Steve Block        totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth();
4192bde8e466a4451c7319e3a072d118917957d6554Steve Block        trailingSpaceWidth = min(trailingSpaceRun->m_box->logicalWidth(), (availableLogicalWidth - totalLogicalWidth + 1) / 2);
4202bde8e466a4451c7319e3a072d118917957d6554Steve Block        trailingSpaceRun->m_box->setLogicalWidth(max<float>(0, trailingSpaceWidth));
4212bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
4222bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (isLeftToRightDirection)
4232bde8e466a4451c7319e3a072d118917957d6554Steve Block        logicalLeft += max<float>((availableLogicalWidth - totalLogicalWidth) / 2, 0);
4242bde8e466a4451c7319e3a072d118917957d6554Steve Block    else
4252bde8e466a4451c7319e3a072d118917957d6554Steve Block        logicalLeft += totalLogicalWidth > availableLogicalWidth ? (availableLogicalWidth - totalLogicalWidth) : (availableLogicalWidth - totalLogicalWidth) / 2 - trailingSpaceWidth;
4262bde8e466a4451c7319e3a072d118917957d6554Steve Block}
4272bde8e466a4451c7319e3a072d118917957d6554Steve Block
4282bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid RenderBlock::computeInlineDirectionPositionsForLine(RootInlineBox* lineBox, bool firstLine, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd,
4292bde8e466a4451c7319e3a072d118917957d6554Steve Block                                                         GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache)
4308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
43181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ETextAlign textAlign = textAlignmentForLine(!reachedEnd && !lineBox->endsWithBreak());
43281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    float logicalLeft = logicalLeftOffsetForLine(logicalHeight(), firstLine);
43381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    float availableLogicalWidth = logicalRightOffsetForLine(logicalHeight(), firstLine) - logicalLeft;
43481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
4358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool needsWordSpacing = false;
43681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    float totalLogicalWidth = lineBox->getFlowSpacingLogicalWidth();
4372fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    unsigned expansionOpportunityCount = 0;
4382fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    bool isAfterExpansion = true;
4392fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    Vector<unsigned, 16> expansionOpportunities;
4402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RenderObject* previousObject = 0;
4418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (BidiRun* r = firstRun; r; r = r->next()) {
4438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!r->m_box || r->m_object->isPositioned() || r->m_box->isLineBreak())
4448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue; // Positioned objects are only participating to figure out their
4458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                      // correct static x position.  They have no effect on the width.
4468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                      // Similarly, line break boxes have no effect on the width.
4478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (r->m_object->isText()) {
448635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            RenderText* rt = toRenderText(r->m_object);
4498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (textAlign == JUSTIFY && r != trailingSpaceRun) {
4512bde8e466a4451c7319e3a072d118917957d6554Steve Block                if (!isAfterExpansion)
4522bde8e466a4451c7319e3a072d118917957d6554Steve Block                    static_cast<InlineTextBox*>(r->m_box)->setCanHaveLeadingExpansion(true);
4532fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                unsigned opportunitiesInRun = Font::expansionOpportunityCount(rt->characters() + r->m_start, r->m_stop - r->m_start, r->m_box->direction(), isAfterExpansion);
4542fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                expansionOpportunities.append(opportunitiesInRun);
4552fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                expansionOpportunityCount += opportunitiesInRun;
4568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
4578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (int length = rt->textLength()) {
459635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                if (!r->m_start && needsWordSpacing && isSpaceOrNewline(rt->characters()[r->m_start]))
460a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                    totalLogicalWidth += rt->style(firstLine)->font().wordSpacing();
4618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                needsWordSpacing = !isSpaceOrNewline(rt->characters()[r->m_stop - 1]) && r->m_stop == length;
4628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
4635f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            HashSet<const SimpleFontData*> fallbackFonts;
464dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            GlyphOverflow glyphOverflow;
4652bde8e466a4451c7319e3a072d118917957d6554Steve Block
4662bde8e466a4451c7319e3a072d118917957d6554Steve Block            // Always compute glyph overflow if the block's line-box-contain value is "glyphs".
4672bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (lineBox->fitsToGlyphs()) {
4682bde8e466a4451c7319e3a072d118917957d6554Steve Block                // If we don't stick out of the root line's font box, then don't bother computing our glyph overflow. This optimization
4692bde8e466a4451c7319e3a072d118917957d6554Steve Block                // will keep us from computing glyph bounds in nearly all cases.
4702bde8e466a4451c7319e3a072d118917957d6554Steve Block                bool includeRootLine = lineBox->includesRootLineBoxFontOrLeading();
4712bde8e466a4451c7319e3a072d118917957d6554Steve Block                int baselineShift = lineBox->verticalPositionForBox(r->m_box, verticalPositionCache);
4722bde8e466a4451c7319e3a072d118917957d6554Steve Block                int rootDescent = includeRootLine ? lineBox->renderer()->style(firstLine)->font().fontMetrics().descent() : 0;
4732bde8e466a4451c7319e3a072d118917957d6554Steve Block                int rootAscent = includeRootLine ? lineBox->renderer()->style(firstLine)->font().fontMetrics().ascent() : 0;
4742bde8e466a4451c7319e3a072d118917957d6554Steve Block                int boxAscent = rt->style(firstLine)->font().fontMetrics().ascent() - baselineShift;
4752bde8e466a4451c7319e3a072d118917957d6554Steve Block                int boxDescent = rt->style(firstLine)->font().fontMetrics().descent() + baselineShift;
4762bde8e466a4451c7319e3a072d118917957d6554Steve Block                if (boxAscent > rootDescent ||  boxDescent > rootAscent)
4772bde8e466a4451c7319e3a072d118917957d6554Steve Block                    glyphOverflow.computeBounds = true;
4782bde8e466a4451c7319e3a072d118917957d6554Steve Block            }
4792bde8e466a4451c7319e3a072d118917957d6554Steve Block
48006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen            int hyphenWidth = 0;
48106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen            if (static_cast<InlineTextBox*>(r->m_box)->hasHyphen()) {
48206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                const AtomicString& hyphenString = rt->style()->hyphenString();
48306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                hyphenWidth = rt->style(firstLine)->font().width(TextRun(hyphenString.characters(), hyphenString.length()));
48406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen            }
485a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            r->m_box->setLogicalWidth(rt->width(r->m_start, r->m_stop - r->m_start, totalLogicalWidth, firstLine, &fallbackFonts, &glyphOverflow) + hyphenWidth);
48606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen            if (!fallbackFonts.isEmpty()) {
4875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                ASSERT(r->m_box->isText());
4886c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen                GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.add(static_cast<InlineTextBox*>(r->m_box), make_pair(Vector<const SimpleFontData*>(), GlyphOverflow())).first;
4896c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen                ASSERT(it->second.first.isEmpty());
4906c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen                copyToVector(fallbackFonts, it->second.first);
4912bde8e466a4451c7319e3a072d118917957d6554Steve Block                r->m_box->parent()->clearDescendantsHaveSameLineHeightAndBaseline();
4925f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            }
49306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen            if ((glyphOverflow.top || glyphOverflow.bottom || glyphOverflow.left || glyphOverflow.right)) {
494dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                ASSERT(r->m_box->isText());
4956c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen                GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.add(static_cast<InlineTextBox*>(r->m_box), make_pair(Vector<const SimpleFontData*>(), GlyphOverflow())).first;
4966c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen                it->second.second = glyphOverflow;
4972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                r->m_box->clearKnownToHaveNoOverflow();
498dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            }
4992fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        } else {
5002fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            isAfterExpansion = false;
5012fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            if (!r->m_object->isRenderInline()) {
5022fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                RenderBox* renderBox = toRenderBox(r->m_object);
5032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                if (renderBox->isRubyRun()) {
5042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    int startOverhang;
5052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    int endOverhang;
5062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    RenderObject* nextObject = 0;
5072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    for (BidiRun* runWithNextObject = r->next(); runWithNextObject; runWithNextObject = runWithNextObject->next()) {
5082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                        if (!runWithNextObject->m_object->isPositioned() && !runWithNextObject->m_box->isLineBreak()) {
5092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                            nextObject = runWithNextObject->m_object;
5102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                            break;
5112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                        }
5122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    }
5132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    toRenderRubyRun(renderBox)->getOverhang(firstLine, renderBox->style()->isLeftToRightDirection() ? previousObject : nextObject, renderBox->style()->isLeftToRightDirection() ? nextObject : previousObject, startOverhang, endOverhang);
5142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    setMarginStartForChild(renderBox, -startOverhang);
5152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    setMarginEndForChild(renderBox, -endOverhang);
5162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                }
5172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                r->m_box->setLogicalWidth(logicalWidthForChild(renderBox));
5182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                totalLogicalWidth += marginStartForChild(renderBox) + marginEndForChild(renderBox);
5192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            }
5208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
5218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
522a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        totalLogicalWidth += r->m_box->logicalWidth();
5232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        previousObject = r->m_object;
5248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (isAfterExpansion && !expansionOpportunities.isEmpty()) {
5272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        expansionOpportunities.last()--;
5282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        expansionOpportunityCount--;
5292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
5302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
5318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Armed with the total width of the line (without justification),
5328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // we now examine our text-align property in order to determine where to position the
5338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // objects horizontally.  The total width of the line can be increased if we end up
5348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // justifying text.
5350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    switch (textAlign) {
5368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        case LEFT:
5378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        case WEBKIT_LEFT:
5382bde8e466a4451c7319e3a072d118917957d6554Steve Block            updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
5398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
5408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        case JUSTIFY:
54181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            adjustInlineDirectionLineBounds(expansionOpportunityCount, logicalLeft, availableLogicalWidth);
54281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            if (expansionOpportunityCount) {
5438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (trailingSpaceRun) {
544a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                    totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth();
545bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen                    trailingSpaceRun->m_box->setLogicalWidth(0);
5468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
5478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                break;
5488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
5498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // fall through
5508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        case TAAUTO:
5518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // for right to left fall through to right aligned
552a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            if (style()->isLeftToRightDirection()) {
553a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                if (totalLogicalWidth > availableLogicalWidth && trailingSpaceRun)
55481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                    trailingSpaceRun->m_box->setLogicalWidth(max<float>(0, trailingSpaceRun->m_box->logicalWidth() - totalLogicalWidth + availableLogicalWidth));
5558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                break;
5568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
5578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        case RIGHT:
5588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        case WEBKIT_RIGHT:
5592bde8e466a4451c7319e3a072d118917957d6554Steve Block            updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
5608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
5618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        case CENTER:
5628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        case WEBKIT_CENTER:
5632bde8e466a4451c7319e3a072d118917957d6554Steve Block            updateLogicalWidthForCenterAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
5642bde8e466a4451c7319e3a072d118917957d6554Steve Block            break;
5652bde8e466a4451c7319e3a072d118917957d6554Steve Block        case TASTART:
566a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            if (style()->isLeftToRightDirection())
5672bde8e466a4451c7319e3a072d118917957d6554Steve Block                updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
5688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            else
5692bde8e466a4451c7319e3a072d118917957d6554Steve Block                updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
5702bde8e466a4451c7319e3a072d118917957d6554Steve Block            break;
5712bde8e466a4451c7319e3a072d118917957d6554Steve Block        case TAEND:
5722bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (style()->isLeftToRightDirection())
5732bde8e466a4451c7319e3a072d118917957d6554Steve Block                updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
5742bde8e466a4451c7319e3a072d118917957d6554Steve Block            else
5752bde8e466a4451c7319e3a072d118917957d6554Steve Block                updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
5768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
5778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5792bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (expansionOpportunityCount && availableLogicalWidth > totalLogicalWidth) {
5802fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        size_t i = 0;
5818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        for (BidiRun* r = firstRun; r; r = r->next()) {
5828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (!r->m_box || r == trailingSpaceRun)
5838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                continue;
5848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
585635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            if (r->m_object->isText()) {
5862fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                unsigned opportunitiesInRun = expansionOpportunities[i++];
5878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5882fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                ASSERT(opportunitiesInRun <= expansionOpportunityCount);
5898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // Only justify text if whitespace is collapsed.
5918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (r->m_object->style()->collapseWhiteSpace()) {
5922fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                    InlineTextBox* textBox = static_cast<InlineTextBox*>(r->m_box);
59381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                    float expansion = (availableLogicalWidth - totalLogicalWidth) * opportunitiesInRun / expansionOpportunityCount;
5942fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                    textBox->setExpansion(expansion);
5952fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                    totalLogicalWidth += expansion;
5968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
5972fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                expansionOpportunityCount -= opportunitiesInRun;
5982fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                if (!expansionOpportunityCount)
5998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    break;
6008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
6018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
6028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
6038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // The widths of all runs are now known.  We can now place every inline box (and
6058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // compute accurate widths for the inline flow boxes).
6068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    needsWordSpacing = false;
607a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    lineBox->placeBoxesInInlineDirection(logicalLeft, needsWordSpacing, textBoxDataMap);
6088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6106b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid RenderBlock::computeBlockDirectionPositionsForLine(RootInlineBox* lineBox, BidiRun* firstRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap,
6116b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                                                        VerticalPositionCache& verticalPositionCache)
6128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6136b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    setLogicalHeight(lineBox->alignBoxesInBlockDirection(logicalHeight(), textBoxDataMap, verticalPositionCache));
614a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    lineBox->setBlockLogicalHeight(logicalHeight());
6158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Now make sure we place replaced render objects correctly.
6178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (BidiRun* r = firstRun; r; r = r->next()) {
6185f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(r->m_box);
6198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!r->m_box)
6208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue; // Skip runs with no line boxes.
6218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Align positioned boxes with the top of the line box.  This is
6238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // a reasonable approximation of an appropriate y position.
6248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (r->m_object->isPositioned())
625a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            r->m_box->setLogicalTop(logicalHeight());
6268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Position is used to properly position both replaced elements and
6288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // to update the static normal flow x/y of positioned elements.
6298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        if (r->m_object->isText())
6308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            toRenderText(r->m_object)->positionLineBox(r->m_box);
6318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        else if (r->m_object->isBox())
6328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            toRenderBox(r->m_object)->positionLineBox(r->m_box);
6338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
6348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Positioned objects and zero-length text nodes destroy their boxes in
6358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // position(), which unnecessarily dirties the line.
6368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    lineBox->markDirty(false);
6378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool isCollapsibleSpace(UChar character, RenderText* renderer)
6408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (character == ' ' || character == '\t' || character == softHyphen)
6428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
6438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (character == '\n')
6448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return !renderer->style()->preserveNewline();
6458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (character == noBreakSpace)
6468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return renderer->style()->nbspMode() == SPACE;
6478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return false;
6488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6502bde8e466a4451c7319e3a072d118917957d6554Steve Block
6512bde8e466a4451c7319e3a072d118917957d6554Steve Blockstatic void setStaticPositions(RenderBlock* block, RenderBox* child)
6522bde8e466a4451c7319e3a072d118917957d6554Steve Block{
6532bde8e466a4451c7319e3a072d118917957d6554Steve Block    // FIXME: The math here is actually not really right. It's a best-guess approximation that
6542bde8e466a4451c7319e3a072d118917957d6554Steve Block    // will work for the common cases
6552bde8e466a4451c7319e3a072d118917957d6554Steve Block    RenderObject* containerBlock = child->container();
6562bde8e466a4451c7319e3a072d118917957d6554Steve Block    int blockHeight = block->logicalHeight();
6572bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (containerBlock->isRenderInline()) {
6582bde8e466a4451c7319e3a072d118917957d6554Steve Block        // A relative positioned inline encloses us. In this case, we also have to determine our
6592bde8e466a4451c7319e3a072d118917957d6554Steve Block        // position as though we were an inline. Set |staticInlinePosition| and |staticBlockPosition| on the relative positioned
6602bde8e466a4451c7319e3a072d118917957d6554Steve Block        // inline so that we can obtain the value later.
6612bde8e466a4451c7319e3a072d118917957d6554Steve Block        toRenderInline(containerBlock)->layer()->setStaticInlinePosition(block->startOffsetForLine(blockHeight, false));
6622bde8e466a4451c7319e3a072d118917957d6554Steve Block        toRenderInline(containerBlock)->layer()->setStaticBlockPosition(blockHeight);
6632bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
6642bde8e466a4451c7319e3a072d118917957d6554Steve Block
6652bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (child->style()->isOriginalDisplayInlineType())
6662bde8e466a4451c7319e3a072d118917957d6554Steve Block        child->layer()->setStaticInlinePosition(block->startOffsetForLine(blockHeight, false));
6672bde8e466a4451c7319e3a072d118917957d6554Steve Block    else
6682bde8e466a4451c7319e3a072d118917957d6554Steve Block        child->layer()->setStaticInlinePosition(block->borderAndPaddingStart());
6692bde8e466a4451c7319e3a072d118917957d6554Steve Block    child->layer()->setStaticBlockPosition(blockHeight);
6702bde8e466a4451c7319e3a072d118917957d6554Steve Block}
6712bde8e466a4451c7319e3a072d118917957d6554Steve Block
6722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochinline BidiRun* RenderBlock::handleTrailingSpaces(BidiRunList<BidiRun>& bidiRuns, BidiContext* currentContext)
6732bde8e466a4451c7319e3a072d118917957d6554Steve Block{
6742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!bidiRuns.runCount()
6752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        || !bidiRuns.logicallyLastRun()->m_object->style()->breakOnlyAfterWhiteSpace()
6762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        || !bidiRuns.logicallyLastRun()->m_object->style()->autoWrap())
6772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return 0;
6782bde8e466a4451c7319e3a072d118917957d6554Steve Block
6792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    BidiRun* trailingSpaceRun = bidiRuns.logicallyLastRun();
6802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RenderObject* lastObject = trailingSpaceRun->m_object;
6812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!lastObject->isText())
6822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return 0;
6832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
6842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RenderText* lastText = toRenderText(lastObject);
6852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const UChar* characters = lastText->characters();
6862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int firstSpace = trailingSpaceRun->stop();
6872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    while (firstSpace > trailingSpaceRun->start()) {
6882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        UChar current = characters[firstSpace - 1];
6892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!isCollapsibleSpace(current, lastText))
6902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            break;
6912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        firstSpace--;
6922bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
6932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (firstSpace == trailingSpaceRun->stop())
6942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return 0;
6952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
6962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    TextDirection direction = style()->direction();
6972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool shouldReorder = trailingSpaceRun != (direction == LTR ? bidiRuns.lastRun() : bidiRuns.firstRun());
6982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (firstSpace != trailingSpaceRun->start()) {
6992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        BidiContext* baseContext = currentContext;
7002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        while (BidiContext* parent = baseContext->parent())
7012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            baseContext = parent;
7022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
7032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        BidiRun* newTrailingRun = new (renderArena()) BidiRun(firstSpace, trailingSpaceRun->m_stop, trailingSpaceRun->m_object, baseContext, OtherNeutral);
7042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        trailingSpaceRun->m_stop = firstSpace;
7052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (direction == LTR)
7062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            bidiRuns.addRun(newTrailingRun);
7072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        else
7082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            bidiRuns.prependRun(newTrailingRun);
7092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        trailingSpaceRun = newTrailingRun;
7102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return trailingSpaceRun;
7112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
7122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!shouldReorder)
7132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return trailingSpaceRun;
7142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
7152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (direction == LTR) {
7162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        bidiRuns.moveRunToEnd(trailingSpaceRun);
7172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        trailingSpaceRun->m_level = 0;
7182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    } else {
7192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        bidiRuns.moveRunToBeginning(trailingSpaceRun);
7202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        trailingSpaceRun->m_level = 1;
7212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
7222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return trailingSpaceRun;
7232bde8e466a4451c7319e3a072d118917957d6554Steve Block}
7242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
7252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid RenderBlock::appendFloatingObjectToLastLine(FloatingObject* floatingObject)
7262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
72754cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block    ASSERT(!floatingObject->m_originatingLine);
72854cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block    floatingObject->m_originatingLine = lastRootBox();
7292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    lastRootBox()->appendFloat(floatingObject->renderer());
7302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
7312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
732a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogicalTop, int& repaintLogicalBottom)
7338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool useRepaintBounds = false;
7358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
736231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    m_overflow.clear();
7378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
738a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    setLogicalHeight(borderBefore() + paddingBefore());
7398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Figure out if we should clear out our line boxes.
7418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: Handle resize eventually!
742d0825bca7fe65beaee391d30da42e937db621564Steve Block    bool fullLayout = !firstLineBox() || selfNeedsLayout() || relayoutChildren;
7438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (fullLayout)
7448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        lineBoxes()->deleteLineBoxes(renderArena());
7458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Text truncation only kicks in if your overflow isn't visible and your text-overflow-mode isn't
7478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // clip.
7488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: CSS3 says that descendants that are clipped must also know how to truncate.  This is insanely
7498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // difficult to figure out (especially in the middle of doing layout), and is really an esoteric pile of nonsense
7508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // anyway, so we won't worry about following the draft here.
7518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool hasTextOverflow = style()->textOverflow() && hasOverflowClip();
7528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Walk all the lines and delete our ellipsis line boxes if they exist.
7548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (hasTextOverflow)
7558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project         deleteEllipsisLineBoxes();
7568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (firstChild()) {
7587cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba#ifdef ANDROID_LAYOUT
7598e7024d69d9885dc2d064817dae1acd41badc23fGrace Kloba        // if we are in fitColumnToScreen mode
7607cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba        // and the current object is not float:right in LTR or not float:left in RTL,
7617cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba        // and text align is auto, or justify or left in LTR, or right in RTL, we
7627cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba        // will wrap text around screen width so that it doesn't need to scroll
7637cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba        // horizontally when reading a paragraph.
764ef5ff0dbc68f344b819b75af5dc5bcc7bda8f411Shimeng (Simon) Wang        // In case the line height is less than the font size, we skip
765ef5ff0dbc68f344b819b75af5dc5bcc7bda8f411Shimeng (Simon) Wang        // the text wrapping since this will cause text overlapping.
766c2af0ea11e14d459b597600184bf0e2a805a29aeShimeng (Simon) Wang        // If a text has background image, we ignore text wrapping,
767c2af0ea11e14d459b597600184bf0e2a805a29aeShimeng (Simon) Wang        // otherwise the background will be potentially messed up.
7687cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba        const Settings* settings = document()->settings();
7698e7024d69d9885dc2d064817dae1acd41badc23fGrace Kloba        bool doTextWrap = settings && settings->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen;
7707cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba        if (doTextWrap) {
7717cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba            int ta = style()->textAlign();
7727cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba            int dir = style()->direction();
7737cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba            bool autowrap = style()->autoWrap();
7747cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba            // if the RenderBlock is positioned, don't wrap text around screen
7757cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba            // width as it may cause text to overlap.
7767cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba            bool positioned = isPositioned();
7777cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba            EFloat cssfloat = style()->floating();
778ef5ff0dbc68f344b819b75af5dc5bcc7bda8f411Shimeng (Simon) Wang            const int lineHeight = style()->computedLineHeight();
779ef5ff0dbc68f344b819b75af5dc5bcc7bda8f411Shimeng (Simon) Wang            const int fontSize = style()->fontSize();
780d5c8fc35c6fd034d37978ad6c4df7e0afdbb0e1bShimeng (Simon) Wang            doTextWrap = autowrap && !positioned &&
78121d8d81a756ca7e60b5131e5f1006f52799179b0Shimeng (Simon) Wang                    (fontSize <= lineHeight) && !style()->hasBackground() &&
7827cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                    (((dir == LTR && cssfloat != FRIGHT) ||
783b62826266ccf1d6f2ede3e9735e2279e6dee5a5bShimeng (Simon) Wang                    (dir == RTL && cssfloat != FNONE)) &&
7847cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                    ((ta == TAAUTO) || (ta == JUSTIFY) ||
7857cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                    ((ta == LEFT || ta == WEBKIT_LEFT) && (dir == LTR)) ||
7867cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                    ((ta == RIGHT || ta == WEBKIT_RIGHT) && (dir == RTL))));
7877cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba        }
7887cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba        bool hasTextToWrap = false;
7897cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba#endif
7908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // layout replaced elements
7918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        bool endOfInline = false;
7928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        RenderObject* o = bidiFirst(this, 0, false);
7938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        Vector<FloatWithRect> floats;
794d0825bca7fe65beaee391d30da42e937db621564Steve Block        bool hasInlineChild = false;
7958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        while (o) {
79668513a70bcd92384395513322f1b801e7bf9c729Steve Block            if (!hasInlineChild && o->isInline())
79768513a70bcd92384395513322f1b801e7bf9c729Steve Block                hasInlineChild = true;
79868513a70bcd92384395513322f1b801e7bf9c729Steve Block
7998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (o->isReplaced() || o->isFloating() || o->isPositioned()) {
800635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                RenderBox* box = toRenderBox(o);
801635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
8028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (relayoutChildren || o->style()->width().isPercent() || o->style()->height().isPercent())
8038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    o->setChildNeedsLayout(true, false);
8048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // If relayoutChildren is set and we have percentage padding, we also need to invalidate the child's pref widths.
806a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                if (relayoutChildren && (o->style()->paddingStart().isPercent() || o->style()->paddingEnd().isPercent()))
807bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen                    o->setPreferredLogicalWidthsDirty(true, false);
8088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (o->isPositioned())
810635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                    o->containingBlock()->insertPositionedObject(box);
8118de7ac488df2f39f82e56811541f4847b3f2e952Steve Block#if PLATFORM(ANDROID)
8128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                else {
8137cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba#ifdef ANDROID_LAYOUT
8147cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                    // ignore text wrap for textField or menuList
8158ffb902ab85b3eb5e2fad95e38034d67e7e2e463Mangesh Ghiware                    if (doTextWrap && (o->isTextField() || o->isMenuList()))
8168de7ac488df2f39f82e56811541f4847b3f2e952Steve Block                        doTextWrap = false;
8177cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba#endif
8188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (o->isFloating())
819635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                        floats.append(FloatWithRect(box));
8208de7ac488df2f39f82e56811541f4847b3f2e952Steve Block                    else if (fullLayout || o->needsLayout()) {
8218de7ac488df2f39f82e56811541f4847b3f2e952Steve Block                        // Replaced elements
8228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                        toRenderBox(o)->dirtyLineBoxes(fullLayout);
8238de7ac488df2f39f82e56811541f4847b3f2e952Steve Block                        o->layoutIfNeeded();
8248de7ac488df2f39f82e56811541f4847b3f2e952Steve Block                    }
8258de7ac488df2f39f82e56811541f4847b3f2e952Steve Block                }
8268de7ac488df2f39f82e56811541f4847b3f2e952Steve Block#else
82768513a70bcd92384395513322f1b801e7bf9c729Steve Block                else if (o->isFloating())
82868513a70bcd92384395513322f1b801e7bf9c729Steve Block                    floats.append(FloatWithRect(box));
82968513a70bcd92384395513322f1b801e7bf9c729Steve Block                else if (fullLayout || o->needsLayout()) {
83068513a70bcd92384395513322f1b801e7bf9c729Steve Block                    // Replaced elements
83168513a70bcd92384395513322f1b801e7bf9c729Steve Block                    toRenderBox(o)->dirtyLineBoxes(fullLayout);
8328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    o->layoutIfNeeded();
8338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
8348de7ac488df2f39f82e56811541f4847b3f2e952Steve Block#endif // PLATFORM(ANDROID)
835635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            } else if (o->isText() || (o->isRenderInline() && !endOfInline)) {
8362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                if (!o->isText())
8372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    toRenderInline(o)->updateAlwaysCreateLineBoxes();
8388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (fullLayout || o->selfNeedsLayout())
8398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                    dirtyLineBoxesForRenderer(o, fullLayout);
8408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                o->setNeedsLayout(false);
8417cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba#ifdef ANDROID_LAYOUT
8427cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                if (doTextWrap && !hasTextToWrap && o->isText()) {
8437cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                    Node* node = o->node();
8447cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                    // as it is very common for sites to use a serial of <a> or
8457cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                    // <li> as tabs, we don't force text to wrap if all the text
8467cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                    // are short and within an <a> or <li> tag, and only separated
8477cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                    // by short word like "|" or ";".
8487cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                    if (node && node->isTextNode() &&
8497cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                            !static_cast<Text*>(node)->containsOnlyWhitespace()) {
8507cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                        int length = static_cast<Text*>(node)->length();
8517cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                        // FIXME, need a magic number to decide it is too long to
8527cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                        // be a tab. Pick 25 for now as it covers around 160px
8537cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                        // (half of 320px) with the default font.
8547cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                        if (length > 25 || (length > 3 &&
855bfce793ad58f0a43e19e55c8ce237cb43a977c42Ben Murdoch                                (!node->parentOrHostNode()->hasTagName(HTMLNames::aTag) &&
856bfce793ad58f0a43e19e55c8ce237cb43a977c42Ben Murdoch                                !node->parentOrHostNode()->hasTagName(HTMLNames::liTag))))
8577cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                            hasTextToWrap = true;
8587cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                    }
8597cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                }
8607cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba#endif
8618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
8628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            o = bidiNext(this, o, 0, false, &endOfInline);
8638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
8648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8657cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba#ifdef ANDROID_LAYOUT
8667cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba        // try to make sure that inline text will not span wider than the
8677cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba        // screen size unless the container has a fixed height,
8687cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba        if (doTextWrap && hasTextToWrap) {
8697cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba            // check all the nested containing blocks, unless it is table or
8707cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba            // table-cell, to make sure there is no fixed height as it implies
8717cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba            // fixed layout. If we constrain the text to fit screen, we may
8727cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba            // cause text overlap with the block after.
8737cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba            bool isConstrained = false;
8747cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba            RenderObject* obj = this;
8757cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba            while (obj) {
8767cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                if (obj->style()->height().isFixed() && (!obj->isTable() && !obj->isTableCell())) {
8777cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                    isConstrained = true;
8787cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                    break;
8797cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                }
8807cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                if (obj->isFloating() || obj->isPositioned()) {
881bc7b84de3fd863c500a8169fd00dca3811cadbb3Steve Block                    // floating and absolute or fixed positioning are done out
8827cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                    // of normal flow. Don't need to worry about height any more.
8837cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                    break;
8847cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                }
8857cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                obj = obj->container();
8867cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba            }
8877cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba            if (!isConstrained) {
888c05b3a990126a5a1de357c025e25e6acd4e4e185Grace Kloba                int textWrapWidth = view()->frameView()->textWrapWidth();
889a56054997e46fcd04621cc67d650b6daf85f7b59Grace Kloba                int padding = paddingLeft() + paddingRight();
890c05b3a990126a5a1de357c025e25e6acd4e4e185Grace Kloba                if (textWrapWidth > 0 && width() > (textWrapWidth + padding)) {
891a56054997e46fcd04621cc67d650b6daf85f7b59Grace Kloba                    // limit the content width (width excluding padding) to be
892c05b3a990126a5a1de357c025e25e6acd4e4e185Grace Kloba                    // (textWrapWidth - 2 * ANDROID_FCTS_MARGIN_PADDING)
893c05b3a990126a5a1de357c025e25e6acd4e4e185Grace Kloba                    int maxWidth = textWrapWidth - 2 * ANDROID_FCTS_MARGIN_PADDING + padding;
8947cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                    setWidth(min(width(), maxWidth));
89515196e7281a07cd210bad6e50ad31dabab648e6cKristian Monsen                    m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, maxWidth);
89615196e7281a07cd210bad6e50ad31dabab648e6cKristian Monsen                    m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, maxWidth);
897e0d453637f1bc58e518a60882c1bdd04ae41d353Steve Block
898ef70308a818da13f513c6e3b640d8228c99abbd0Mangesh Ghiware                    // if overflow isn't visible, block elements may get clipped
899ef70308a818da13f513c6e3b640d8228c99abbd0Mangesh Ghiware                    // due to the limited content width. disable overflow clipping.
900ef70308a818da13f513c6e3b640d8228c99abbd0Mangesh Ghiware                    setHasOverflowClip(false);
901ef70308a818da13f513c6e3b640d8228c99abbd0Mangesh Ghiware
902e0d453637f1bc58e518a60882c1bdd04ae41d353Steve Block                    IntRect overflow = layoutOverflowRect();
903e0d453637f1bc58e518a60882c1bdd04ae41d353Steve Block                    if (overflow.width() > maxWidth) {
904e0d453637f1bc58e518a60882c1bdd04ae41d353Steve Block                        overflow.setWidth(maxWidth);
905e0d453637f1bc58e518a60882c1bdd04ae41d353Steve Block                        clearLayoutOverflow();
906e0d453637f1bc58e518a60882c1bdd04ae41d353Steve Block                        addLayoutOverflow(overflow);
907e0d453637f1bc58e518a60882c1bdd04ae41d353Steve Block                    }
9087cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba                }
9097cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba            }
9107cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba        }
9117cc8cd1a39eab64760ba9f012efd77e0ce048053Grace Kloba#endif
9128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // We want to skip ahead to the first dirty line
9138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        InlineBidiResolver resolver;
9148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        unsigned floatIndex;
9158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        bool firstLine = true;
9160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        bool previousLineBrokeCleanly = true;
91768513a70bcd92384395513322f1b801e7bf9c729Steve Block        RootInlineBox* startLine = determineStartPosition(firstLine, fullLayout, previousLineBrokeCleanly, resolver, floats, floatIndex,
918a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                                                          useRepaintBounds, repaintLogicalTop, repaintLogicalBottom);
9198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
920d0825bca7fe65beaee391d30da42e937db621564Steve Block        if (fullLayout && hasInlineChild && !selfNeedsLayout()) {
9218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            setNeedsLayout(true, false);  // Mark ourselves as needing a full layout. This way we'll repaint like
9228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                          // we're supposed to.
923635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            RenderView* v = view();
9248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            if (v && !v->doingFullRepaint() && hasLayer()) {
9258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // Because we waited until we were already inside layout to discover
9268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // that the block really needed a full layout, we missed our chance to repaint the layer
9278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // before layout started.  Luckily the layer has cached the repaint rect for its original
9288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // position and size, and so we can use that to make a repaint happen now.
9298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                repaintUsingContainer(containerForRepaint(), layer()->repaintRect());
9308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
9318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
9328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
93381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        FloatingObject* lastFloat = (m_floatingObjects && !m_floatingObjects->set().isEmpty()) ? m_floatingObjects->set().last() : 0;
9348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        LineMidpointState& lineMidpointState = resolver.midpointState();
9368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // We also find the first clean line and extract these lines.  We will add them back
9388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // if we determine that we're able to synchronize after handling all our dirty lines.
9398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        InlineIterator cleanLineStart;
9408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        BidiStatus cleanLineBidiStatus;
941a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        int endLineLogicalTop = 0;
9428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        RootInlineBox* endLine = (fullLayout || !startLine) ?
9432bde8e466a4451c7319e3a072d118917957d6554Steve Block                                 0 : determineEndPosition(startLine, floats, floatIndex, cleanLineStart, cleanLineBidiStatus, endLineLogicalTop);
9448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (startLine) {
94668513a70bcd92384395513322f1b801e7bf9c729Steve Block            if (!useRepaintBounds) {
94768513a70bcd92384395513322f1b801e7bf9c729Steve Block                useRepaintBounds = true;
948a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                repaintLogicalTop = logicalHeight();
949a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                repaintLogicalBottom = logicalHeight();
95068513a70bcd92384395513322f1b801e7bf9c729Steve Block            }
9518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            RenderArena* arena = renderArena();
9528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            RootInlineBox* box = startLine;
9538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            while (box) {
9542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                repaintLogicalTop = min(repaintLogicalTop, box->logicalTopVisualOverflow());
9552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                repaintLogicalBottom = max(repaintLogicalBottom, box->logicalBottomVisualOverflow());
9568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                RootInlineBox* next = box->nextRootBox();
9578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                box->deleteLine(arena);
9588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                box = next;
9598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
9608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
9618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        InlineIterator end = resolver.position();
9638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!fullLayout && lastRootBox() && lastRootBox()->endsWithBreak()) {
9658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // If the last line before the start line ends with a line break that clear floats,
9668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // adjust the height accordingly.
9678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // A line break can be either the first or the last object on a line, depending on its direction.
9688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (InlineBox* lastLeafChild = lastRootBox()->lastLeafChild()) {
9698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                RenderObject* lastObject = lastLeafChild->renderer();
9708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (!lastObject->isBR())
9718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                    lastObject = lastRootBox()->firstLeafChild()->renderer();
9728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (lastObject->isBR()) {
9738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    EClear clear = lastObject->style()->clear();
9748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (clear != CNONE)
9758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        newLine(clear);
9768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
9778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
9788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
9798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        bool endLineMatched = false;
9818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        bool checkForEndLineMatch = endLine;
9828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        bool checkForFloatsFromLastLine = false;
9838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        bool isLineEmpty = true;
98568513a70bcd92384395513322f1b801e7bf9c729Steve Block        bool paginated = view()->layoutState() && view()->layoutState()->isPaginated();
9860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
98781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        LineBreakIteratorInfo lineBreakIteratorInfo;
9886b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        VerticalPositionCache verticalPositionCache;
9896b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
9908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        while (!end.atEnd()) {
9918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // FIXME: Is this check necessary before the first iteration or can it be moved to the end?
992a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            if (checkForEndLineMatch && (endLineMatched = matchedEndLine(resolver, cleanLineStart, cleanLineBidiStatus, endLine, endLineLogicalTop, repaintLogicalBottom, repaintLogicalTop)))
9938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                break;
9948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            lineMidpointState.reset();
9960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
9978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            isLineEmpty = true;
998635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
9998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            EClear clear = CNONE;
100006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen            bool hyphenated;
10012bde8e466a4451c7319e3a072d118917957d6554Steve Block            Vector<RenderBox*> positionedObjects;
100268513a70bcd92384395513322f1b801e7bf9c729Steve Block
100368513a70bcd92384395513322f1b801e7bf9c729Steve Block            InlineIterator oldEnd = end;
100481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            FloatingObject* lastFloatFromPreviousLine = (m_floatingObjects && !m_floatingObjects->set().isEmpty()) ? m_floatingObjects->set().last() : 0;
10052bde8e466a4451c7319e3a072d118917957d6554Steve Block            end = findNextLineBreak(resolver, firstLine, isLineEmpty, lineBreakIteratorInfo, previousLineBrokeCleanly, hyphenated, &clear, lastFloatFromPreviousLine, positionedObjects);
10068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (resolver.position().atEnd()) {
10072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                // FIXME: We shouldn't be creating any runs in findNextLineBreak to begin with!
10082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                // Once BidiRunList is separated from BidiResolver this will not be needed.
10092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                resolver.runs().deleteRuns();
10102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                resolver.markCurrentRunEmpty(); // FIXME: This can probably be replaced by an ASSERT (or just removed).
10118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                checkForFloatsFromLastLine = true;
10128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                break;
10138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
10148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            ASSERT(end != resolver.position());
10158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10162bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (isLineEmpty) {
10172bde8e466a4451c7319e3a072d118917957d6554Steve Block                if (lastRootBox())
10182bde8e466a4451c7319e3a072d118917957d6554Steve Block                    lastRootBox()->setLineBreakInfo(end.m_obj, end.m_pos, resolver.status());
10192bde8e466a4451c7319e3a072d118917957d6554Steve Block            } else {
102081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                VisualDirectionOverride override = (style()->visuallyOrdered() ? (style()->direction() == LTR ? VisualLeftToRightOverride : VisualRightToLeftOverride) : NoVisualOverride);
10212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                // FIXME: This ownership is reversed. We should own the BidiRunList and pass it to createBidiRunsForLine.
10222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                BidiRunList<BidiRun>& bidiRuns = resolver.runs();
102381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                resolver.createBidiRunsForLine(end, override, previousLineBrokeCleanly);
10248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                ASSERT(resolver.position() == end);
10258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                BidiRun* trailingSpaceRun = !previousLineBrokeCleanly ? handleTrailingSpaces(bidiRuns, resolver.context()) : 0;
10278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // Now that the runs have been ordered, we create the line boxes.
10298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // At the same time we figure out where border/padding/margin should be applied for
10308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // inline flow boxes.
10318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                RootInlineBox* lineBox = 0;
1033a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                int oldLogicalHeight = logicalHeight();
10342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                if (bidiRuns.runCount()) {
103506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                    if (hyphenated)
10362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                        bidiRuns.logicallyLastRun()->m_hasHyphen = true;
10372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    lineBox = constructLine(bidiRuns, firstLine, !end.m_obj);
10388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (lineBox) {
10398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        lineBox->setEndsWithBreak(previousLineBrokeCleanly);
10408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
104106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen#if ENABLE(SVG)
104206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                        bool isSVGRootInlineBox = lineBox->isSVGRootInlineBox();
104306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen#else
104406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                        bool isSVGRootInlineBox = false;
104506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen#endif
104606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
10476c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen                        GlyphOverflowAndFallbackFontsMap textBoxDataMap;
10482bde8e466a4451c7319e3a072d118917957d6554Steve Block
104906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                        // Now we position all of our text runs horizontally.
105006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                        if (!isSVGRootInlineBox)
10512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                            computeInlineDirectionPositionsForLine(lineBox, firstLine, bidiRuns.firstRun(), trailingSpaceRun, end.atEnd(), textBoxDataMap, verticalPositionCache);
10528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        // Now position our text runs vertically.
10542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                        computeBlockDirectionPositionsForLine(lineBox, bidiRuns.firstRun(), textBoxDataMap, verticalPositionCache);
10558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if ENABLE(SVG)
105706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                        // SVG text layout code computes vertical & horizontal positions on its own.
105806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                        // Note that we still need to execute computeVerticalPositionsForLine() as
105906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                        // it calls InlineTextBox::positionLineBox(), which tracks whether the box
106006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                        // contains reversed text or not. If we wouldn't do that editing and thus
106106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                        // text selection in RTL boxes would not work as expected.
106206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                        if (isSVGRootInlineBox) {
106306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                            ASSERT(isSVGText());
106406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                            static_cast<SVGRootInlineBox*>(lineBox)->computePerCharacterLayoutInformation();
106506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                        }
10668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
10678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1068f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch                        // Compute our overflow now.
10692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                        lineBox->computeOverflow(lineBox->lineTop(), lineBox->lineBottom(), textBoxDataMap);
1070f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
10718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if PLATFORM(MAC)
10728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        // Highlight acts as an overflow inflation.
10738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        if (style()->highlight() != nullAtom)
10748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            lineBox->addHighlightOverflow();
10758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
10768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    }
10778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
10788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                bidiRuns.deleteRuns();
10802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                resolver.markCurrentRunEmpty(); // FIXME: This can probably be replaced by an ASSERT (or just removed).
10818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (lineBox) {
10832bde8e466a4451c7319e3a072d118917957d6554Steve Block                    lineBox->setLineBreakInfo(end.m_obj, end.m_pos, resolver.status());
10848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (useRepaintBounds) {
10852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                        repaintLogicalTop = min(repaintLogicalTop, lineBox->logicalTopVisualOverflow());
10862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                        repaintLogicalBottom = max(repaintLogicalBottom, lineBox->logicalBottomVisualOverflow());
10878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    }
108868513a70bcd92384395513322f1b801e7bf9c729Steve Block
108968513a70bcd92384395513322f1b801e7bf9c729Steve Block                    if (paginated) {
109068513a70bcd92384395513322f1b801e7bf9c729Steve Block                        int adjustment = 0;
109168513a70bcd92384395513322f1b801e7bf9c729Steve Block                        adjustLinePositionForPagination(lineBox, adjustment);
109268513a70bcd92384395513322f1b801e7bf9c729Steve Block                        if (adjustment) {
1093a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                            int oldLineWidth = availableLogicalWidthForLine(oldLogicalHeight, firstLine);
10942fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                            lineBox->adjustBlockDirectionPosition(adjustment);
109568513a70bcd92384395513322f1b801e7bf9c729Steve Block                            if (useRepaintBounds) // This can only be a positive adjustment, so no need to update repaintTop.
10962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                                repaintLogicalBottom = max(repaintLogicalBottom, lineBox->logicalBottomVisualOverflow());
109768513a70bcd92384395513322f1b801e7bf9c729Steve Block
1098a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                            if (availableLogicalWidthForLine(oldLogicalHeight + adjustment, firstLine) != oldLineWidth) {
109968513a70bcd92384395513322f1b801e7bf9c729Steve Block                                // We have to delete this line, remove all floats that got added, and let line layout re-run.
110068513a70bcd92384395513322f1b801e7bf9c729Steve Block                                lineBox->deleteLine(renderArena());
1101a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                                removeFloatingObjectsBelow(lastFloatFromPreviousLine, oldLogicalHeight);
1102a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                                setLogicalHeight(oldLogicalHeight + adjustment);
110368513a70bcd92384395513322f1b801e7bf9c729Steve Block                                resolver.setPosition(oldEnd);
110468513a70bcd92384395513322f1b801e7bf9c729Steve Block                                end = oldEnd;
110568513a70bcd92384395513322f1b801e7bf9c729Steve Block                                continue;
110668513a70bcd92384395513322f1b801e7bf9c729Steve Block                            }
110768513a70bcd92384395513322f1b801e7bf9c729Steve Block
1108a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                            setLogicalHeight(lineBox->blockLogicalHeight());
110968513a70bcd92384395513322f1b801e7bf9c729Steve Block                        }
111068513a70bcd92384395513322f1b801e7bf9c729Steve Block                    }
11118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
11128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11132bde8e466a4451c7319e3a072d118917957d6554Steve Block                for (size_t i = 0; i < positionedObjects.size(); ++i)
11142bde8e466a4451c7319e3a072d118917957d6554Steve Block                    setStaticPositions(this, positionedObjects[i]);
11152bde8e466a4451c7319e3a072d118917957d6554Steve Block
11168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                firstLine = false;
11178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                newLine(clear);
11188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
11198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (m_floatingObjects && lastRootBox()) {
112181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
112281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                FloatingObjectSetIterator it = floatingObjectSet.begin();
112381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                FloatingObjectSetIterator end = floatingObjectSet.end();
11248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (lastFloat) {
112581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                    FloatingObjectSetIterator lastFloatIterator = floatingObjectSet.find(lastFloat);
112681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                    ASSERT(lastFloatIterator != end);
112781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                    ++lastFloatIterator;
112881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                    it = lastFloatIterator;
112981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                }
113081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                for (; it != end; ++it) {
113181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                    FloatingObject* f = *it;
11322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    appendFloatingObjectToLastLine(f);
11338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    ASSERT(f->m_renderer == floats[floatIndex].object);
11348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    // If a float's geometry has changed, give up on syncing with clean lines.
1135a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                    if (floats[floatIndex].rect != f->frameRect())
11368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        checkForEndLineMatch = false;
11378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    floatIndex++;
11388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
113981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                lastFloat = !floatingObjectSet.isEmpty() ? floatingObjectSet.last() : 0;
11408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
11418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            lineMidpointState.reset();
11438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            resolver.setPosition(end);
11448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
11458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (endLine) {
11478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (endLineMatched) {
11488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // Attach all the remaining lines, and then adjust their y-positions as needed.
1149a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                int delta = logicalHeight() - endLineLogicalTop;
11508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                for (RootInlineBox* line = endLine; line; line = line->nextRootBox()) {
11518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    line->attachLine();
115268513a70bcd92384395513322f1b801e7bf9c729Steve Block                    if (paginated) {
115368513a70bcd92384395513322f1b801e7bf9c729Steve Block                        delta -= line->paginationStrut();
115468513a70bcd92384395513322f1b801e7bf9c729Steve Block                        adjustLinePositionForPagination(line, delta);
115568513a70bcd92384395513322f1b801e7bf9c729Steve Block                    }
11568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (delta) {
11572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                        repaintLogicalTop = min(repaintLogicalTop, line->logicalTopVisualOverflow() + min(delta, 0));
11582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                        repaintLogicalBottom = max(repaintLogicalBottom, line->logicalBottomVisualOverflow() + max(delta, 0));
11592fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                        line->adjustBlockDirectionPosition(delta);
11608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    }
1161635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                    if (Vector<RenderBox*>* cleanLineFloats = line->floatsPtr()) {
1162635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                        Vector<RenderBox*>::iterator end = cleanLineFloats->end();
1163635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                        for (Vector<RenderBox*>::iterator f = cleanLineFloats->begin(); f != end; ++f) {
116454cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block                            FloatingObject* floatingObject = insertFloatingObject(*f);
116554cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block                            ASSERT(!floatingObject->m_originatingLine);
116654cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block                            floatingObject->m_originatingLine = line;
1167a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                            setLogicalHeight(logicalTopForChild(*f) - marginBeforeForChild(*f) + delta);
11688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            positionNewFloats();
11698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        }
11708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    }
11718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
1172a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                setLogicalHeight(lastRootBox()->blockLogicalHeight());
11738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            } else {
11748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // Delete all the remaining lines.
1175231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                RootInlineBox* line = endLine;
11768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                RenderArena* arena = renderArena();
11778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                while (line) {
11782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    repaintLogicalTop = min(repaintLogicalTop, line->logicalTopVisualOverflow());
11792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    repaintLogicalBottom = max(repaintLogicalBottom, line->logicalBottomVisualOverflow());
1180231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                    RootInlineBox* next = line->nextRootBox();
11818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    line->deleteLine(arena);
11828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    line = next;
11838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
11848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
11858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
11868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (m_floatingObjects && (checkForFloatsFromLastLine || positionNewFloats()) && lastRootBox()) {
11878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // In case we have a float on the last line, it might not be positioned up to now.
11888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // This has to be done before adding in the bottom border/padding, or the float will
11898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // include the padding incorrectly. -dwh
1190d0825bca7fe65beaee391d30da42e937db621564Steve Block            if (checkForFloatsFromLastLine) {
11912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                int bottomVisualOverflow = lastRootBox()->logicalBottomVisualOverflow();
11922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                int bottomLayoutOverflow = lastRootBox()->logicalBottomLayoutOverflow();
1193d0825bca7fe65beaee391d30da42e937db621564Steve Block                TrailingFloatsRootInlineBox* trailingFloatsLineBox = new (renderArena()) TrailingFloatsRootInlineBox(this);
1194d0825bca7fe65beaee391d30da42e937db621564Steve Block                m_lineBoxes.appendLineBox(trailingFloatsLineBox);
1195d0825bca7fe65beaee391d30da42e937db621564Steve Block                trailingFloatsLineBox->setConstructed();
11966c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen                GlyphOverflowAndFallbackFontsMap textBoxDataMap;
11976b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                VerticalPositionCache verticalPositionCache;
11986b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                trailingFloatsLineBox->alignBoxesInBlockDirection(logicalHeight(), textBoxDataMap, verticalPositionCache);
11992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                int blockLogicalHeight = logicalHeight();
12002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                IntRect logicalLayoutOverflow(0, blockLogicalHeight, 1, bottomLayoutOverflow - blockLogicalHeight);
12012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                IntRect logicalVisualOverflow(0, blockLogicalHeight, 1, bottomVisualOverflow - blockLogicalHeight);
12022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                trailingFloatsLineBox->setOverflowFromLogicalRects(logicalLayoutOverflow, logicalVisualOverflow, trailingFloatsLineBox->lineTop(), trailingFloatsLineBox->lineBottom());
1203a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                trailingFloatsLineBox->setBlockLogicalHeight(logicalHeight());
1204d0825bca7fe65beaee391d30da42e937db621564Steve Block            }
120581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
120681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
120781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            FloatingObjectSetIterator it = floatingObjectSet.begin();
120881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            FloatingObjectSetIterator end = floatingObjectSet.end();
12098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (lastFloat) {
121081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                FloatingObjectSetIterator lastFloatIterator = floatingObjectSet.find(lastFloat);
121181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                ASSERT(lastFloatIterator != end);
121281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                ++lastFloatIterator;
121381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                it = lastFloatIterator;
121481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            }
121581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            for (; it != end; ++it)
12162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                appendFloatingObjectToLastLine(*it);
121781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            lastFloat = !floatingObjectSet.isEmpty() ? floatingObjectSet.last() : 0;
12188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
12190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        size_t floatCount = floats.size();
12200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // Floats that did not have layout did not repaint when we laid them out. They would have
12210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // painted by now if they had moved, but if they stayed at (0, 0), they still need to be
12220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // painted.
12230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        for (size_t i = 0; i < floatCount; ++i) {
12240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            if (!floats[i].everHadLayout) {
12250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                RenderBox* f = floats[i].object;
12260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                if (!f->x() && !f->y() && f->checkForRepaintDuringLayout())
12270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                    f->repaint();
12280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            }
12290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        }
12308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
12318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1232f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // Expand the last line to accommodate Ruby and emphasis marks.
1233f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    int lastLineAnnotationsAdjustment = 0;
1234f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (lastRootBox()) {
12354576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        int lowestAllowedPosition = max(lastRootBox()->lineBottom(), logicalHeight() + paddingAfter());
1236f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        if (!style()->isFlippedLinesWritingMode())
1237f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            lastLineAnnotationsAdjustment = lastRootBox()->computeUnderAnnotationAdjustment(lowestAllowedPosition);
1238f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        else
1239f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            lastLineAnnotationsAdjustment = lastRootBox()->computeOverAnnotationAdjustment(lowestAllowedPosition);
12404576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    }
1241f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
12428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Now add in the bottom border/padding.
1243f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    setLogicalHeight(logicalHeight() + lastLineAnnotationsAdjustment + borderAfter() + paddingAfter() + scrollbarLogicalHeight());
12448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
12458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!firstLineBox() && hasLineIfEmpty())
12462bde8e466a4451c7319e3a072d118917957d6554Steve Block        setLogicalHeight(logicalHeight() + lineHeight(true, isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes));
12478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
12488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // See if we have any lines that spill out of our block.  If we do, then we will possibly need to
12498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // truncate text.
12508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (hasTextOverflow)
12518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        checkLinesForTextOverflow();
12528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
12538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
12542bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid RenderBlock::checkFloatsInCleanLine(RootInlineBox* line, Vector<FloatWithRect>& floats, size_t& floatIndex, bool& encounteredNewFloat, bool& dirtiedByFloat)
12552bde8e466a4451c7319e3a072d118917957d6554Steve Block{
12562bde8e466a4451c7319e3a072d118917957d6554Steve Block    Vector<RenderBox*>* cleanLineFloats = line->floatsPtr();
12572bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (!cleanLineFloats)
12582bde8e466a4451c7319e3a072d118917957d6554Steve Block        return;
12592bde8e466a4451c7319e3a072d118917957d6554Steve Block
12602bde8e466a4451c7319e3a072d118917957d6554Steve Block    Vector<RenderBox*>::iterator end = cleanLineFloats->end();
12612bde8e466a4451c7319e3a072d118917957d6554Steve Block    for (Vector<RenderBox*>::iterator it = cleanLineFloats->begin(); it != end; ++it) {
12622bde8e466a4451c7319e3a072d118917957d6554Steve Block        RenderBox* floatingBox = *it;
12632bde8e466a4451c7319e3a072d118917957d6554Steve Block        floatingBox->layoutIfNeeded();
12642bde8e466a4451c7319e3a072d118917957d6554Steve Block        IntSize newSize(floatingBox->width() + floatingBox->marginLeft() + floatingBox->marginRight(), floatingBox->height() + floatingBox->marginTop() + floatingBox->marginBottom());
12652bde8e466a4451c7319e3a072d118917957d6554Steve Block        ASSERT(floatIndex < floats.size());
12662bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (floats[floatIndex].object != floatingBox) {
12672bde8e466a4451c7319e3a072d118917957d6554Steve Block            encounteredNewFloat = true;
12682bde8e466a4451c7319e3a072d118917957d6554Steve Block            return;
12692bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
12702bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (floats[floatIndex].rect.size() != newSize) {
12712bde8e466a4451c7319e3a072d118917957d6554Steve Block            int floatTop = isHorizontalWritingMode() ? floats[floatIndex].rect.y() : floats[floatIndex].rect.x();
12722bde8e466a4451c7319e3a072d118917957d6554Steve Block            int floatHeight = isHorizontalWritingMode() ? max(floats[floatIndex].rect.height(), newSize.height())
12732bde8e466a4451c7319e3a072d118917957d6554Steve Block                                                                 : max(floats[floatIndex].rect.width(), newSize.width());
12742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            floatHeight = min(floatHeight, numeric_limits<int>::max() - floatTop);
12752bde8e466a4451c7319e3a072d118917957d6554Steve Block            line->markDirty();
12762bde8e466a4451c7319e3a072d118917957d6554Steve Block            markLinesDirtyInBlockRange(line->blockLogicalHeight(), floatTop + floatHeight, line);
12772bde8e466a4451c7319e3a072d118917957d6554Steve Block            floats[floatIndex].rect.setSize(newSize);
12782bde8e466a4451c7319e3a072d118917957d6554Steve Block            dirtiedByFloat = true;
12792bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
12802bde8e466a4451c7319e3a072d118917957d6554Steve Block        floatIndex++;
12812bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
12822bde8e466a4451c7319e3a072d118917957d6554Steve Block}
12832bde8e466a4451c7319e3a072d118917957d6554Steve Block
12840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochRootInlineBox* RenderBlock::determineStartPosition(bool& firstLine, bool& fullLayout, bool& previousLineBrokeCleanly,
128568513a70bcd92384395513322f1b801e7bf9c729Steve Block                                                   InlineBidiResolver& resolver, Vector<FloatWithRect>& floats, unsigned& numCleanFloats,
1286a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                                                   bool& useRepaintBounds, int& repaintLogicalTop, int& repaintLogicalBottom)
12878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
12888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RootInlineBox* curr = 0;
12898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RootInlineBox* last = 0;
12908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
12918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool dirtiedByFloat = false;
12928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!fullLayout) {
129368513a70bcd92384395513322f1b801e7bf9c729Steve Block        // Paginate all of the clean lines.
129468513a70bcd92384395513322f1b801e7bf9c729Steve Block        bool paginated = view()->layoutState() && view()->layoutState()->isPaginated();
129568513a70bcd92384395513322f1b801e7bf9c729Steve Block        int paginationDelta = 0;
12968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        size_t floatIndex = 0;
12978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        for (curr = firstRootBox(); curr && !curr->isDirty(); curr = curr->nextRootBox()) {
129868513a70bcd92384395513322f1b801e7bf9c729Steve Block            if (paginated) {
129968513a70bcd92384395513322f1b801e7bf9c729Steve Block                paginationDelta -= curr->paginationStrut();
130068513a70bcd92384395513322f1b801e7bf9c729Steve Block                adjustLinePositionForPagination(curr, paginationDelta);
130168513a70bcd92384395513322f1b801e7bf9c729Steve Block                if (paginationDelta) {
130268513a70bcd92384395513322f1b801e7bf9c729Steve Block                    if (containsFloats() || !floats.isEmpty()) {
130368513a70bcd92384395513322f1b801e7bf9c729Steve Block                        // FIXME: Do better eventually.  For now if we ever shift because of pagination and floats are present just go to a full layout.
130468513a70bcd92384395513322f1b801e7bf9c729Steve Block                        fullLayout = true;
130568513a70bcd92384395513322f1b801e7bf9c729Steve Block                        break;
130668513a70bcd92384395513322f1b801e7bf9c729Steve Block                    }
130768513a70bcd92384395513322f1b801e7bf9c729Steve Block
130868513a70bcd92384395513322f1b801e7bf9c729Steve Block                    if (!useRepaintBounds)
130968513a70bcd92384395513322f1b801e7bf9c729Steve Block                        useRepaintBounds = true;
131068513a70bcd92384395513322f1b801e7bf9c729Steve Block
13112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    repaintLogicalTop = min(repaintLogicalTop, curr->logicalTopVisualOverflow() + min(paginationDelta, 0));
13122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    repaintLogicalBottom = max(repaintLogicalBottom, curr->logicalBottomVisualOverflow() + max(paginationDelta, 0));
13132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                    curr->adjustBlockDirectionPosition(paginationDelta);
131468513a70bcd92384395513322f1b801e7bf9c729Steve Block                }
131568513a70bcd92384395513322f1b801e7bf9c729Steve Block            }
13162bde8e466a4451c7319e3a072d118917957d6554Steve Block
13172bde8e466a4451c7319e3a072d118917957d6554Steve Block            // If a new float has been inserted before this line or before its last known float,just do a full layout.
13182bde8e466a4451c7319e3a072d118917957d6554Steve Block            checkFloatsInCleanLine(curr, floats, floatIndex, fullLayout, dirtiedByFloat);
13198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (dirtiedByFloat || fullLayout)
13208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                break;
13218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
13228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Check if a new float has been inserted after the last known float.
13238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!curr && floatIndex < floats.size())
13248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            fullLayout = true;
13258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
13268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
13278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (fullLayout) {
13288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Nuke all our lines.
13298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (firstRootBox()) {
13308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            RenderArena* arena = renderArena();
13318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            curr = firstRootBox();
13328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            while (curr) {
13338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                RootInlineBox* next = curr->nextRootBox();
13348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                curr->deleteLine(arena);
13358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                curr = next;
13368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
13378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            ASSERT(!firstLineBox() && !lastLineBox());
13388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
13398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else {
13408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (curr) {
13418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // We have a dirty line.
13428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (RootInlineBox* prevRootBox = curr->prevRootBox()) {
13438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // We have a previous line.
13448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                if (!dirtiedByFloat && (!prevRootBox->endsWithBreak() || (prevRootBox->lineBreakObj()->isText() && prevRootBox->lineBreakPos() >= toRenderText(prevRootBox->lineBreakObj())->textLength())))
13458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    // The previous line didn't break cleanly or broke at a newline
13468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    // that has been deleted, so treat it as dirty too.
13478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    curr = prevRootBox;
13488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
13498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else {
13508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // No dirty lines were found.
13518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // If the last line didn't break cleanly, treat it as dirty.
13528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (lastRootBox() && !lastRootBox()->endsWithBreak())
13538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                curr = lastRootBox();
13548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
13558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
13568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // If we have no dirty lines, then last is just the last root box.
13578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        last = curr ? curr->prevRootBox() : lastRootBox();
13588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
13598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
13608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    numCleanFloats = 0;
13618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!floats.isEmpty()) {
1362a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        int savedLogicalHeight = logicalHeight();
13638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Restore floats from clean lines.
13648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        RootInlineBox* line = firstRootBox();
13658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        while (line != curr) {
1366635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            if (Vector<RenderBox*>* cleanLineFloats = line->floatsPtr()) {
1367635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                Vector<RenderBox*>::iterator end = cleanLineFloats->end();
1368635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                for (Vector<RenderBox*>::iterator f = cleanLineFloats->begin(); f != end; ++f) {
136954cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block                    FloatingObject* floatingObject = insertFloatingObject(*f);
137054cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block                    ASSERT(!floatingObject->m_originatingLine);
137154cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block                    floatingObject->m_originatingLine = line;
1372a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                    setLogicalHeight(logicalTopForChild(*f) - marginBeforeForChild(*f));
13738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    positionNewFloats();
13748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    ASSERT(floats[numCleanFloats].object == *f);
13758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    numCleanFloats++;
13768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
13778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
13788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            line = line->nextRootBox();
13798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1380a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        setLogicalHeight(savedLogicalHeight);
13818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
13828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
13838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    firstLine = !last;
13848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    previousLineBrokeCleanly = !last || last->endsWithBreak();
13858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
13868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RenderObject* startObj;
13878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int pos = 0;
13888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (last) {
1389a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        setLogicalHeight(last->blockLogicalHeight());
13908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        startObj = last->lineBreakObj();
13918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        pos = last->lineBreakPos();
13928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        resolver.setStatus(last->lineBreakBidiStatus());
13938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else {
13942bde8e466a4451c7319e3a072d118917957d6554Steve Block        bool ltr = style()->isLeftToRightDirection();
13955f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        Direction direction = ltr ? LeftToRight : RightToLeft;
13965f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        resolver.setLastStrongDir(direction);
13975f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        resolver.setLastDir(direction);
13985f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        resolver.setEorDir(direction);
13992bde8e466a4451c7319e3a072d118917957d6554Steve Block        resolver.setContext(BidiContext::create(ltr ? 0 : 1, direction, style()->unicodeBidi() == Override, FromStyleOrDOM));
14008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
14018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        startObj = bidiFirst(this, &resolver);
14028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
14038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
14048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    resolver.setPosition(InlineIterator(this, startObj, pos));
14058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
14068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return curr;
14078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
14088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
14092bde8e466a4451c7319e3a072d118917957d6554Steve BlockRootInlineBox* RenderBlock::determineEndPosition(RootInlineBox* startLine, Vector<FloatWithRect>& floats, size_t floatIndex, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus, int& logicalTop)
14108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
14118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RootInlineBox* last = 0;
14122bde8e466a4451c7319e3a072d118917957d6554Steve Block    for (RootInlineBox* curr = startLine->nextRootBox(); curr; curr = curr->nextRootBox()) {
14132bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (!curr->isDirty()) {
14142bde8e466a4451c7319e3a072d118917957d6554Steve Block            bool encounteredNewFloat = false;
14152bde8e466a4451c7319e3a072d118917957d6554Steve Block            bool dirtiedByFloat = false;
14162bde8e466a4451c7319e3a072d118917957d6554Steve Block            checkFloatsInCleanLine(curr, floats, floatIndex, encounteredNewFloat, dirtiedByFloat);
14172bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (encounteredNewFloat)
14182bde8e466a4451c7319e3a072d118917957d6554Steve Block                return 0;
14198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
14202bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (curr->isDirty())
14212bde8e466a4451c7319e3a072d118917957d6554Steve Block            last = 0;
14222bde8e466a4451c7319e3a072d118917957d6554Steve Block        else if (!last)
14232bde8e466a4451c7319e3a072d118917957d6554Steve Block            last = curr;
14248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
14258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
14268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!last)
14278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
14288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
14292bde8e466a4451c7319e3a072d118917957d6554Steve Block    // At this point, |last| is the first line in a run of clean lines that ends with the last line
14302bde8e466a4451c7319e3a072d118917957d6554Steve Block    // in the block.
14312bde8e466a4451c7319e3a072d118917957d6554Steve Block
14328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RootInlineBox* prev = last->prevRootBox();
14338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    cleanLineStart = InlineIterator(this, prev->lineBreakObj(), prev->lineBreakPos());
14348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    cleanLineBidiStatus = prev->lineBreakBidiStatus();
1435a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    logicalTop = prev->blockLogicalHeight();
14368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
14378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (RootInlineBox* line = last; line; line = line->nextRootBox())
14388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        line->extractLine(); // Disconnect all line boxes from their render objects while preserving
14398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                             // their connections to one another.
14408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
14418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return last;
14428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
14438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1444a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochbool RenderBlock::matchedEndLine(const InlineBidiResolver& resolver, const InlineIterator& endLineStart, const BidiStatus& endLineStatus, RootInlineBox*& endLine,
1445a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                                 int& endLogicalTop, int& repaintLogicalBottom, int& repaintLogicalTop)
14468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
14478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (resolver.position() == endLineStart) {
14488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (resolver.status() != endLineStatus)
14498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
14508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1451a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        int delta = logicalHeight() - endLogicalTop;
14528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!delta || !m_floatingObjects)
14538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return true;
14548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
14558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // See if any floats end in the range along which we want to shift the lines vertically.
1456a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        int logicalTop = min(logicalHeight(), endLogicalTop);
14578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
14588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        RootInlineBox* lastLine = endLine;
14598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        while (RootInlineBox* nextLine = lastLine->nextRootBox())
14608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            lastLine = nextLine;
14618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1462a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        int logicalBottom = lastLine->blockLogicalHeight() + abs(delta);
14638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
146481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
146581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        FloatingObjectSetIterator end = floatingObjectSet.end();
146681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
146781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            FloatingObject* f = *it;
1468a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            if (logicalBottomForFloat(f) >= logicalTop && logicalBottomForFloat(f) < logicalBottom)
14698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return false;
14708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
14718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
14728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
14738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
14748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
14758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // The first clean line doesn't match, but we can check a handful of following lines to try
14768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // to match back up.
14778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static int numLines = 8; // The # of lines we're willing to match against.
14788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RootInlineBox* line = endLine;
14798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (int i = 0; i < numLines && line; i++, line = line->nextRootBox()) {
14802bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (line->lineBreakObj() == resolver.position().m_obj && line->lineBreakPos() == resolver.position().m_pos) {
14818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // We have a match.
14828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (line->lineBreakBidiStatus() != resolver.status())
14838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return false; // ...but the bidi state doesn't match.
14848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            RootInlineBox* result = line->nextRootBox();
14858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1486a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            // Set our logical top to be the block height of endLine.
14878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (result)
1488a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                endLogicalTop = line->blockLogicalHeight();
14898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1490a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            int delta = logicalHeight() - endLogicalTop;
14918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (delta && m_floatingObjects) {
14928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // See if any floats end in the range along which we want to shift the lines vertically.
1493a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                int logicalTop = min(logicalHeight(), endLogicalTop);
14948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
14958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                RootInlineBox* lastLine = endLine;
14968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                while (RootInlineBox* nextLine = lastLine->nextRootBox())
14978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    lastLine = nextLine;
14988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1499a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                int logicalBottom = lastLine->blockLogicalHeight() + abs(delta);
15008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
150181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
150281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                FloatingObjectSetIterator end = floatingObjectSet.end();
150381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
150481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                    FloatingObject* f = *it;
1505a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                    if (logicalBottomForFloat(f) >= logicalTop && logicalBottomForFloat(f) < logicalBottom)
15068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        return false;
15078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
15088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
15098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
15108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Now delete the lines that we failed to sync.
15118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            RootInlineBox* boxToDelete = endLine;
15128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            RenderArena* arena = renderArena();
15138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            while (boxToDelete && boxToDelete != result) {
15142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                repaintLogicalTop = min(repaintLogicalTop, boxToDelete->logicalTopVisualOverflow());
15152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                repaintLogicalBottom = max(repaintLogicalBottom, boxToDelete->logicalBottomVisualOverflow());
15168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                RootInlineBox* next = boxToDelete->nextRootBox();
15178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                boxToDelete->deleteLine(arena);
15188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                boxToDelete = next;
15198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
15208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
15218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            endLine = result;
15228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return result;
15238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
15248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
15258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
15268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return false;
15278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
15288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
15290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic inline bool skipNonBreakingSpace(const InlineIterator& it, bool isLineEmpty, bool previousLineBrokeCleanly)
15308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
15312bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (it.m_obj->style()->nbspMode() != SPACE || it.current() != noBreakSpace)
15328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
15338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
15348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: This is bad.  It makes nbsp inconsistent with space and won't work correctly
15358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // with m_minWidth/m_maxWidth.
15368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Do not skip a non-breaking space if it is the first character
15378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // on a line after a clean line break (or on the first line, since previousLineBrokeCleanly starts off
15388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // |true|).
15398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (isLineEmpty && previousLineBrokeCleanly)
15408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
15418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
15428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return true;
15438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
15448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
15450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic inline bool shouldCollapseWhiteSpace(const RenderStyle* style, bool isLineEmpty, bool previousLineBrokeCleanly)
15468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
15478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return style->collapseWhiteSpace() || (style->whiteSpace() == PRE_WRAP && (!isLineEmpty || !previousLineBrokeCleanly));
15488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
15498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
15508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic bool inlineFlowRequiresLineBox(RenderInline* flow)
15518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
15528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: Right now, we only allow line boxes for inlines that are truly empty.
15538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // We need to fix this, though, because at the very least, inlines containing only
15548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // ignorable whitespace should should also have line boxes.
1555a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    return !flow->firstChild() && flow->hasInlineDirectionBordersPaddingOrMargin();
15568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
15578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
15588a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Blockbool RenderBlock::requiresLineBox(const InlineIterator& it, bool isLineEmpty, bool previousLineBrokeCleanly)
15598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
15602bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (it.m_obj->isFloatingOrPositioned())
15618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
15628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
15632bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (it.m_obj->isRenderInline() && !inlineFlowRequiresLineBox(toRenderInline(it.m_obj)))
15648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
15658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
15662bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (!shouldCollapseWhiteSpace(it.m_obj->style(), isLineEmpty, previousLineBrokeCleanly) || it.m_obj->isBR())
15678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
15688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
15698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    UChar current = it.current();
15702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return current != ' ' && current != '\t' && current != softHyphen && (current != '\n' || it.m_obj->preservesNewline())
15710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            && !skipNonBreakingSpace(it, isLineEmpty, previousLineBrokeCleanly);
15728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
15738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
15740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochbool RenderBlock::generatesLineBoxesForInlineChild(RenderObject* inlineObj, bool isLineEmpty, bool previousLineBrokeCleanly)
15758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
15768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(inlineObj->parent() == this);
15778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
15788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    InlineIterator it(this, inlineObj, 0);
15790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    while (!it.atEnd() && !requiresLineBox(it, isLineEmpty, previousLineBrokeCleanly))
15808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        it.increment();
15818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
15828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return !it.atEnd();
15838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
15848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
15858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// FIXME: The entire concept of the skipTrailingWhitespace function is flawed, since we really need to be building
15868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// line boxes even for containers that may ultimately collapse away.  Otherwise we'll never get positioned
15878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// elements quite right.  In other words, we need to build this function's work into the normal line
15888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// object iteration process.
15898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// NB. this function will insert any floating elements that would otherwise
15908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// be skipped but it will not position them.
15910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid RenderBlock::skipTrailingWhitespace(InlineIterator& iterator, bool isLineEmpty, bool previousLineBrokeCleanly)
15928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
15930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    while (!iterator.atEnd() && !requiresLineBox(iterator, isLineEmpty, previousLineBrokeCleanly)) {
15942bde8e466a4451c7319e3a072d118917957d6554Steve Block        RenderObject* object = iterator.m_obj;
15958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (object->isFloating()) {
1596635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            insertFloatingObject(toRenderBox(object));
159781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        } else if (object->isPositioned())
159881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            setStaticPositions(this, toRenderBox(object));
15998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        iterator.increment();
16008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
16018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
16028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
16032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid RenderBlock::skipLeadingWhitespace(InlineBidiResolver& resolver, bool isLineEmpty, bool previousLineBrokeCleanly,
16042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    FloatingObject* lastFloatFromPreviousLine, LineWidth& width)
16058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
16060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    while (!resolver.position().atEnd() && !requiresLineBox(resolver.position(), isLineEmpty, previousLineBrokeCleanly)) {
16072bde8e466a4451c7319e3a072d118917957d6554Steve Block        RenderObject* object = resolver.position().m_obj;
16082bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (object->isFloating())
16092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            positionNewFloatOnLine(insertFloatingObject(toRenderBox(object)), lastFloatFromPreviousLine, width);
16102bde8e466a4451c7319e3a072d118917957d6554Steve Block        else if (object->isPositioned())
161181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            setStaticPositions(this, toRenderBox(object));
16128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        resolver.increment();
16138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
16148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    resolver.commitExplicitEmbedding();
16158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
16168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
16178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// This is currently just used for list markers and inline flows that have line boxes. Neither should
16188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// have an effect on whitespace at the start of the line.
16190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic bool shouldSkipWhitespaceAfterStartObject(RenderBlock* block, RenderObject* o, LineMidpointState& lineMidpointState)
16208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
16218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RenderObject* next = bidiNext(block, o);
1622635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (next && !next->isBR() && next->isText() && toRenderText(next)->textLength() > 0) {
1623635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        RenderText* nextText = toRenderText(next);
16248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        UChar nextChar = nextText->characters()[0];
16258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (nextText->style()->isCollapsibleWhiteSpace(nextChar)) {
16260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            addMidpoint(lineMidpointState, InlineIterator(0, o, 0));
16278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return true;
16288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
16298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
16308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
16318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return false;
16328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
16338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
163481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochstatic inline float textWidth(RenderText* text, unsigned from, unsigned len, const Font& font, float xPos, bool isFixedPitch, bool collapseWhiteSpace)
16358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
16362fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (isFixedPitch || (!from && len == text->textLength()) || text->style()->hasTextCombine())
16378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return text->width(from, len, font, xPos);
16388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return font.width(TextRun(text->characters() + from, len, !collapseWhiteSpace, xPos));
16398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
16408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
164181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochstatic void tryHyphenating(RenderText* text, const Font& font, const AtomicString& localeIdentifier, int minimumPrefixLength, int minimumSuffixLength, int lastSpace, int pos, float xPos, int availableWidth, bool isFixedPitch, bool collapseWhiteSpace, int lastSpaceWordSpacing, InlineIterator& lineBreak, int nextBreakable, bool& hyphenated)
164206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen{
164381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    // Map 'hyphenate-limit-{before,after}: auto;' to 2.
164481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (minimumPrefixLength < 0)
164581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        minimumPrefixLength = 2;
164681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
164781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (minimumSuffixLength < 0)
164881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        minimumSuffixLength = 2;
164981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
165081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (pos - lastSpace <= minimumSuffixLength)
165181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return;
165281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
165306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    const AtomicString& hyphenString = text->style()->hyphenString();
165406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    int hyphenWidth = font.width(TextRun(hyphenString.characters(), hyphenString.length()));
165506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
165681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    float maxPrefixWidth = availableWidth - xPos - hyphenWidth - lastSpaceWordSpacing;
165768513a70bcd92384395513322f1b801e7bf9c729Steve Block    // If the maximum width available for the prefix before the hyphen is small, then it is very unlikely
165868513a70bcd92384395513322f1b801e7bf9c729Steve Block    // that an hyphenation opportunity exists, so do not bother to look for it.
165968513a70bcd92384395513322f1b801e7bf9c729Steve Block    if (maxPrefixWidth <= font.pixelSize() * 5 / 4)
166068513a70bcd92384395513322f1b801e7bf9c729Steve Block        return;
166168513a70bcd92384395513322f1b801e7bf9c729Steve Block
166268513a70bcd92384395513322f1b801e7bf9c729Steve Block    unsigned prefixLength = font.offsetForPosition(TextRun(text->characters() + lastSpace, pos - lastSpace, !collapseWhiteSpace, xPos + lastSpaceWordSpacing), maxPrefixWidth, false);
166381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (prefixLength < static_cast<unsigned>(minimumPrefixLength))
166406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        return;
166506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
166681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    prefixLength = lastHyphenLocation(text->characters() + lastSpace, pos - lastSpace, min(prefixLength, static_cast<unsigned>(pos - lastSpace - minimumSuffixLength)) + 1, localeIdentifier);
166781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    // FIXME: The following assumes that the character at lastSpace is a space (and therefore should not factor
166881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    // into hyphenate-limit-before) unless lastSpace is 0. This is wrong in the rare case of hyphenating
166981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    // the first word in a text node which has leading whitespace.
16702bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (!prefixLength || prefixLength - (lastSpace ? 1 : 0) < static_cast<unsigned>(minimumPrefixLength))
167106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        return;
167206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
167381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT(pos - lastSpace - prefixLength >= static_cast<unsigned>(minimumSuffixLength));
167481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
167506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen#if !ASSERT_DISABLED
167681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    float prefixWidth = hyphenWidth + textWidth(text, lastSpace, prefixLength, font, xPos, isFixedPitch, collapseWhiteSpace) + lastSpaceWordSpacing;
167706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    ASSERT(xPos + prefixWidth <= availableWidth);
167806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen#else
167906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    UNUSED_PARAM(isFixedPitch);
168006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen#endif
168106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
16822bde8e466a4451c7319e3a072d118917957d6554Steve Block    lineBreak.moveTo(text, lastSpace + prefixLength, nextBreakable);
168306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    hyphenated = true;
168406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen}
168506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
16862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochclass LineWidth {
16872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochpublic:
16882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    LineWidth(RenderBlock* block, bool isFirstLine)
16892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        : m_block(block)
16902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_uncommittedWidth(0)
16912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_committedWidth(0)
16922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_overhangWidth(0)
16932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_left(0)
16942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_right(0)
16952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_availableWidth(0)
16962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_isFirstLine(isFirstLine)
16972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
16982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(block);
16992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        updateAvailableWidth();
17002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
17012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool fitsOnLine() const { return currentWidth() <= m_availableWidth; }
17022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool fitsOnLine(float extra) const { return currentWidth() + extra <= m_availableWidth; }
17032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    float currentWidth() const { return m_committedWidth + m_uncommittedWidth; }
17042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // FIXME: We should eventually replace these three functions by ones that work on a higher abstraction.
17062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    float uncommittedWidth() const { return m_uncommittedWidth; }
17072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    float committedWidth() const { return m_committedWidth; }
17082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    float availableWidth() const { return m_availableWidth; }
17092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    void updateAvailableWidth();
17112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    void shrinkAvailableWidthForNewFloatIfNeeded(RenderBlock::FloatingObject*);
17122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    void addUncommittedWidth(float delta) { m_uncommittedWidth += delta; }
17132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    void commit()
17142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
17152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        m_committedWidth += m_uncommittedWidth;
17162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        m_uncommittedWidth = 0;
17172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
17182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    void applyOverhang(RenderRubyRun*, RenderObject* startRenderer, RenderObject* endRenderer);
17192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    void fitBelowFloats();
17202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochprivate:
17222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    void computeAvailableWidthFromLeftAndRight()
17232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
17242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        m_availableWidth = max(0, m_right - m_left) + m_overhangWidth;
17252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
17262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochprivate:
17282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RenderBlock* m_block;
17292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    float m_uncommittedWidth;
17302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    float m_committedWidth;
17312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    float m_overhangWidth; // The amount by which |m_availableWidth| has been inflated to account for possible contraction due to ruby overhang.
17322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int m_left;
17332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int m_right;
17342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    float m_availableWidth;
17352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool m_isFirstLine;
17362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch};
17372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochinline void LineWidth::updateAvailableWidth()
17392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
17402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int height = m_block->logicalHeight();
17412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_left = m_block->logicalLeftOffsetForLine(height, m_isFirstLine);
17422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_right = m_block->logicalRightOffsetForLine(height, m_isFirstLine);
17432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    computeAvailableWidthFromLeftAndRight();
17452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
17462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochinline void LineWidth::shrinkAvailableWidthForNewFloatIfNeeded(RenderBlock::FloatingObject* newFloat)
17482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
17492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int height = m_block->logicalHeight();
17502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (height < m_block->logicalTopForFloat(newFloat) || height >= m_block->logicalBottomForFloat(newFloat))
17512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return;
17522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (newFloat->type() == RenderBlock::FloatingObject::FloatLeft)
17542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        m_left = m_block->logicalRightForFloat(newFloat);
17552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    else
17562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        m_right = m_block->logicalLeftForFloat(newFloat);
17572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    computeAvailableWidthFromLeftAndRight();
17592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
17602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid LineWidth::applyOverhang(RenderRubyRun* rubyRun, RenderObject* startRenderer, RenderObject* endRenderer)
17622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
17632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int startOverhang;
17642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int endOverhang;
17652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    rubyRun->getOverhang(m_isFirstLine, startRenderer, endRenderer, startOverhang, endOverhang);
17662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    startOverhang = min<int>(startOverhang, m_committedWidth);
17682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_availableWidth += startOverhang;
17692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    endOverhang = max(min<int>(endOverhang, m_availableWidth - currentWidth()), 0);
17712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_availableWidth += endOverhang;
17722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_overhangWidth += startOverhang + endOverhang;
17732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
17742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid LineWidth::fitBelowFloats()
17762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
17772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(!m_committedWidth);
17782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(!fitsOnLine());
17792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int floatLogicalBottom;
17812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int lastFloatLogicalBottom = m_block->logicalHeight();
17822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    float newLineWidth = m_availableWidth;
17832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    while (true) {
17842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        floatLogicalBottom = m_block->nextFloatLogicalBottomBelow(lastFloatLogicalBottom);
17852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!floatLogicalBottom)
17862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            break;
17872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        newLineWidth = m_block->availableLogicalWidthForLine(floatLogicalBottom, m_isFirstLine);
17892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        lastFloatLogicalBottom = floatLogicalBottom;
17902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (newLineWidth >= m_uncommittedWidth)
17912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            break;
17922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
17932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (newLineWidth > m_availableWidth) {
17952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        m_block->setLogicalHeight(lastFloatLogicalBottom);
17962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        m_availableWidth = newLineWidth + m_overhangWidth;
17972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
17982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
17992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
180081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen MurdochInlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool firstLine, bool& isLineEmpty, LineBreakIteratorInfo& lineBreakIteratorInfo, bool& previousLineBrokeCleanly,
18012bde8e466a4451c7319e3a072d118917957d6554Steve Block                                              bool& hyphenated, EClear* clear, FloatingObject* lastFloatFromPreviousLine, Vector<RenderBox*>& positionedBoxes)
18028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
18032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(resolver.position().root() == this);
18048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
18052bde8e466a4451c7319e3a072d118917957d6554Steve Block    bool appliedStartWidth = resolver.position().m_pos > 0;
18060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    LineMidpointState& lineMidpointState = resolver.midpointState();
18078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
18082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    LineWidth width(this, firstLine);
18092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
18102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    skipLeadingWhitespace(resolver, isLineEmpty, previousLineBrokeCleanly, lastFloatFromPreviousLine, width);
18118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
18128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (resolver.position().atEnd())
18138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return resolver.position();
18148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
18158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // This variable is used only if whitespace isn't set to PRE, and it tells us whether
18168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // or not we are currently ignoring whitespace.
18178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool ignoringSpaces = false;
18188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    InlineIterator ignoreStart;
18198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
18208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // This variable tracks whether the very last character we saw was a space.  We use
18218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // this to detect when we encounter a second space so we know we have to terminate
18228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // a run.
18238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool currentCharacterIsSpace = false;
18248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool currentCharacterIsWS = false;
18258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RenderObject* trailingSpaceObject = 0;
18262bde8e466a4451c7319e3a072d118917957d6554Steve Block    Vector<RenderBox*, 4> trailingPositionedBoxes;
18278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
18288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    InlineIterator lBreak = resolver.position();
18298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
18302bde8e466a4451c7319e3a072d118917957d6554Steve Block    // FIXME: It is error-prone to split the position object out like this.
18312bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Teach this code to work with objects instead of this split tuple.
18322bde8e466a4451c7319e3a072d118917957d6554Steve Block    RenderObject* o = resolver.position().m_obj;
183381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    RenderObject* last = o;
18342bde8e466a4451c7319e3a072d118917957d6554Steve Block    unsigned pos = resolver.position().m_pos;
18352bde8e466a4451c7319e3a072d118917957d6554Steve Block    int nextBreakable = resolver.position().m_nextBreakablePosition;
18368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool atStart = true;
18378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
18388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool prevLineBrokeCleanly = previousLineBrokeCleanly;
18398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    previousLineBrokeCleanly = false;
18408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
184106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    hyphenated = false;
184206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
18438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool autoWrapWasEverTrueOnLine = false;
18448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool floatsFitOnLine = true;
18458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
18468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Firefox and Opera will allow a table cell to grow to fit an image inside it under
18478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // very specific circumstances (in order to match common WinIE renderings).
18488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Not supporting the quirk has caused us to mis-render some real sites. (See Bugzilla 10517.)
1849a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    bool allowImagesToBreak = !document()->inQuirksMode() || !isTableCell() || !style()->logicalWidth().isIntrinsicOrAuto();
18508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
18518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    EWhiteSpace currWS = style()->whiteSpace();
18528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    EWhiteSpace lastWS = currWS;
18538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (o) {
18542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        RenderObject* next = bidiNext(this, o);
18552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
18568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        currWS = o->isReplaced() ? o->parent()->style()->whiteSpace() : o->style()->whiteSpace();
18578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        lastWS = last->isReplaced() ? last->parent()->style()->whiteSpace() : last->style()->whiteSpace();
18588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
18598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        bool autoWrap = RenderStyle::autoWrap(currWS);
18608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        autoWrapWasEverTrueOnLine = autoWrapWasEverTrueOnLine || autoWrap;
18618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
18628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if ENABLE(SVG)
186306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        bool preserveNewline = o->isSVGInlineText() ? false : RenderStyle::preserveNewline(currWS);
18648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#else
18658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        bool preserveNewline = RenderStyle::preserveNewline(currWS);
18668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
18678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
18688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        bool collapseWhiteSpace = RenderStyle::collapseWhiteSpace(currWS);
18698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
18708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (o->isBR()) {
18712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            if (width.fitsOnLine()) {
18722bde8e466a4451c7319e3a072d118917957d6554Steve Block                lBreak.moveToStartOf(o);
18738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                lBreak.increment();
18748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
18758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // A <br> always breaks a line, so don't let the line be collapsed
18768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // away. Also, the space at the end of a line with a <br> does not
18778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // get collapsed away.  It only does this if the previous line broke
18788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // cleanly.  Otherwise the <br> has no effect on whether the line is
18798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // empty or not.
18808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (prevLineBrokeCleanly)
18818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    isLineEmpty = false;
18828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                trailingSpaceObject = 0;
18838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                previousLineBrokeCleanly = true;
18848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
18858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (!isLineEmpty && clear)
18868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    *clear = o->style()->clear();
18878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
18888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            goto end;
18898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
18908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
18918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (o->isFloatingOrPositioned()) {
18928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // add to special objects...
18938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (o->isFloating()) {
1894635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                RenderBox* floatBox = toRenderBox(o);
189568513a70bcd92384395513322f1b801e7bf9c729Steve Block                FloatingObject* f = insertFloatingObject(floatBox);
18968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // check if it fits in the current line.
18978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // If it does, position it now, otherwise, position
18988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // it after moving to next line (in newLine() func)
18992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                if (floatsFitOnLine && width.fitsOnLine(logicalWidthForFloat(f))) {
19002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    positionNewFloatOnLine(f, lastFloatFromPreviousLine, width);
19012bde8e466a4451c7319e3a072d118917957d6554Steve Block                    if (lBreak.m_obj == o) {
19022bde8e466a4451c7319e3a072d118917957d6554Steve Block                        ASSERT(!lBreak.m_pos);
19032bde8e466a4451c7319e3a072d118917957d6554Steve Block                        lBreak.increment();
19042bde8e466a4451c7319e3a072d118917957d6554Steve Block                    }
19058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                } else
19068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    floatsFitOnLine = false;
19078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            } else if (o->isPositioned()) {
19088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // If our original display wasn't an inline type, then we can
190981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                // go ahead and determine our static inline position now.
19108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                RenderBox* box = toRenderBox(o);
19118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                bool isInlineType = box->style()->isOriginalDisplayInlineType();
19122bde8e466a4451c7319e3a072d118917957d6554Steve Block                if (!isInlineType)
191381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                    box->layer()->setStaticInlinePosition(borderAndPaddingStart());
19142bde8e466a4451c7319e3a072d118917957d6554Steve Block                else  {
19152bde8e466a4451c7319e3a072d118917957d6554Steve Block                    // If our original display was an INLINE type, then we can go ahead
19162bde8e466a4451c7319e3a072d118917957d6554Steve Block                    // and determine our static y position now.
191781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                    box->layer()->setStaticBlockPosition(logicalHeight());
19188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
19198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
19208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // If we're ignoring spaces, we have to stop and include this object and
19218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // then start ignoring spaces again.
19222bde8e466a4451c7319e3a072d118917957d6554Steve Block                if (isInlineType || o->container()->isRenderInline()) {
19238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (ignoringSpaces) {
19242bde8e466a4451c7319e3a072d118917957d6554Steve Block                        ignoreStart.m_obj = o;
19252bde8e466a4451c7319e3a072d118917957d6554Steve Block                        ignoreStart.m_pos = 0;
19260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                        addMidpoint(lineMidpointState, ignoreStart); // Stop ignoring spaces.
19270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                        addMidpoint(lineMidpointState, ignoreStart); // Start ignoring again.
19288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    }
19292bde8e466a4451c7319e3a072d118917957d6554Steve Block                    if (trailingSpaceObject)
19302bde8e466a4451c7319e3a072d118917957d6554Steve Block                        trailingPositionedBoxes.append(box);
19312bde8e466a4451c7319e3a072d118917957d6554Steve Block                } else
19322bde8e466a4451c7319e3a072d118917957d6554Steve Block                    positionedBoxes.append(box);
19338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
1934635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        } else if (o->isRenderInline()) {
19358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Right now, we should only encounter empty inlines here.
19368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            ASSERT(!o->firstChild());
19378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
19388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            RenderInline* flowBox = toRenderInline(o);
1939635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
19408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Now that some inline flows have line boxes, if we are already ignoring spaces, we need
19418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // to make sure that we stop to include this object and then start ignoring spaces again.
19428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // If this object is at the start of the line, we need to behave like list markers and
19438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // start ignoring spaces.
1944635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            if (inlineFlowRequiresLineBox(flowBox)) {
19458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                isLineEmpty = false;
19468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (ignoringSpaces) {
19478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    trailingSpaceObject = 0;
19482bde8e466a4451c7319e3a072d118917957d6554Steve Block                    trailingPositionedBoxes.clear();
19490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                    addMidpoint(lineMidpointState, InlineIterator(0, o, 0)); // Stop ignoring spaces.
19500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                    addMidpoint(lineMidpointState, InlineIterator(0, o, 0)); // Start ignoring again.
19512bde8e466a4451c7319e3a072d118917957d6554Steve Block                } else if (style()->collapseWhiteSpace() && resolver.position().m_obj == o
19520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                    && shouldSkipWhitespaceAfterStartObject(this, o, lineMidpointState)) {
19538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    // Like with list markers, we start ignoring spaces to make sure that any
19548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    // additional spaces we see will be discarded.
19558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    currentCharacterIsSpace = true;
19568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    currentCharacterIsWS = true;
19578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    ignoringSpaces = true;
19588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
19598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
19608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
19612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            width.addUncommittedWidth(borderPaddingMarginStart(flowBox) + borderPaddingMarginEnd(flowBox));
19628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else if (o->isReplaced()) {
1963635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            RenderBox* replacedBox = toRenderBox(o);
1964635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
19658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Break on replaced elements if either has normal white-space.
19668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if ((autoWrap || RenderStyle::autoWrap(lastWS)) && (!o->isImage() || allowImagesToBreak)) {
19672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                width.commit();
19682bde8e466a4451c7319e3a072d118917957d6554Steve Block                lBreak.moveToStartOf(o);
19698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
19708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
19718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (ignoringSpaces)
19720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                addMidpoint(lineMidpointState, InlineIterator(0, o, 0));
19738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
19748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            isLineEmpty = false;
19758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            ignoringSpaces = false;
19768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            currentCharacterIsSpace = false;
19778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            currentCharacterIsWS = false;
19788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            trailingSpaceObject = 0;
19792bde8e466a4451c7319e3a072d118917957d6554Steve Block            trailingPositionedBoxes.clear();
1980643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
19818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Optimize for a common case. If we can't find whitespace after the list
1982a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            // item, then this is all moot.
1983a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            int replacedLogicalWidth = logicalWidthForChild(replacedBox) + marginStartForChild(replacedBox) + marginEndForChild(replacedBox) + inlineLogicalWidth(o);
1984643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            if (o->isListMarker()) {
19850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                if (style()->collapseWhiteSpace() && shouldSkipWhitespaceAfterStartObject(this, o, lineMidpointState)) {
19868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    // Like with inline flows, we start ignoring spaces to make sure that any
19878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    // additional spaces we see will be discarded.
19888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    currentCharacterIsSpace = true;
19898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    currentCharacterIsWS = true;
19908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    ignoringSpaces = true;
19918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
1992643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                if (toRenderListMarker(o)->isInside())
19932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    width.addUncommittedWidth(replacedLogicalWidth);
19948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            } else
19952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                width.addUncommittedWidth(replacedLogicalWidth);
19962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            if (o->isRubyRun())
19972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                width.applyOverhang(toRenderRubyRun(o), last, next);
19988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else if (o->isText()) {
19998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (!pos)
20008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                appliedStartWidth = false;
20018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2002635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            RenderText* t = toRenderText(o);
20038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
200468513a70bcd92384395513322f1b801e7bf9c729Steve Block#if ENABLE(SVG)
200568513a70bcd92384395513322f1b801e7bf9c729Steve Block            bool isSVGText = t->isSVGInlineText();
200668513a70bcd92384395513322f1b801e7bf9c729Steve Block#endif
200768513a70bcd92384395513322f1b801e7bf9c729Steve Block
20082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            RenderStyle* style = t->style(firstLine);
20092bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (style->hasTextCombine() && o->isCombineText())
20102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                toRenderCombineText(o)->combineText();
20112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
20128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            int strlen = t->textLength();
20138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            int len = strlen - pos;
20148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            const UChar* str = t->characters();
20158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
201606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen            const Font& f = style->font();
20178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            bool isFixedPitch = f.isFixedPitch();
201881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            bool canHyphenate = style->hyphens() == HyphensAuto && WebCore::canHyphenate(style->locale());
20198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
20208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            int lastSpace = pos;
202181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            float wordSpacing = o->style()->wordSpacing();
202281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            float lastSpaceWordSpacing = 0;
20238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2024d0825bca7fe65beaee391d30da42e937db621564Steve Block            // Non-zero only when kerning is enabled, in which case we measure words with their trailing
2025d0825bca7fe65beaee391d30da42e937db621564Steve Block            // space, then subtract its width.
202681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            float wordTrailingSpaceWidth = f.typesettingFeatures() & Kerning ? f.width(TextRun(&space, 1)) + wordSpacing : 0;
2027d0825bca7fe65beaee391d30da42e937db621564Steve Block
20282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            float wrapW = width.uncommittedWidth() + inlineLogicalWidth(o, !appliedStartWidth, true);
202981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            float charWidth = 0;
20308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            bool breakNBSP = autoWrap && o->style()->nbspMode() == SPACE;
20318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Auto-wrapping text should wrap in the middle of a word only if it could not wrap before the word,
20328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // which is only possible if the word is the first thing on the line, that is, if |w| is zero.
20332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            bool breakWords = o->style()->breakWords() && ((autoWrap && !width.committedWidth()) || currWS == PRE);
20348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            bool midWordBreak = false;
20358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            bool breakAll = o->style()->wordBreak() == BreakAllWordBreak && autoWrap;
203681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            float hyphenWidth = 0;
20378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
20388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (t->isWordBreak()) {
20392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                width.commit();
20402bde8e466a4451c7319e3a072d118917957d6554Steve Block                lBreak.moveToStartOf(o);
20418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                ASSERT(!len);
20428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
20438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
20448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            while (len) {
20458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                bool previousCharacterIsSpace = currentCharacterIsSpace;
20468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                bool previousCharacterIsWS = currentCharacterIsWS;
20478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                UChar c = str[pos];
20488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                currentCharacterIsSpace = c == ' ' || c == '\t' || (!preserveNewline && (c == '\n'));
20498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
20508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (!collapseWhiteSpace || !currentCharacterIsSpace)
20518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    isLineEmpty = false;
20528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2053bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen                if (c == softHyphen && autoWrap && !hyphenWidth && style->hyphens() != HyphensNone) {
2054bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen                    const AtomicString& hyphenString = style->hyphenString();
2055bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen                    hyphenWidth = f.width(TextRun(hyphenString.characters(), hyphenString.length()));
20562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    width.addUncommittedWidth(hyphenWidth);
20578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
2058bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
20598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                bool applyWordSpacing = false;
20608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
20618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                currentCharacterIsWS = currentCharacterIsSpace || (breakNBSP && c == noBreakSpace);
20628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
20638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if ((breakAll || breakWords) && !midWordBreak) {
20648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    wrapW += charWidth;
20652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    charWidth = textWidth(t, pos, 1, f, width.committedWidth() + wrapW, isFixedPitch, collapseWhiteSpace);
20662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    midWordBreak = width.committedWidth() + wrapW + charWidth > width.availableWidth();
20678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
20688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
206981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                if (lineBreakIteratorInfo.first != t) {
207081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                    lineBreakIteratorInfo.first = t;
207181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                    lineBreakIteratorInfo.second.reset(str, strlen);
207281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                }
207381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
207481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                bool betweenWords = c == '\n' || (currWS != PRE && !atStart && isBreakable(lineBreakIteratorInfo.second, pos, nextBreakable, breakNBSP) && (style->hyphens() != HyphensNone || (pos && str[pos - 1] != softHyphen)));
2075bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
20768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (betweenWords || midWordBreak) {
20778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    bool stoppedIgnoringSpaces = false;
20788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (ignoringSpaces) {
20798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        if (!currentCharacterIsSpace) {
20808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            // Stop ignoring spaces and begin at this
20818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            // new point.
20828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            ignoringSpaces = false;
20838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            lastSpaceWordSpacing = 0;
20848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            lastSpace = pos; // e.g., "Foo    goo", don't add in any of the ignored spaces.
20850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                            addMidpoint(lineMidpointState, InlineIterator(0, o, pos));
20868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            stoppedIgnoringSpaces = true;
20878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        } else {
20888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            // Just keep ignoring these spaces.
20898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            pos++;
20908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            len--;
20918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            continue;
20928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        }
20938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    }
20948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
209581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                    float additionalTmpW;
2096d0825bca7fe65beaee391d30da42e937db621564Steve Block                    if (wordTrailingSpaceWidth && currentCharacterIsSpace)
20972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                        additionalTmpW = textWidth(t, lastSpace, pos + 1 - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace) - wordTrailingSpaceWidth + lastSpaceWordSpacing;
2098d0825bca7fe65beaee391d30da42e937db621564Steve Block                    else
20992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                        additionalTmpW = textWidth(t, lastSpace, pos - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace) + lastSpaceWordSpacing;
21002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    width.addUncommittedWidth(additionalTmpW);
21018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (!appliedStartWidth) {
21022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                        width.addUncommittedWidth(inlineLogicalWidth(o, true, false));
21038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        appliedStartWidth = true;
21048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    }
21058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
21068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    applyWordSpacing =  wordSpacing && currentCharacterIsSpace && !previousCharacterIsSpace;
21078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
21082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    if (!width.committedWidth() && autoWrap && !width.fitsOnLine())
21092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                        width.fitBelowFloats();
21108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
21118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (autoWrap || breakWords) {
21128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        // If we break only after white-space, consider the current character
21138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        // as candidate width for this line.
21148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        bool lineWasTooWide = false;
21152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                        if (width.fitsOnLine() && currentCharacterIsWS && o->style()->breakOnlyAfterWhiteSpace() && !midWordBreak) {
21162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                            int charWidth = textWidth(t, pos, 1, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace) + (applyWordSpacing ? wordSpacing : 0);
21178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            // Check if line is too big even without the extra space
21188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            // at the end of the line. If it is not, do nothing.
21198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            // If the line needs the extra whitespace to be too long,
21208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            // then move the line break to the space and skip all
21218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            // additional whitespace.
21222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                            if (!width.fitsOnLine(charWidth)) {
21238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                lineWasTooWide = true;
21242bde8e466a4451c7319e3a072d118917957d6554Steve Block                                lBreak.moveTo(o, pos, nextBreakable);
21250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                                skipTrailingWhitespace(lBreak, isLineEmpty, previousLineBrokeCleanly);
21268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            }
21278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        }
21282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                        if (lineWasTooWide || !width.fitsOnLine()) {
21292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                            if (canHyphenate && !width.fitsOnLine()) {
21302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                                tryHyphenating(t, f, style->locale(), style->hyphenationLimitBefore(), style->hyphenationLimitAfter(), lastSpace, pos, width.currentWidth() - additionalTmpW, width.availableWidth(), isFixedPitch, collapseWhiteSpace, lastSpaceWordSpacing, lBreak, nextBreakable, hyphenated);
213106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                                if (hyphenated)
213206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                                    goto end;
213306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                            }
21342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                            if (lBreak.atTextParagraphSeparator()) {
21358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                if (!stoppedIgnoringSpaces && pos > 0) {
21368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                    // We need to stop right before the newline and then start up again.
21370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                                    addMidpoint(lineMidpointState, InlineIterator(0, o, pos - 1)); // Stop
21380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                                    addMidpoint(lineMidpointState, InlineIterator(0, o, pos)); // Start
21398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                }
21408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                lBreak.increment();
21418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                previousLineBrokeCleanly = true;
21428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            }
21432bde8e466a4451c7319e3a072d118917957d6554Steve Block                            if (lBreak.m_obj && lBreak.m_pos && lBreak.m_obj->isText() && toRenderText(lBreak.m_obj)->textLength() && toRenderText(lBreak.m_obj)->characters()[lBreak.m_pos - 1] == softHyphen && style->hyphens() != HyphensNone)
2144bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen                                hyphenated = true;
21458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            goto end; // Didn't fit. Jump to the end.
21468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        } else {
21478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            if (!betweenWords || (midWordBreak && !autoWrap))
21482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                                width.addUncommittedWidth(-additionalTmpW);
2149bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen                            if (hyphenWidth) {
21508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                // Subtract the width of the soft hyphen out since we fit on a line.
21512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                                width.addUncommittedWidth(-hyphenWidth);
2152bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen                                hyphenWidth = 0;
2153bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen                            }
21548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        }
21558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    }
21568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
21578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (c == '\n' && preserveNewline) {
21588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        if (!stoppedIgnoringSpaces && pos > 0) {
21598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            // We need to stop right before the newline and then start up again.
21600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                            addMidpoint(lineMidpointState, InlineIterator(0, o, pos - 1)); // Stop
21610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                            addMidpoint(lineMidpointState, InlineIterator(0, o, pos)); // Start
21628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        }
21632bde8e466a4451c7319e3a072d118917957d6554Steve Block                        lBreak.moveTo(o, pos, nextBreakable);
21648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        lBreak.increment();
21658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        previousLineBrokeCleanly = true;
21668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        return lBreak;
21678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    }
21688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
21698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (autoWrap && betweenWords) {
21702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                        width.commit();
21718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        wrapW = 0;
21722bde8e466a4451c7319e3a072d118917957d6554Steve Block                        lBreak.moveTo(o, pos, nextBreakable);
21738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        // Auto-wrapping text should not wrap in the middle of a word once it has had an
21748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        // opportunity to break after a word.
21758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        breakWords = false;
21768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    }
21778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
21788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (midWordBreak) {
21798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        // Remember this as a breakable position in case
21808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        // adding the end width forces a break.
21812bde8e466a4451c7319e3a072d118917957d6554Steve Block                        lBreak.moveTo(o, pos, nextBreakable);
21828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        midWordBreak &= (breakWords || breakAll);
21838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    }
21848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
21858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (betweenWords) {
21868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0;
21878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        lastSpace = pos;
21888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    }
21898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
21908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (!ignoringSpaces && o->style()->collapseWhiteSpace()) {
21918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        // If we encounter a newline, or if we encounter a
21928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        // second space, we need to go ahead and break up this
21938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        // run and enter a mode where we start collapsing spaces.
21948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        if (currentCharacterIsSpace && previousCharacterIsSpace) {
21958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            ignoringSpaces = true;
21968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
21978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            // We just entered a mode where we are ignoring
21988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            // spaces. Create a midpoint to terminate the run
21998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            // before the second space.
22000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                            addMidpoint(lineMidpointState, ignoreStart);
22018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        }
22028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    }
22038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                } else if (ignoringSpaces) {
22048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    // Stop ignoring spaces and begin at this
22058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    // new point.
22068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    ignoringSpaces = false;
22078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0;
22088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    lastSpace = pos; // e.g., "Foo    goo", don't add in any of the ignored spaces.
22090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                    addMidpoint(lineMidpointState, InlineIterator(0, o, pos));
22108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
22118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
22122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#if ENABLE(SVG)
22132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                if (isSVGText && pos > 0) {
22142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    // Force creation of new InlineBoxes for each absolute positioned character (those that start new text chunks).
22152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    if (static_cast<RenderSVGInlineText*>(t)->characterStartsNewTextChunk(pos)) {
22162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                        addMidpoint(lineMidpointState, InlineIterator(0, o, pos - 1));
22172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                        addMidpoint(lineMidpointState, InlineIterator(0, o, pos));
22182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    }
22192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                }
22202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#endif
22212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
22228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (currentCharacterIsSpace && !previousCharacterIsSpace) {
22232bde8e466a4451c7319e3a072d118917957d6554Steve Block                    ignoreStart.m_obj = o;
22242bde8e466a4451c7319e3a072d118917957d6554Steve Block                    ignoreStart.m_pos = pos;
22258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
22268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
22278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (!currentCharacterIsWS && previousCharacterIsWS) {
22282bde8e466a4451c7319e3a072d118917957d6554Steve Block                    if (autoWrap && o->style()->breakOnlyAfterWhiteSpace())
22292bde8e466a4451c7319e3a072d118917957d6554Steve Block                        lBreak.moveTo(o, pos, nextBreakable);
22308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
22318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
22328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (collapseWhiteSpace && currentCharacterIsSpace && !ignoringSpaces)
22338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    trailingSpaceObject = o;
22342bde8e466a4451c7319e3a072d118917957d6554Steve Block                else if (!o->style()->collapseWhiteSpace() || !currentCharacterIsSpace) {
22358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    trailingSpaceObject = 0;
22362bde8e466a4451c7319e3a072d118917957d6554Steve Block                    trailingPositionedBoxes.clear();
22372bde8e466a4451c7319e3a072d118917957d6554Steve Block                }
22388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
22398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                pos++;
22408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                len--;
22418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                atStart = false;
22428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
22438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
22448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // IMPORTANT: pos is > length here!
22452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            float additionalTmpW = ignoringSpaces ? 0 : textWidth(t, lastSpace, pos - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace) + lastSpaceWordSpacing;
22462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            width.addUncommittedWidth(additionalTmpW + inlineLogicalWidth(o, !appliedStartWidth, true));
224706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
22482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            if (!width.fitsOnLine()) {
22492bde8e466a4451c7319e3a072d118917957d6554Steve Block                if (canHyphenate)
22502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    tryHyphenating(t, f, style->locale(), style->hyphenationLimitBefore(), style->hyphenationLimitAfter(), lastSpace, pos, width.currentWidth() - additionalTmpW, width.availableWidth(), isFixedPitch, collapseWhiteSpace, lastSpaceWordSpacing, lBreak, nextBreakable, hyphenated);
22512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
22522bde8e466a4451c7319e3a072d118917957d6554Steve Block                if (!hyphenated && lBreak.m_obj && lBreak.m_pos && lBreak.m_obj->isText() && toRenderText(lBreak.m_obj)->textLength() && toRenderText(lBreak.m_obj)->characters()[lBreak.m_pos - 1] == softHyphen && style->hyphens() != HyphensNone)
22532bde8e466a4451c7319e3a072d118917957d6554Steve Block                    hyphenated = true;
22542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
225506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                if (hyphenated)
225606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                    goto end;
225706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen            }
22588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else
22598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            ASSERT_NOT_REACHED();
22608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
22618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        bool checkForBreak = autoWrap;
22622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (width.committedWidth() && !width.fitsOnLine() && lBreak.m_obj && currWS == NOWRAP)
22638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            checkForBreak = true;
22648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        else if (next && o->isText() && next->isText() && !next->isBR()) {
22658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (autoWrap || (next->style()->autoWrap())) {
22668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (currentCharacterIsSpace)
22678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    checkForBreak = true;
22688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                else {
22698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    checkForBreak = false;
2270635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                    RenderText* nextText = toRenderText(next);
22718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (nextText->textLength()) {
22728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        UChar c = nextText->characters()[0];
22732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                        if (c == ' ' || c == '\t' || (c == '\n' && !next->preservesNewline()))
22748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            // If the next item on the line is text, and if we did not end with
22758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            // a space, then the next text run continues our word (and so it needs to
22768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            // keep adding to |tmpW|.  Just update and continue.
22778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            checkForBreak = true;
22788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    } else if (nextText->isWordBreak())
22798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        checkForBreak = true;
22802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
22812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    if (!width.fitsOnLine() && !width.committedWidth())
22822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                        width.fitBelowFloats();
22832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
22842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    bool canPlaceOnLine = width.fitsOnLine() || !autoWrapWasEverTrueOnLine;
22858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (canPlaceOnLine && checkForBreak) {
22862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                        width.commit();
22872bde8e466a4451c7319e3a072d118917957d6554Steve Block                        lBreak.moveToStartOf(next);
22888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    }
22898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
22908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
22918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
22928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
22932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (checkForBreak && !width.fitsOnLine()) {
22948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // if we have floats, try to get below them.
22952bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (currentCharacterIsSpace && !ignoringSpaces && o->style()->collapseWhiteSpace()) {
22968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                trailingSpaceObject = 0;
22972bde8e466a4451c7319e3a072d118917957d6554Steve Block                trailingPositionedBoxes.clear();
22982bde8e466a4451c7319e3a072d118917957d6554Steve Block            }
22998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
23002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            if (width.committedWidth())
23018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                goto end;
23028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
23032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            width.fitBelowFloats();
23048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
23058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // |width| may have been adjusted because we got shoved down past a float (thus
23068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // giving us more room), so we need to retest, and only jump to
23078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // the end label if we still don't fit on the line. -dwh
23082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            if (!width.fitsOnLine())
23098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                goto end;
23108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
23118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
23128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!o->isFloatingOrPositioned()) {
23138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            last = o;
23140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            if (last->isReplaced() && autoWrap && (!last->isImage() || allowImagesToBreak) && (!last->isListMarker() || toRenderListMarker(last)->isInside())) {
23152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                width.commit();
23162bde8e466a4451c7319e3a072d118917957d6554Steve Block                lBreak.moveToStartOf(next);
23178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
23188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
23198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
23208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        o = next;
23218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        nextBreakable = -1;
23228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
23238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Clear out our character space bool, since inline <pre>s don't collapse whitespace
23248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // with adjacent inline normal/nowrap spans.
23258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!collapseWhiteSpace)
23268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            currentCharacterIsSpace = false;
23278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
23288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        pos = 0;
23298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        atStart = false;
23308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
23318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
23322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (width.fitsOnLine() || lastWS == NOWRAP)
23332bde8e466a4451c7319e3a072d118917957d6554Steve Block        lBreak.clear();
23348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
23358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project end:
23362bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (lBreak == resolver.position() && (!lBreak.m_obj || !lBreak.m_obj->isBR())) {
23378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // we just add as much as possible
23388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (style()->whiteSpace() == PRE) {
23398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // FIXME: Don't really understand this case.
23408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (pos != 0) {
23412bde8e466a4451c7319e3a072d118917957d6554Steve Block                // FIXME: This should call moveTo which would clear m_nextBreakablePosition
23422bde8e466a4451c7319e3a072d118917957d6554Steve Block                // this code as-is is likely wrong.
23432bde8e466a4451c7319e3a072d118917957d6554Steve Block                lBreak.m_obj = o;
23442bde8e466a4451c7319e3a072d118917957d6554Steve Block                lBreak.m_pos = pos - 1;
23452bde8e466a4451c7319e3a072d118917957d6554Steve Block            } else
23462bde8e466a4451c7319e3a072d118917957d6554Steve Block                lBreak.moveTo(last, last->isText() ? last->length() : 0);
23472bde8e466a4451c7319e3a072d118917957d6554Steve Block        } else if (lBreak.m_obj) {
23488a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block            // Don't ever break in the middle of a word if we can help it.
23498a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block            // There's no room at all. We just have to be on this line,
23508a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block            // even though we'll spill out.
23512bde8e466a4451c7319e3a072d118917957d6554Steve Block            lBreak.moveTo(o, pos);
23528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
23538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
23548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
23558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // make sure we consume at least one char/object.
23568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (lBreak == resolver.position())
23578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        lBreak.increment();
23588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
23598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Sanity check our midpoints.
23600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    checkMidpoints(lineMidpointState, lBreak);
23618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
23628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (trailingSpaceObject) {
23638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // This object is either going to be part of the last midpoint, or it is going
23648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // to be the actual endpoint.  In both cases we just decrease our pos by 1 level to
23658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // exclude the space, allowing it to - in effect - collapse into the newline.
23660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (lineMidpointState.numMidpoints % 2) {
23672bde8e466a4451c7319e3a072d118917957d6554Steve Block            // Find the trailing space object's midpoint.
23682bde8e466a4451c7319e3a072d118917957d6554Steve Block            int trailingSpaceMidpoint = lineMidpointState.numMidpoints - 1;
23692bde8e466a4451c7319e3a072d118917957d6554Steve Block            for ( ; trailingSpaceMidpoint >= 0 && lineMidpointState.midpoints[trailingSpaceMidpoint].m_obj != trailingSpaceObject; --trailingSpaceMidpoint) { }
23702bde8e466a4451c7319e3a072d118917957d6554Steve Block            ASSERT(trailingSpaceMidpoint >= 0);
23712bde8e466a4451c7319e3a072d118917957d6554Steve Block            lineMidpointState.midpoints[trailingSpaceMidpoint].m_pos--;
23722bde8e466a4451c7319e3a072d118917957d6554Steve Block
23732bde8e466a4451c7319e3a072d118917957d6554Steve Block            // Now make sure every single trailingPositionedBox following the trailingSpaceMidpoint properly stops and starts
23742bde8e466a4451c7319e3a072d118917957d6554Steve Block            // ignoring spaces.
23752bde8e466a4451c7319e3a072d118917957d6554Steve Block            size_t currentMidpoint = trailingSpaceMidpoint + 1;
23762bde8e466a4451c7319e3a072d118917957d6554Steve Block            for (size_t i = 0; i < trailingPositionedBoxes.size(); ++i) {
23772bde8e466a4451c7319e3a072d118917957d6554Steve Block                if (currentMidpoint >= lineMidpointState.numMidpoints) {
23782bde8e466a4451c7319e3a072d118917957d6554Steve Block                    // We don't have a midpoint for this box yet.
23792bde8e466a4451c7319e3a072d118917957d6554Steve Block                    InlineIterator ignoreStart(this, trailingPositionedBoxes[i], 0);
23802bde8e466a4451c7319e3a072d118917957d6554Steve Block                    addMidpoint(lineMidpointState, ignoreStart); // Stop ignoring.
23812bde8e466a4451c7319e3a072d118917957d6554Steve Block                    addMidpoint(lineMidpointState, ignoreStart); // Start ignoring again.
23822bde8e466a4451c7319e3a072d118917957d6554Steve Block                } else {
23832bde8e466a4451c7319e3a072d118917957d6554Steve Block                    ASSERT(lineMidpointState.midpoints[currentMidpoint].m_obj == trailingPositionedBoxes[i]);
23842bde8e466a4451c7319e3a072d118917957d6554Steve Block                    ASSERT(lineMidpointState.midpoints[currentMidpoint + 1].m_obj == trailingPositionedBoxes[i]);
23852bde8e466a4451c7319e3a072d118917957d6554Steve Block                }
23862bde8e466a4451c7319e3a072d118917957d6554Steve Block                currentMidpoint += 2;
23872bde8e466a4451c7319e3a072d118917957d6554Steve Block            }
23882bde8e466a4451c7319e3a072d118917957d6554Steve Block        } else if (!lBreak.m_obj && trailingSpaceObject->isText()) {
23898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Add a new end midpoint that stops right at the very end.
2390635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            RenderText* text = toRenderText(trailingSpaceObject);
23918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            unsigned length = text->textLength();
23928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            unsigned pos = length >= 2 ? length - 2 : UINT_MAX;
23938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            InlineIterator endMid(0, trailingSpaceObject, pos);
23940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            addMidpoint(lineMidpointState, endMid);
23952bde8e466a4451c7319e3a072d118917957d6554Steve Block            for (size_t i = 0; i < trailingPositionedBoxes.size(); ++i) {
23962bde8e466a4451c7319e3a072d118917957d6554Steve Block                ignoreStart.m_obj = trailingPositionedBoxes[i];
23972bde8e466a4451c7319e3a072d118917957d6554Steve Block                ignoreStart.m_pos = 0;
23982bde8e466a4451c7319e3a072d118917957d6554Steve Block                addMidpoint(lineMidpointState, ignoreStart); // Stop ignoring spaces.
23992bde8e466a4451c7319e3a072d118917957d6554Steve Block                addMidpoint(lineMidpointState, ignoreStart); // Start ignoring again.
24002bde8e466a4451c7319e3a072d118917957d6554Steve Block            }
24018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
24028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
24038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
24048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // We might have made lBreak an iterator that points past the end
24058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // of the object. Do this adjustment to make it point to the start
24068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // of the next object instead to avoid confusing the rest of the
24078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // code.
24082bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (lBreak.m_pos > 0) {
24092bde8e466a4451c7319e3a072d118917957d6554Steve Block        lBreak.m_pos--;
24108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        lBreak.increment();
24118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
24128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
24138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return lBreak;
24148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
24158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2416231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid RenderBlock::addOverflowFromInlineChildren()
24178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2418f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    int endPadding = hasOverflowClip() ? paddingEnd() : 0;
2419f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // FIXME: Need to find another way to do this, since scrollbars could show when we don't want them to.
24202bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (hasOverflowClip() && !endPadding && node() && node()->rendererIsEditable() && node() == node()->rootEditableElement() && style()->isLeftToRightDirection())
2421f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        endPadding = 1;
24228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
2423f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        addLayoutOverflow(curr->paddedLayoutOverflowRect(endPadding));
2424231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (!hasOverflowClip())
24252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            addVisualOverflow(curr->visualOverflowRect(curr->lineTop(), curr->lineBottom()));
24268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
24278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
24288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
24298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid RenderBlock::deleteEllipsisLineBoxes()
24308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
24318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox())
24328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        curr->clearTruncation();
24338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
24348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
24358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid RenderBlock::checkLinesForTextOverflow()
24368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
24378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Determine the width of the ellipsis using the current font.
24388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: CSS3 says this is configurable, also need to use 0x002E (FULL STOP) if horizontal ellipsis is "not renderable"
24398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    TextRun ellipsisRun(&horizontalEllipsis, 1);
2440635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    DEFINE_STATIC_LOCAL(AtomicString, ellipsisStr, (&horizontalEllipsis, 1));
24418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const Font& firstLineFont = firstLineStyle()->font();
24428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const Font& font = style()->font();
24438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int firstLineEllipsisWidth = firstLineFont.width(ellipsisRun);
24448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int ellipsisWidth = (font == firstLineFont) ? firstLineEllipsisWidth : font.width(ellipsisRun);
24458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
24468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // For LTR text truncation, we want to get the right edge of our padding box, and then we want to see
24478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // if the right edge of a line box exceeds that.  For RTL, we use the left edge of the padding box and
24488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // check the left edge of the line box to see if it is less
24498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Include the scrollbar for overflow blocks, which means we want to use "contentWidth()"
2450a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    bool ltr = style()->isLeftToRightDirection();
24518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
2452bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        int blockRightEdge = logicalRightOffsetForLine(curr->y(), curr == firstRootBox());
2453bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        int blockLeftEdge = logicalLeftOffsetForLine(curr->y(), curr == firstRootBox());
2454bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        int lineBoxEdge = ltr ? curr->x() + curr->logicalWidth() : curr->x();
24555f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if ((ltr && lineBoxEdge > blockRightEdge) || (!ltr && lineBoxEdge < blockLeftEdge)) {
24568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // This line spills out of our box in the appropriate direction.  Now we need to see if the line
24578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // can be truncated.  In order for truncation to be possible, the line must have sufficient space to
24588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // accommodate our truncation string, and no replaced elements (images, tables) can overlap the ellipsis
24598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // space.
24608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            int width = curr == firstRootBox() ? firstLineEllipsisWidth : ellipsisWidth;
24615f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            int blockEdge = ltr ? blockRightEdge : blockLeftEdge;
246281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            if (curr->lineCanAccommodateEllipsis(ltr, blockEdge, lineBoxEdge, width))
24635f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                curr->placeEllipsis(ellipsisStr, ltr, blockLeftEdge, blockRightEdge, width);
24648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
24658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
24668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
24678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
24682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochbool RenderBlock::positionNewFloatOnLine(FloatingObject* newFloat, FloatingObject* lastFloatFromPreviousLine, LineWidth& width)
24692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
24702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!positionNewFloats())
24712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
24722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
24732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    width.shrinkAvailableWidthForNewFloatIfNeeded(newFloat);
24742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
24752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!newFloat->m_paginationStrut)
24762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return true;
24772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
24782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
24792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(floatingObjectSet.last() == newFloat);
24802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
24812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int floatLogicalTop = logicalTopForFloat(newFloat);
24822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int paginationStrut = newFloat->m_paginationStrut;
24832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
24842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (floatLogicalTop - paginationStrut != logicalHeight())
24852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return true;
24862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
24872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    FloatingObjectSetIterator it = floatingObjectSet.end();
24882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    --it; // Last float is newFloat, skip that one.
24892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    FloatingObjectSetIterator begin = floatingObjectSet.begin();
24902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    while (it != begin) {
24912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        --it;
24922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        FloatingObject* f = *it;
24932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (f == lastFloatFromPreviousLine)
24942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            break;
24952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (logicalTopForFloat(f) == logicalHeight()) {
24962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            ASSERT(!f->m_paginationStrut);
24972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            f->m_paginationStrut = paginationStrut;
24982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            RenderBox* o = f->m_renderer;
24992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            setLogicalTopForChild(o, logicalTopForChild(o) + marginBeforeForChild(o) + paginationStrut);
25002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            if (o->isRenderBlock())
25012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                toRenderBlock(o)->setChildNeedsLayout(true, false);
25022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            o->layoutIfNeeded();
25032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            setLogicalTopForFloat(f, logicalTopForFloat(f) + f->m_paginationStrut);
25042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
25052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
25062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
25072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    setLogicalHeight(logicalHeight() + paginationStrut);
25082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    width.updateAvailableWidth();
25092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
25102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return true;
25112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
25122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
25138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2514