RenderBlock.cpp 180 KB
Newer Older
1
/*
2 3
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
dsmith's avatar
dsmith committed
4
 *           (C) 2007 David Smith (catfish.man@gmail.com)
mitz@apple.com's avatar
mitz@apple.com committed
5
 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
6 7 8 9 10 11 12 13 14 15 16 17 18
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
ddkilzer's avatar
ddkilzer committed
19 20
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
21 22
 */

mjs's avatar
mjs committed
23
#include "config.h"
24
#include "RenderBlock.h"
25

darin's avatar
darin committed
26
#include "Document.h"
27
#include "Element.h"
mjs's avatar
mjs committed
28
#include "Frame.h"
darin's avatar
darin committed
29
#include "FrameView.h"
darin's avatar
darin committed
30
#include "GraphicsContext.h"
weinig's avatar
weinig committed
31
#include "HTMLNames.h"
bdakin's avatar
bdakin committed
32
#include "HitTestResult.h"
weinig's avatar
weinig committed
33
#include "InlineTextBox.h"
bdakin's avatar
bdakin committed
34
#include "RenderImage.h"
hyatt@apple.com's avatar
hyatt@apple.com committed
35
#include "RenderReplica.h"
darin's avatar
darin committed
36
#include "RenderTableCell.h"
darin's avatar
darin committed
37
#include "RenderTextFragment.h"
darin's avatar
darin committed
38
#include "RenderTheme.h"
weinig's avatar
weinig committed
39 40
#include "RenderView.h"
#include "SelectionController.h"
41

darin's avatar
darin committed
42
using namespace std;
darin's avatar
darin committed
43 44
using namespace WTF;
using namespace Unicode;
darin's avatar
darin committed
45

darin's avatar
darin committed
46 47
namespace WebCore {

aliceli1's avatar
aliceli1 committed
48 49 50 51
// Number of pixels to allow as a fudge factor when clicking above or below a line.
// clicking up to verticalLineClickFudgeFactor pixels above a line will correspond to the closest point on the line.   
const int verticalLineClickFudgeFactor= 3;

darin's avatar
darin committed
52
using namespace HTMLNames;
53

antti's avatar
antti committed
54 55 56 57 58 59 60 61 62 63 64 65 66
struct ColumnInfo {
    ColumnInfo()
        : m_desiredColumnWidth(0)
        , m_desiredColumnCount(1)
        { }
    int m_desiredColumnWidth;
    unsigned m_desiredColumnCount;
    Vector<IntRect> m_columnRects;
};

typedef WTF::HashMap<const RenderBox*, ColumnInfo*> ColumnInfoMap;
static ColumnInfoMap* gColumnInfoMap = 0;

67 68 69 70 71 72
// Our MarginInfo state used when laying out block children.
RenderBlock::MarginInfo::MarginInfo(RenderBlock* block, int top, int bottom)
{
    // Whether or not we can collapse our own margins with our children.  We don't do this
    // if we had any border/padding (obviously), if we're the root or HTML elements, or if
    // we're positioned, floating, a table cell.
73
    m_canCollapseWithChildren = !block->isRenderView() && !block->isRoot() && !block->isPositioned() &&
74 75 76 77 78 79 80 81 82
        !block->isFloating() && !block->isTableCell() && !block->hasOverflowClip() && !block->isInlineBlockOrInlineTable();

    m_canCollapseTopWithChildren = m_canCollapseWithChildren && (top == 0) && block->style()->marginTopCollapse() != MSEPARATE;

    // If any height other than auto is specified in CSS, then we don't collapse our bottom
    // margins with our children's margins.  To do otherwise would be to risk odd visual
    // effects when the children overflow out of the parent block and yet still collapse
    // with it.  We also don't collapse if we have any bottom border/padding.
    m_canCollapseBottomWithChildren = m_canCollapseWithChildren && (bottom == 0) &&
darin's avatar
darin committed
83
        (block->style()->height().isAuto() && block->style()->height().value() == 0) && block->style()->marginBottomCollapse() != MSEPARATE;
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
    
    m_quirkContainer = block->isTableCell() || block->isBody() || block->style()->marginTopCollapse() == MDISCARD || 
        block->style()->marginBottomCollapse() == MDISCARD;

    m_atTopOfBlock = true;
    m_atBottomOfBlock = false;

    m_posMargin = m_canCollapseTopWithChildren ? block->maxTopMargin(true) : 0;
    m_negMargin = m_canCollapseTopWithChildren ? block->maxTopMargin(false) : 0;

    m_selfCollapsingBlockClearedFloat = false;
    
    m_topQuirk = m_bottomQuirk = m_determinedTopQuirk = false;
}

// -------------------------------------------------------------------------------------------------------

darin's avatar
darin committed
101
RenderBlock::RenderBlock(Node* node)
antti's avatar
antti committed
102 103 104 105 106 107 108 109 110
      : RenderFlow(node)
      , m_floatingObjects(0)
      , m_positionedObjects(0)
      , m_maxMargin(0)
      , m_overflowHeight(0)
      , m_overflowWidth(0)
      , m_overflowLeft(0)
      , m_overflowTop(0)
{
111 112 113 114
}

RenderBlock::~RenderBlock()
{
115 116
    delete m_floatingObjects;
    delete m_positionedObjects;
antti's avatar
antti committed
117 118
    delete m_maxMargin;
    
darin@apple.com's avatar
darin@apple.com committed
119 120
    if (m_hasColumns)
        delete gColumnInfoMap->take(this);
121 122 123 124
}

void RenderBlock::setStyle(RenderStyle* _style)
{
125 126
    setReplaced(_style->isDisplayReplacedType());

127
    RenderFlow::setStyle(_style);
128

129 130 131
    // FIXME: We could save this call when the change only affected non-inherited properties
    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
        if (child->isAnonymousBlock()) {
132
            RenderStyle* newStyle = new (renderArena()) RenderStyle();
133 134 135 136
            newStyle->inheritFrom(style());
            newStyle->setDisplay(BLOCK);
            child->setStyle(newStyle);
        }
137 138
    }

139 140
    m_lineHeight = -1;

141
    // Update pseudos for :before and :after now.
142
    if (!isAnonymous() && canHaveChildren()) {
hyatt's avatar
hyatt committed
143 144 145
        updateBeforeAfterContent(RenderStyle::BEFORE);
        updateBeforeAfterContent(RenderStyle::AFTER);
    }
weinig's avatar
weinig committed
146
    updateFirstLetter();
darin's avatar
darin committed
147 148
}

