diff options
Diffstat (limited to 'WebCore/rendering/RenderBlockLineLayout.cpp')
| -rw-r--r-- | WebCore/rendering/RenderBlockLineLayout.cpp | 441 |
1 files changed, 77 insertions, 364 deletions
diff --git a/WebCore/rendering/RenderBlockLineLayout.cpp b/WebCore/rendering/RenderBlockLineLayout.cpp index 615a369..a7f3553 100644 --- a/WebCore/rendering/RenderBlockLineLayout.cpp +++ b/WebCore/rendering/RenderBlockLineLayout.cpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2000 Lars Knoll (knoll@kde.org) - * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009 Apple Inc. All right reserved. + * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010 Apple Inc. All right reserved. + * Copyright (C) 2010 Google Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -23,12 +24,14 @@ #include "BidiResolver.h" #include "CharacterNames.h" +#include "InlineIterator.h" #include "InlineTextBox.h" #include "Logging.h" #include "RenderArena.h" #include "RenderInline.h" #include "RenderListMarker.h" #include "RenderView.h" +#include "TrailingFloatsRootInlineBox.h" #include "break_lines.h" #include <wtf/AlwaysInline.h> #include <wtf/RefCountedLeakCounter.h> @@ -51,36 +54,6 @@ namespace WebCore { // We don't let our line box tree for a single line get any deeper than this. const unsigned cMaxLineDepth = 200; -class InlineIterator { -public: - InlineIterator() - : block(0) - , obj(0) - , pos(0) - , nextBreakablePosition(-1) - { - } - - InlineIterator(RenderBlock* b, RenderObject* o, unsigned p) - : block(b) - , obj(o) - , pos(p) - , nextBreakablePosition(-1) - { - } - - void increment(InlineBidiResolver* resolver = 0); - bool atEnd() const; - - UChar current() const; - Direction direction() const; - - RenderBlock* block; - RenderObject* obj; - unsigned pos; - int nextBreakablePosition; -}; - static int getBorderPaddingMargin(RenderBoxModelObject* child, bool endOfInline) { bool leftSide = (child->style()->direction() == LTR) ? !endOfInline : endOfInline; @@ -105,247 +78,6 @@ static int inlineWidth(RenderObject* child, bool start = true, bool end = true) return extraWidth; } -struct BidiRun : BidiCharacterRun { - BidiRun(int start, int stop, RenderObject* object, BidiContext* context, Direction dir) - : BidiCharacterRun(start, stop, context, dir) - , m_object(object) - , m_box(0) - { - } - - void destroy(); - - // Overloaded new operator. - void* operator new(size_t, RenderArena*) throw(); - - // Overridden to prevent the normal delete from being called. - void operator delete(void*, size_t); - - BidiRun* next() { return static_cast<BidiRun*>(m_next); } - -private: - // The normal operator new is disallowed. - void* operator new(size_t) throw(); - -public: - RenderObject* m_object; - InlineBox* m_box; -}; - -#ifndef NDEBUG -static RefCountedLeakCounter bidiRunCounter("BidiRun"); - -static bool inBidiRunDestroy; -#endif - -void BidiRun::destroy() -{ -#ifndef NDEBUG - inBidiRunDestroy = true; -#endif - RenderArena* renderArena = m_object->renderArena(); - delete this; -#ifndef NDEBUG - inBidiRunDestroy = false; -#endif - - // Recover the size left there for us by operator delete and free the memory. - renderArena->free(*reinterpret_cast<size_t*>(this), this); -} - -void* BidiRun::operator new(size_t sz, RenderArena* renderArena) throw() -{ -#ifndef NDEBUG - bidiRunCounter.increment(); -#endif - return renderArena->allocate(sz); -} - -void BidiRun::operator delete(void* ptr, size_t sz) -{ -#ifndef NDEBUG - bidiRunCounter.decrement(); -#endif - ASSERT(inBidiRunDestroy); - - // Stash size where destroy() can find it. - *(size_t*)ptr = sz; -} - -// --------------------------------------------------------------------- - -inline bool operator==(const InlineIterator& it1, const InlineIterator& it2) -{ - return it1.pos == it2.pos && it1.obj == it2.obj; -} - -inline bool operator!=(const InlineIterator& it1, const InlineIterator& it2) -{ - return it1.pos != it2.pos || it1.obj != it2.obj; -} - -static inline RenderObject* bidiNext(RenderBlock* block, RenderObject* current, InlineBidiResolver* resolver = 0, bool skipInlines = true, bool* endOfInlinePtr = 0) -{ - RenderObject* next = 0; - bool oldEndOfInline = endOfInlinePtr ? *endOfInlinePtr : false; - bool endOfInline = false; - - while (current) { - next = 0; - if (!oldEndOfInline && !current->isFloating() && !current->isReplaced() && !current->isPositioned() && !current->isText()) { - next = current->firstChild(); - if (next && resolver && next->isRenderInline()) { - EUnicodeBidi ub = next->style()->unicodeBidi(); - if (ub != UBNormal) { - TextDirection dir = next->style()->direction(); - Direction d = (ub == Embed - ? (dir == RTL ? RightToLeftEmbedding : LeftToRightEmbedding) - : (dir == RTL ? RightToLeftOverride : LeftToRightOverride)); - resolver->embed(d); - } - } - } - - if (!next) { - if (!skipInlines && !oldEndOfInline && current->isRenderInline()) { - next = current; - endOfInline = true; - break; - } - - while (current && current != block) { - if (resolver && current->isRenderInline() && current->style()->unicodeBidi() != UBNormal) - resolver->embed(PopDirectionalFormat); - - next = current->nextSibling(); - if (next) { - if (resolver && next->isRenderInline()) { - EUnicodeBidi ub = next->style()->unicodeBidi(); - if (ub != UBNormal) { - TextDirection dir = next->style()->direction(); - Direction d = (ub == Embed - ? (dir == RTL ? RightToLeftEmbedding: LeftToRightEmbedding) - : (dir == RTL ? RightToLeftOverride : LeftToRightOverride)); - resolver->embed(d); - } - } - break; - } - - current = current->parent(); - if (!skipInlines && current && current != block && current->isRenderInline()) { - next = current; - endOfInline = true; - break; - } - } - } - - if (!next) - break; - - if (next->isText() || next->isFloating() || next->isReplaced() || next->isPositioned() - || ((!skipInlines || !next->firstChild()) // Always return EMPTY inlines. - && next->isRenderInline())) - break; - current = next; - } - - if (endOfInlinePtr) - *endOfInlinePtr = endOfInline; - - return next; -} - -static RenderObject* bidiFirst(RenderBlock* block, InlineBidiResolver* resolver, bool skipInlines = true) -{ - if (!block->firstChild()) - return 0; - - RenderObject* o = block->firstChild(); - if (o->isRenderInline()) { - if (resolver) { - EUnicodeBidi ub = o->style()->unicodeBidi(); - if (ub != UBNormal) { - TextDirection dir = o->style()->direction(); - Direction d = (ub == Embed - ? (dir == RTL ? RightToLeftEmbedding : LeftToRightEmbedding) - : (dir == RTL ? RightToLeftOverride : LeftToRightOverride)); - resolver->embed(d); - } - } - if (skipInlines && o->firstChild()) - o = bidiNext(block, o, resolver, skipInlines); - else { - // Never skip empty inlines. - if (resolver) - resolver->commitExplicitEmbedding(); - return o; - } - } - - if (o && !o->isText() && !o->isReplaced() && !o->isFloating() && !o->isPositioned()) - o = bidiNext(block, o, resolver, skipInlines); - - if (resolver) - resolver->commitExplicitEmbedding(); - return o; -} - -inline void InlineIterator::increment(InlineBidiResolver* resolver) -{ - if (!obj) - return; - if (obj->isText()) { - pos++; - if (pos >= toRenderText(obj)->textLength()) { - obj = bidiNext(block, obj, resolver); - pos = 0; - nextBreakablePosition = -1; - } - } else { - obj = bidiNext(block, obj, resolver); - pos = 0; - nextBreakablePosition = -1; - } -} - -template<> -inline void InlineBidiResolver::increment() -{ - current.increment(this); -} - -inline bool InlineIterator::atEnd() const -{ - return !obj; -} - -inline UChar InlineIterator::current() const -{ - if (!obj || !obj->isText()) - return 0; - - RenderText* text = toRenderText(obj); - if (pos >= text->textLength()) - return 0; - - return text->characters()[pos]; -} - -ALWAYS_INLINE Direction InlineIterator::direction() const -{ - if (UChar c = current()) - return Unicode::direction(c); - - if (obj && obj->isListMarker()) - return obj->style()->direction() == LTR ? LeftToRight : RightToLeft; - - return OtherNeutral; -} - -// ------------------------------------------------------------------------------------------------- - static void chopMidpointsAt(LineMidpointState& lineMidpointState, RenderObject* obj, unsigned pos) { if (!lineMidpointState.numMidpoints) @@ -403,7 +135,7 @@ static void addMidpoint(LineMidpointState& lineMidpointState, const InlineIterat midpoints[lineMidpointState.numMidpoints++] = midpoint; } -static void appendRunsForObject(int start, int end, RenderObject* obj, InlineBidiResolver& resolver) +void RenderBlock::appendRunsForObject(int start, int end, RenderObject* obj, InlineBidiResolver& resolver) { if (start > end || obj->isFloating() || (obj->isPositioned() && !obj->style()->hasStaticX() && !obj->style()->hasStaticY() && !obj->container()->isRenderInline())) @@ -446,36 +178,6 @@ static void appendRunsForObject(int start, int end, RenderObject* obj, InlineBid } } -template <> -void InlineBidiResolver::appendRun() -{ - if (!emptyRun && !eor.atEnd()) { - int start = sor.pos; - RenderObject *obj = sor.obj; - while (obj && obj != eor.obj && obj != endOfLine.obj) { - appendRunsForObject(start, obj->length(), obj, *this); - start = 0; - obj = bidiNext(sor.block, obj); - } - if (obj) { - unsigned pos = obj == eor.obj ? eor.pos : UINT_MAX; - if (obj == endOfLine.obj && endOfLine.pos <= pos) { - reachedEndOfLine = true; - pos = endOfLine.pos; - } - // It's OK to add runs for zero-length RenderObjects, just don't make the run larger than it should be - int end = obj->length() ? pos+1 : 0; - appendRunsForObject(start, end, obj, *this); - } - - eor.increment(); - sor = eor; - } - - m_direction = OtherNeutral; - m_status.eor = OtherNeutral; -} - static inline InlineBox* createInlineBoxForRenderer(RenderObject* obj, bool isRootLineBox, bool isOnlyRun = false) { if (isRootLineBox) @@ -770,11 +472,8 @@ void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, bool // The widths of all runs are now known. We can now place every inline box (and // compute accurate widths for the inline flow boxes). - int leftPosition = x; - int rightPosition = x; needsWordSpacing = false; - lineBox->placeBoxesHorizontally(x, leftPosition, rightPosition, needsWordSpacing); - lineBox->setHorizontalOverflowPositions(leftPosition, rightPosition); + lineBox->placeBoxesHorizontally(x, needsWordSpacing); } void RenderBlock::computeVerticalPositionsForLine(RootInlineBox* lineBox, BidiRun* firstRun) @@ -782,11 +481,6 @@ void RenderBlock::computeVerticalPositionsForLine(RootInlineBox* lineBox, BidiRu setHeight(lineBox->verticallyAlignBoxes(height())); lineBox->setBlockHeight(height()); - // See if the line spilled out. If so set overflow height accordingly. - int bottomOfLine = lineBox->bottomOverflow(); - if (bottomOfLine > height() && bottomOfLine > m_overflowHeight) - m_overflowHeight = bottomOfLine; - // Now make sure we place replaced render objects correctly. for (BidiRun* r = firstRun; r; r = r->next()) { ASSERT(r->m_box); @@ -831,14 +525,14 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i { bool useRepaintBounds = false; - m_overflowHeight = 0; + m_overflow.clear(); setHeight(borderTop() + paddingTop()); int toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight(); // Figure out if we should clear out our line boxes. // FIXME: Handle resize eventually! - bool fullLayout = !firstLineBox() || !firstChild() || selfNeedsLayout() || relayoutChildren; + bool fullLayout = !firstLineBox() || selfNeedsLayout() || relayoutChildren; if (fullLayout) lineBoxes()->deleteLineBoxes(renderArena()); @@ -855,14 +549,17 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i if (firstChild()) { #ifdef ANDROID_LAYOUT - // if we are in fitColumnToScreen mode and viewport width is not device-width, + // if we are in fitColumnToScreen mode // and the current object is not float:right in LTR or not float:left in RTL, // and text align is auto, or justify or left in LTR, or right in RTL, we // will wrap text around screen width so that it doesn't need to scroll // horizontally when reading a paragraph. + // In case the line height is less than the font size, we skip + // the text wrapping since this will cause text overlapping. + // If a text has background image, we ignore text wrapping, + // otherwise the background will be potentially messed up. const Settings* settings = document()->settings(); - bool doTextWrap = settings && settings->viewportWidth() != 0 && - settings->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen; + bool doTextWrap = settings && settings->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen; if (doTextWrap) { int ta = style()->textAlign(); int dir = style()->direction(); @@ -871,9 +568,12 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i // width as it may cause text to overlap. bool positioned = isPositioned(); EFloat cssfloat = style()->floating(); + const int lineHeight = style()->computedLineHeight(); + const int fontSize = style()->fontSize(); doTextWrap = autowrap && !positioned && + (fontSize <= lineHeight) && !style()->hasBackgroundImage() && (((dir == LTR && cssfloat != FRIGHT) || - (dir == RTL && cssfloat != FLEFT)) && + (dir == RTL && cssfloat != FLEFT)) && ((ta == TAAUTO) || (ta == JUSTIFY) || ((ta == LEFT || ta == WEBKIT_LEFT) && (dir == LTR)) || ((ta == RIGHT || ta == WEBKIT_RIGHT) && (dir == RTL)))); @@ -884,6 +584,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i bool endOfInline = false; RenderObject* o = bidiFirst(this, 0, false); Vector<FloatWithRect> floats; + bool hasInlineChild = false; while (o) { if (o->isReplaced() || o->isFloating() || o->isPositioned()) { RenderBox* box = toRenderBox(o); @@ -911,6 +612,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i o->layoutIfNeeded(); } } else if (o->isText() || (o->isRenderInline() && !endOfInline)) { + hasInlineChild = true; if (fullLayout || o->selfNeedsLayout()) dirtyLineBoxesForRenderer(o, fullLayout); o->setNeedsLayout(false); @@ -956,7 +658,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i break; } if (obj->isFloating() || obj->isPositioned()) { - // floating and absolute or fixed positioning are done out + // floating and absolute or fixed positioning are done out // of normal flow. Don't need to worry about height any more. break; } @@ -972,7 +674,13 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i setWidth(min(width(), maxWidth)); m_minPrefWidth = min(m_minPrefWidth, maxWidth); m_maxPrefWidth = min(m_maxPrefWidth, maxWidth); - m_overflowWidth = min(m_overflowWidth, maxWidth); + + IntRect overflow = layoutOverflowRect(); + if (overflow.width() > maxWidth) { + overflow.setWidth(maxWidth); + clearLayoutOverflow(); + addLayoutOverflow(overflow); + } } } } @@ -984,7 +692,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i bool previousLineBrokeCleanly = true; RootInlineBox* startLine = determineStartPosition(firstLine, fullLayout, previousLineBrokeCleanly, resolver, floats, floatIndex); - if (fullLayout && !selfNeedsLayout()) { + if (fullLayout && hasInlineChild && !selfNeedsLayout()) { setNeedsLayout(true, false); // Mark ourselves as needing a full layout. This way we'll repaint like // we're supposed to. RenderView* v = view(); @@ -1016,8 +724,8 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i RenderArena* arena = renderArena(); RootInlineBox* box = startLine; while (box) { - repaintTop = min(repaintTop, box->topOverflow()); - repaintBottom = max(repaintBottom, box->bottomOverflow()); + repaintTop = min(repaintTop, box->topVisibleOverflow()); + repaintBottom = max(repaintBottom, box->bottomVisibleOverflow()); RootInlineBox* next = box->nextRootBox(); box->deleteLine(arena); box = next; @@ -1153,8 +861,8 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i if (lineBox) { lineBox->setLineBreakInfo(end.obj, end.pos, resolver.status()); if (useRepaintBounds) { - repaintTop = min(repaintTop, lineBox->topOverflow()); - repaintBottom = max(repaintBottom, lineBox->bottomOverflow()); + repaintTop = min(repaintTop, lineBox->topVisibleOverflow()); + repaintBottom = max(repaintBottom, lineBox->bottomVisibleOverflow()); } } @@ -1193,8 +901,8 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i for (RootInlineBox* line = endLine; line; line = line->nextRootBox()) { line->attachLine(); if (delta) { - repaintTop = min(repaintTop, line->topOverflow() + min(delta, 0)); - repaintBottom = max(repaintBottom, line->bottomOverflow() + max(delta, 0)); + repaintTop = min(repaintTop, line->topVisibleOverflow() + min(delta, 0)); + repaintBottom = max(repaintBottom, line->bottomVisibleOverflow() + max(delta, 0)); line->adjustPosition(0, delta); } if (Vector<RenderBox*>* cleanLineFloats = line->floatsPtr()) { @@ -1210,12 +918,12 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i setHeight(lastRootBox()->blockHeight()); } else { // Delete all the remaining lines. - InlineRunBox* line = endLine; + RootInlineBox* line = endLine; RenderArena* arena = renderArena(); while (line) { - repaintTop = min(repaintTop, line->topOverflow()); - repaintBottom = max(repaintBottom, line->bottomOverflow()); - InlineRunBox* next = line->nextLineBox(); + repaintTop = min(repaintTop, line->topVisibleOverflow()); + repaintBottom = max(repaintBottom, line->bottomVisibleOverflow()); + RootInlineBox* next = line->nextRootBox(); line->deleteLine(arena); line = next; } @@ -1225,6 +933,16 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i // In case we have a float on the last line, it might not be positioned up to now. // This has to be done before adding in the bottom border/padding, or the float will // include the padding incorrectly. -dwh + if (checkForFloatsFromLastLine) { + int bottomVisualOverflow = lastRootBox()->bottomVisualOverflow(); + int bottomLayoutOverflow = lastRootBox()->bottomLayoutOverflow(); + TrailingFloatsRootInlineBox* trailingFloatsLineBox = new (renderArena()) TrailingFloatsRootInlineBox(this); + m_lineBoxes.appendLineBox(trailingFloatsLineBox); + trailingFloatsLineBox->setConstructed(); + trailingFloatsLineBox->verticallyAlignBoxes(height()); + trailingFloatsLineBox->setVerticalOverflowPositions(height(), bottomLayoutOverflow, height(), bottomVisualOverflow, 0); + trailingFloatsLineBox->setBlockHeight(height()); + } if (lastFloat) { for (FloatingObject* f = m_floatingObjects->last(); f != lastFloat; f = m_floatingObjects->prev()) { } @@ -1253,12 +971,6 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i // Now add in the bottom border/padding. setHeight(height() + toAdd); - // Always make sure this is at least our height. - m_overflowHeight = max(height(), m_overflowHeight); - - // See if any lines spill out of the block. If so, we need to update our overflow width. - checkLinesForOverflow(); - if (!firstLineBox() && hasLineIfEmpty()) setHeight(height() + lineHeight(true, true)); @@ -1293,7 +1005,7 @@ RootInlineBox* RenderBlock::determineStartPosition(bool& firstLine, bool& fullLa if (floats[floatIndex].rect.size() != newSize) { int floatTop = floats[floatIndex].rect.y(); curr->markDirty(); - markLinesDirtyInVerticalRange(curr->blockHeight(), floatTop + max(floats[floatIndex].rect.height(), newSize.height())); + markLinesDirtyInVerticalRange(curr->blockHeight(), floatTop + max(floats[floatIndex].rect.height(), newSize.height()), curr); floats[floatIndex].rect.setSize(newSize); dirtiedByFloat = true; } @@ -1485,8 +1197,8 @@ bool RenderBlock::matchedEndLine(const InlineBidiResolver& resolver, const Inlin RootInlineBox* boxToDelete = endLine; RenderArena* arena = renderArena(); while (boxToDelete && boxToDelete != result) { - repaintTop = min(repaintTop, boxToDelete->topOverflow()); - repaintBottom = max(repaintBottom, boxToDelete->bottomOverflow()); + repaintTop = min(repaintTop, boxToDelete->topVisibleOverflow()); + repaintBottom = max(repaintBottom, boxToDelete->bottomVisibleOverflow()); RootInlineBox* next = boxToDelete->nextRootBox(); boxToDelete->deleteLine(arena); boxToDelete = next; @@ -1539,7 +1251,7 @@ static bool inlineFlowRequiresLineBox(RenderInline* flow) return !flow->firstChild() && flow->hasHorizontalBordersPaddingOrMargin(); } -static inline bool requiresLineBox(const InlineIterator& it, bool isLineEmpty, bool previousLineBrokeCleanly) +bool RenderBlock::requiresLineBox(const InlineIterator& it, bool isLineEmpty, bool previousLineBrokeCleanly) { if (it.obj->isFloatingOrPositioned()) return false; @@ -1878,10 +1590,10 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool currentCharacterIsSpace = false; currentCharacterIsWS = false; trailingSpaceObject = 0; - + // Optimize for a common case. If we can't find whitespace after the list // item, then this is all moot. -dwh - if (o->isListMarker() && !toRenderListMarker(o)->isInside()) { + if (o->isListMarker()) { if (style()->collapseWhiteSpace() && shouldSkipWhitespaceAfterStartObject(this, o, lineMidpointState)) { // Like with inline flows, we start ignoring spaces to make sure that any // additional spaces we see will be discarded. @@ -1889,6 +1601,8 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool currentCharacterIsWS = true; ignoringSpaces = true; } + if (toRenderListMarker(o)->isInside()) + tmpW += replacedBox->width() + replacedBox->marginLeft() + replacedBox->marginRight() + inlineWidth(o); } else tmpW += replacedBox->width() + replacedBox->marginLeft() + replacedBox->marginRight() + inlineWidth(o); } else if (o->isText()) { @@ -1908,6 +1622,10 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool int wordSpacing = o->style()->wordSpacing(); int lastSpaceWordSpacing = 0; + // Non-zero only when kerning is enabled, in which case we measure words with their trailing + // space, then subtract its width. + int wordTrailingSpaceWidth = f.typesettingFeatures() & Kerning ? f.spaceWidth() + wordSpacing : 0; + int wrapW = tmpW + inlineWidth(o, !appliedStartWidth, true); int charWidth = 0; bool breakNBSP = autoWrap && o->style()->nbspMode() == SPACE; @@ -2002,7 +1720,11 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool } } - int additionalTmpW = textWidth(t, lastSpace, pos - lastSpace, f, w + tmpW, isFixedPitch, collapseWhiteSpace) + lastSpaceWordSpacing; + int additionalTmpW; + if (wordTrailingSpaceWidth && currentCharacterIsSpace) + additionalTmpW = textWidth(t, lastSpace, pos + 1 - lastSpace, f, w + tmpW, isFixedPitch, collapseWhiteSpace) - wordTrailingSpaceWidth + lastSpaceWordSpacing; + else + additionalTmpW = textWidth(t, lastSpace, pos - lastSpace, f, w + tmpW, isFixedPitch, collapseWhiteSpace) + lastSpaceWordSpacing; tmpW += additionalTmpW; if (!appliedStartWidth) { tmpW += inlineWidth(o, true, false); @@ -2034,7 +1756,7 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool } } if (lineWasTooWide || w + tmpW > width) { - if (lBreak.obj && shouldPreserveNewline(lBreak.obj) && lBreak.obj->isText() && !toRenderText(lBreak.obj)->isWordBreak() && toRenderText(lBreak.obj)->characters()[lBreak.pos] == '\n') { + if (lBreak.obj && shouldPreserveNewline(lBreak.obj) && lBreak.obj->isText() && toRenderText(lBreak.obj)->textLength() && !toRenderText(lBreak.obj)->isWordBreak() && toRenderText(lBreak.obj)->characters()[lBreak.pos] == '\n') { if (!stoppedIgnoringSpaces && pos > 0) { // We need to stop right before the newline and then start up again. addMidpoint(lineMidpointState, InlineIterator(0, o, pos - 1)); // Stop @@ -2243,19 +1965,12 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool lBreak.nextBreakablePosition = -1; } } else if (lBreak.obj) { - if (last != o && !last->isListMarker()) { - // better to break between object boundaries than in the middle of a word (except for list markers) - lBreak.obj = o; - lBreak.pos = 0; - lBreak.nextBreakablePosition = -1; - } else { - // Don't ever break in the middle of a word if we can help it. - // There's no room at all. We just have to be on this line, - // even though we'll spill out. - lBreak.obj = o; - lBreak.pos = pos; - lBreak.nextBreakablePosition = -1; - } + // Don't ever break in the middle of a word if we can help it. + // There's no room at all. We just have to be on this line, + // even though we'll spill out. + lBreak.obj = o; + lBreak.pos = pos; + lBreak.nextBreakablePosition = -1; } } @@ -2306,14 +2021,12 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool return lBreak; } -void RenderBlock::checkLinesForOverflow() +void RenderBlock::addOverflowFromInlineChildren() { - m_overflowWidth = width(); for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) { - m_overflowLeft = min(curr->leftOverflow(), m_overflowLeft); - m_overflowTop = min(curr->topOverflow(), m_overflowTop); - m_overflowWidth = max(curr->rightOverflow(), m_overflowWidth); - m_overflowHeight = max(curr->bottomOverflow(), m_overflowHeight); + addLayoutOverflow(curr->layoutOverflowRect()); + if (!hasOverflowClip()) + addVisualOverflow(curr->visualOverflowRect()); } } |