149 150
void RenderBlock::addChildToFlow(RenderObject* newChild, RenderObject* beforeChild)
{
151
    // Make sure we don't append things after :after-generated content if we have it.
darin's avatar
darin committed
152
    if (!beforeChild && isAfterContent(lastChild()))
153
        beforeChild = lastChild();
mitz@apple.com's avatar
mitz@apple.com committed
154

155
    bool madeBoxesNonInline = false;
156 157 158 159 160

    // If the requested beforeChild is not one of our children, then this is most likely because
    // there is an anonymous block box within this object that contains the beforeChild. So
    // just insert the child into the anonymous block box instead of here.
    if (beforeChild && beforeChild->parent() != this) {
darin's avatar
darin committed
161 162
        ASSERT(beforeChild->parent());
        ASSERT(beforeChild->parent()->isAnonymousBlock());
163

mitz@apple.com's avatar
mitz@apple.com committed
164 165
        if (newChild->isInline() || beforeChild->parent()->firstChild() != beforeChild)
            beforeChild->parent()->addChild(newChild, beforeChild);
166
        else
mitz@apple.com's avatar
mitz@apple.com committed
167 168 169
            addChildToFlow(newChild, beforeChild->parent());

        return;
170 171 172 173
    }

    // A block has to either have all of its children inline, or all of its children as blocks.
    // So, if our children are currently inline and a block child has to be inserted, we move all our
mitz@apple.com's avatar
mitz@apple.com committed
174 175
    // inline children into anonymous block boxes.
    if (m_childrenInline && !newChild->isInline() && !newChild->isFloatingOrPositioned()) {
176 177 178
        // This is a block with inline content. Wrap the inline content in anonymous blocks.
        makeChildrenNonInline(beforeChild);
        madeBoxesNonInline = true;
mitz@apple.com's avatar
mitz@apple.com committed
179

180 181
        if (beforeChild && beforeChild->parent() != this) {
            beforeChild = beforeChild->parent();
darin's avatar
darin committed
182 183
            ASSERT(beforeChild->isAnonymousBlock());
            ASSERT(beforeChild->parent() == this);
184
        }
mitz@apple.com's avatar
mitz@apple.com committed
185
    } else if (!m_childrenInline && (newChild->isFloatingOrPositioned() || newChild->isInline())) {
186 187 188
        // If we're inserting an inline child but all of our children are blocks, then we have to make sure
        // it is put into an anomyous block box. We try to use an existing anonymous box if possible, otherwise
        // a new one is created and inserted into our list of children in the appropriate position.
mitz@apple.com's avatar
mitz@apple.com committed
189 190 191 192 193 194 195
        RenderObject* afterChild = beforeChild ? beforeChild->previousSibling() : lastChild();

        if (afterChild && afterChild->isAnonymousBlock()) {
            afterChild->addChild(newChild);
            return;
        }

196
        if (newChild->isInline()) {
mitz@apple.com's avatar
mitz@apple.com committed
197
            // No suitable existing anonymous box - create a new one.
198
            RenderBlock* newBox = createAnonymousBlock();
mitz@apple.com's avatar
mitz@apple.com committed
199
            RenderContainer::addChild(newBox, beforeChild);
200 201 202 203 204
            newBox->addChild(newChild);
            return;
        }
    }

mitz@apple.com's avatar
mitz@apple.com committed
205
    RenderContainer::addChild(newChild, beforeChild);
206 207
    // ### care about aligned stuff

antti's avatar
antti committed
208 209 210
    if (madeBoxesNonInline && parent() && isAnonymousBlock())
        parent()->removeLeftoverAnonymousBlock(this);
    // this object may be dead here
211 212
}

hyatt's avatar
hyatt committed
213
static void getInlineRun(RenderObject* start, RenderObject* boundary,
214 215 216 217 218 219 220 221 222 223 224
                         RenderObject*& inlineRunStart,
                         RenderObject*& inlineRunEnd)
{
    // Beginning at |start| we find the largest contiguous run of inlines that
    // we can.  We denote the run with start and end points, |inlineRunStart|
    // and |inlineRunEnd|.  Note that these two values may be the same if
    // we encounter only one inline.
    //
    // We skip any non-inlines we encounter as long as we haven't found any
    // inlines yet.
    //
hyatt's avatar
hyatt committed
225 226
    // |boundary| indicates a non-inclusive boundary point.  Regardless of whether |boundary|
    // is inline or not, we will not include it in a run with inlines before it.  It's as though we encountered
227
    // a non-inline.
hyatt's avatar
hyatt committed
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
    
    // Start by skipping as many non-inlines as we can.
    RenderObject * curr = start;
    bool sawInline;
    do {
        while (curr && !(curr->isInline() || curr->isFloatingOrPositioned()))
            curr = curr->nextSibling();
        
        inlineRunStart = inlineRunEnd = curr;
        
        if (!curr)
            return; // No more inline children to be found.
        
        sawInline = curr->isInline();
        
        curr = curr->nextSibling();
        while (curr && (curr->isInline() || curr->isFloatingOrPositioned()) && (curr != boundary)) {
hyatt's avatar
hyatt committed
245
            inlineRunEnd = curr;
hyatt's avatar
hyatt committed
246 247 248 249 250
            if (curr->isInline())
                sawInline = true;
            curr = curr->nextSibling();
        }
    } while (!sawInline);
251 252
}

bdakin's avatar
bdakin committed
253 254 255 256 257 258 259 260 261 262 263 264
void RenderBlock::deleteLineBoxTree()
{
    InlineFlowBox* line = m_firstLineBox;
    InlineFlowBox* nextLine;
    while (line) {
        nextLine = line->nextFlowBox();
        line->deleteLine(renderArena());
        line = nextLine;
    }
    m_firstLineBox = m_lastLineBox = 0;
}

265
void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint)
hyatt's avatar
hyatt committed
266
{    
267 268 269 270 271 272 273
    // makeChildrenNonInline takes a block whose children are *all* inline and it
    // makes sure that inline children are coalesced under anonymous
    // blocks.  If |insertionPoint| is defined, then it represents the insertion point for
    // the new block child that is causing us to have to wrap all the inlines.  This
    // means that we cannot coalesce inlines before |insertionPoint| with inlines following
    // |insertionPoint|, because the new child is going to be inserted in between the inlines,
    // splitting them.
darin's avatar
darin committed
274 275
    ASSERT(isInlineBlockOrInlineTable() || !isInline());
    ASSERT(!insertionPoint || insertionPoint->parent() == this);
276 277 278 279

    m_childrenInline = false;

    RenderObject *child = firstChild();
mitz@apple.com's avatar
mitz@apple.com committed
280 281 282 283
    if (!child)
        return;

    deleteLineBoxTree();
284 285 286 287 288 289 290 291 292 293

    while (child) {
        RenderObject *inlineRunStart, *inlineRunEnd;
        getInlineRun(child, insertionPoint, inlineRunStart, inlineRunEnd);

        if (!inlineRunStart)
            break;

        child = inlineRunEnd->nextSibling();

294
        RenderBlock* box = createAnonymousBlock();
295 296 297 298 299 300
        insertChildNode(box, inlineRunStart);
        RenderObject* o = inlineRunStart;
        while(o != inlineRunEnd)
        {
            RenderObject* no = o;
            o = no->nextSibling();
301
            box->moveChildNode(no);
302
        }
303
        box->moveChildNode(inlineRunEnd);
304
    }
hyatt's avatar
hyatt committed
305 306 307

#ifndef NDEBUG
    for (RenderObject *c = firstChild(); c; c = c->nextSibling())
darin's avatar
darin committed
308
        ASSERT(!c->isInline());
hyatt's avatar
hyatt committed
309
#endif
mitz@apple.com's avatar
mitz@apple.com committed
310 311

    repaint();
312 313 314 315 316 317 318 319 320
}

void RenderBlock::removeChild(RenderObject *oldChild)
{
    // If this child is a block, and if our previous and next siblings are
    // both anonymous blocks with inline content, then we can go ahead and
    // fold the inline content back together.
    RenderObject* prev = oldChild->previousSibling();
    RenderObject* next = oldChild->nextSibling();
321
    bool canDeleteAnonymousBlocks = !documentBeingDestroyed() && !isInline() && !oldChild->isInline() && 
322 323 324
                                    !oldChild->continuation() && 
                                    (!prev || (prev->isAnonymousBlock() && prev->childrenInline())) &&
                                    (!next || (next->isAnonymousBlock() && next->childrenInline()));
325
    if (canDeleteAnonymousBlocks && prev && next) {
326 327
        // Take all the children out of the |next| block and put them in
        // the |prev| block.
darin's avatar
darin committed
328
        prev->setNeedsLayoutAndPrefWidthsRecalc();
329 330 331 332
        RenderObject* o = next->firstChild();
        while (o) {
            RenderObject* no = o;
            o = no->nextSibling();
333
            prev->moveChildNode(no);
334
        }
bdakin's avatar
bdakin committed
335
 
weinig's avatar
weinig committed
336
        RenderBlock* nextBlock = static_cast<RenderBlock*>(next);
bdakin's avatar
bdakin committed
337
        nextBlock->deleteLineBoxTree();
weinig's avatar
weinig committed
338
        
339
        // Nuke the now-empty block.
harrison's avatar
harrison committed
340
        next->destroy();
341 342 343 344
    }

    RenderFlow::removeChild(oldChild);

345
    RenderObject* child = prev ? prev : next;
antti's avatar
antti committed
346
    if (canDeleteAnonymousBlocks && child && !child->previousSibling() && !child->nextSibling() && !isFlexibleBox()) {
347
        // The removal has knocked us down to containing only a single anonymous
348 349
        // box.  We can go ahead and pull the content right back up into our
        // box.
darin's avatar
darin committed
350
        setNeedsLayoutAndPrefWidthsRecalc();
darin's avatar
darin committed
351
        RenderBlock* anonBlock = static_cast<RenderBlock*>(removeChildNode(child, false));
352 353 354 355 356
        m_childrenInline = true;
        RenderObject* o = anonBlock->firstChild();
        while (o) {
            RenderObject* no = o;
            o = no->nextSibling();
357
            moveChildNode(no);
358
        }
359

bdakin's avatar
bdakin committed
360 361
        // Delete the now-empty block's lines and nuke it.
        anonBlock->deleteLineBoxTree();
harrison's avatar
harrison committed
362
        anonBlock->destroy();
363 364 365
    }
}

366 367
int RenderBlock::overflowHeight(bool includeInterior) const
{
368
    if (!includeInterior && hasOverflowClip()) {
mitz@apple.com's avatar
mitz@apple.com committed
369 370 371
        int shadowHeight = 0;
        for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next)
            shadowHeight = max(boxShadow->y + boxShadow->blur, shadowHeight);
hyatt@apple.com's avatar
hyatt@apple.com committed
372 373 374 375
        int height = m_height + shadowHeight;
        if (hasReflection())
            height = max(height, reflectionBox().bottom());
        return height;
376 377
    }
    return m_overflowHeight;
378 379 380 381
}

int RenderBlock::overflowWidth(bool includeInterior) const
{
382
    if (!includeInterior && hasOverflowClip()) {
mitz@apple.com's avatar
mitz@apple.com committed
383 384 385
        int shadowWidth = 0;
        for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next)
            shadowWidth = max(boxShadow->x + boxShadow->blur, shadowWidth);
hyatt@apple.com's avatar
hyatt@apple.com committed
386 387 388 389
        int width = m_width + shadowWidth;
        if (hasReflection())
            width = max(width, reflectionBox().right());
        return width;
390 391
    }
    return m_overflowWidth;
392
}
393

394 395
int RenderBlock::overflowLeft(bool includeInterior) const
{
396
    if (!includeInterior && hasOverflowClip()) {
mitz@apple.com's avatar
mitz@apple.com committed
397 398 399
        int shadowLeft = 0;
        for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next)
            shadowLeft = min(boxShadow->x - boxShadow->blur, shadowLeft);
hyatt@apple.com's avatar
hyatt@apple.com committed
400 401 402 403
        int left = shadowLeft;
        if (hasReflection())
            left = min(left, reflectionBox().x());
        return left;
404 405
    }
    return m_overflowLeft;
406 407 408 409
}

int RenderBlock::overflowTop(bool includeInterior) const
{
410
    if (!includeInterior && hasOverflowClip()) {
mitz@apple.com's avatar
mitz@apple.com committed
411 412 413
        int shadowTop = 0;
        for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next)
            shadowTop = min(boxShadow->y - boxShadow->blur, shadowTop);
hyatt@apple.com's avatar
hyatt@apple.com committed
414 415 416 417
        int top = shadowTop;
        if (hasReflection())
            top = min(top, reflectionBox().y());
        return top;
418 419
    }
    return m_overflowTop;
420 421
}

422
IntRect RenderBlock::overflowRect(bool includeInterior) const
423
{
424 425
    if (!includeInterior && hasOverflowClip()) {
        IntRect box = borderBox();
mitz@apple.com's avatar
mitz@apple.com committed
426 427 428 429 430 431 432 433 434 435
        int shadowLeft = 0;
        int shadowRight = 0;
        int shadowTop = 0;
        int shadowBottom = 0;

        for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next) {
            shadowLeft = min(boxShadow->x - boxShadow->blur, shadowLeft);
            shadowRight = max(boxShadow->x + boxShadow->blur, shadowRight);
            shadowTop = min(boxShadow->y - boxShadow->blur, shadowTop);
            shadowBottom = max(boxShadow->y + boxShadow->blur, shadowBottom);
436
        }
mitz@apple.com's avatar
mitz@apple.com committed
437 438 439 440

        box.move(shadowLeft, shadowTop);
        box.setWidth(box.width() - shadowLeft + shadowRight);
        box.setHeight(box.height() - shadowTop + shadowBottom);
hyatt@apple.com's avatar
hyatt@apple.com committed
441 442 443 444 445 446 447 448 449 450 451 452 453

        if (hasReflection()) {
            IntRect reflection(reflectionBox());
            int reflectTop = min(box.y(), reflection.y());
            int reflectBottom = max(box.bottom(), reflection.bottom());
            box.setHeight(reflectBottom - reflectTop);
            box.setY(reflectTop);
            
            int reflectLeft = min(box.x(), reflection.x());
            int reflectRight = max(box.right(), reflection.right());
            box.setWidth(reflectRight - reflectLeft);
            box.setX(reflectLeft);
        }
454 455 456
        return box;
    }

457 458 459
    if (!includeInterior && hasOverflowClip())
        return borderBox();
    int l = overflowLeft(includeInterior);
darin's avatar
darin committed
460
    int t = min(overflowTop(includeInterior), -borderTopExtra());
461
    return IntRect(l, t, overflowWidth(includeInterior) - l, max(overflowHeight(includeInterior), height() + borderBottomExtra()) - t);
462 463
}

464 465 466 467 468 469 470
bool RenderBlock::isSelfCollapsingBlock() const
{
    // We are not self-collapsing if we
    // (a) have a non-zero height according to layout (an optimization to avoid wasting time)
    // (b) are a table,
    // (c) have border/padding,
    // (d) have a min-height
471
    // (e) have specified that one of our margins can't collapse using a CSS extension
472 473
    if (m_height > 0 ||
        isTable() || (borderBottom() + paddingBottom() + borderTop() + paddingTop()) != 0 ||
ddkilzer's avatar
ddkilzer committed
474
        style()->minHeight().isPositive() || 
475
        style()->marginTopCollapse() == MSEPARATE || style()->marginBottomCollapse() == MSEPARATE)
476 477
        return false;

478
    bool hasAutoHeight = style()->height().isAuto();
479 480
    if (style()->height().isPercent() && !style()->htmlHacks()) {
        hasAutoHeight = true;
481
        for (RenderBlock* cb = containingBlock(); !cb->isRenderView(); cb = cb->containingBlock()) {
482 483 484 485 486
            if (cb->style()->height().isFixed() || cb->isTableCell())
                hasAutoHeight = false;
        }
    }

487 488
    // If the height is 0 or auto, then whether or not we are a self-collapsing block depends
    // on whether we have content that is all self-collapsing or not.
ddkilzer's avatar
ddkilzer committed
489
    if (hasAutoHeight || ((style()->height().isFixed() || style()->height().isPercent()) && style()->height().isZero())) {
490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
        // If the block has inline children, see if we generated any line boxes.  If we have any
        // line boxes, then we can't be self-collapsing, since we have content.
        if (childrenInline())
            return !firstLineBox();
        
        // Whether or not we collapse is dependent on whether all our normal flow children
        // are also self-collapsing.
        for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
            if (child->isFloatingOrPositioned())
                continue;
            if (!child->isSelfCollapsingBlock())
                return false;
        }
        return true;
    }
    return false;
}

508 509
void RenderBlock::layout()
{
510 511 512
    // Update our first letter info now.
    updateFirstLetter();

513 514 515
    // Table cells call layoutBlock directly, so don't add any logic here.  Put code into
    // layoutBlock().
    layoutBlock(false);
516 517 518 519 520 521 522 523 524
    
    // It's safe to check for control clip here, since controls can never be table cells.
    if (hasControlClip()) {
        // Because of the lightweight clip, there can never be any overflow from children.
        m_overflowWidth = m_width;
        m_overflowHeight = m_height;
        m_overflowLeft = 0;
        m_overflowTop = 0;
    }
525 526 527 528
}

void RenderBlock::layoutBlock(bool relayoutChildren)
{
darin's avatar
darin committed
529
    ASSERT(needsLayout());
530

531
    if (isInline() && !isInlineBlockOrInlineTable()) // Inline <form>s inside various table elements can
532
        return;                                      // cause us to come in here.  Just bail.
533

weinig's avatar
weinig committed
534
    if (!relayoutChildren && layoutOnlyPositionedObjects())
535
        return;
weinig's avatar
weinig committed
536

ap's avatar
ap committed
537
    IntRect oldBounds;
538
    IntRect oldOutlineBox;
539
    bool checkForRepaint = checkForRepaintDuringLayout();
540
    if (checkForRepaint) {
541 542
        oldBounds = absoluteClippedOverflowRect();
        oldOutlineBox = absoluteOutlineBox();
543
    }
544

weinig's avatar
weinig committed
545
    bool hadColumns = m_hasColumns;
hyatt@apple.com's avatar
hyatt@apple.com committed
546
    if (!hadColumns && !hasReflection())
weinig's avatar
weinig committed
547 548 549 550
        view()->pushLayoutState(this, IntSize(xPos(), yPos()));
    else
        view()->disableLayoutState();

551
    int oldWidth = m_width;
antti's avatar
antti committed
552
    int oldColumnWidth = desiredColumnWidth();
553

554
    calcWidth();
555 556
    calcColumnWidth();

557
    m_overflowWidth = m_width;
558
    m_overflowLeft = 0;
559

antti's avatar
antti committed
560
    if (oldWidth != m_width || oldColumnWidth != desiredColumnWidth())
561 562 563 564
        relayoutChildren = true;

    clearFloats();

565
    int previousHeight = m_height;
566 567 568 569 570 571 572 573 574 575 576 577 578
    m_height = 0;
    m_overflowHeight = 0;

    // We use four values, maxTopPos, maxPosNeg, maxBottomPos, and maxBottomNeg, to track
    // our current maximal positive and negative margins.  These values are used when we
    // are collapsed with adjacent blocks, so for example, if you have block A and B
    // collapsing together, then you'd take the maximal positive margin from both A and B
    // and subtract it from the maximal negative margin from both A and B to get the
    // true collapsed margin.  This algorithm is recursive, so when we finish layout()
    // our block knows its current maximal positive/negative values.
    //
    // Start out by setting our margin values to our current margins.  Table cells have
    // no margins, so we don't fill in the values for table cells.
darin's avatar
darin committed
579 580
    bool isCell = isTableCell();
    if (!isCell) {
581 582
        initMaxMarginValues();

darin's avatar
darin committed
583 584
        m_topMarginQuirk = style()->marginTop().quirk();
        m_bottomMarginQuirk = style()->marginBottom().quirk();
585

586
        if (element() && element()->hasTagName(formTag) && element()->isMalformed())
587 588
            // See if this form is malformed (i.e., unclosed). If so, don't give the form
            // a bottom margin.
antti's avatar
antti committed
589
            setMaxBottomMargins(0, 0);
590 591
    }

592
    // For overflow:scroll blocks, ensure we have both scrollbars in place always.
593
    if (scrollsOverflow()) {
594
        if (style()->overflowX() == OSCROLL)
595
            m_layer->setHasHorizontalScrollbar(true);
596
        if (style()->overflowY() == OSCROLL)
597 598
            m_layer->setHasVerticalScrollbar(true);
    }
599

ap's avatar
ap committed
600 601
    int repaintTop = 0;
    int repaintBottom = 0;
mitz@apple.com's avatar
mitz@apple.com committed
602
    int maxFloatBottom = 0;
603
    if (childrenInline())
ap's avatar
ap committed
604
        layoutInlineChildren(relayoutChildren, repaintTop, repaintBottom);
605
    else
mitz@apple.com's avatar
mitz@apple.com committed
606
        layoutBlockChildren(relayoutChildren, maxFloatBottom);
607

608
    // Expand our intrinsic height to encompass floats.
609
    int toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight();
bdakin's avatar
Bug #:  
bdakin committed
610
    if (floatBottom() > (m_height - toAdd) && (isInlineBlockOrInlineTable() || isFloatingOrPositioned() || hasOverflowClip() ||
antti's avatar
antti committed
611
                                    (parent() && parent()->isFlexibleBox() || m_hasColumns)))
612
        m_height = floatBottom() + toAdd;
613
    
614 615
    // Now lay out our columns within this intrinsic height, since they can slightly affect the intrinsic height as
    // we adjust for clean column breaks.
616
    int singleColumnBottom = layoutColumns();
617 618

    // Calculate our new height.
619 620 621
    int oldHeight = m_height;
    calcHeight();
    if (oldHeight != m_height) {
mitz@apple.com's avatar
mitz@apple.com committed
622 623 624 625 626 627
        if (oldHeight > m_height && maxFloatBottom > m_height && !childrenInline()) {
            // One of our children's floats may have become an overhanging float for us. We need to look for it.
            for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
                if (child->isBlockFlow() && !child->isFloatingOrPositioned()) {
                    RenderBlock* block = static_cast<RenderBlock*>(child);
                    if (block->floatBottom() + block->yPos() > m_height)
mitz@apple.com's avatar
mitz@apple.com committed
628
                        addOverhangingFloats(block, -block->xPos(), -block->yPos(), false);
mitz@apple.com's avatar
mitz@apple.com committed
629 630 631
                }
            }
        }
632 633 634
        // We have to rebalance columns to the new height.
        layoutColumns(singleColumnBottom);

635 636
        // If the block got expanded in size, then increase our overflowheight to match.
        if (m_overflowHeight > m_height)
637
            m_overflowHeight -= toAdd;
638 639 640
        if (m_overflowHeight < m_height)
            m_overflowHeight = m_height;
    }
641 642
    if (previousHeight != m_height)
        relayoutChildren = true;
643

644 645 646
    // Some classes of objects (floats and fieldsets with no specified heights and table cells) expand to encompass
    // overhanging floats.
    if (hasOverhangingFloats() && expandsToEncloseOverhangingFloats()) {
647 648 649 650
        m_height = floatBottom();
        m_height += borderBottom() + paddingBottom();
    }

darin's avatar
darin committed
651
    if ((isCell || isInline() || isFloatingOrPositioned() || isRoot()) && !hasOverflowClip() && !hasControlClip())
ap's avatar
ap committed
652 653
        addVisualOverflow(floatRect());

654
    layoutPositionedObjects(relayoutChildren || isRoot());
655

justing's avatar
justing committed
656 657
    positionListMarker();

658
    // Always ensure our overflow width/height are at least as large as our width/height.
darin's avatar
darin committed
659 660
    m_overflowWidth = max(m_overflowWidth, m_width);
    m_overflowHeight = max(m_overflowHeight, m_height);
661

662
    if (!hasOverflowClip()) {
mitz@apple.com's avatar
mitz@apple.com committed
663
        for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next) {
664 665 666 667 668
            m_overflowLeft = min(m_overflowLeft, boxShadow->x - boxShadow->blur);
            m_overflowWidth = max(m_overflowWidth, m_width + boxShadow->x + boxShadow->blur);
            m_overflowTop = min(m_overflowTop, boxShadow->y - boxShadow->blur);
            m_overflowHeight = max(m_overflowHeight, m_height + boxShadow->y + boxShadow->blur);
        }
hyatt@apple.com's avatar
hyatt@apple.com committed
669 670 671 672 673
        
        if (hasReflection()) {
            m_overflowTop = min(m_overflowTop, reflectionBox().y());
            m_overflowHeight = max(m_overflowHeight, reflectionBox().bottom());
        }
674 675
    }

hyatt@apple.com's avatar
hyatt@apple.com committed
676
    if (!hadColumns && !hasReflection())
weinig's avatar
weinig committed
677 678 679 680
        view()->popLayoutState();
    else
        view()->enableLayoutState();

681
    // Update our scroll information if we're overflow:auto/scroll/hidden now that we know if
682
    // we overflow or not.
683
    if (hasOverflowClip())
684
        m_layer->updateScrollInfoAfterLayout();
685 686

    // Repaint with our new bounds if they are different from our old bounds.
687
    bool didFullRepaint = false;
688
    if (checkForRepaint)
689
        didFullRepaint = repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);
mitz@apple.com's avatar
mitz@apple.com committed
690
    if (!didFullRepaint && repaintTop != repaintBottom && (style()->visibility() == VISIBLE || enclosingLayer()->hasVisibleContent())) {
ap's avatar
ap committed
691 692
        IntRect repaintRect(m_overflowLeft, repaintTop, m_overflowWidth - m_overflowLeft, repaintBottom - repaintTop);

693 694 695
        // FIXME: Deal with multiple column repainting.  We have to split the repaint
        // rect up into multiple rects if it spans columns.

adele's avatar
adele committed
696 697 698 699 700 701 702 703 704 705 706 707 708
        repaintRect.inflate(maximalOutlineSize(PaintPhaseOutline));
        
        if (hasOverflowClip()) {
            // Adjust repaint rect for scroll offset
            int x = repaintRect.x();
            int y = repaintRect.y();
            layer()->subtractScrollOffset(x, y);
            repaintRect.setX(x);
            repaintRect.setY(y);

            // Don't allow this rect to spill out of our overflow box.
            repaintRect.intersect(IntRect(0, 0, m_width, m_height));
        }
mitz@apple.com's avatar
mitz@apple.com committed
709

adele's avatar
adele committed
710
        // Make sure the rect is still non-empty after intersecting for overflow above
hyatt@apple.com's avatar
hyatt@apple.com committed
711
        if (!repaintRect.isEmpty()) {
mitz@apple.com's avatar
mitz@apple.com committed
712
            repaintRectangle(repaintRect); // We need to do a partial repaint of our content.
hyatt@apple.com's avatar
hyatt@apple.com committed
713 714 715
            if (hasReflection())
                layer()->reflection()->repaintRectangle(repaintRect);
        }
716
    }
717
    setNeedsLayout(false);
718 719
}

720
void RenderBlock::adjustPositionedBlock(RenderObject* child, const MarginInfo& marginInfo)
721
{
722 723 724 725 726 727 728 729
    if (child->hasStaticX()) {
        if (style()->direction() == LTR)
            child->setStaticX(borderLeft() + paddingLeft());
        else
            child->setStaticX(borderRight() + paddingRight());
    }

    if (child->hasStaticY()) {
darin's avatar
darin committed
730
        int y = m_height;
731
        if (!marginInfo.canCollapseWithTop()) {
darin's avatar
darin committed
732 733
            child->calcVerticalMargins();
            int marginTop = child->marginTop();
734 735
            int collapsedTopPos = marginInfo.posMargin();
            int collapsedTopNeg = marginInfo.negMargin();
darin's avatar
darin committed
736 737 738 739 740 741 742 743
            if (marginTop > 0) {
                if (marginTop > collapsedTopPos)
                    collapsedTopPos = marginTop;
            } else {
                if (-marginTop > collapsedTopNeg)
                    collapsedTopNeg = -marginTop;
            }
            y += (collapsedTopPos - collapsedTopNeg) - marginTop;
744
        }
darin's avatar
darin committed
745
        child->setStaticY(y);
746 747
    }
}
748

749 750 751 752 753 754 755 756 757 758 759 760
void RenderBlock::adjustFloatingBlock(const MarginInfo& marginInfo)
{
    // The float should be positioned taking into account the bottom margin
    // of the previous flow.  We add that margin into the height, get the
    // float positioned properly, and then subtract the margin out of the
    // height again.  In the case of self-collapsing blocks, we always just
    // use the top margins, since the self-collapsing block collapsed its
    // own bottom margin into its top margin.
    //
    // Note also that the previous flow may collapse its margin into the top of
    // our block.  If this is the case, then we do not add the margin in to our
    // height when computing the position of the float.   This condition can be tested
hyatt's avatar
hyatt committed
761
    // for by simply calling canCollapseWithTop.  See
762 763 764 765 766 767 768
    // http://www.hixie.ch/tests/adhoc/css/box/block/margin-collapse/046.html for
    // an example of this scenario.
    int marginOffset = marginInfo.canCollapseWithTop() ? 0 : marginInfo.margin();
    m_height += marginOffset;
    positionNewFloats();
    m_height -= marginOffset;
}
769

770 771
RenderObject* RenderBlock::handleSpecialChild(RenderObject* child, const MarginInfo& marginInfo, CompactInfo& compactInfo, bool& handled)
{
772 773
    // Handle positioned children first.
    RenderObject* next = handlePositionedChild(child, marginInfo, handled);
774
    if (handled) return next;
775
    
776 777 778 779
    // Handle floating children next.
    next = handleFloatingChild(child, marginInfo, handled);
    if (handled) return next;

780 781 782
    // See if we have a compact element.  If we do, then try to tuck the compact element into the margin space of the next block.
    next = handleCompactChild(child, compactInfo, handled);
    if (handled) return next;
783

784 785 786
    // Finally, see if we have a run-in element.
    return handleRunInChild(child, handled);
}
787

788

789
RenderObject* RenderBlock::handlePositionedChild(RenderObject* child, const MarginInfo& marginInfo, bool& handled)
790 791 792 793 794 795 796 797
{
    if (child->isPositioned()) {
        handled = true;
        child->containingBlock()->insertPositionedObject(child);
        adjustPositionedBlock(child, marginInfo);
        return child->nextSibling();
    }

798 799 800 801 802
    return 0;
}

RenderObject* RenderBlock::handleFloatingChild(RenderObject* child, const MarginInfo& marginInfo, bool& handled)
{
803 804 805 806 807 808
    if (child->isFloating()) {
        handled = true;
        insertFloatingObject(child);
        adjustFloatingBlock(marginInfo);
        return child->nextSibling();
    }
809
    
810 811
    return 0;
}
812

813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831
RenderObject* RenderBlock::handleCompactChild(RenderObject* child, CompactInfo& compactInfo, bool& handled)
{
    // FIXME: We only deal with one compact at a time.  It is unclear what should be
    // done if multiple contiguous compacts are encountered.  For now we assume that
    // compact A followed by another compact B should simply be treated as block A.
    if (child->isCompact() && !compactInfo.compact() && (child->childrenInline() || child->isReplaced())) {
        // Get the next non-positioned/non-floating RenderBlock.
        RenderObject* next = child->nextSibling();
        RenderObject* curr = next;
        while (curr && curr->isFloatingOrPositioned())
            curr = curr->nextSibling();
        if (curr && curr->isRenderBlock() && !curr->isCompact() && !curr->isRunIn()) {
            curr->calcWidth(); // So that horizontal margins are correct.
                               
            child->setInline(true); // Need to compute the margins/width for the child as though it is an inline, so that it won't try to puff up the margins to
                                    // fill the containing block width.
            child->calcWidth();
            int childMargins = child->marginLeft() + child->marginRight();
            int margin = style()->direction() == LTR ? curr->marginLeft() : curr->marginRight();
darin's avatar
darin committed
832
            if (margin >= (childMargins + child->maxPrefWidth())) {
833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853
                // The compact will fit in the margin.
                handled = true;
                compactInfo.set(child, curr);
                child->setPos(0,0); // This position will be updated to reflect the compact's
                                    // desired position and the line box for the compact will
                                    // pick that position up.
                
                // Remove the child.
                RenderObject* next = child->nextSibling();
                removeChildNode(child);
                
                // Now insert the child under |curr|.
                curr->insertChildNode(child, curr->firstChild());
                return next;
            }
            else
                child->setInline(false); // We didn't fit, so we remain a block-level element.
        }
    }
    return 0;
}
854

855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870
void RenderBlock::insertCompactIfNeeded(RenderObject* child, CompactInfo& compactInfo)
{
    if (compactInfo.matches(child)) {
        // We have a compact child to squeeze in.
        RenderObject* compactChild = compactInfo.compact();
        int compactXPos = borderLeft() + paddingLeft() + compactChild->marginLeft();
        if (style()->direction() == RTL) {
            compactChild->calcWidth(); // have to do this because of the capped maxwidth
            compactXPos = width() - borderRight() - paddingRight() - marginRight() -
                compactChild->width() - compactChild->marginRight();
        }
        compactXPos -= child->xPos(); // Put compactXPos into the child's coordinate space.
        compactChild->setPos(compactXPos, compactChild->yPos()); // Set the x position.
        compactInfo.clear();
    }
}
871

872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899
RenderObject* RenderBlock::handleRunInChild(RenderObject* child, bool& handled)
{
    // See if we have a run-in element with inline children.  If the
    // children aren't inline, then just treat the run-in as a normal
    // block.
    if (child->isRunIn() && (child->childrenInline() || child->isReplaced())) {
        // Get the next non-positioned/non-floating RenderBlock.
        RenderObject* curr = child->nextSibling();
        while (curr && curr->isFloatingOrPositioned())
            curr = curr->nextSibling();
        if (curr && (curr->isRenderBlock() && curr->childrenInline() && !curr->isCompact() && !curr->isRunIn())) {
            // The block acts like an inline, so just null out its
            // position.
            handled = true;
            child->setInline(true);
            child->setPos(0,0);
            
            // Remove the child.
            RenderObject* next = child->nextSibling();
            removeChildNode(child);
            
            // Now insert the child under |curr|.
            curr->insertChildNode(child, curr->firstChild());
            return next;
        }
    }
    return 0;
}
900

901 902 903 904 905
void RenderBlock::collapseMargins(RenderObject* child, MarginInfo& marginInfo, int yPosEstimate)
{
    // Get our max pos and neg top margins.
    int posTop = child->maxTopMargin(true);
    int negTop = child->maxTopMargin(false);
906

907 908 909
    // For self-collapsing blocks, collapse our bottom margins into our
    // top to get new posTop and negTop values.
    if (child->isSelfCollapsingBlock()) {
darin's avatar
darin committed
910 911
        posTop = max(posTop, child->maxBottomMargin(true));
        negTop = max(negTop, child->maxBottomMargin(false));
912 913 914 915 916 917 918 919 920 921
    }
    
    // See if the top margin is quirky. We only care if this child has
    // margins that will collapse with us.
    bool topQuirk = child->isTopMarginQuirk() || style()->marginTopCollapse() == MDISCARD;

    if (marginInfo.canCollapseWithTop()) {
        // This child is collapsing with the top of the
        // block.  If it has larger margin values, then we need to update
        // our own maximal values.
antti's avatar
antti committed
922 923
        if (!style()->htmlHacks() || !marginInfo.quirkContainer() || !topQuirk)
            setMaxTopMargins(max(posTop, maxTopPosMargin()), max(negTop, maxTopNegMargin()));
924

925 926 927 928 929 930 931 932
        // The minute any of the margins involved isn't a quirk, don't
        // collapse it away, even if the margin is smaller (www.webreference.com
        // has an example of this, a <dt> with 0.8em author-specified inside
        // a <dl> inside a <td>.
        if (!marginInfo.determinedTopQuirk() && !topQuirk && (posTop-negTop)) {
            m_topMarginQuirk = false;
            marginInfo.setDeterminedTopQuirk(true);
        }
933

934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950
        if (!marginInfo.determinedTopQuirk() && topQuirk && marginTop() == 0)
            // We have no top margin and our top child has a quirky margin.
            // We will pick up this quirky margin and pass it through.
            // This deals with the <td><div><p> case.
            // Don't do this for a block that split two inlines though.  You do
            // still apply margins in this case.
            m_topMarginQuirk = true;
    }

    if (marginInfo.quirkContainer() && marginInfo.atTopOfBlock() && (posTop - negTop))
        marginInfo.setTopQuirk(topQuirk);

    int ypos = m_height;
    if (child->isSelfCollapsingBlock()) {
        // This child has no height.  We need to compute our
        // position before we collapse the child's margins together,
        // so that we can get an accurate position for the zero-height block.
darin's avatar
darin committed
951 952
        int collapsedTopPos = max(marginInfo.posMargin(), child->maxTopMargin(true));
        int collapsedTopNeg = max(marginInfo.negMargin(), child->maxTopMargin(false));
953
        marginInfo.setMargin(collapsedTopPos, collapsedTopNeg);
954
        
955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970
        // Now collapse the child's margins together, which means examining our
        // bottom margin values as well. 
        marginInfo.setPosMarginIfLarger(child->maxBottomMargin(true));
        marginInfo.setNegMarginIfLarger(child->maxBottomMargin(false));

        if (!marginInfo.canCollapseWithTop())
            // We need to make sure that the position of the self-collapsing block
            // is correct, since it could have overflowing content
            // that needs to be positioned correctly (e.g., a block that
            // had a specified height of 0 but that actually had subcontent).
            ypos = m_height + collapsedTopPos - collapsedTopNeg;
    }
    else {
        if (child->style()->marginTopCollapse() == MSEPARATE) {
            m_height += marginInfo.margin() + child->marginTop();
            ypos = m_height;
971
        }
972 973 974 975 976
        else if (!marginInfo.atTopOfBlock() ||
            (!marginInfo.canCollapseTopWithChildren()
             && (!style()->htmlHacks() || !marginInfo.quirkContainer() || !marginInfo.topQuirk()))) {
            // We're collapsing with a previous sibling's margins and not
            // with the top of the block.
darin's avatar
darin committed
977
            m_height += max(marginInfo.posMargin(), posTop) - max(marginInfo.negMargin(), negTop);
978
            ypos = m_height;
979 980
        }

981 982
        marginInfo.setPosMargin(child->maxBottomMargin(true));
        marginInfo.setNegMargin(child->maxBottomMargin(false));
983

984 985
        if (marginInfo.margin())
            marginInfo.setBottomQuirk(child->isBottomMarginQuirk() || style()->marginBottomCollapse() == MDISCARD);
986

987 988 989
        marginInfo.setSelfCollapsingBlockClearedFloat(false);
    }