~ubuntu-branches/ubuntu/raring/qtwebkit-source/raring-proposed

« back to all changes in this revision

Viewing changes to Source/WebCore/rendering/RenderBlock.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2013-02-18 14:24:18 UTC
  • Revision ID: package-import@ubuntu.com-20130218142418-eon0jmjg3nj438uy
Tags: upstream-2.3
ImportĀ upstreamĀ versionĀ 2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 
3
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 
4
 *           (C) 2007 David Smith (catfish.man@gmail.com)
 
5
 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
 
6
 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
 
7
 *
 
8
 * This library is free software; you can redistribute it and/or
 
9
 * modify it under the terms of the GNU Library General Public
 
10
 * License as published by the Free Software Foundation; either
 
11
 * version 2 of the License, or (at your option) any later version.
 
12
 *
 
13
 * This library is distributed in the hope that it will be useful,
 
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
16
 * Library General Public License for more details.
 
17
 *
 
18
 * You should have received a copy of the GNU Library General Public License
 
19
 * along with this library; see the file COPYING.LIB.  If not, write to
 
20
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
21
 * Boston, MA 02110-1301, USA.
 
22
 */
 
23
 
 
24
#include "config.h"
 
25
#include "RenderBlock.h"
 
26
 
 
27
#include "AXObjectCache.h"
 
28
#include "ColumnInfo.h"
 
29
#include "Document.h"
 
30
#include "Element.h"
 
31
#include "FloatQuad.h"
 
32
#include "Frame.h"
 
33
#include "FrameSelection.h"
 
34
#include "FrameView.h"
 
35
#include "GraphicsContext.h"
 
36
#include "HTMLFormElement.h"
 
37
#include "HTMLNames.h"
 
38
#include "HitTestResult.h"
 
39
#include "InlineIterator.h"
 
40
#include "InlineTextBox.h"
 
41
#include "LayoutRepainter.h"
 
42
#include "OverflowEvent.h"
 
43
#include "PODFreeListArena.h"
 
44
#include "Page.h"
 
45
#include "PaintInfo.h"
 
46
#include "RenderBoxRegionInfo.h"
 
47
#include "RenderCombineText.h"
 
48
#include "RenderDeprecatedFlexibleBox.h"
 
49
#include "RenderImage.h"
 
50
#include "RenderInline.h"
 
51
#include "RenderLayer.h"
 
52
#include "RenderMarquee.h"
 
53
#include "RenderNamedFlowThread.h"
 
54
#include "RenderRegion.h"
 
55
#include "RenderReplica.h"
 
56
#include "RenderTableCell.h"
 
57
#include "RenderTextFragment.h"
 
58
#include "RenderTheme.h"
 
59
#include "RenderView.h"
 
60
#include "Settings.h"
 
61
#include "SVGTextRunRenderingContext.h"
 
62
#include "ShadowRoot.h"
 
63
#include "TransformState.h"
 
64
#include <wtf/StdLibExtras.h>
 
65
#include <wtf/TemporaryChange.h>
 
66
#if ENABLE(CSS_EXCLUSIONS)
 
67
#include "ExclusionShapeInsideInfo.h"
 
68
#endif
 
69
 
 
70
using namespace std;
 
71
using namespace WTF;
 
72
using namespace Unicode;
 
73
 
 
74
namespace WebCore {
 
75
 
 
76
using namespace HTMLNames;
 
77
 
 
78
struct SameSizeAsRenderBlock : public RenderBox {
 
79
    void* pointers[2];
 
80
    RenderObjectChildList children;
 
81
    RenderLineBoxList lineBoxes;
 
82
    uint32_t bitfields;
 
83
};
 
84
 
 
85
COMPILE_ASSERT(sizeof(RenderBlock) == sizeof(SameSizeAsRenderBlock), RenderBlock_should_stay_small);
 
86
 
 
87
struct SameSizeAsFloatingObject {
 
88
    void* pointers[2];
 
89
    LayoutRect rect;
 
90
    int paginationStrut;
 
91
    uint32_t bitfields : 8;
 
92
};
 
93
 
 
94
COMPILE_ASSERT(sizeof(RenderBlock::MarginValues) == sizeof(LayoutUnit[4]), MarginValues_should_stay_small);
 
95
 
 
96
struct SameSizeAsMarginInfo {
 
97
    uint32_t bitfields : 16;
 
98
    LayoutUnit margins[2];
 
99
};
 
100
 
 
101
typedef WTF::HashMap<const RenderBox*, ColumnInfo*> ColumnInfoMap;
 
102
static ColumnInfoMap* gColumnInfoMap = 0;
 
103
 
 
104
static TrackedDescendantsMap* gPositionedDescendantsMap = 0;
 
105
static TrackedDescendantsMap* gPercentHeightDescendantsMap = 0;
 
106
 
 
107
static TrackedContainerMap* gPositionedContainerMap = 0;
 
108
static TrackedContainerMap* gPercentHeightContainerMap = 0;
 
109
    
 
110
typedef WTF::HashMap<RenderBlock*, ListHashSet<RenderInline*>*> ContinuationOutlineTableMap;
 
111
 
 
112
typedef WTF::HashSet<RenderBlock*> DelayedUpdateScrollInfoSet;
 
113
static int gDelayUpdateScrollInfo = 0;
 
114
static DelayedUpdateScrollInfoSet* gDelayedUpdateScrollInfoSet = 0;
 
115
 
 
116
static bool gIsInColumnFlowSplit = false;
 
117
 
 
118
bool RenderBlock::s_canPropagateFloatIntoSibling = false;
 
119
 
 
120
// This class helps dispatching the 'overflow' event on layout change. overflow can be set on RenderBoxes, yet the existing code
 
121
// only works on RenderBlocks. If this change, this class should be shared with other RenderBoxes.
 
122
class OverflowEventDispatcher {
 
123
    WTF_MAKE_NONCOPYABLE(OverflowEventDispatcher);
 
124
public:
 
125
    OverflowEventDispatcher(const RenderBlock* block)
 
126
        : m_block(block)
 
127
        , m_hadHorizontalLayoutOverflow(false)
 
128
        , m_hadVerticalLayoutOverflow(false)
 
129
    {
 
130
        m_shouldDispatchEvent = !m_block->isAnonymous() && m_block->hasOverflowClip() && m_block->document()->hasListenerType(Document::OVERFLOWCHANGED_LISTENER);
 
131
        if (m_shouldDispatchEvent) {
 
132
            m_hadHorizontalLayoutOverflow = m_block->hasHorizontalLayoutOverflow();
 
133
            m_hadVerticalLayoutOverflow = m_block->hasVerticalLayoutOverflow();
 
134
        }
 
135
    }
 
136
 
 
137
    ~OverflowEventDispatcher()
 
138
    {
 
139
        if (!m_shouldDispatchEvent)
 
140
            return;
 
141
 
 
142
        bool hasHorizontalLayoutOverflow = m_block->hasHorizontalLayoutOverflow();
 
143
        bool hasVerticalLayoutOverflow = m_block->hasVerticalLayoutOverflow();
 
144
 
 
145
        bool horizontalLayoutOverflowChanged = hasHorizontalLayoutOverflow != m_hadHorizontalLayoutOverflow;
 
146
        bool verticalLayoutOverflowChanged = hasVerticalLayoutOverflow != m_hadVerticalLayoutOverflow;
 
147
        if (horizontalLayoutOverflowChanged || verticalLayoutOverflowChanged) {
 
148
            if (FrameView* frameView = m_block->document()->view())
 
149
                frameView->scheduleEvent(OverflowEvent::create(horizontalLayoutOverflowChanged, hasHorizontalLayoutOverflow, verticalLayoutOverflowChanged, hasVerticalLayoutOverflow), m_block->node());
 
150
        }
 
151
    }
 
152
 
 
153
private:
 
154
    const RenderBlock* m_block;
 
155
    bool m_shouldDispatchEvent;
 
156
    bool m_hadHorizontalLayoutOverflow;
 
157
    bool m_hadVerticalLayoutOverflow;
 
158
};
 
159
 
 
160
// Our MarginInfo state used when laying out block children.
 
161
RenderBlock::MarginInfo::MarginInfo(RenderBlock* block, LayoutUnit beforeBorderPadding, LayoutUnit afterBorderPadding)
 
162
    : m_atBeforeSideOfBlock(true)
 
163
    , m_atAfterSideOfBlock(false)
 
164
    , m_marginBeforeQuirk(false)
 
165
    , m_marginAfterQuirk(false)
 
166
    , m_determinedMarginBeforeQuirk(false)
 
167
{
 
168
    RenderStyle* blockStyle = block->style();
 
169
    ASSERT(block->isRenderView() || block->parent());
 
170
    m_canCollapseWithChildren = !block->isRenderView() && !block->isRoot() && !block->isOutOfFlowPositioned()
 
171
        && !block->isFloating() && !block->isTableCell() && !block->hasOverflowClip() && !block->isInlineBlockOrInlineTable()
 
172
        && !block->isWritingModeRoot() && !block->parent()->isFlexibleBox() && blockStyle->hasAutoColumnCount() && blockStyle->hasAutoColumnWidth()
 
173
        && !blockStyle->columnSpan();
 
174
 
 
175
    m_canCollapseMarginBeforeWithChildren = m_canCollapseWithChildren && !beforeBorderPadding && blockStyle->marginBeforeCollapse() != MSEPARATE;
 
176
 
 
177
    // If any height other than auto is specified in CSS, then we don't collapse our bottom
 
178
    // margins with our children's margins.  To do otherwise would be to risk odd visual
 
179
    // effects when the children overflow out of the parent block and yet still collapse
 
180
    // with it.  We also don't collapse if we have any bottom border/padding.
 
181
    m_canCollapseMarginAfterWithChildren = m_canCollapseWithChildren && (afterBorderPadding == 0) &&
 
182
        (blockStyle->logicalHeight().isAuto() && !blockStyle->logicalHeight().value()) && blockStyle->marginAfterCollapse() != MSEPARATE;
 
183
    
 
184
    m_quirkContainer = block->isTableCell() || block->isBody() || blockStyle->marginBeforeCollapse() == MDISCARD
 
185
        || blockStyle->marginAfterCollapse() == MDISCARD;
 
186
 
 
187
    m_positiveMargin = m_canCollapseMarginBeforeWithChildren ? block->maxPositiveMarginBefore() : LayoutUnit();
 
188
    m_negativeMargin = m_canCollapseMarginBeforeWithChildren ? block->maxNegativeMarginBefore() : LayoutUnit();
 
189
}
 
190
 
 
191
// -------------------------------------------------------------------------------------------------------
 
192
 
 
193
RenderBlock::RenderBlock(Node* node)
 
194
      : RenderBox(node)
 
195
      , m_lineHeight(-1)
 
196
      , m_beingDestroyed(false)
 
197
      , m_hasMarkupTruncation(false)
 
198
{
 
199
    setChildrenInline(true);
 
200
    COMPILE_ASSERT(sizeof(RenderBlock::FloatingObject) == sizeof(SameSizeAsFloatingObject), FloatingObject_should_stay_small);
 
201
    COMPILE_ASSERT(sizeof(RenderBlock::MarginInfo) == sizeof(SameSizeAsMarginInfo), MarginInfo_should_stay_small);
 
202
}
 
203
 
 
204
static void removeBlockFromDescendantAndContainerMaps(RenderBlock* block, TrackedDescendantsMap*& descendantMap, TrackedContainerMap*& containerMap)
 
205
{
 
206
    if (TrackedRendererListHashSet* descendantSet = descendantMap->take(block)) {
 
207
        TrackedRendererListHashSet::iterator end = descendantSet->end();
 
208
        for (TrackedRendererListHashSet::iterator descendant = descendantSet->begin(); descendant != end; ++descendant) {
 
209
            HashSet<RenderBlock*>* containerSet = containerMap->get(*descendant);
 
210
            ASSERT(containerSet);
 
211
            if (!containerSet)
 
212
                continue;
 
213
            ASSERT(containerSet->contains(block));
 
214
            containerSet->remove(block);
 
215
            if (containerSet->isEmpty()) {
 
216
                containerMap->remove(*descendant);
 
217
                delete containerSet;
 
218
            }
 
219
        }
 
220
        delete descendantSet;
 
221
    }
 
222
}
 
223
 
 
224
RenderBlock::~RenderBlock()
 
225
{
 
226
    if (m_floatingObjects)
 
227
        deleteAllValues(m_floatingObjects->set());
 
228
    
 
229
    if (hasColumns())
 
230
        delete gColumnInfoMap->take(this);
 
231
 
 
232
    if (gPercentHeightDescendantsMap)
 
233
        removeBlockFromDescendantAndContainerMaps(this, gPercentHeightDescendantsMap, gPercentHeightContainerMap);
 
234
    if (gPositionedDescendantsMap)
 
235
        removeBlockFromDescendantAndContainerMaps(this, gPositionedDescendantsMap, gPositionedContainerMap);
 
236
}
 
237
 
 
238
void RenderBlock::willBeDestroyed()
 
239
{
 
240
    // Mark as being destroyed to avoid trouble with merges in removeChild().
 
241
    m_beingDestroyed = true;
 
242
 
 
243
    // Make sure to destroy anonymous children first while they are still connected to the rest of the tree, so that they will
 
244
    // properly dirty line boxes that they are removed from. Effects that do :before/:after only on hover could crash otherwise.
 
245
    children()->destroyLeftoverChildren();
 
246
 
 
247
    // Destroy our continuation before anything other than anonymous children.
 
248
    // The reason we don't destroy it before anonymous children is that they may
 
249
    // have continuations of their own that are anonymous children of our continuation.
 
250
    RenderBoxModelObject* continuation = this->continuation();
 
251
    if (continuation) {
 
252
        continuation->destroy();
 
253
        setContinuation(0);
 
254
    }
 
255
    
 
256
    if (!documentBeingDestroyed()) {
 
257
        if (firstLineBox()) {
 
258
            // We can't wait for RenderBox::destroy to clear the selection,
 
259
            // because by then we will have nuked the line boxes.
 
260
            // FIXME: The FrameSelection should be responsible for this when it
 
261
            // is notified of DOM mutations.
 
262
            if (isSelectionBorder())
 
263
                view()->clearSelection();
 
264
 
 
265
            // If we are an anonymous block, then our line boxes might have children
 
266
            // that will outlast this block. In the non-anonymous block case those
 
267
            // children will be destroyed by the time we return from this function.
 
268
            if (isAnonymousBlock()) {
 
269
                for (InlineFlowBox* box = firstLineBox(); box; box = box->nextLineBox()) {
 
270
                    while (InlineBox* childBox = box->firstChild())
 
271
                        childBox->remove();
 
272
                }
 
273
            }
 
274
        } else if (parent())
 
275
            parent()->dirtyLinesFromChangedChild(this);
 
276
    }
 
277
 
 
278
    m_lineBoxes.deleteLineBoxes(renderArena());
 
279
 
 
280
    if (lineGridBox())
 
281
        lineGridBox()->destroy(renderArena());
 
282
 
 
283
#if ENABLE(CSS_EXCLUSIONS)
 
284
    ExclusionShapeInsideInfo::removeExclusionShapeInsideInfoForRenderBlock(this);
 
285
#endif
 
286
 
 
287
    if (UNLIKELY(gDelayedUpdateScrollInfoSet != 0))
 
288
        gDelayedUpdateScrollInfoSet->remove(this);
 
289
 
 
290
    RenderBox::willBeDestroyed();
 
291
}
 
292
 
 
293
void RenderBlock::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
 
294
{
 
295
    RenderStyle* oldStyle = style();
 
296
    s_canPropagateFloatIntoSibling = oldStyle ? !isFloatingOrOutOfFlowPositioned() && !avoidsFloats() : false;
 
297
 
 
298
    setReplaced(newStyle->isDisplayInlineType());
 
299
    
 
300
    if (oldStyle && parent() && diff == StyleDifferenceLayout && oldStyle->position() != newStyle->position()) {
 
301
        if (newStyle->position() == StaticPosition)
 
302
            // Clear our positioned objects list. Our absolutely positioned descendants will be
 
303
            // inserted into our containing block's positioned objects list during layout.
 
304
            removePositionedObjects(0, NewContainingBlock);
 
305
        else if (oldStyle->position() == StaticPosition) {
 
306
            // Remove our absolutely positioned descendants from their current containing block.
 
307
            // They will be inserted into our positioned objects list during layout.
 
308
            RenderObject* cb = parent();
 
309
            while (cb && (cb->style()->position() == StaticPosition || (cb->isInline() && !cb->isReplaced())) && !cb->isRenderView()) {
 
310
                if (cb->style()->position() == RelativePosition && cb->isInline() && !cb->isReplaced()) {
 
311
                    cb = cb->containingBlock();
 
312
                    break;
 
313
                }
 
314
                cb = cb->parent();
 
315
            }
 
316
            
 
317
            if (cb->isRenderBlock())
 
318
                toRenderBlock(cb)->removePositionedObjects(this, NewContainingBlock);
 
319
        }
 
320
 
 
321
        if (containsFloats() && !isFloating() && !isOutOfFlowPositioned() && newStyle->hasOutOfFlowPosition())
 
322
            markAllDescendantsWithFloatsForLayout();
 
323
    }
 
324
 
 
325
    RenderBox::styleWillChange(diff, newStyle);
 
326
}
 
327
 
 
328
void RenderBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
 
329
{
 
330
    RenderBox::styleDidChange(diff, oldStyle);
 
331
 
 
332
#if ENABLE(CSS_EXCLUSIONS)
 
333
    // FIXME: Bug 89993: Style changes should affect the ExclusionShapeInsideInfos for other render blocks that
 
334
    // share the same ExclusionShapeInsideInfo
 
335
    updateExclusionShapeInsideInfoAfterStyleChange(style()->shapeInside(), oldStyle ? oldStyle->shapeInside() : 0);
 
336
#endif
 
337
 
 
338
    if (!isAnonymousBlock()) {
 
339
        // Ensure that all of our continuation blocks pick up the new style.
 
340
        for (RenderBlock* currCont = blockElementContinuation(); currCont; currCont = currCont->blockElementContinuation()) {
 
341
            RenderBoxModelObject* nextCont = currCont->continuation();
 
342
            currCont->setContinuation(0);
 
343
            currCont->setStyle(style());
 
344
            currCont->setContinuation(nextCont);
 
345
        }
 
346
    }
 
347
 
 
348
    propagateStyleToAnonymousChildren(true);    
 
349
    m_lineHeight = -1;
 
350
 
 
351
    // Update pseudos for :before and :after now.
 
352
    if (!isAnonymous() && document()->styleSheetCollection()->usesBeforeAfterRules() && canHaveGeneratedChildren()) {
 
353
        updateBeforeAfterContent(BEFORE);
 
354
        updateBeforeAfterContent(AFTER);
 
355
    }
 
356
 
 
357
    // After our style changed, if we lose our ability to propagate floats into next sibling
 
358
    // blocks, then we need to find the top most parent containing that overhanging float and
 
359
    // then mark its descendants with floats for layout and clear all floats from its next
 
360
    // sibling blocks that exist in our floating objects list. See bug 56299 and 62875.
 
361
    bool canPropagateFloatIntoSibling = !isFloatingOrOutOfFlowPositioned() && !avoidsFloats();
 
362
    if (diff == StyleDifferenceLayout && s_canPropagateFloatIntoSibling && !canPropagateFloatIntoSibling && hasOverhangingFloats()) {
 
363
        RenderBlock* parentBlock = this;
 
364
        const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
 
365
        FloatingObjectSetIterator end = floatingObjectSet.end();
 
366
 
 
367
        for (RenderObject* curr = parent(); curr && !curr->isRenderView(); curr = curr->parent()) {
 
368
            if (curr->isRenderBlock()) {
 
369
                RenderBlock* currBlock = toRenderBlock(curr);
 
370
 
 
371
                if (currBlock->hasOverhangingFloats()) {
 
372
                    for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
 
373
                        RenderBox* renderer = (*it)->renderer();
 
374
                        if (currBlock->hasOverhangingFloat(renderer)) {
 
375
                            parentBlock = currBlock;
 
376
                            break;
 
377
                        }
 
378
                    }
 
379
                }
 
380
            }
 
381
        }
 
382
              
 
383
        parentBlock->markAllDescendantsWithFloatsForLayout();
 
384
        parentBlock->markSiblingsWithFloatsForLayout();
 
385
    }
 
386
}
 
387
 
 
388
void RenderBlock::updateBeforeAfterContent(PseudoId pseudoId)
 
389
{
 
390
    // If this is an anonymous wrapper, then the parent applies its own pseudo-element style to it.
 
391
    if (parent() && parent()->createsAnonymousWrapper())
 
392
        return;
 
393
    children()->updateBeforeAfterContent(this, pseudoId);
 
394
}
 
395
 
 
396
RenderBlock* RenderBlock::continuationBefore(RenderObject* beforeChild)
 
397
{
 
398
    if (beforeChild && beforeChild->parent() == this)
 
399
        return this;
 
400
 
 
401
    RenderBlock* curr = toRenderBlock(continuation());
 
402
    RenderBlock* nextToLast = this;
 
403
    RenderBlock* last = this;
 
404
    while (curr) {
 
405
        if (beforeChild && beforeChild->parent() == curr) {
 
406
            if (curr->firstChild() == beforeChild)
 
407
                return last;
 
408
            return curr;
 
409
        }
 
410
 
 
411
        nextToLast = last;
 
412
        last = curr;
 
413
        curr = toRenderBlock(curr->continuation());
 
414
    }
 
415
 
 
416
    if (!beforeChild && !last->firstChild())
 
417
        return nextToLast;
 
418
    return last;
 
419
}
 
420
 
 
421
void RenderBlock::addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild)
 
422
{
 
423
    RenderBlock* flow = continuationBefore(beforeChild);
 
424
    ASSERT(!beforeChild || beforeChild->parent()->isAnonymousColumnSpanBlock() || beforeChild->parent()->isRenderBlock());
 
425
    RenderBoxModelObject* beforeChildParent = 0;
 
426
    if (beforeChild)
 
427
        beforeChildParent = toRenderBoxModelObject(beforeChild->parent());
 
428
    else {
 
429
        RenderBoxModelObject* cont = flow->continuation();
 
430
        if (cont)
 
431
            beforeChildParent = cont;
 
432
        else
 
433
            beforeChildParent = flow;
 
434
    }
 
435
 
 
436
    if (newChild->isFloatingOrOutOfFlowPositioned()) {
 
437
        beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
 
438
        return;
 
439
    }
 
440
 
 
441
    // A continuation always consists of two potential candidates: a block or an anonymous
 
442
    // column span box holding column span children.
 
443
    bool childIsNormal = newChild->isInline() || !newChild->style()->columnSpan();
 
444
    bool bcpIsNormal = beforeChildParent->isInline() || !beforeChildParent->style()->columnSpan();
 
445
    bool flowIsNormal = flow->isInline() || !flow->style()->columnSpan();
 
446
 
 
447
    if (flow == beforeChildParent) {
 
448
        flow->addChildIgnoringContinuation(newChild, beforeChild);
 
449
        return;
 
450
    }
 
451
    
 
452
    // The goal here is to match up if we can, so that we can coalesce and create the
 
453
    // minimal # of continuations needed for the inline.
 
454
    if (childIsNormal == bcpIsNormal) {
 
455
        beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
 
456
        return;
 
457
    }
 
458
    if (flowIsNormal == childIsNormal) {
 
459
        flow->addChildIgnoringContinuation(newChild, 0); // Just treat like an append.
 
460
        return;
 
461
    }
 
462
    beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
 
463
}
 
464
 
 
465
 
 
466
void RenderBlock::addChildToAnonymousColumnBlocks(RenderObject* newChild, RenderObject* beforeChild)
 
467
{
 
468
    ASSERT(!continuation()); // We don't yet support column spans that aren't immediate children of the multi-column block.
 
469
        
 
470
    // The goal is to locate a suitable box in which to place our child.
 
471
    RenderBlock* beforeChildParent = 0;
 
472
    if (beforeChild) {
 
473
        RenderObject* curr = beforeChild;
 
474
        while (curr && curr->parent() != this)
 
475
            curr = curr->parent();
 
476
        beforeChildParent = toRenderBlock(curr);
 
477
        ASSERT(beforeChildParent);
 
478
        ASSERT(beforeChildParent->isAnonymousColumnsBlock() || beforeChildParent->isAnonymousColumnSpanBlock());
 
479
    } else
 
480
        beforeChildParent = toRenderBlock(lastChild());
 
481
 
 
482
    // If the new child is floating or positioned it can just go in that block.
 
483
    if (newChild->isFloatingOrOutOfFlowPositioned()) {
 
484
        beforeChildParent->addChildIgnoringAnonymousColumnBlocks(newChild, beforeChild);
 
485
        return;
 
486
    }
 
487
 
 
488
    // See if the child can be placed in the box.
 
489
    bool newChildHasColumnSpan = newChild->style()->columnSpan() && !newChild->isInline();
 
490
    bool beforeChildParentHoldsColumnSpans = beforeChildParent->isAnonymousColumnSpanBlock();
 
491
 
 
492
    if (newChildHasColumnSpan == beforeChildParentHoldsColumnSpans) {
 
493
        beforeChildParent->addChildIgnoringAnonymousColumnBlocks(newChild, beforeChild);
 
494
        return;
 
495
    }
 
496
 
 
497
    if (!beforeChild) {
 
498
        // Create a new block of the correct type.
 
499
        RenderBlock* newBox = newChildHasColumnSpan ? createAnonymousColumnSpanBlock() : createAnonymousColumnsBlock();
 
500
        children()->appendChildNode(this, newBox);
 
501
        newBox->addChildIgnoringAnonymousColumnBlocks(newChild, 0);
 
502
        return;
 
503
    }
 
504
 
 
505
    RenderObject* immediateChild = beforeChild;
 
506
    bool isPreviousBlockViable = true;
 
507
    while (immediateChild->parent() != this) {
 
508
        if (isPreviousBlockViable)
 
509
            isPreviousBlockViable = !immediateChild->previousSibling();
 
510
        immediateChild = immediateChild->parent();
 
511
    }
 
512
    if (isPreviousBlockViable && immediateChild->previousSibling()) {
 
513
        toRenderBlock(immediateChild->previousSibling())->addChildIgnoringAnonymousColumnBlocks(newChild, 0); // Treat like an append.
 
514
        return;
 
515
    }
 
516
        
 
517
    // Split our anonymous blocks.
 
518
    RenderObject* newBeforeChild = splitAnonymousBoxesAroundChild(beforeChild);
 
519
 
 
520
    
 
521
    // Create a new anonymous box of the appropriate type.
 
522
    RenderBlock* newBox = newChildHasColumnSpan ? createAnonymousColumnSpanBlock() : createAnonymousColumnsBlock();
 
523
    children()->insertChildNode(this, newBox, newBeforeChild);
 
524
    newBox->addChildIgnoringAnonymousColumnBlocks(newChild, 0);
 
525
    return;
 
526
}
 
527
 
 
528
RenderBlock* RenderBlock::containingColumnsBlock(bool allowAnonymousColumnBlock)
 
529
{
 
530
    RenderBlock* firstChildIgnoringAnonymousWrappers = 0;
 
531
    for (RenderObject* curr = this; curr; curr = curr->parent()) {
 
532
        if (!curr->isRenderBlock() || curr->isFloatingOrOutOfFlowPositioned() || curr->isTableCell() || curr->isRoot() || curr->isRenderView() || curr->hasOverflowClip()
 
533
            || curr->isInlineBlockOrInlineTable())
 
534
            return 0;
 
535
 
 
536
        // FIXME: Table manages its own table parts, most of which are RenderBoxes.
 
537
        // Multi-column code cannot handle splitting the flow in table. Disabling it
 
538
        // to prevent crashes.
 
539
        // Similarly, RenderButton maintains an anonymous block child and overrides
 
540
        // addChild() to prevent itself from having additional direct children. This
 
541
        // causes problems for split flows.
 
542
        if (curr->isTable() || curr->isRenderButton())
 
543
            return 0;
 
544
        
 
545
        RenderBlock* currBlock = toRenderBlock(curr);
 
546
        if (!currBlock->createsAnonymousWrapper())
 
547
            firstChildIgnoringAnonymousWrappers = currBlock;
 
548
 
 
549
        if (currBlock->style()->specifiesColumns() && (allowAnonymousColumnBlock || !currBlock->isAnonymousColumnsBlock()))
 
550
            return firstChildIgnoringAnonymousWrappers;
 
551
            
 
552
        if (currBlock->isAnonymousColumnSpanBlock())
 
553
            return 0;
 
554
    }
 
555
    return 0;
 
556
}
 
557
 
 
558
RenderBlock* RenderBlock::clone() const
 
559
{
 
560
    RenderBlock* cloneBlock;
 
561
    if (isAnonymousBlock()) {
 
562
        cloneBlock = createAnonymousBlock();
 
563
        cloneBlock->setChildrenInline(childrenInline());
 
564
    }
 
565
    else {
 
566
        RenderObject* cloneRenderer = toElement(node())->createRenderer(renderArena(), style());
 
567
        cloneBlock = toRenderBlock(cloneRenderer);
 
568
        cloneBlock->setStyle(style());
 
569
 
 
570
        // This takes care of setting the right value of childrenInline in case
 
571
        // generated content is added to cloneBlock and 'this' does not have
 
572
        // generated content added yet.
 
573
        cloneBlock->setChildrenInline(cloneBlock->firstChild() ? cloneBlock->firstChild()->isInline() : childrenInline());
 
574
    }
 
575
    cloneBlock->setInRenderFlowThread(inRenderFlowThread());
 
576
    return cloneBlock;
 
577
}
 
578
 
 
579
void RenderBlock::splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock,
 
580
                              RenderBlock* middleBlock,
 
581
                              RenderObject* beforeChild, RenderBoxModelObject* oldCont)
 
582
{
 
583
    // Create a clone of this inline.
 
584
    RenderBlock* cloneBlock = clone();
 
585
    if (!isAnonymousBlock())
 
586
        cloneBlock->setContinuation(oldCont);
 
587
 
 
588
    if (!beforeChild && isAfterContent(lastChild()))
 
589
        beforeChild = lastChild();
 
590
 
 
591
    // If we are moving inline children from |this| to cloneBlock, then we need
 
592
    // to clear our line box tree.
 
593
    if (beforeChild && childrenInline())
 
594
        deleteLineBoxTree();
 
595
 
 
596
    // Now take all of the children from beforeChild to the end and remove
 
597
    // them from |this| and place them in the clone.
 
598
    moveChildrenTo(cloneBlock, beforeChild, 0, true);
 
599
    
 
600
    // Hook |clone| up as the continuation of the middle block.
 
601
    if (!cloneBlock->isAnonymousBlock())
 
602
        middleBlock->setContinuation(cloneBlock);
 
603
 
 
604
    // We have been reparented and are now under the fromBlock.  We need
 
605
    // to walk up our block parent chain until we hit the containing anonymous columns block.
 
606
    // Once we hit the anonymous columns block we're done.
 
607
    RenderBoxModelObject* curr = toRenderBoxModelObject(parent());
 
608
    RenderBoxModelObject* currChild = this;
 
609
    RenderObject* currChildNextSibling = currChild->nextSibling();
 
610
    bool documentUsesBeforeAfterRules = document()->styleSheetCollection()->usesBeforeAfterRules();
 
611
 
 
612
    // Note: |this| can be destroyed inside this loop if it is an empty anonymous
 
613
    // block and we try to call updateBeforeAfterContent inside which removes the
 
614
    // generated content and additionally cleans up |this| empty anonymous block.
 
615
    // See RenderBlock::removeChild(). DO NOT reference any local variables to |this|
 
616
    // after this point.
 
617
    while (curr && curr != fromBlock) {
 
618
        ASSERT(curr->isRenderBlock());
 
619
        
 
620
        RenderBlock* blockCurr = toRenderBlock(curr);
 
621
        
 
622
        // Create a new clone.
 
623
        RenderBlock* cloneChild = cloneBlock;
 
624
        cloneBlock = blockCurr->clone();
 
625
 
 
626
        // Insert our child clone as the first child.
 
627
        cloneBlock->addChildIgnoringContinuation(cloneChild, 0);
 
628
 
 
629
        // Hook the clone up as a continuation of |curr|.  Note we do encounter
 
630
        // anonymous blocks possibly as we walk up the block chain.  When we split an
 
631
        // anonymous block, there's no need to do any continuation hookup, since we haven't
 
632
        // actually split a real element.
 
633
        if (!blockCurr->isAnonymousBlock()) {
 
634
            oldCont = blockCurr->continuation();
 
635
            blockCurr->setContinuation(cloneBlock);
 
636
            cloneBlock->setContinuation(oldCont);
 
637
        }
 
638
 
 
639
        // Someone may have indirectly caused a <q> to split.  When this happens, the :after content
 
640
        // has to move into the inline continuation.  Call updateBeforeAfterContent to ensure that the inline's :after
 
641
        // content gets properly destroyed.
 
642
        bool isLastChild = (currChildNextSibling == blockCurr->lastChild());
 
643
        if (documentUsesBeforeAfterRules)
 
644
            blockCurr->children()->updateBeforeAfterContent(blockCurr, AFTER);
 
645
        if (isLastChild && currChildNextSibling != blockCurr->lastChild())
 
646
            currChildNextSibling = 0; // We destroyed the last child, so now we need to update
 
647
                                      // the value of currChildNextSibling.
 
648
 
 
649
        // Now we need to take all of the children starting from the first child
 
650
        // *after* currChild and append them all to the clone.
 
651
        blockCurr->moveChildrenTo(cloneBlock, currChildNextSibling, 0, true);
 
652
 
 
653
        // Keep walking up the chain.
 
654
        currChild = curr;
 
655
        currChildNextSibling = currChild->nextSibling();
 
656
        curr = toRenderBoxModelObject(curr->parent());
 
657
    }
 
658
 
 
659
    // Now we are at the columns block level. We need to put the clone into the toBlock.
 
660
    toBlock->children()->appendChildNode(toBlock, cloneBlock);
 
661
 
 
662
    // Now take all the children after currChild and remove them from the fromBlock
 
663
    // and put them in the toBlock.
 
664
    fromBlock->moveChildrenTo(toBlock, currChildNextSibling, 0, true);
 
665
}
 
666
 
 
667
void RenderBlock::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,
 
668
                            RenderObject* newChild, RenderBoxModelObject* oldCont)
 
669
{
 
670
    RenderBlock* pre = 0;
 
671
    RenderBlock* block = containingColumnsBlock();
 
672
    
 
673
    // Delete our line boxes before we do the inline split into continuations.
 
674
    block->deleteLineBoxTree();
 
675
    
 
676
    bool madeNewBeforeBlock = false;
 
677
    if (block->isAnonymousColumnsBlock()) {
 
678
        // We can reuse this block and make it the preBlock of the next continuation.
 
679
        pre = block;
 
680
        pre->removePositionedObjects(0);
 
681
        pre->removeFloatingObjects();
 
682
        block = toRenderBlock(block->parent());
 
683
    } else {
 
684
        // No anonymous block available for use.  Make one.
 
685
        pre = block->createAnonymousColumnsBlock();
 
686
        pre->setChildrenInline(false);
 
687
        madeNewBeforeBlock = true;
 
688
    }
 
689
 
 
690
    RenderBlock* post = block->createAnonymousColumnsBlock();
 
691
    post->setChildrenInline(false);
 
692
 
 
693
    RenderObject* boxFirst = madeNewBeforeBlock ? block->firstChild() : pre->nextSibling();
 
694
    if (madeNewBeforeBlock)
 
695
        block->children()->insertChildNode(block, pre, boxFirst);
 
696
    block->children()->insertChildNode(block, newBlockBox, boxFirst);
 
697
    block->children()->insertChildNode(block, post, boxFirst);
 
698
    block->setChildrenInline(false);
 
699
    
 
700
    if (madeNewBeforeBlock)
 
701
        block->moveChildrenTo(pre, boxFirst, 0, true);
 
702
 
 
703
    splitBlocks(pre, post, newBlockBox, beforeChild, oldCont);
 
704
 
 
705
    // We already know the newBlockBox isn't going to contain inline kids, so avoid wasting
 
706
    // time in makeChildrenNonInline by just setting this explicitly up front.
 
707
    newBlockBox->setChildrenInline(false);
 
708
 
 
709
    // We delayed adding the newChild until now so that the |newBlockBox| would be fully
 
710
    // connected, thus allowing newChild access to a renderArena should it need
 
711
    // to wrap itself in additional boxes (e.g., table construction).
 
712
    newBlockBox->addChild(newChild);
 
713
 
 
714
    // Always just do a full layout in order to ensure that line boxes (especially wrappers for images)
 
715
    // get deleted properly.  Because objects moves from the pre block into the post block, we want to
 
716
    // make new line boxes instead of leaving the old line boxes around.
 
717
    pre->setNeedsLayoutAndPrefWidthsRecalc();
 
718
    block->setNeedsLayoutAndPrefWidthsRecalc();
 
719
    post->setNeedsLayoutAndPrefWidthsRecalc();
 
720
}
 
721
 
 
722
void RenderBlock::makeChildrenAnonymousColumnBlocks(RenderObject* beforeChild, RenderBlock* newBlockBox, RenderObject* newChild)
 
723
{
 
724
    RenderBlock* pre = 0;
 
725
    RenderBlock* post = 0;
 
726
    RenderBlock* block = this; // Eventually block will not just be |this|, but will also be a block nested inside |this|.  Assign to a variable
 
727
                               // so that we don't have to patch all of the rest of the code later on.
 
728
    
 
729
    // Delete the block's line boxes before we do the split.
 
730
    block->deleteLineBoxTree();
 
731
 
 
732
    if (beforeChild && beforeChild->parent() != this)
 
733
        beforeChild = splitAnonymousBoxesAroundChild(beforeChild);
 
734
 
 
735
    if (beforeChild != firstChild()) {
 
736
        pre = block->createAnonymousColumnsBlock();
 
737
        pre->setChildrenInline(block->childrenInline());
 
738
    }
 
739
 
 
740
    if (beforeChild) {
 
741
        post = block->createAnonymousColumnsBlock();
 
742
        post->setChildrenInline(block->childrenInline());
 
743
    }
 
744
 
 
745
    RenderObject* boxFirst = block->firstChild();
 
746
    if (pre)
 
747
        block->children()->insertChildNode(block, pre, boxFirst);
 
748
    block->children()->insertChildNode(block, newBlockBox, boxFirst);
 
749
    if (post)
 
750
        block->children()->insertChildNode(block, post, boxFirst);
 
751
    block->setChildrenInline(false);
 
752
    
 
753
    // The pre/post blocks always have layers, so we know to always do a full insert/remove (so we pass true as the last argument).
 
754
    block->moveChildrenTo(pre, boxFirst, beforeChild, true);
 
755
    block->moveChildrenTo(post, beforeChild, 0, true);
 
756
 
 
757
    // We already know the newBlockBox isn't going to contain inline kids, so avoid wasting
 
758
    // time in makeChildrenNonInline by just setting this explicitly up front.
 
759
    newBlockBox->setChildrenInline(false);
 
760
 
 
761
    // We delayed adding the newChild until now so that the |newBlockBox| would be fully
 
762
    // connected, thus allowing newChild access to a renderArena should it need
 
763
    // to wrap itself in additional boxes (e.g., table construction).
 
764
    newBlockBox->addChild(newChild);
 
765
 
 
766
    // Always just do a full layout in order to ensure that line boxes (especially wrappers for images)
 
767
    // get deleted properly.  Because objects moved from the pre block into the post block, we want to
 
768
    // make new line boxes instead of leaving the old line boxes around.
 
769
    if (pre)
 
770
        pre->setNeedsLayoutAndPrefWidthsRecalc();
 
771
    block->setNeedsLayoutAndPrefWidthsRecalc();
 
772
    if (post)
 
773
        post->setNeedsLayoutAndPrefWidthsRecalc();
 
774
}
 
775
 
 
776
RenderBlock* RenderBlock::columnsBlockForSpanningElement(RenderObject* newChild)
 
777
{
 
778
    // FIXME: This function is the gateway for the addition of column-span support.  It will
 
779
    // be added to in three stages:
 
780
    // (1) Immediate children of a multi-column block can span.
 
781
    // (2) Nested block-level children with only block-level ancestors between them and the multi-column block can span.
 
782
    // (3) Nested children with block or inline ancestors between them and the multi-column block can span (this is when we
 
783
    // cross the streams and have to cope with both types of continuations mixed together).
 
784
    // This function currently supports (1) and (2).
 
785
    RenderBlock* columnsBlockAncestor = 0;
 
786
    if (!newChild->isText() && newChild->style()->columnSpan() && !newChild->isBeforeOrAfterContent()
 
787
        && !newChild->isFloatingOrOutOfFlowPositioned() && !newChild->isInline() && !isAnonymousColumnSpanBlock()) {
 
788
        columnsBlockAncestor = containingColumnsBlock(false);
 
789
        if (columnsBlockAncestor) {
 
790
            // Make sure that none of the parent ancestors have a continuation.
 
791
            // If yes, we do not want split the block into continuations.
 
792
            RenderObject* curr = this;
 
793
            while (curr && curr != columnsBlockAncestor) {
 
794
                if (curr->isRenderBlock() && toRenderBlock(curr)->continuation()) {
 
795
                    columnsBlockAncestor = 0;
 
796
                    break;
 
797
                }
 
798
                curr = curr->parent();
 
799
            }
 
800
        }
 
801
    }
 
802
    return columnsBlockAncestor;
 
803
}
 
804
 
 
805
void RenderBlock::addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild, RenderObject* beforeChild)
 
806
{
 
807
    // Make sure we don't append things after :after-generated content if we have it.
 
808
    if (!beforeChild)
 
809
        beforeChild = afterPseudoElementRenderer();
 
810
 
 
811
    if (beforeChild && beforeChild->parent() != this) {
 
812
        RenderObject* beforeChildContainer = beforeChild->parent();
 
813
        while (beforeChildContainer->parent() != this)
 
814
            beforeChildContainer = beforeChildContainer->parent();
 
815
        ASSERT(beforeChildContainer);
 
816
 
 
817
        if (beforeChildContainer->isAnonymous()) {
 
818
            // If the requested beforeChild is not one of our children, then this is because
 
819
            // there is an anonymous container within this object that contains the beforeChild.
 
820
            RenderObject* beforeChildAnonymousContainer = beforeChildContainer;
 
821
            if (beforeChildAnonymousContainer->isAnonymousBlock()
 
822
#if ENABLE(FULLSCREEN_API)
 
823
                // Full screen renderers and full screen placeholders act as anonymous blocks, not tables:
 
824
                || beforeChildAnonymousContainer->isRenderFullScreen()
 
825
                || beforeChildAnonymousContainer->isRenderFullScreenPlaceholder()
 
826
#endif
 
827
                ) {
 
828
                // Insert the child into the anonymous block box instead of here.
 
829
                if (newChild->isInline() || beforeChild->parent()->firstChild() != beforeChild)
 
830
                    beforeChild->parent()->addChild(newChild, beforeChild);
 
831
                else
 
832
                    addChild(newChild, beforeChild->parent());
 
833
                return;
 
834
            }
 
835
 
 
836
            ASSERT(beforeChildAnonymousContainer->isTable());
 
837
            if (newChild->isTablePart()) {
 
838
                // Insert into the anonymous table.
 
839
                beforeChildAnonymousContainer->addChild(newChild, beforeChild);
 
840
                return;
 
841
            }
 
842
 
 
843
            beforeChild = splitAnonymousBoxesAroundChild(beforeChild);
 
844
 
 
845
            ASSERT(beforeChild->parent() == this);
 
846
            if (beforeChild->parent() != this) {
 
847
                // We should never reach here. If we do, we need to use the
 
848
                // safe fallback to use the topmost beforeChild container.
 
849
                beforeChild = beforeChildContainer;
 
850
            }
 
851
        } else {
 
852
            // We will reach here when beforeChild is a run-in element.
 
853
            // If run-in element precedes a block-level element, it becomes the
 
854
            // the first inline child of that block level element. The insertion
 
855
            // point will be before that block-level element.
 
856
            ASSERT(beforeChild->isRunIn());
 
857
            beforeChild = beforeChildContainer;
 
858
        }
 
859
    }
 
860
 
 
861
    // Nothing goes before the intruded run-in.
 
862
    if (beforeChild && beforeChild->isRunIn() && runInIsPlacedIntoSiblingBlock(beforeChild))
 
863
        beforeChild = beforeChild->nextSibling();
 
864
 
 
865
    if (!gIsInColumnFlowSplit) {
 
866
        RenderBlock* columnsBlockAncestor = columnsBlockForSpanningElement(newChild);
 
867
        if (columnsBlockAncestor) {
 
868
            TemporaryChange<bool> isInColumnFlowSplit(gIsInColumnFlowSplit, true);
 
869
            // We are placing a column-span element inside a block.
 
870
            RenderBlock* newBox = createAnonymousColumnSpanBlock();
 
871
 
 
872
            if (columnsBlockAncestor != this) {
 
873
                // We are nested inside a multi-column element and are being split by the span.  We have to break up
 
874
                // our block into continuations.
 
875
                RenderBoxModelObject* oldContinuation = continuation();
 
876
 
 
877
                // When we split an anonymous block, there's no need to do any continuation hookup,
 
878
                // since we haven't actually split a real element.
 
879
                if (!isAnonymousBlock())
 
880
                    setContinuation(newBox);
 
881
 
 
882
                // Someone may have put a <p> inside a <q>, causing a split.  When this happens, the :after content
 
883
                // has to move into the inline continuation.  Call updateBeforeAfterContent to ensure that our :after
 
884
                // content gets properly destroyed.
 
885
                bool isFirstChild = (beforeChild == firstChild());
 
886
                bool isLastChild = (beforeChild == lastChild());
 
887
                if (document()->styleSheetCollection()->usesBeforeAfterRules())
 
888
                    children()->updateBeforeAfterContent(this, AFTER);
 
889
                if (isLastChild && beforeChild != lastChild()) {
 
890
                    // We destroyed the last child, so now we need to update our insertion
 
891
                    // point to be 0. It's just a straight append now.
 
892
                    beforeChild = 0;
 
893
                } else if (isFirstChild && beforeChild != firstChild()) {
 
894
                    // If beforeChild was the last anonymous block that collapsed,
 
895
                    // then we need to update its value.
 
896
                    beforeChild = firstChild();
 
897
                }
 
898
 
 
899
                splitFlow(beforeChild, newBox, newChild, oldContinuation);
 
900
                return;
 
901
            }
 
902
 
 
903
            // We have to perform a split of this block's children.  This involves creating an anonymous block box to hold
 
904
            // the column-spanning |newChild|.  We take all of the children from before |newChild| and put them into
 
905
            // one anonymous columns block, and all of the children after |newChild| go into another anonymous block.
 
906
            makeChildrenAnonymousColumnBlocks(beforeChild, newBox, newChild);
 
907
            return;
 
908
        }
 
909
    }
 
910
 
 
911
    bool madeBoxesNonInline = false;
 
912
 
 
913
    // A block has to either have all of its children inline, or all of its children as blocks.
 
914
    // So, if our children are currently inline and a block child has to be inserted, we move all our
 
915
    // inline children into anonymous block boxes.
 
916
    if (childrenInline() && !newChild->isInline() && !newChild->isFloatingOrOutOfFlowPositioned()) {
 
917
        // This is a block with inline content. Wrap the inline content in anonymous blocks.
 
918
        makeChildrenNonInline(beforeChild);
 
919
        madeBoxesNonInline = true;
 
920
 
 
921
        if (beforeChild && beforeChild->parent() != this) {
 
922
            beforeChild = beforeChild->parent();
 
923
            ASSERT(beforeChild->isAnonymousBlock());
 
924
            ASSERT(beforeChild->parent() == this);
 
925
        }
 
926
    } else if (!childrenInline() && (newChild->isFloatingOrOutOfFlowPositioned() || newChild->isInline())) {
 
927
        // If we're inserting an inline child but all of our children are blocks, then we have to make sure
 
928
        // it is put into an anomyous block box. We try to use an existing anonymous box if possible, otherwise
 
929
        // a new one is created and inserted into our list of children in the appropriate position.
 
930
        RenderObject* afterChild = beforeChild ? beforeChild->previousSibling() : lastChild();
 
931
 
 
932
        if (afterChild && afterChild->isAnonymousBlock()) {
 
933
            afterChild->addChild(newChild);
 
934
            return;
 
935
        }
 
936
 
 
937
        if (newChild->isInline()) {
 
938
            // No suitable existing anonymous box - create a new one.
 
939
            RenderBlock* newBox = createAnonymousBlock();
 
940
            RenderBox::addChild(newBox, beforeChild);
 
941
            newBox->addChild(newChild);
 
942
            return;
 
943
        }
 
944
    }
 
945
 
 
946
    RenderBox::addChild(newChild, beforeChild);
 
947
 
 
948
    // Handle placement of run-ins.
 
949
    placeRunInIfNeeded(newChild, DoNotPlaceGeneratedRunIn);
 
950
 
 
951
    if (madeBoxesNonInline && parent() && isAnonymousBlock() && parent()->isRenderBlock())
 
952
        toRenderBlock(parent())->removeLeftoverAnonymousBlock(this);
 
953
    // this object may be dead here
 
954
}
 
955
 
 
956
void RenderBlock::addChild(RenderObject* newChild, RenderObject* beforeChild)
 
957
{
 
958
    if (continuation() && !isAnonymousBlock())
 
959
        addChildToContinuation(newChild, beforeChild);
 
960
    else
 
961
        addChildIgnoringContinuation(newChild, beforeChild);
 
962
}
 
963
 
 
964
void RenderBlock::addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild)
 
965
{
 
966
    if (!isAnonymousBlock() && firstChild() && (firstChild()->isAnonymousColumnsBlock() || firstChild()->isAnonymousColumnSpanBlock()))
 
967
        addChildToAnonymousColumnBlocks(newChild, beforeChild);
 
968
    else
 
969
        addChildIgnoringAnonymousColumnBlocks(newChild, beforeChild);
 
970
}
 
971
 
 
972
static void getInlineRun(RenderObject* start, RenderObject* boundary,
 
973
                         RenderObject*& inlineRunStart,
 
974
                         RenderObject*& inlineRunEnd)
 
975
{
 
976
    // Beginning at |start| we find the largest contiguous run of inlines that
 
977
    // we can.  We denote the run with start and end points, |inlineRunStart|
 
978
    // and |inlineRunEnd|.  Note that these two values may be the same if
 
979
    // we encounter only one inline.
 
980
    //
 
981
    // We skip any non-inlines we encounter as long as we haven't found any
 
982
    // inlines yet.
 
983
    //
 
984
    // |boundary| indicates a non-inclusive boundary point.  Regardless of whether |boundary|
 
985
    // is inline or not, we will not include it in a run with inlines before it.  It's as though we encountered
 
986
    // a non-inline.
 
987
    
 
988
    // Start by skipping as many non-inlines as we can.
 
989
    RenderObject * curr = start;
 
990
    bool sawInline;
 
991
    do {
 
992
        while (curr && !(curr->isInline() || curr->isFloatingOrOutOfFlowPositioned()))
 
993
            curr = curr->nextSibling();
 
994
        
 
995
        inlineRunStart = inlineRunEnd = curr;
 
996
        
 
997
        if (!curr)
 
998
            return; // No more inline children to be found.
 
999
        
 
1000
        sawInline = curr->isInline();
 
1001
        
 
1002
        curr = curr->nextSibling();
 
1003
        while (curr && (curr->isInline() || curr->isFloatingOrOutOfFlowPositioned()) && (curr != boundary)) {
 
1004
            inlineRunEnd = curr;
 
1005
            if (curr->isInline())
 
1006
                sawInline = true;
 
1007
            curr = curr->nextSibling();
 
1008
        }
 
1009
    } while (!sawInline);
 
1010
}
 
1011
 
 
1012
void RenderBlock::deleteLineBoxTree()
 
1013
{
 
1014
    if (containsFloats()) {
 
1015
        // Clear references to originating lines, since the lines are being deleted
 
1016
        const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
 
1017
        FloatingObjectSetIterator end = floatingObjectSet.end();
 
1018
        for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
 
1019
            ASSERT(!((*it)->m_originatingLine) || (*it)->m_originatingLine->renderer() == this);
 
1020
            (*it)->m_originatingLine = 0;
 
1021
        }
 
1022
    }
 
1023
    m_lineBoxes.deleteLineBoxTree(renderArena());
 
1024
    if (UNLIKELY(AXObjectCache::accessibilityEnabled()))
 
1025
        document()->axObjectCache()->recomputeIsIgnored(this);
 
1026
}
 
1027
 
 
1028
RootInlineBox* RenderBlock::createRootInlineBox() 
 
1029
{
 
1030
    return new (renderArena()) RootInlineBox(this);
 
1031
}
 
1032
 
 
1033
RootInlineBox* RenderBlock::createAndAppendRootInlineBox()
 
1034
{
 
1035
    RootInlineBox* rootBox = createRootInlineBox();
 
1036
    m_lineBoxes.appendLineBox(rootBox);
 
1037
 
 
1038
    if (UNLIKELY(AXObjectCache::accessibilityEnabled()) && m_lineBoxes.firstLineBox() == rootBox)
 
1039
        document()->axObjectCache()->recomputeIsIgnored(this);
 
1040
 
 
1041
    return rootBox;
 
1042
}
 
1043
 
 
1044
void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint)
 
1045
{    
 
1046
    // makeChildrenNonInline takes a block whose children are *all* inline and it
 
1047
    // makes sure that inline children are coalesced under anonymous
 
1048
    // blocks.  If |insertionPoint| is defined, then it represents the insertion point for
 
1049
    // the new block child that is causing us to have to wrap all the inlines.  This
 
1050
    // means that we cannot coalesce inlines before |insertionPoint| with inlines following
 
1051
    // |insertionPoint|, because the new child is going to be inserted in between the inlines,
 
1052
    // splitting them.
 
1053
    ASSERT(isInlineBlockOrInlineTable() || !isInline());
 
1054
    ASSERT(!insertionPoint || insertionPoint->parent() == this);
 
1055
 
 
1056
    setChildrenInline(false);
 
1057
 
 
1058
    RenderObject *child = firstChild();
 
1059
    if (!child)
 
1060
        return;
 
1061
 
 
1062
    deleteLineBoxTree();
 
1063
 
 
1064
    // Since we are going to have block children, we have to move
 
1065
    // back the run-in to its original place.
 
1066
    if (child->isRunIn()) {
 
1067
        moveRunInToOriginalPosition(child);
 
1068
        child = firstChild();
 
1069
    }
 
1070
 
 
1071
    while (child) {
 
1072
        RenderObject *inlineRunStart, *inlineRunEnd;
 
1073
        getInlineRun(child, insertionPoint, inlineRunStart, inlineRunEnd);
 
1074
 
 
1075
        if (!inlineRunStart)
 
1076
            break;
 
1077
 
 
1078
        child = inlineRunEnd->nextSibling();
 
1079
 
 
1080
        RenderBlock* block = createAnonymousBlock();
 
1081
        children()->insertChildNode(this, block, inlineRunStart);
 
1082
        moveChildrenTo(block, inlineRunStart, child);
 
1083
    }
 
1084
 
 
1085
#ifndef NDEBUG
 
1086
    for (RenderObject *c = firstChild(); c; c = c->nextSibling())
 
1087
        ASSERT(!c->isInline());
 
1088
#endif
 
1089
 
 
1090
    repaint();
 
1091
}
 
1092
 
 
1093
void RenderBlock::removeLeftoverAnonymousBlock(RenderBlock* child)
 
1094
{
 
1095
    ASSERT(child->isAnonymousBlock());
 
1096
    ASSERT(!child->childrenInline());
 
1097
    
 
1098
    if (child->continuation() || (child->firstChild() && (child->isAnonymousColumnSpanBlock() || child->isAnonymousColumnsBlock())))
 
1099
        return;
 
1100
    
 
1101
    RenderObject* firstAnChild = child->m_children.firstChild();
 
1102
    RenderObject* lastAnChild = child->m_children.lastChild();
 
1103
    if (firstAnChild) {
 
1104
        RenderObject* o = firstAnChild;
 
1105
        while (o) {
 
1106
            o->setParent(this);
 
1107
            o = o->nextSibling();
 
1108
        }
 
1109
        firstAnChild->setPreviousSibling(child->previousSibling());
 
1110
        lastAnChild->setNextSibling(child->nextSibling());
 
1111
        if (child->previousSibling())
 
1112
            child->previousSibling()->setNextSibling(firstAnChild);
 
1113
        if (child->nextSibling())
 
1114
            child->nextSibling()->setPreviousSibling(lastAnChild);
 
1115
            
 
1116
        if (child == m_children.firstChild())
 
1117
            m_children.setFirstChild(firstAnChild);
 
1118
        if (child == m_children.lastChild())
 
1119
            m_children.setLastChild(lastAnChild);
 
1120
    } else {
 
1121
        if (child == m_children.firstChild())
 
1122
            m_children.setFirstChild(child->nextSibling());
 
1123
        if (child == m_children.lastChild())
 
1124
            m_children.setLastChild(child->previousSibling());
 
1125
 
 
1126
        if (child->previousSibling())
 
1127
            child->previousSibling()->setNextSibling(child->nextSibling());
 
1128
        if (child->nextSibling())
 
1129
            child->nextSibling()->setPreviousSibling(child->previousSibling());
 
1130
    }
 
1131
    child->setParent(0);
 
1132
    child->setPreviousSibling(0);
 
1133
    child->setNextSibling(0);
 
1134
    
 
1135
    child->children()->setFirstChild(0);
 
1136
    child->m_next = 0;
 
1137
 
 
1138
    child->destroy();
 
1139
}
 
1140
 
 
1141
static bool canMergeContiguousAnonymousBlocks(RenderObject* oldChild, RenderObject* prev, RenderObject* next)
 
1142
{
 
1143
    if (oldChild->documentBeingDestroyed() || oldChild->isInline() || oldChild->virtualContinuation())
 
1144
        return false;
 
1145
 
 
1146
    if ((prev && (!prev->isAnonymousBlock() || toRenderBlock(prev)->continuation() || toRenderBlock(prev)->beingDestroyed()))
 
1147
        || (next && (!next->isAnonymousBlock() || toRenderBlock(next)->continuation() || toRenderBlock(next)->beingDestroyed())))
 
1148
        return false;
 
1149
 
 
1150
    // FIXME: This check isn't required when inline run-ins can't be split into continuations.
 
1151
    if (prev && prev->firstChild() && prev->firstChild()->isInline() && prev->firstChild()->isRunIn())
 
1152
        return false;
 
1153
 
 
1154
    if ((prev && (prev->isRubyRun() || prev->isRubyBase()))
 
1155
        || (next && (next->isRubyRun() || next->isRubyBase())))
 
1156
        return false;
 
1157
 
 
1158
    if (!prev || !next)
 
1159
        return true;
 
1160
 
 
1161
    // Make sure the types of the anonymous blocks match up.
 
1162
    return prev->isAnonymousColumnsBlock() == next->isAnonymousColumnsBlock()
 
1163
           && prev->isAnonymousColumnSpanBlock() == next->isAnonymousColumnSpanBlock();
 
1164
}
 
1165
 
 
1166
void RenderBlock::collapseAnonymousBoxChild(RenderBlock* parent, RenderObject* child)
 
1167
{
 
1168
    parent->setNeedsLayoutAndPrefWidthsRecalc();
 
1169
    parent->setChildrenInline(child->childrenInline());
 
1170
    RenderObject* nextSibling = child->nextSibling();
 
1171
 
 
1172
    RenderFlowThread* childFlowThread = child->enclosingRenderFlowThread();
 
1173
    CurrentRenderFlowThreadMaintainer flowThreadMaintainer(childFlowThread);
 
1174
    
 
1175
    RenderBlock* anonBlock = toRenderBlock(parent->children()->removeChildNode(parent, child, child->hasLayer()));
 
1176
    anonBlock->moveAllChildrenTo(parent, nextSibling, child->hasLayer());
 
1177
    // Delete the now-empty block's lines and nuke it.
 
1178
    anonBlock->deleteLineBoxTree();
 
1179
    if (childFlowThread && childFlowThread->isRenderNamedFlowThread())
 
1180
        toRenderNamedFlowThread(childFlowThread)->removeFlowChildInfo(anonBlock);
 
1181
    anonBlock->destroy();
 
1182
}
 
1183
 
 
1184
void RenderBlock::removeChild(RenderObject* oldChild)
 
1185
{
 
1186
    // No need to waste time in merging or removing empty anonymous blocks.
 
1187
    // We can just bail out if our document is getting destroyed.
 
1188
    if (documentBeingDestroyed()) {
 
1189
        RenderBox::removeChild(oldChild);
 
1190
        return;
 
1191
    }
 
1192
 
 
1193
    // If this child is a block, and if our previous and next siblings are
 
1194
    // both anonymous blocks with inline content, then we can go ahead and
 
1195
    // fold the inline content back together.
 
1196
    RenderObject* prev = oldChild->previousSibling();
 
1197
    RenderObject* next = oldChild->nextSibling();
 
1198
    bool canMergeAnonymousBlocks = canMergeContiguousAnonymousBlocks(oldChild, prev, next);
 
1199
    if (canMergeAnonymousBlocks && prev && next) {
 
1200
        prev->setNeedsLayoutAndPrefWidthsRecalc();
 
1201
        RenderBlock* nextBlock = toRenderBlock(next);
 
1202
        RenderBlock* prevBlock = toRenderBlock(prev);
 
1203
       
 
1204
        if (prev->childrenInline() != next->childrenInline()) {
 
1205
            RenderBlock* inlineChildrenBlock = prev->childrenInline() ? prevBlock : nextBlock;
 
1206
            RenderBlock* blockChildrenBlock = prev->childrenInline() ? nextBlock : prevBlock;
 
1207
            
 
1208
            // Place the inline children block inside of the block children block instead of deleting it.
 
1209
            // In order to reuse it, we have to reset it to just be a generic anonymous block.  Make sure
 
1210
            // to clear out inherited column properties by just making a new style, and to also clear the
 
1211
            // column span flag if it is set.
 
1212
            ASSERT(!inlineChildrenBlock->continuation());
 
1213
            RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(style(), BLOCK);
 
1214
            // Cache this value as it might get changed in setStyle() call.
 
1215
            bool inlineChildrenBlockHasLayer = inlineChildrenBlock->hasLayer();
 
1216
            inlineChildrenBlock->setStyle(newStyle);
 
1217
            children()->removeChildNode(this, inlineChildrenBlock, inlineChildrenBlockHasLayer);
 
1218
            
 
1219
            // Now just put the inlineChildrenBlock inside the blockChildrenBlock.
 
1220
            blockChildrenBlock->children()->insertChildNode(blockChildrenBlock, inlineChildrenBlock, prev == inlineChildrenBlock ? blockChildrenBlock->firstChild() : 0,
 
1221
                                                            inlineChildrenBlockHasLayer || blockChildrenBlock->hasLayer());
 
1222
            next->setNeedsLayoutAndPrefWidthsRecalc();
 
1223
            
 
1224
            // inlineChildrenBlock got reparented to blockChildrenBlock, so it is no longer a child
 
1225
            // of "this". we null out prev or next so that is not used later in the function.
 
1226
            if (inlineChildrenBlock == prevBlock)
 
1227
                prev = 0;
 
1228
            else
 
1229
                next = 0;
 
1230
        } else {
 
1231
            // Take all the children out of the |next| block and put them in
 
1232
            // the |prev| block.
 
1233
            nextBlock->moveAllChildrenTo(prevBlock, nextBlock->hasLayer() || prevBlock->hasLayer());        
 
1234
            
 
1235
            // Delete the now-empty block's lines and nuke it.
 
1236
            nextBlock->deleteLineBoxTree();
 
1237
            nextBlock->destroy();
 
1238
            next = 0;
 
1239
        }
 
1240
    }
 
1241
 
 
1242
    RenderBox::removeChild(oldChild);
 
1243
 
 
1244
    RenderObject* child = prev ? prev : next;
 
1245
    if (canMergeAnonymousBlocks && child && !child->previousSibling() && !child->nextSibling() && canCollapseAnonymousBlockChild()) {
 
1246
        // The removal has knocked us down to containing only a single anonymous
 
1247
        // box.  We can go ahead and pull the content right back up into our
 
1248
        // box.
 
1249
        collapseAnonymousBoxChild(this, child);
 
1250
    } else if (((prev && prev->isAnonymousBlock()) || (next && next->isAnonymousBlock())) && canCollapseAnonymousBlockChild()) {
 
1251
        // It's possible that the removal has knocked us down to a single anonymous
 
1252
        // block with pseudo-style element siblings (e.g. first-letter). If these
 
1253
        // are floating, then we need to pull the content up also.
 
1254
        RenderBlock* anonBlock = toRenderBlock((prev && prev->isAnonymousBlock()) ? prev : next);
 
1255
        if ((anonBlock->previousSibling() || anonBlock->nextSibling())
 
1256
            && (!anonBlock->previousSibling() || (anonBlock->previousSibling()->style()->styleType() != NOPSEUDO && anonBlock->previousSibling()->isFloating() && !anonBlock->previousSibling()->previousSibling()))
 
1257
            && (!anonBlock->nextSibling() || (anonBlock->nextSibling()->style()->styleType() != NOPSEUDO && anonBlock->nextSibling()->isFloating() && !anonBlock->nextSibling()->nextSibling()))) {
 
1258
            collapseAnonymousBoxChild(this, anonBlock);
 
1259
        }
 
1260
    }
 
1261
 
 
1262
    if (!firstChild()) {
 
1263
        // If this was our last child be sure to clear out our line boxes.
 
1264
        if (childrenInline())
 
1265
            deleteLineBoxTree();
 
1266
 
 
1267
        // If we are an empty anonymous block in the continuation chain,
 
1268
        // we need to remove ourself and fix the continuation chain.
 
1269
        if (!beingDestroyed() && isAnonymousBlockContinuation() && !oldChild->isListMarker()) {
 
1270
            RenderObject* containingBlockIgnoringAnonymous = containingBlock();
 
1271
            while (containingBlockIgnoringAnonymous && containingBlockIgnoringAnonymous->isAnonymousBlock())
 
1272
                containingBlockIgnoringAnonymous = containingBlockIgnoringAnonymous->containingBlock();
 
1273
            for (RenderObject* curr = this; curr; curr = curr->previousInPreOrder(containingBlockIgnoringAnonymous)) {
 
1274
                if (curr->virtualContinuation() != this)
 
1275
                    continue;
 
1276
 
 
1277
                // Found our previous continuation. We just need to point it to
 
1278
                // |this|'s next continuation.
 
1279
                RenderBoxModelObject* nextContinuation = continuation();
 
1280
                if (curr->isRenderInline())
 
1281
                    toRenderInline(curr)->setContinuation(nextContinuation);
 
1282
                else if (curr->isRenderBlock())
 
1283
                    toRenderBlock(curr)->setContinuation(nextContinuation);
 
1284
                else
 
1285
                    ASSERT_NOT_REACHED();
 
1286
 
 
1287
                break;
 
1288
            }
 
1289
            setContinuation(0);
 
1290
            destroy();
 
1291
        }
 
1292
    }
 
1293
}
 
1294
 
 
1295
bool RenderBlock::isSelfCollapsingBlock() const
 
1296
{
 
1297
    // We are not self-collapsing if we
 
1298
    // (a) have a non-zero height according to layout (an optimization to avoid wasting time)
 
1299
    // (b) are a table,
 
1300
    // (c) have border/padding,
 
1301
    // (d) have a min-height
 
1302
    // (e) have specified that one of our margins can't collapse using a CSS extension
 
1303
    if (logicalHeight() > 0
 
1304
        || isTable() || borderAndPaddingLogicalHeight()
 
1305
        || style()->logicalMinHeight().isPositive()
 
1306
        || style()->marginBeforeCollapse() == MSEPARATE || style()->marginAfterCollapse() == MSEPARATE)
 
1307
        return false;
 
1308
 
 
1309
    Length logicalHeightLength = style()->logicalHeight();
 
1310
    bool hasAutoHeight = logicalHeightLength.isAuto();
 
1311
    if (logicalHeightLength.isPercent() && !document()->inQuirksMode()) {
 
1312
        hasAutoHeight = true;
 
1313
        for (RenderBlock* cb = containingBlock(); !cb->isRenderView(); cb = cb->containingBlock()) {
 
1314
            if (cb->style()->logicalHeight().isFixed() || cb->isTableCell())
 
1315
                hasAutoHeight = false;
 
1316
        }
 
1317
    }
 
1318
 
 
1319
    // If the height is 0 or auto, then whether or not we are a self-collapsing block depends
 
1320
    // on whether we have content that is all self-collapsing or not.
 
1321
    if (hasAutoHeight || ((logicalHeightLength.isFixed() || logicalHeightLength.isPercent()) && logicalHeightLength.isZero())) {
 
1322
        // If the block has inline children, see if we generated any line boxes.  If we have any
 
1323
        // line boxes, then we can't be self-collapsing, since we have content.
 
1324
        if (childrenInline())
 
1325
            return !firstLineBox();
 
1326
        
 
1327
        // Whether or not we collapse is dependent on whether all our normal flow children
 
1328
        // are also self-collapsing.
 
1329
        for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
 
1330
            if (child->isFloatingOrOutOfFlowPositioned())
 
1331
                continue;
 
1332
            if (!child->isSelfCollapsingBlock())
 
1333
                return false;
 
1334
        }
 
1335
        return true;
 
1336
    }
 
1337
    return false;
 
1338
}
 
1339
 
 
1340
void RenderBlock::startDelayUpdateScrollInfo()
 
1341
{
 
1342
    if (gDelayUpdateScrollInfo == 0) {
 
1343
        ASSERT(!gDelayedUpdateScrollInfoSet);
 
1344
        gDelayedUpdateScrollInfoSet = new DelayedUpdateScrollInfoSet;
 
1345
    }
 
1346
    ASSERT(gDelayedUpdateScrollInfoSet);
 
1347
    ++gDelayUpdateScrollInfo;
 
1348
}
 
1349
 
 
1350
void RenderBlock::finishDelayUpdateScrollInfo()
 
1351
{
 
1352
    --gDelayUpdateScrollInfo;
 
1353
    ASSERT(gDelayUpdateScrollInfo >= 0);
 
1354
    if (gDelayUpdateScrollInfo == 0) {
 
1355
        ASSERT(gDelayedUpdateScrollInfoSet);
 
1356
 
 
1357
        OwnPtr<DelayedUpdateScrollInfoSet> infoSet(adoptPtr(gDelayedUpdateScrollInfoSet));
 
1358
        gDelayedUpdateScrollInfoSet = 0;
 
1359
 
 
1360
        for (DelayedUpdateScrollInfoSet::iterator it = infoSet->begin(); it != infoSet->end(); ++it) {
 
1361
            RenderBlock* block = *it;
 
1362
            if (block->hasOverflowClip()) {
 
1363
                block->layer()->updateScrollInfoAfterLayout();
 
1364
            }
 
1365
        }
 
1366
    }
 
1367
}
 
1368
 
 
1369
void RenderBlock::updateScrollInfoAfterLayout()
 
1370
{
 
1371
    if (hasOverflowClip()) {
 
1372
        if (style()->isFlippedBlocksWritingMode()) {
 
1373
            // FIXME: https://bugs.webkit.org/show_bug.cgi?id=97937
 
1374
            // Workaround for now. We cannot delay the scroll info for overflow
 
1375
            // for items with opposite writing directions, as the contents needs
 
1376
            // to overflow in that direction
 
1377
            layer()->updateScrollInfoAfterLayout();
 
1378
            return;
 
1379
        }
 
1380
 
 
1381
        if (gDelayUpdateScrollInfo)
 
1382
            gDelayedUpdateScrollInfoSet->add(this);
 
1383
        else
 
1384
            layer()->updateScrollInfoAfterLayout();
 
1385
    }
 
1386
}
 
1387
 
 
1388
void RenderBlock::layout()
 
1389
{
 
1390
    StackStats::LayoutCheckPoint layoutCheckPoint;
 
1391
    OverflowEventDispatcher dispatcher(this);
 
1392
 
 
1393
    // Update our first letter info now.
 
1394
    updateFirstLetter();
 
1395
 
 
1396
    // Table cells call layoutBlock directly, so don't add any logic here.  Put code into
 
1397
    // layoutBlock().
 
1398
    layoutBlock(false);
 
1399
    
 
1400
    // It's safe to check for control clip here, since controls can never be table cells.
 
1401
    // If we have a lightweight clip, there can never be any overflow from children.
 
1402
    if (hasControlClip() && m_overflow)
 
1403
        clearLayoutOverflow();
 
1404
}
 
1405
 
 
1406
#if ENABLE(CSS_EXCLUSIONS)
 
1407
void RenderBlock::updateExclusionShapeInsideInfoAfterStyleChange(const ExclusionShapeValue* shapeInside, const ExclusionShapeValue* oldShapeInside)
 
1408
{
 
1409
    // FIXME: A future optimization would do a deep comparison for equality.
 
1410
    if (shapeInside == oldShapeInside)
 
1411
        return;
 
1412
 
 
1413
    if (shapeInside) {
 
1414
        ExclusionShapeInsideInfo* exclusionShapeInsideInfo = ExclusionShapeInsideInfo::ensureExclusionShapeInsideInfoForRenderBlock(this);
 
1415
        exclusionShapeInsideInfo->dirtyShapeSize();
 
1416
    } else
 
1417
        ExclusionShapeInsideInfo::removeExclusionShapeInsideInfoForRenderBlock(this);
 
1418
}
 
1419
#endif
 
1420
 
 
1421
void RenderBlock::updateRegionsAndExclusionsLogicalSize()
 
1422
{
 
1423
#if ENABLE(CSS_EXCLUSIONS)
 
1424
    if (!inRenderFlowThread() && !exclusionShapeInsideInfo())
 
1425
#else
 
1426
    if (!inRenderFlowThread())
 
1427
#endif
 
1428
        return;
 
1429
 
 
1430
    LayoutUnit oldHeight = logicalHeight();
 
1431
    LayoutUnit oldTop = logicalTop();
 
1432
 
 
1433
    // Compute the maximum logical height content may cause this block to expand to
 
1434
    // FIXME: These should eventually use the const computeLogicalHeight rather than updateLogicalHeight
 
1435
    setLogicalHeight(LayoutUnit::max() / 2);
 
1436
    updateLogicalHeight();
 
1437
 
 
1438
#if ENABLE(CSS_EXCLUSIONS)
 
1439
    computeExclusionShapeSize();
 
1440
#endif
 
1441
 
 
1442
    // Set our start and end regions. No regions above or below us will be considered by our children. They are
 
1443
    // effectively clamped to our region range.
 
1444
    computeRegionRangeForBlock();
 
1445
 
 
1446
    setLogicalHeight(oldHeight);
 
1447
    setLogicalTop(oldTop);
 
1448
}
 
1449
 
 
1450
#if ENABLE(CSS_EXCLUSIONS)
 
1451
void RenderBlock::computeExclusionShapeSize()
 
1452
{
 
1453
    ExclusionShapeInsideInfo* exclusionShapeInsideInfo = this->exclusionShapeInsideInfo();
 
1454
    if (exclusionShapeInsideInfo) {
 
1455
        bool percentageLogicalHeightResolvable = percentageLogicalHeightIsResolvableFromBlock(this, false);
 
1456
        exclusionShapeInsideInfo->computeShapeSize(logicalWidth(), percentageLogicalHeightResolvable ? logicalHeight() : LayoutUnit());
 
1457
    }
 
1458
}
 
1459
#endif
 
1460
 
 
1461
void RenderBlock::computeRegionRangeForBlock()
 
1462
{
 
1463
    if (inRenderFlowThread())
 
1464
        enclosingRenderFlowThread()->setRegionRangeForBox(this, offsetFromLogicalTopOfFirstPage());
 
1465
}
 
1466
 
 
1467
bool RenderBlock::updateLogicalWidthAndColumnWidth()
 
1468
{
 
1469
    LayoutUnit oldWidth = logicalWidth();
 
1470
    LayoutUnit oldColumnWidth = desiredColumnWidth();
 
1471
 
 
1472
    updateLogicalWidth();
 
1473
    calcColumnWidth();
 
1474
 
 
1475
    return oldWidth != logicalWidth() || oldColumnWidth != desiredColumnWidth();
 
1476
}
 
1477
 
 
1478
void RenderBlock::checkForPaginationLogicalHeightChange(LayoutUnit& pageLogicalHeight, bool& pageLogicalHeightChanged, bool& hasSpecifiedPageLogicalHeight)
 
1479
{
 
1480
    ColumnInfo* colInfo = columnInfo();
 
1481
    if (hasColumns()) {
 
1482
        if (!pageLogicalHeight) {
 
1483
            // We need to go ahead and set our explicit page height if one exists, so that we can
 
1484
            // avoid doing two layout passes.
 
1485
            updateLogicalHeight();
 
1486
            LayoutUnit columnHeight = contentLogicalHeight();
 
1487
            if (columnHeight > 0) {
 
1488
                pageLogicalHeight = columnHeight;
 
1489
                hasSpecifiedPageLogicalHeight = true;
 
1490
            }
 
1491
            setLogicalHeight(0);
 
1492
        }
 
1493
        if (colInfo->columnHeight() != pageLogicalHeight && everHadLayout()) {
 
1494
            colInfo->setColumnHeight(pageLogicalHeight);
 
1495
            pageLogicalHeightChanged = true;
 
1496
        }
 
1497
        
 
1498
        if (!hasSpecifiedPageLogicalHeight && !pageLogicalHeight)
 
1499
            colInfo->clearForcedBreaks();
 
1500
 
 
1501
        colInfo->setPaginationUnit(paginationUnit());
 
1502
    } else if (isRenderFlowThread()) {
 
1503
        pageLogicalHeight = 1; // This is just a hack to always make sure we have a page logical height.
 
1504
        pageLogicalHeightChanged = toRenderFlowThread(this)->pageLogicalHeightChanged();
 
1505
    }
 
1506
}
 
1507
 
 
1508
void RenderBlock::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight)
 
1509
{
 
1510
    ASSERT(needsLayout());
 
1511
 
 
1512
    if (isInline() && !isInlineBlockOrInlineTable()) // Inline <form>s inside various table elements can
 
1513
        return;                                      // cause us to come in here.  Just bail.
 
1514
 
 
1515
    if (!relayoutChildren && simplifiedLayout())
 
1516
        return;
 
1517
 
 
1518
    LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
 
1519
 
 
1520
    if (updateLogicalWidthAndColumnWidth())
 
1521
        relayoutChildren = true;
 
1522
 
 
1523
    m_overflow.clear();
 
1524
 
 
1525
    clearFloats();
 
1526
 
 
1527
    LayoutUnit previousHeight = logicalHeight();
 
1528
    setLogicalHeight(0);
 
1529
 
 
1530
    bool pageLogicalHeightChanged = false;
 
1531
    bool hasSpecifiedPageLogicalHeight = false;
 
1532
    checkForPaginationLogicalHeightChange(pageLogicalHeight, pageLogicalHeightChanged, hasSpecifiedPageLogicalHeight);
 
1533
 
 
1534
    RenderView* renderView = view();
 
1535
    RenderStyle* styleToUse = style();
 
1536
    LayoutStateMaintainer statePusher(renderView, this, locationOffset(), hasColumns() || hasTransform() || hasReflection() || styleToUse->isFlippedBlocksWritingMode(), pageLogicalHeight, pageLogicalHeightChanged, columnInfo());
 
1537
 
 
1538
    if (inRenderFlowThread()) {
 
1539
        // Regions changing widths can force us to relayout our children.
 
1540
        if (logicalWidthChangedInRegions())
 
1541
            relayoutChildren = true;
 
1542
    }
 
1543
    updateRegionsAndExclusionsLogicalSize();
 
1544
 
 
1545
    // We use four values, maxTopPos, maxTopNeg, maxBottomPos, and maxBottomNeg, to track
 
1546
    // our current maximal positive and negative margins.  These values are used when we
 
1547
    // are collapsed with adjacent blocks, so for example, if you have block A and B
 
1548
    // collapsing together, then you'd take the maximal positive margin from both A and B
 
1549
    // and subtract it from the maximal negative margin from both A and B to get the
 
1550
    // true collapsed margin.  This algorithm is recursive, so when we finish layout()
 
1551
    // our block knows its current maximal positive/negative values.
 
1552
    //
 
1553
    // Start out by setting our margin values to our current margins.  Table cells have
 
1554
    // no margins, so we don't fill in the values for table cells.
 
1555
    bool isCell = isTableCell();
 
1556
    if (!isCell) {
 
1557
        initMaxMarginValues();
 
1558
        
 
1559
        setMarginBeforeQuirk(styleToUse->marginBefore().quirk());
 
1560
        setMarginAfterQuirk(styleToUse->marginAfter().quirk());
 
1561
        setPaginationStrut(0);
 
1562
    }
 
1563
 
 
1564
    LayoutUnit repaintLogicalTop = 0;
 
1565
    LayoutUnit repaintLogicalBottom = 0;
 
1566
    LayoutUnit maxFloatLogicalBottom = 0;
 
1567
    if (!firstChild() && !isAnonymousBlock())
 
1568
        setChildrenInline(true);
 
1569
    if (childrenInline())
 
1570
        layoutInlineChildren(relayoutChildren, repaintLogicalTop, repaintLogicalBottom);
 
1571
    else
 
1572
        layoutBlockChildren(relayoutChildren, maxFloatLogicalBottom);
 
1573
 
 
1574
    // Expand our intrinsic height to encompass floats.
 
1575
    LayoutUnit toAdd = borderAfter() + paddingAfter() + scrollbarLogicalHeight();
 
1576
    if (lowestFloatLogicalBottom() > (logicalHeight() - toAdd) && expandsToEncloseOverhangingFloats())
 
1577
        setLogicalHeight(lowestFloatLogicalBottom() + toAdd);
 
1578
    
 
1579
    if (relayoutForPagination(hasSpecifiedPageLogicalHeight, pageLogicalHeight, statePusher))
 
1580
        return;
 
1581
 
 
1582
    // Calculate our new height.
 
1583
    LayoutUnit oldHeight = logicalHeight();
 
1584
    LayoutUnit oldClientAfterEdge = clientLogicalBottom();
 
1585
    updateLogicalHeight();
 
1586
    LayoutUnit newHeight = logicalHeight();
 
1587
    if (oldHeight != newHeight) {
 
1588
        if (oldHeight > newHeight && maxFloatLogicalBottom > newHeight && !childrenInline()) {
 
1589
            // One of our children's floats may have become an overhanging float for us. We need to look for it.
 
1590
            for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
 
1591
                if (child->isBlockFlow() && !child->isFloatingOrOutOfFlowPositioned()) {
 
1592
                    RenderBlock* block = toRenderBlock(child);
 
1593
                    if (block->lowestFloatLogicalBottom() + block->logicalTop() > newHeight)
 
1594
                        addOverhangingFloats(block, false);
 
1595
                }
 
1596
            }
 
1597
        }
 
1598
    }
 
1599
 
 
1600
    if (previousHeight != newHeight)
 
1601
        relayoutChildren = true;
 
1602
 
 
1603
    layoutPositionedObjects(relayoutChildren || isRoot());
 
1604
 
 
1605
    computeRegionRangeForBlock();
 
1606
 
 
1607
    // Add overflow from children (unless we're multi-column, since in that case all our child overflow is clipped anyway).
 
1608
    computeOverflow(oldClientAfterEdge);
 
1609
    
 
1610
    statePusher.pop();
 
1611
 
 
1612
    if (renderView->layoutState()->m_pageLogicalHeight)
 
1613
        setPageLogicalOffset(renderView->layoutState()->pageLogicalOffset(this, logicalTop()));
 
1614
 
 
1615
    updateLayerTransform();
 
1616
 
 
1617
    // Update our scroll information if we're overflow:auto/scroll/hidden now that we know if
 
1618
    // we overflow or not.
 
1619
    updateScrollInfoAfterLayout();
 
1620
 
 
1621
    // FIXME: This repaint logic should be moved into a separate helper function!
 
1622
    // Repaint with our new bounds if they are different from our old bounds.
 
1623
    bool didFullRepaint = repainter.repaintAfterLayout();
 
1624
    if (!didFullRepaint && repaintLogicalTop != repaintLogicalBottom && (styleToUse->visibility() == VISIBLE || enclosingLayer()->hasVisibleContent())) {
 
1625
        // FIXME: We could tighten up the left and right invalidation points if we let layoutInlineChildren fill them in based off the particular lines
 
1626
        // it had to lay out.  We wouldn't need the hasOverflowClip() hack in that case either.
 
1627
        LayoutUnit repaintLogicalLeft = logicalLeftVisualOverflow();
 
1628
        LayoutUnit repaintLogicalRight = logicalRightVisualOverflow();
 
1629
        if (hasOverflowClip()) {
 
1630
            // If we have clipped overflow, we should use layout overflow as well, since visual overflow from lines didn't propagate to our block's overflow.
 
1631
            // Note the old code did this as well but even for overflow:visible.  The addition of hasOverflowClip() at least tightens up the hack a bit.
 
1632
            // layoutInlineChildren should be patched to compute the entire repaint rect.
 
1633
            repaintLogicalLeft = min(repaintLogicalLeft, logicalLeftLayoutOverflow());
 
1634
            repaintLogicalRight = max(repaintLogicalRight, logicalRightLayoutOverflow());
 
1635
        }
 
1636
        
 
1637
        LayoutRect repaintRect;
 
1638
        if (isHorizontalWritingMode())
 
1639
            repaintRect = LayoutRect(repaintLogicalLeft, repaintLogicalTop, repaintLogicalRight - repaintLogicalLeft, repaintLogicalBottom - repaintLogicalTop);
 
1640
        else
 
1641
            repaintRect = LayoutRect(repaintLogicalTop, repaintLogicalLeft, repaintLogicalBottom - repaintLogicalTop, repaintLogicalRight - repaintLogicalLeft);
 
1642
 
 
1643
        // The repaint rect may be split across columns, in which case adjustRectForColumns() will return the union.
 
1644
        adjustRectForColumns(repaintRect);
 
1645
 
 
1646
        repaintRect.inflate(maximalOutlineSize(PaintPhaseOutline));
 
1647
        
 
1648
        if (hasOverflowClip()) {
 
1649
            // Adjust repaint rect for scroll offset
 
1650
            repaintRect.move(-scrolledContentOffset());
 
1651
 
 
1652
            // Don't allow this rect to spill out of our overflow box.
 
1653
            repaintRect.intersect(LayoutRect(LayoutPoint(), size()));
 
1654
        }
 
1655
 
 
1656
        // Make sure the rect is still non-empty after intersecting for overflow above
 
1657
        if (!repaintRect.isEmpty()) {
 
1658
            repaintRectangle(repaintRect); // We need to do a partial repaint of our content.
 
1659
            if (hasReflection())
 
1660
                repaintRectangle(reflectedRect(repaintRect));
 
1661
        }
 
1662
    }
 
1663
    
 
1664
    setNeedsLayout(false);
 
1665
}
 
1666
 
 
1667
void RenderBlock::addOverflowFromChildren()
 
1668
{
 
1669
    if (!hasColumns()) {
 
1670
        if (childrenInline())
 
1671
            addOverflowFromInlineChildren();
 
1672
        else
 
1673
            addOverflowFromBlockChildren();
 
1674
    } else {
 
1675
        ColumnInfo* colInfo = columnInfo();
 
1676
        if (columnCount(colInfo)) {
 
1677
            LayoutRect lastRect = columnRectAt(colInfo, columnCount(colInfo) - 1);
 
1678
            addLayoutOverflow(lastRect);
 
1679
            if (!hasOverflowClip())
 
1680
                addVisualOverflow(lastRect);
 
1681
        }
 
1682
    }
 
1683
}
 
1684
 
 
1685
void RenderBlock::computeOverflow(LayoutUnit oldClientAfterEdge, bool recomputeFloats)
 
1686
{
 
1687
    // Add overflow from children.
 
1688
    addOverflowFromChildren();
 
1689
 
 
1690
    if (!hasColumns() && (recomputeFloats || isRoot() || expandsToEncloseOverhangingFloats() || hasSelfPaintingLayer()))
 
1691
        addOverflowFromFloats();
 
1692
 
 
1693
    // Add in the overflow from positioned objects.
 
1694
    addOverflowFromPositionedObjects();
 
1695
 
 
1696
    if (hasOverflowClip()) {
 
1697
        // When we have overflow clip, propagate the original spillout since it will include collapsed bottom margins
 
1698
        // and bottom padding.  Set the axis we don't care about to be 1, since we want this overflow to always
 
1699
        // be considered reachable.
 
1700
        LayoutRect clientRect(clientBoxRect());
 
1701
        LayoutRect rectToApply;
 
1702
        if (isHorizontalWritingMode())
 
1703
            rectToApply = LayoutRect(clientRect.x(), clientRect.y(), 1, max<LayoutUnit>(0, oldClientAfterEdge - clientRect.y()));
 
1704
        else
 
1705
            rectToApply = LayoutRect(clientRect.x(), clientRect.y(), max<LayoutUnit>(0, oldClientAfterEdge - clientRect.x()), 1);
 
1706
        addLayoutOverflow(rectToApply);
 
1707
    }
 
1708
        
 
1709
    // Add visual overflow from box-shadow and border-image-outset.
 
1710
    addVisualEffectOverflow();
 
1711
 
 
1712
    // Add visual overflow from theme.
 
1713
    addVisualOverflowFromTheme();
 
1714
 
 
1715
    if (isRenderFlowThread())
 
1716
        enclosingRenderFlowThread()->computeOverflowStateForRegions(oldClientAfterEdge);
 
1717
}
 
1718
 
 
1719
void RenderBlock::addOverflowFromBlockChildren()
 
1720
{
 
1721
    for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
 
1722
        if (!child->isFloatingOrOutOfFlowPositioned())
 
1723
            addOverflowFromChild(child);
 
1724
    }
 
1725
}
 
1726
 
 
1727
void RenderBlock::addOverflowFromFloats()
 
1728
{
 
1729
    if (!m_floatingObjects)
 
1730
        return;
 
1731
 
 
1732
    const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
 
1733
    FloatingObjectSetIterator end = floatingObjectSet.end();
 
1734
    for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
 
1735
        FloatingObject* r = *it;
 
1736
        if (r->isDescendant())
 
1737
            addOverflowFromChild(r->m_renderer, IntSize(xPositionForFloatIncludingMargin(r), yPositionForFloatIncludingMargin(r)));
 
1738
    }
 
1739
    return;
 
1740
}
 
1741
 
 
1742
void RenderBlock::addOverflowFromPositionedObjects()
 
1743
{
 
1744
    TrackedRendererListHashSet* positionedDescendants = positionedObjects();
 
1745
    if (!positionedDescendants)
 
1746
        return;
 
1747
 
 
1748
    RenderBox* positionedObject;
 
1749
    TrackedRendererListHashSet::iterator end = positionedDescendants->end();
 
1750
    for (TrackedRendererListHashSet::iterator it = positionedDescendants->begin(); it != end; ++it) {
 
1751
        positionedObject = *it;
 
1752
        
 
1753
        // Fixed positioned elements don't contribute to layout overflow, since they don't scroll with the content.
 
1754
        if (positionedObject->style()->position() != FixedPosition) {
 
1755
            LayoutUnit x = positionedObject->x();
 
1756
            if (style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
 
1757
                x -= verticalScrollbarWidth();
 
1758
            addOverflowFromChild(positionedObject, LayoutSize(x, positionedObject->y()));
 
1759
        }
 
1760
    }
 
1761
}
 
1762
 
 
1763
void RenderBlock::addVisualOverflowFromTheme()
 
1764
{
 
1765
    if (!style()->hasAppearance())
 
1766
        return;
 
1767
 
 
1768
    IntRect inflatedRect = pixelSnappedBorderBoxRect();
 
1769
    theme()->adjustRepaintRect(this, inflatedRect);
 
1770
    addVisualOverflow(inflatedRect);
 
1771
}
 
1772
 
 
1773
bool RenderBlock::expandsToEncloseOverhangingFloats() const
 
1774
{
 
1775
    return isInlineBlockOrInlineTable() || isFloatingOrOutOfFlowPositioned() || hasOverflowClip() || (parent() && parent()->isDeprecatedFlexibleBox())
 
1776
           || hasColumns() || isTableCell() || isTableCaption() || isFieldset() || isWritingModeRoot() || isRoot();
 
1777
}
 
1778
 
 
1779
void RenderBlock::adjustPositionedBlock(RenderBox* child, const MarginInfo& marginInfo)
 
1780
{
 
1781
    bool isHorizontal = isHorizontalWritingMode();
 
1782
    bool hasStaticBlockPosition = child->style()->hasStaticBlockPosition(isHorizontal);
 
1783
    
 
1784
    LayoutUnit logicalTop = logicalHeight();
 
1785
    setStaticInlinePositionForChild(child, logicalTop, startOffsetForContent(logicalTop));
 
1786
 
 
1787
    if (!marginInfo.canCollapseWithMarginBefore()) {
 
1788
        // Positioned blocks don't collapse margins, so add the margin provided by
 
1789
        // the container now. The child's own margin is added later when calculating its logical top.
 
1790
        LayoutUnit collapsedBeforePos = marginInfo.positiveMargin();
 
1791
        LayoutUnit collapsedBeforeNeg = marginInfo.negativeMargin();
 
1792
        logicalTop += collapsedBeforePos - collapsedBeforeNeg;
 
1793
    }
 
1794
    
 
1795
    RenderLayer* childLayer = child->layer();
 
1796
    if (childLayer->staticBlockPosition() != logicalTop) {
 
1797
        childLayer->setStaticBlockPosition(logicalTop);
 
1798
        if (hasStaticBlockPosition)
 
1799
            child->setChildNeedsLayout(true, MarkOnlyThis);
 
1800
    }
 
1801
}
 
1802
 
 
1803
void RenderBlock::adjustFloatingBlock(const MarginInfo& marginInfo)
 
1804
{
 
1805
    // The float should be positioned taking into account the bottom margin
 
1806
    // of the previous flow.  We add that margin into the height, get the
 
1807
    // float positioned properly, and then subtract the margin out of the
 
1808
    // height again.  In the case of self-collapsing blocks, we always just
 
1809
    // use the top margins, since the self-collapsing block collapsed its
 
1810
    // own bottom margin into its top margin.
 
1811
    //
 
1812
    // Note also that the previous flow may collapse its margin into the top of
 
1813
    // our block.  If this is the case, then we do not add the margin in to our
 
1814
    // height when computing the position of the float.   This condition can be tested
 
1815
    // for by simply calling canCollapseWithMarginBefore.  See
 
1816
    // http://www.hixie.ch/tests/adhoc/css/box/block/margin-collapse/046.html for
 
1817
    // an example of this scenario.
 
1818
    LayoutUnit marginOffset = marginInfo.canCollapseWithMarginBefore() ? LayoutUnit() : marginInfo.margin();
 
1819
    setLogicalHeight(logicalHeight() + marginOffset);
 
1820
    positionNewFloats();
 
1821
    setLogicalHeight(logicalHeight() - marginOffset);
 
1822
}
 
1823
 
 
1824
bool RenderBlock::handleSpecialChild(RenderBox* child, const MarginInfo& marginInfo)
 
1825
{
 
1826
    // Handle in the given order
 
1827
    return handlePositionedChild(child, marginInfo)
 
1828
        || handleFloatingChild(child, marginInfo);
 
1829
}
 
1830
 
 
1831
 
 
1832
bool RenderBlock::handlePositionedChild(RenderBox* child, const MarginInfo& marginInfo)
 
1833
{
 
1834
    if (child->isOutOfFlowPositioned()) {
 
1835
        child->containingBlock()->insertPositionedObject(child);
 
1836
        adjustPositionedBlock(child, marginInfo);
 
1837
        return true;
 
1838
    }
 
1839
    return false;
 
1840
}
 
1841
 
 
1842
bool RenderBlock::handleFloatingChild(RenderBox* child, const MarginInfo& marginInfo)
 
1843
{
 
1844
    if (child->isFloating()) {
 
1845
        insertFloatingObject(child);
 
1846
        adjustFloatingBlock(marginInfo);
 
1847
        return true;
 
1848
    }
 
1849
    return false;
 
1850
}
 
1851
 
 
1852
static void destroyRunIn(RenderBoxModelObject* runIn)
 
1853
{
 
1854
    ASSERT(runIn->isRunIn());
 
1855
    ASSERT(!runIn->firstChild());
 
1856
 
 
1857
    // Delete our line box tree. This is needed as our children got moved
 
1858
    // and our line box tree is no longer valid.
 
1859
    if (runIn->isRenderBlock())
 
1860
        toRenderBlock(runIn)->deleteLineBoxTree();
 
1861
    else if (runIn->isRenderInline())
 
1862
        toRenderInline(runIn)->deleteLineBoxTree();
 
1863
    else
 
1864
        ASSERT_NOT_REACHED();
 
1865
 
 
1866
    runIn->destroy();
 
1867
}
 
1868
 
 
1869
void RenderBlock::placeRunInIfNeeded(RenderObject* newChild, PlaceGeneratedRunInFlag flag)
 
1870
{
 
1871
    if (newChild->isRunIn() && (flag == PlaceGeneratedRunIn || !newChild->isBeforeOrAfterContent()))
 
1872
        moveRunInUnderSiblingBlockIfNeeded(newChild);
 
1873
    else if (RenderObject* prevSibling = newChild->previousSibling()) {
 
1874
        if (prevSibling->isRunIn() && (flag == PlaceGeneratedRunIn || !newChild->isBeforeOrAfterContent()))
 
1875
            moveRunInUnderSiblingBlockIfNeeded(prevSibling);
 
1876
    }
 
1877
}
 
1878
 
 
1879
RenderBoxModelObject* RenderBlock::createReplacementRunIn(RenderBoxModelObject* runIn)
 
1880
{
 
1881
    ASSERT(runIn->isRunIn());
 
1882
 
 
1883
    // First we destroy any :before/:after content. It will be regenerated by the new run-in.
 
1884
    // Exception is if the run-in itself is generated.
 
1885
    if (runIn->style()->styleType() != BEFORE && runIn->style()->styleType() != AFTER) {
 
1886
        RenderObject* generatedContent;
 
1887
        if (runIn->getCachedPseudoStyle(BEFORE) && (generatedContent = runIn->beforePseudoElementRenderer()))
 
1888
            generatedContent->destroy();
 
1889
        if (runIn->getCachedPseudoStyle(AFTER) && (generatedContent = runIn->afterPseudoElementRenderer()))
 
1890
            generatedContent->destroy();
 
1891
    }
 
1892
 
 
1893
    bool newRunInShouldBeBlock = !runIn->isRenderBlock();
 
1894
    Node* runInNode = runIn->node();
 
1895
    RenderBoxModelObject* newRunIn = 0;
 
1896
    if (newRunInShouldBeBlock)
 
1897
        newRunIn = new (renderArena()) RenderBlock(runInNode ? runInNode : document());
 
1898
    else
 
1899
        newRunIn = new (renderArena()) RenderInline(runInNode ? runInNode : document());
 
1900
    newRunIn->setStyle(runIn->style());
 
1901
 
 
1902
    runIn->moveAllChildrenTo(newRunIn, true);
 
1903
 
 
1904
    // If the run-in had an element, we need to set the new renderer.
 
1905
    if (runInNode)
 
1906
        runInNode->setRenderer(newRunIn);
 
1907
 
 
1908
    return newRunIn;
 
1909
}
 
1910
 
 
1911
void RenderBlock::moveRunInUnderSiblingBlockIfNeeded(RenderObject* runIn)
 
1912
{
 
1913
    ASSERT(runIn->isRunIn());
 
1914
 
 
1915
    // See if we have inline children. If the children aren't inline,
 
1916
    // then just treat the run-in as a normal block.
 
1917
    if (!runIn->childrenInline())
 
1918
        return;
 
1919
 
 
1920
    // FIXME: We don't handle non-block elements with run-in for now.
 
1921
    if (!runIn->isRenderBlock())
 
1922
        return;
 
1923
 
 
1924
    // FIXME: We don't support run-ins with or as part of a continuation
 
1925
    // as it makes the back-and-forth placing complex.
 
1926
    if (runIn->isElementContinuation() || runIn->virtualContinuation())
 
1927
        return;
 
1928
 
 
1929
    // Check if this node is allowed to run-in. E.g. <select> expects its renderer to
 
1930
    // be a RenderListBox or RenderMenuList, and hence cannot be a RenderInline run-in.
 
1931
    if (!runIn->canBeReplacedWithInlineRunIn())
 
1932
        return;
 
1933
 
 
1934
    RenderObject* curr = runIn->nextSibling();
 
1935
    if (!curr || !curr->isRenderBlock() || !curr->childrenInline())
 
1936
        return;
 
1937
 
 
1938
    // Per CSS3, "A run-in cannot run in to a block that already starts with a
 
1939
    // run-in or that itself is a run-in".
 
1940
    if (curr->isRunIn() || (curr->firstChild() && curr->firstChild()->isRunIn()))
 
1941
        return;
 
1942
 
 
1943
    if (curr->isAnonymous() || curr->isFloatingOrOutOfFlowPositioned())
 
1944
        return;
 
1945
 
 
1946
    RenderBoxModelObject* oldRunIn = toRenderBoxModelObject(runIn);
 
1947
    RenderBoxModelObject* newRunIn = createReplacementRunIn(oldRunIn);
 
1948
    destroyRunIn(oldRunIn);
 
1949
 
 
1950
    // Now insert the new child under |curr| block. Use addChild instead of insertChildNode
 
1951
    // since it handles correct placement of the children, especially where we cannot insert
 
1952
    // anything before the first child. e.g. details tag. See https://bugs.webkit.org/show_bug.cgi?id=58228.
 
1953
    curr->addChild(newRunIn, curr->firstChild());
 
1954
 
 
1955
    // Make sure that |this| get a layout since its run-in child moved.
 
1956
    curr->setNeedsLayoutAndPrefWidthsRecalc();
 
1957
}
 
1958
 
 
1959
bool RenderBlock::runInIsPlacedIntoSiblingBlock(RenderObject* runIn)
 
1960
{
 
1961
    ASSERT(runIn->isRunIn());
 
1962
 
 
1963
    // If we don't have a parent, we can't be moved into our sibling block.
 
1964
    if (!parent())
 
1965
        return false;
 
1966
 
 
1967
    // An intruded run-in needs to be an inline.
 
1968
    if (!runIn->isRenderInline())
 
1969
        return false;
 
1970
 
 
1971
    return true;
 
1972
}
 
1973
 
 
1974
void RenderBlock::moveRunInToOriginalPosition(RenderObject* runIn)
 
1975
{
 
1976
    ASSERT(runIn->isRunIn());
 
1977
 
 
1978
    if (!runInIsPlacedIntoSiblingBlock(runIn))
 
1979
        return;
 
1980
 
 
1981
    // FIXME: Run-in that are now placed in sibling block can break up into continuation
 
1982
    // chains when new children are added to it. We cannot easily send them back to their
 
1983
    // original place since that requires writing integration logic with RenderInline::addChild
 
1984
    // and all other places that might cause continuations to be created (without blowing away
 
1985
    // |this|). Disabling this feature for now to prevent crashes.
 
1986
    if (runIn->isElementContinuation() || runIn->virtualContinuation())
 
1987
        return;
 
1988
 
 
1989
    RenderBoxModelObject* oldRunIn = toRenderBoxModelObject(runIn);
 
1990
    RenderBoxModelObject* newRunIn = createReplacementRunIn(oldRunIn);
 
1991
    destroyRunIn(oldRunIn);
 
1992
 
 
1993
    // Add the run-in block as our previous sibling.
 
1994
    parent()->addChild(newRunIn, this);
 
1995
 
 
1996
    // Make sure that the parent holding the new run-in gets layout.
 
1997
    parent()->setNeedsLayoutAndPrefWidthsRecalc();
 
1998
}
 
1999
 
 
2000
LayoutUnit RenderBlock::collapseMargins(RenderBox* child, MarginInfo& marginInfo)
 
2001
{
 
2002
    // Get the four margin values for the child and cache them.
 
2003
    const MarginValues childMargins = marginValuesForChild(child);
 
2004
 
 
2005
    // Get our max pos and neg top margins.
 
2006
    LayoutUnit posTop = childMargins.positiveMarginBefore();
 
2007
    LayoutUnit negTop = childMargins.negativeMarginBefore();
 
2008
 
 
2009
    // For self-collapsing blocks, collapse our bottom margins into our
 
2010
    // top to get new posTop and negTop values.
 
2011
    if (child->isSelfCollapsingBlock()) {
 
2012
        posTop = max(posTop, childMargins.positiveMarginAfter());
 
2013
        negTop = max(negTop, childMargins.negativeMarginAfter());
 
2014
    }
 
2015
    
 
2016
    // See if the top margin is quirky. We only care if this child has
 
2017
    // margins that will collapse with us.
 
2018
    bool topQuirk = child->isMarginBeforeQuirk() || style()->marginBeforeCollapse() == MDISCARD;
 
2019
 
 
2020
    if (marginInfo.canCollapseWithMarginBefore()) {
 
2021
        // This child is collapsing with the top of the
 
2022
        // block.  If it has larger margin values, then we need to update
 
2023
        // our own maximal values.
 
2024
        if (!document()->inQuirksMode() || !marginInfo.quirkContainer() || !topQuirk)
 
2025
            setMaxMarginBeforeValues(max(posTop, maxPositiveMarginBefore()), max(negTop, maxNegativeMarginBefore()));
 
2026
 
 
2027
        // The minute any of the margins involved isn't a quirk, don't
 
2028
        // collapse it away, even if the margin is smaller (www.webreference.com
 
2029
        // has an example of this, a <dt> with 0.8em author-specified inside
 
2030
        // a <dl> inside a <td>.
 
2031
        if (!marginInfo.determinedMarginBeforeQuirk() && !topQuirk && (posTop - negTop)) {
 
2032
            setMarginBeforeQuirk(false);
 
2033
            marginInfo.setDeterminedMarginBeforeQuirk(true);
 
2034
        }
 
2035
 
 
2036
        if (!marginInfo.determinedMarginBeforeQuirk() && topQuirk && !marginBefore())
 
2037
            // We have no top margin and our top child has a quirky margin.
 
2038
            // We will pick up this quirky margin and pass it through.
 
2039
            // This deals with the <td><div><p> case.
 
2040
            // Don't do this for a block that split two inlines though.  You do
 
2041
            // still apply margins in this case.
 
2042
            setMarginBeforeQuirk(true);
 
2043
    }
 
2044
 
 
2045
    if (marginInfo.quirkContainer() && marginInfo.atBeforeSideOfBlock() && (posTop - negTop))
 
2046
        marginInfo.setMarginBeforeQuirk(topQuirk);
 
2047
 
 
2048
    LayoutUnit beforeCollapseLogicalTop = logicalHeight();
 
2049
    LayoutUnit logicalTop = beforeCollapseLogicalTop;
 
2050
    if (child->isSelfCollapsingBlock()) {
 
2051
        // This child has no height.  We need to compute our
 
2052
        // position before we collapse the child's margins together,
 
2053
        // so that we can get an accurate position for the zero-height block.
 
2054
        LayoutUnit collapsedBeforePos = max(marginInfo.positiveMargin(), childMargins.positiveMarginBefore());
 
2055
        LayoutUnit collapsedBeforeNeg = max(marginInfo.negativeMargin(), childMargins.negativeMarginBefore());
 
2056
        marginInfo.setMargin(collapsedBeforePos, collapsedBeforeNeg);
 
2057
        
 
2058
        // Now collapse the child's margins together, which means examining our
 
2059
        // bottom margin values as well. 
 
2060
        marginInfo.setPositiveMarginIfLarger(childMargins.positiveMarginAfter());
 
2061
        marginInfo.setNegativeMarginIfLarger(childMargins.negativeMarginAfter());
 
2062
 
 
2063
        if (!marginInfo.canCollapseWithMarginBefore())
 
2064
            // We need to make sure that the position of the self-collapsing block
 
2065
            // is correct, since it could have overflowing content
 
2066
            // that needs to be positioned correctly (e.g., a block that
 
2067
            // had a specified height of 0 but that actually had subcontent).
 
2068
            logicalTop = logicalHeight() + collapsedBeforePos - collapsedBeforeNeg;
 
2069
    }
 
2070
    else {
 
2071
        if (child->style()->marginBeforeCollapse() == MSEPARATE) {
 
2072
            setLogicalHeight(logicalHeight() + marginInfo.margin() + marginBeforeForChild(child));
 
2073
            logicalTop = logicalHeight();
 
2074
        }
 
2075
        else if (!marginInfo.atBeforeSideOfBlock() ||
 
2076
            (!marginInfo.canCollapseMarginBeforeWithChildren()
 
2077
             && (!document()->inQuirksMode() || !marginInfo.quirkContainer() || !marginInfo.marginBeforeQuirk()))) {
 
2078
            // We're collapsing with a previous sibling's margins and not
 
2079
            // with the top of the block.
 
2080
            setLogicalHeight(logicalHeight() + max(marginInfo.positiveMargin(), posTop) - max(marginInfo.negativeMargin(), negTop));
 
2081
            logicalTop = logicalHeight();
 
2082
        }
 
2083
 
 
2084
        marginInfo.setPositiveMargin(childMargins.positiveMarginAfter());
 
2085
        marginInfo.setNegativeMargin(childMargins.negativeMarginAfter());
 
2086
 
 
2087
        if (marginInfo.margin())
 
2088
            marginInfo.setMarginAfterQuirk(child->isMarginAfterQuirk() || style()->marginAfterCollapse() == MDISCARD);
 
2089
    }
 
2090
    
 
2091
    // If margins would pull us past the top of the next page, then we need to pull back and pretend like the margins
 
2092
    // collapsed into the page edge.
 
2093
    LayoutState* layoutState = view()->layoutState();
 
2094
    if (layoutState->isPaginated() && layoutState->pageLogicalHeight() && logicalTop > beforeCollapseLogicalTop
 
2095
        && hasNextPage(beforeCollapseLogicalTop)) {
 
2096
        LayoutUnit oldLogicalTop = logicalTop;
 
2097
        logicalTop = min(logicalTop, nextPageLogicalTop(beforeCollapseLogicalTop));
 
2098
        setLogicalHeight(logicalHeight() + (logicalTop - oldLogicalTop));
 
2099
    }
 
2100
 
 
2101
    // If we have collapsed into a previous sibling and so reduced the height of the parent, ensure any floats that now
 
2102
    // overhang from the previous sibling are added to our parent. If the child's previous sibling itself is a float the child will avoid
 
2103
    // or clear it anyway, so don't worry about any floating children it may contain.
 
2104
    RenderObject* prev = child->previousSibling();
 
2105
    if (prev && prev->isBlockFlow() && !prev->isFloatingOrOutOfFlowPositioned()) {
 
2106
        RenderBlock* block = toRenderBlock(prev);
 
2107
        if (block->containsFloats() && !block->avoidsFloats() && (block->logicalTop() + block->lowestFloatLogicalBottom()) > logicalTop) 
 
2108
            addOverhangingFloats(block, false);
 
2109
    }
 
2110
 
 
2111
    return logicalTop;
 
2112
}
 
2113
 
 
2114
LayoutUnit RenderBlock::clearFloatsIfNeeded(RenderBox* child, MarginInfo& marginInfo, LayoutUnit oldTopPosMargin, LayoutUnit oldTopNegMargin, LayoutUnit yPos)
 
2115
{
 
2116
    LayoutUnit heightIncrease = getClearDelta(child, yPos);
 
2117
    if (!heightIncrease)
 
2118
        return yPos;
 
2119
 
 
2120
    if (child->isSelfCollapsingBlock()) {
 
2121
        // For self-collapsing blocks that clear, they can still collapse their
 
2122
        // margins with following siblings.  Reset the current margins to represent
 
2123
        // the self-collapsing block's margins only.
 
2124
        MarginValues childMargins = marginValuesForChild(child);
 
2125
        marginInfo.setPositiveMargin(max(childMargins.positiveMarginBefore(), childMargins.positiveMarginAfter()));
 
2126
        marginInfo.setNegativeMargin(max(childMargins.negativeMarginBefore(), childMargins.negativeMarginAfter()));
 
2127
 
 
2128
        // CSS2.1 states:
 
2129
        // "If the top and bottom margins of an element with clearance are adjoining, its margins collapse with 
 
2130
        // the adjoining margins of following siblings but that resulting margin does not collapse with the bottom margin of the parent block."
 
2131
        // So the parent's bottom margin cannot collapse through this block or any subsequent self-collapsing blocks. Check subsequent siblings
 
2132
        // for a block with height - if none is found then don't allow the margins to collapse with the parent.
 
2133
        bool wouldCollapseMarginsWithParent = marginInfo.canCollapseMarginAfterWithChildren();
 
2134
        for (RenderBox* curr = child->nextSiblingBox(); curr && wouldCollapseMarginsWithParent; curr = curr->nextSiblingBox()) {
 
2135
            if (!curr->isFloatingOrOutOfFlowPositioned() && !curr->isSelfCollapsingBlock())
 
2136
                wouldCollapseMarginsWithParent = false;
 
2137
        }
 
2138
        if (wouldCollapseMarginsWithParent)
 
2139
            marginInfo.setCanCollapseMarginAfterWithChildren(false);
 
2140
 
 
2141
        // CSS2.1: "the amount of clearance is set so that clearance + margin-top = [height of float], i.e., clearance = [height of float] - margin-top"
 
2142
        // Move the top of the child box to the bottom of the float ignoring the child's top margin.
 
2143
        LayoutUnit collapsedMargin = collapsedMarginBeforeForChild(child);
 
2144
        setLogicalHeight(child->logicalTop() - collapsedMargin);
 
2145
        heightIncrease -= collapsedMargin;
 
2146
    } else
 
2147
        // Increase our height by the amount we had to clear.
 
2148
        setLogicalHeight(logicalHeight() + heightIncrease);
 
2149
    
 
2150
    if (marginInfo.canCollapseWithMarginBefore()) {
 
2151
        // We can no longer collapse with the top of the block since a clear
 
2152
        // occurred.  The empty blocks collapse into the cleared block.
 
2153
        // FIXME: This isn't quite correct.  Need clarification for what to do
 
2154
        // if the height the cleared block is offset by is smaller than the
 
2155
        // margins involved.
 
2156
        setMaxMarginBeforeValues(oldTopPosMargin, oldTopNegMargin);
 
2157
        marginInfo.setAtBeforeSideOfBlock(false);
 
2158
    }
 
2159
 
 
2160
    LayoutUnit logicalTop = yPos + heightIncrease;
 
2161
    // After margin collapsing, one of our floats may now intrude into the child. If the child doesn't contain floats of its own it
 
2162
    // won't get picked up for relayout even though the logical top estimate was wrong - so add the newly intruding float now.
 
2163
    if (containsFloats() && child->isRenderBlock() && !toRenderBlock(child)->containsFloats() && !child->avoidsFloats() && lowestFloatLogicalBottom() > logicalTop)
 
2164
        toRenderBlock(child)->addIntrudingFloats(this, logicalLeftOffsetForContent(), logicalTop);
 
2165
 
 
2166
    return logicalTop;
 
2167
}
 
2168
 
 
2169
void RenderBlock::marginBeforeEstimateForChild(RenderBox* child, LayoutUnit& positiveMarginBefore, LayoutUnit& negativeMarginBefore) const
 
2170
{
 
2171
    // FIXME: We should deal with the margin-collapse-* style extensions that prevent collapsing and that discard margins.
 
2172
    // Give up if in quirks mode and we're a body/table cell and the top margin of the child box is quirky.
 
2173
    if (document()->inQuirksMode() && child->isMarginBeforeQuirk() && (isTableCell() || isBody()))
 
2174
        return;
 
2175
 
 
2176
    LayoutUnit beforeChildMargin = marginBeforeForChild(child);
 
2177
    positiveMarginBefore = max(positiveMarginBefore, beforeChildMargin);
 
2178
    negativeMarginBefore = max(negativeMarginBefore, -beforeChildMargin);
 
2179
 
 
2180
    if (!child->isRenderBlock())
 
2181
        return;
 
2182
    
 
2183
    RenderBlock* childBlock = toRenderBlock(child);
 
2184
    if (childBlock->childrenInline() || childBlock->isWritingModeRoot())
 
2185
        return;
 
2186
 
 
2187
    MarginInfo childMarginInfo(childBlock, childBlock->borderBefore() + childBlock->paddingBefore(), childBlock->borderAfter() + childBlock->paddingAfter());
 
2188
    if (!childMarginInfo.canCollapseMarginBeforeWithChildren())
 
2189
        return;
 
2190
 
 
2191
    RenderBox* grandchildBox = childBlock->firstChildBox();
 
2192
    for ( ; grandchildBox; grandchildBox = grandchildBox->nextSiblingBox()) {
 
2193
        if (!grandchildBox->isFloatingOrOutOfFlowPositioned())
 
2194
            break;
 
2195
    }
 
2196
    
 
2197
    // Give up if there is clearance on the box, since it probably won't collapse into us.
 
2198
    if (!grandchildBox || grandchildBox->style()->clear() != CNONE)
 
2199
        return;
 
2200
 
 
2201
    // Make sure to update the block margins now for the grandchild box so that we're looking at current values.
 
2202
    if (grandchildBox->needsLayout()) {
 
2203
        grandchildBox->computeAndSetBlockDirectionMargins(this);
 
2204
        grandchildBox->setMarginBeforeQuirk(grandchildBox->style()->marginBefore().quirk());
 
2205
        grandchildBox->setMarginAfterQuirk(grandchildBox->style()->marginAfter().quirk());
 
2206
    }
 
2207
 
 
2208
    // Collapse the margin of the grandchild box with our own to produce an estimate.
 
2209
    childBlock->marginBeforeEstimateForChild(grandchildBox, positiveMarginBefore, negativeMarginBefore);
 
2210
}
 
2211
 
 
2212
LayoutUnit RenderBlock::estimateLogicalTopPosition(RenderBox* child, const MarginInfo& marginInfo, LayoutUnit& estimateWithoutPagination)
 
2213
{
 
2214
    // FIXME: We need to eliminate the estimation of vertical position, because when it's wrong we sometimes trigger a pathological
 
2215
    // relayout if there are intruding floats.
 
2216
    LayoutUnit logicalTopEstimate = logicalHeight();
 
2217
    if (!marginInfo.canCollapseWithMarginBefore()) {
 
2218
        LayoutUnit positiveMarginBefore = 0;
 
2219
        LayoutUnit negativeMarginBefore = 0;
 
2220
        if (child->selfNeedsLayout()) {
 
2221
            // Try to do a basic estimation of how the collapse is going to go.
 
2222
            marginBeforeEstimateForChild(child, positiveMarginBefore, negativeMarginBefore);
 
2223
        } else {
 
2224
            // Use the cached collapsed margin values from a previous layout. Most of the time they
 
2225
            // will be right.
 
2226
            MarginValues marginValues = marginValuesForChild(child);
 
2227
            positiveMarginBefore = max(positiveMarginBefore, marginValues.positiveMarginBefore());
 
2228
            negativeMarginBefore = max(negativeMarginBefore, marginValues.negativeMarginBefore());
 
2229
        }
 
2230
 
 
2231
        // Collapse the result with our current margins.
 
2232
        logicalTopEstimate += max(marginInfo.positiveMargin(), positiveMarginBefore) - max(marginInfo.negativeMargin(), negativeMarginBefore);
 
2233
    }
 
2234
 
 
2235
    // Adjust logicalTopEstimate down to the next page if the margins are so large that we don't fit on the current
 
2236
    // page.
 
2237
    LayoutState* layoutState = view()->layoutState();
 
2238
    if (layoutState->isPaginated() && layoutState->pageLogicalHeight() && logicalTopEstimate > logicalHeight()
 
2239
        && hasNextPage(logicalHeight()))
 
2240
        logicalTopEstimate = min(logicalTopEstimate, nextPageLogicalTop(logicalHeight()));
 
2241
 
 
2242
    logicalTopEstimate += getClearDelta(child, logicalTopEstimate);
 
2243
    
 
2244
    estimateWithoutPagination = logicalTopEstimate;
 
2245
 
 
2246
    if (layoutState->isPaginated()) {
 
2247
        // If the object has a page or column break value of "before", then we should shift to the top of the next page.
 
2248
        logicalTopEstimate = applyBeforeBreak(child, logicalTopEstimate);
 
2249
    
 
2250
        // For replaced elements and scrolled elements, we want to shift them to the next page if they don't fit on the current one.
 
2251
        logicalTopEstimate = adjustForUnsplittableChild(child, logicalTopEstimate);
 
2252
        
 
2253
        if (!child->selfNeedsLayout() && child->isRenderBlock())
 
2254
            logicalTopEstimate += toRenderBlock(child)->paginationStrut();
 
2255
    }
 
2256
 
 
2257
    return logicalTopEstimate;
 
2258
}
 
2259
 
 
2260
LayoutUnit RenderBlock::computeStartPositionDeltaForChildAvoidingFloats(const RenderBox* child, LayoutUnit childMarginStart,
 
2261
    RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage)
 
2262
{
 
2263
    LayoutUnit startPosition = startOffsetForContent(region, offsetFromLogicalTopOfFirstPage);
 
2264
 
 
2265
    // Add in our start margin.
 
2266
    LayoutUnit oldPosition = startPosition + childMarginStart;
 
2267
    LayoutUnit newPosition = oldPosition;
 
2268
 
 
2269
    LayoutUnit blockOffset = logicalTopForChild(child);
 
2270
    if (region)
 
2271
        blockOffset = max(blockOffset, blockOffset + (region->logicalTopForFlowThreadContent() - offsetFromLogicalTopOfFirstPage));
 
2272
 
 
2273
    LayoutUnit startOff = startOffsetForLine(blockOffset, false, region, offsetFromLogicalTopOfFirstPage, logicalHeightForChild(child));
 
2274
 
 
2275
    if (style()->textAlign() != WEBKIT_CENTER && !child->style()->marginStartUsing(style()).isAuto()) {
 
2276
        if (childMarginStart < 0)
 
2277
            startOff += childMarginStart;
 
2278
        newPosition = max(newPosition, startOff); // Let the float sit in the child's margin if it can fit.
 
2279
    } else if (startOff != startPosition)
 
2280
        newPosition = startOff + childMarginStart;
 
2281
 
 
2282
    return newPosition - oldPosition;
 
2283
}
 
2284
 
 
2285
void RenderBlock::determineLogicalLeftPositionForChild(RenderBox* child)
 
2286
{
 
2287
    LayoutUnit startPosition = borderStart() + paddingStart();
 
2288
    if (style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
 
2289
        startPosition -= verticalScrollbarWidth();
 
2290
    LayoutUnit totalAvailableLogicalWidth = borderAndPaddingLogicalWidth() + availableLogicalWidth();
 
2291
 
 
2292
    // Add in our start margin.
 
2293
    LayoutUnit childMarginStart = marginStartForChild(child);
 
2294
    LayoutUnit newPosition = startPosition + childMarginStart;
 
2295
        
 
2296
    // Some objects (e.g., tables, horizontal rules, overflow:auto blocks) avoid floats.  They need
 
2297
    // to shift over as necessary to dodge any floats that might get in the way.
 
2298
    if (child->avoidsFloats() && containsFloats() && !inRenderFlowThread())
 
2299
        newPosition += computeStartPositionDeltaForChildAvoidingFloats(child, marginStartForChild(child));
 
2300
 
 
2301
    setLogicalLeftForChild(child, style()->isLeftToRightDirection() ? newPosition : totalAvailableLogicalWidth - newPosition - logicalWidthForChild(child), ApplyLayoutDelta);
 
2302
}
 
2303
 
 
2304
void RenderBlock::setCollapsedBottomMargin(const MarginInfo& marginInfo)
 
2305
{
 
2306
    if (marginInfo.canCollapseWithMarginAfter() && !marginInfo.canCollapseWithMarginBefore()) {
 
2307
        // Update our max pos/neg bottom margins, since we collapsed our bottom margins
 
2308
        // with our children.
 
2309
        setMaxMarginAfterValues(max(maxPositiveMarginAfter(), marginInfo.positiveMargin()), max(maxNegativeMarginAfter(), marginInfo.negativeMargin()));
 
2310
 
 
2311
        if (!marginInfo.marginAfterQuirk())
 
2312
            setMarginAfterQuirk(false);
 
2313
 
 
2314
        if (marginInfo.marginAfterQuirk() && marginAfter() == 0)
 
2315
            // We have no bottom margin and our last child has a quirky margin.
 
2316
            // We will pick up this quirky margin and pass it through.
 
2317
            // This deals with the <td><div><p> case.
 
2318
            setMarginAfterQuirk(true);
 
2319
    }
 
2320
}
 
2321
 
 
2322
void RenderBlock::handleAfterSideOfBlock(LayoutUnit beforeSide, LayoutUnit afterSide, MarginInfo& marginInfo)
 
2323
{
 
2324
    marginInfo.setAtAfterSideOfBlock(true);
 
2325
 
 
2326
    // If we can't collapse with children then go ahead and add in the bottom margin.
 
2327
    // Don't do this for ordinary anonymous blocks as only the enclosing box should add in
 
2328
    // its margin.
 
2329
    if (!marginInfo.canCollapseWithMarginAfter() && !marginInfo.canCollapseWithMarginBefore()
 
2330
        && (!isAnonymousBlock() || isAnonymousColumnsBlock() || isAnonymousColumnSpanBlock())
 
2331
        && (!document()->inQuirksMode() || !marginInfo.quirkContainer() || !marginInfo.marginAfterQuirk()))
 
2332
        setLogicalHeight(logicalHeight() + marginInfo.margin());
 
2333
        
 
2334
    // Now add in our bottom border/padding.
 
2335
    setLogicalHeight(logicalHeight() + afterSide);
 
2336
 
 
2337
    // Negative margins can cause our height to shrink below our minimal height (border/padding).
 
2338
    // If this happens, ensure that the computed height is increased to the minimal height.
 
2339
    setLogicalHeight(max(logicalHeight(), beforeSide + afterSide));
 
2340
 
 
2341
    // Update our bottom collapsed margin info.
 
2342
    setCollapsedBottomMargin(marginInfo);
 
2343
}
 
2344
 
 
2345
void RenderBlock::setLogicalLeftForChild(RenderBox* child, LayoutUnit logicalLeft, ApplyLayoutDeltaMode applyDelta)
 
2346
{
 
2347
    if (isHorizontalWritingMode()) {
 
2348
        if (applyDelta == ApplyLayoutDelta)
 
2349
            view()->addLayoutDelta(LayoutSize(child->x() - logicalLeft, 0));
 
2350
        child->setX(logicalLeft);
 
2351
    } else {
 
2352
        if (applyDelta == ApplyLayoutDelta)
 
2353
            view()->addLayoutDelta(LayoutSize(0, child->y() - logicalLeft));
 
2354
        child->setY(logicalLeft);
 
2355
    }
 
2356
}
 
2357
 
 
2358
void RenderBlock::setLogicalTopForChild(RenderBox* child, LayoutUnit logicalTop, ApplyLayoutDeltaMode applyDelta)
 
2359
{
 
2360
    if (isHorizontalWritingMode()) {
 
2361
        if (applyDelta == ApplyLayoutDelta)
 
2362
            view()->addLayoutDelta(LayoutSize(0, child->y() - logicalTop));
 
2363
        child->setY(logicalTop);
 
2364
    } else {
 
2365
        if (applyDelta == ApplyLayoutDelta)
 
2366
            view()->addLayoutDelta(LayoutSize(child->x() - logicalTop, 0));
 
2367
        child->setX(logicalTop);
 
2368
    }
 
2369
}
 
2370
 
 
2371
void RenderBlock::layoutBlockChildren(bool relayoutChildren, LayoutUnit& maxFloatLogicalBottom)
 
2372
{
 
2373
    if (gPercentHeightDescendantsMap) {
 
2374
        if (TrackedRendererListHashSet* descendants = gPercentHeightDescendantsMap->get(this)) {
 
2375
            TrackedRendererListHashSet::iterator end = descendants->end();
 
2376
            for (TrackedRendererListHashSet::iterator it = descendants->begin(); it != end; ++it) {
 
2377
                RenderBox* box = *it;
 
2378
                while (box != this) {
 
2379
                    if (box->normalChildNeedsLayout())
 
2380
                        break;
 
2381
                    box->setChildNeedsLayout(true, MarkOnlyThis);
 
2382
                    box = box->containingBlock();
 
2383
                    ASSERT(box);
 
2384
                    if (!box)
 
2385
                        break;
 
2386
                }
 
2387
            }
 
2388
        }
 
2389
    }
 
2390
 
 
2391
    LayoutUnit beforeEdge = borderBefore() + paddingBefore();
 
2392
    LayoutUnit afterEdge = borderAfter() + paddingAfter() + scrollbarLogicalHeight();
 
2393
 
 
2394
    setLogicalHeight(beforeEdge);
 
2395
    
 
2396
    // Lay out our hypothetical grid line as though it occurs at the top of the block.
 
2397
    if (view()->layoutState()->lineGrid() == this)
 
2398
        layoutLineGridBox();
 
2399
 
 
2400
    // The margin struct caches all our current margin collapsing state.  The compact struct caches state when we encounter compacts,
 
2401
    MarginInfo marginInfo(this, beforeEdge, afterEdge);
 
2402
 
 
2403
    // Fieldsets need to find their legend and position it inside the border of the object.
 
2404
    // The legend then gets skipped during normal layout.  The same is true for ruby text.
 
2405
    // It doesn't get included in the normal layout process but is instead skipped.
 
2406
    RenderObject* childToExclude = layoutSpecialExcludedChild(relayoutChildren);
 
2407
 
 
2408
    LayoutUnit previousFloatLogicalBottom = 0;
 
2409
    maxFloatLogicalBottom = 0;
 
2410
 
 
2411
    RenderBox* next = firstChildBox();
 
2412
 
 
2413
    while (next) {
 
2414
        RenderBox* child = next;
 
2415
        next = child->nextSiblingBox();
 
2416
 
 
2417
        if (childToExclude == child)
 
2418
            continue; // Skip this child, since it will be positioned by the specialized subclass (fieldsets and ruby runs).
 
2419
 
 
2420
        // Make sure we layout children if they need it.
 
2421
        // FIXME: Technically percentage height objects only need a relayout if their percentage isn't going to be turned into
 
2422
        // an auto value.  Add a method to determine this, so that we can avoid the relayout.
 
2423
        if (relayoutChildren || (child->hasRelativeLogicalHeight() && !isRenderView()))
 
2424
            child->setChildNeedsLayout(true, MarkOnlyThis);
 
2425
 
 
2426
        // If relayoutChildren is set and the child has percentage padding or an embedded content box, we also need to invalidate the childs pref widths.
 
2427
        if (relayoutChildren && child->needsPreferredWidthsRecalculation())
 
2428
            child->setPreferredLogicalWidthsDirty(true, MarkOnlyThis);
 
2429
 
 
2430
        // Handle the four types of special elements first.  These include positioned content, floating content, compacts and
 
2431
        // run-ins.  When we encounter these four types of objects, we don't actually lay them out as normal flow blocks.
 
2432
        if (handleSpecialChild(child, marginInfo))
 
2433
            continue;
 
2434
 
 
2435
        // Lay out the child.
 
2436
        layoutBlockChild(child, marginInfo, previousFloatLogicalBottom, maxFloatLogicalBottom);
 
2437
    }
 
2438
    
 
2439
    // Now do the handling of the bottom of the block, adding in our bottom border/padding and
 
2440
    // determining the correct collapsed bottom margin information.
 
2441
    handleAfterSideOfBlock(beforeEdge, afterEdge, marginInfo);
 
2442
}
 
2443
 
 
2444
void RenderBlock::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, LayoutUnit& previousFloatLogicalBottom, LayoutUnit& maxFloatLogicalBottom)
 
2445
{
 
2446
    LayoutUnit oldPosMarginBefore = maxPositiveMarginBefore();
 
2447
    LayoutUnit oldNegMarginBefore = maxNegativeMarginBefore();
 
2448
 
 
2449
    // The child is a normal flow object.  Compute the margins we will use for collapsing now.
 
2450
    child->computeAndSetBlockDirectionMargins(this);
 
2451
 
 
2452
    // Do not allow a collapse if the margin-before-collapse style is set to SEPARATE.
 
2453
    RenderStyle* childStyle = child->style();
 
2454
    if (childStyle->marginBeforeCollapse() == MSEPARATE) {
 
2455
        marginInfo.setAtBeforeSideOfBlock(false);
 
2456
        marginInfo.clearMargin();
 
2457
    }
 
2458
 
 
2459
    // Try to guess our correct logical top position.  In most cases this guess will
 
2460
    // be correct.  Only if we're wrong (when we compute the real logical top position)
 
2461
    // will we have to potentially relayout.
 
2462
    LayoutUnit estimateWithoutPagination;
 
2463
    LayoutUnit logicalTopEstimate = estimateLogicalTopPosition(child, marginInfo, estimateWithoutPagination);
 
2464
 
 
2465
    // Cache our old rect so that we can dirty the proper repaint rects if the child moves.
 
2466
    LayoutRect oldRect = child->frameRect();
 
2467
    LayoutUnit oldLogicalTop = logicalTopForChild(child);
 
2468
 
 
2469
#if !ASSERT_DISABLED
 
2470
    LayoutSize oldLayoutDelta = view()->layoutDelta();
 
2471
#endif
 
2472
    // Go ahead and position the child as though it didn't collapse with the top.
 
2473
    setLogicalTopForChild(child, logicalTopEstimate, ApplyLayoutDelta);
 
2474
 
 
2475
    RenderBlock* childRenderBlock = child->isRenderBlock() ? toRenderBlock(child) : 0;
 
2476
    bool markDescendantsWithFloats = false;
 
2477
    if (logicalTopEstimate != oldLogicalTop && !child->avoidsFloats() && childRenderBlock && childRenderBlock->containsFloats())
 
2478
        markDescendantsWithFloats = true;
 
2479
    else if (!child->avoidsFloats() || child->shrinkToAvoidFloats()) {
 
2480
        // If an element might be affected by the presence of floats, then always mark it for
 
2481
        // layout.
 
2482
        LayoutUnit fb = max(previousFloatLogicalBottom, lowestFloatLogicalBottom());
 
2483
        if (fb > logicalTopEstimate)
 
2484
            markDescendantsWithFloats = true;
 
2485
    }
 
2486
 
 
2487
    if (childRenderBlock) {
 
2488
        if (markDescendantsWithFloats)
 
2489
            childRenderBlock->markAllDescendantsWithFloatsForLayout();
 
2490
        if (!child->isWritingModeRoot())
 
2491
            previousFloatLogicalBottom = max(previousFloatLogicalBottom, oldLogicalTop + childRenderBlock->lowestFloatLogicalBottom());
 
2492
    }
 
2493
 
 
2494
    if (!child->needsLayout())
 
2495
        child->markForPaginationRelayoutIfNeeded();
 
2496
 
 
2497
    bool childHadLayout = child->everHadLayout();
 
2498
    bool childNeededLayout = child->needsLayout();
 
2499
    if (childNeededLayout)
 
2500
        child->layout();
 
2501
 
 
2502
    // Cache if we are at the top of the block right now.
 
2503
    bool atBeforeSideOfBlock = marginInfo.atBeforeSideOfBlock();
 
2504
 
 
2505
    // Now determine the correct ypos based off examination of collapsing margin
 
2506
    // values.
 
2507
    LayoutUnit logicalTopBeforeClear = collapseMargins(child, marginInfo);
 
2508
 
 
2509
    // Now check for clear.
 
2510
    LayoutUnit logicalTopAfterClear = clearFloatsIfNeeded(child, marginInfo, oldPosMarginBefore, oldNegMarginBefore, logicalTopBeforeClear);
 
2511
    
 
2512
    bool paginated = view()->layoutState()->isPaginated();
 
2513
    if (paginated)
 
2514
        logicalTopAfterClear = adjustBlockChildForPagination(logicalTopAfterClear, estimateWithoutPagination, child,
 
2515
            atBeforeSideOfBlock && logicalTopBeforeClear == logicalTopAfterClear);
 
2516
 
 
2517
    setLogicalTopForChild(child, logicalTopAfterClear, ApplyLayoutDelta);
 
2518
 
 
2519
    // Now we have a final top position.  See if it really does end up being different from our estimate.
 
2520
    // clearFloatsIfNeeded can also mark the child as needing a layout even though we didn't move. This happens
 
2521
    // when collapseMargins dynamically adds overhanging floats because of a child with negative margins.
 
2522
    if (logicalTopAfterClear != logicalTopEstimate || child->needsLayout()) {
 
2523
        if (child->shrinkToAvoidFloats()) {
 
2524
            // The child's width depends on the line width.
 
2525
            // When the child shifts to clear an item, its width can
 
2526
            // change (because it has more available line width).
 
2527
            // So go ahead and mark the item as dirty.
 
2528
            child->setChildNeedsLayout(true, MarkOnlyThis);
 
2529
        }
 
2530
        
 
2531
        if (childRenderBlock) {
 
2532
            if (!child->avoidsFloats() && childRenderBlock->containsFloats())
 
2533
                childRenderBlock->markAllDescendantsWithFloatsForLayout();
 
2534
            if (!child->needsLayout())
 
2535
                child->markForPaginationRelayoutIfNeeded();
 
2536
        }
 
2537
 
 
2538
        // Our guess was wrong. Make the child lay itself out again.
 
2539
        child->layoutIfNeeded();
 
2540
    }
 
2541
 
 
2542
    // We are no longer at the top of the block if we encounter a non-empty child.  
 
2543
    // This has to be done after checking for clear, so that margins can be reset if a clear occurred.
 
2544
    if (marginInfo.atBeforeSideOfBlock() && !child->isSelfCollapsingBlock())
 
2545
        marginInfo.setAtBeforeSideOfBlock(false);
 
2546
 
 
2547
    // Now place the child in the correct left position
 
2548
    determineLogicalLeftPositionForChild(child);
 
2549
 
 
2550
    // Update our height now that the child has been placed in the correct position.
 
2551
    setLogicalHeight(logicalHeight() + logicalHeightForChild(child));
 
2552
    if (childStyle->marginAfterCollapse() == MSEPARATE) {
 
2553
        setLogicalHeight(logicalHeight() + marginAfterForChild(child));
 
2554
        marginInfo.clearMargin();
 
2555
    }
 
2556
    // If the child has overhanging floats that intrude into following siblings (or possibly out
 
2557
    // of this block), then the parent gets notified of the floats now.
 
2558
    if (childRenderBlock && childRenderBlock->containsFloats())
 
2559
        maxFloatLogicalBottom = max(maxFloatLogicalBottom, addOverhangingFloats(toRenderBlock(child), !childNeededLayout));
 
2560
 
 
2561
    LayoutSize childOffset = child->location() - oldRect.location();
 
2562
    if (childOffset.width() || childOffset.height()) {
 
2563
        view()->addLayoutDelta(childOffset);
 
2564
 
 
2565
        // If the child moved, we have to repaint it as well as any floating/positioned
 
2566
        // descendants.  An exception is if we need a layout.  In this case, we know we're going to
 
2567
        // repaint ourselves (and the child) anyway.
 
2568
        if (childHadLayout && !selfNeedsLayout() && child->checkForRepaintDuringLayout())
 
2569
            child->repaintDuringLayoutIfMoved(oldRect);
 
2570
    }
 
2571
 
 
2572
    if (!childHadLayout && child->checkForRepaintDuringLayout()) {
 
2573
        child->repaint();
 
2574
        child->repaintOverhangingFloats(true);
 
2575
    }
 
2576
 
 
2577
    if (paginated) {
 
2578
        // Check for an after page/column break.
 
2579
        LayoutUnit newHeight = applyAfterBreak(child, logicalHeight(), marginInfo);
 
2580
        if (newHeight != height())
 
2581
            setLogicalHeight(newHeight);
 
2582
    }
 
2583
 
 
2584
    ASSERT(view()->layoutDeltaMatches(oldLayoutDelta));
 
2585
}
 
2586
 
 
2587
void RenderBlock::simplifiedNormalFlowLayout()
 
2588
{
 
2589
    if (childrenInline()) {
 
2590
        ListHashSet<RootInlineBox*> lineBoxes;
 
2591
        for (InlineWalker walker(this); !walker.atEnd(); walker.advance()) {
 
2592
            RenderObject* o = walker.current();
 
2593
            if (!o->isOutOfFlowPositioned() && (o->isReplaced() || o->isFloating())) {
 
2594
                o->layoutIfNeeded();
 
2595
                if (toRenderBox(o)->inlineBoxWrapper()) {
 
2596
                    RootInlineBox* box = toRenderBox(o)->inlineBoxWrapper()->root();
 
2597
                    lineBoxes.add(box);
 
2598
                }
 
2599
            } else if (o->isText() || (o->isRenderInline() && !walker.atEndOfInline()))
 
2600
                o->setNeedsLayout(false);
 
2601
        }
 
2602
 
 
2603
        // FIXME: Glyph overflow will get lost in this case, but not really a big deal.
 
2604
        GlyphOverflowAndFallbackFontsMap textBoxDataMap;                  
 
2605
        for (ListHashSet<RootInlineBox*>::const_iterator it = lineBoxes.begin(); it != lineBoxes.end(); ++it) {
 
2606
            RootInlineBox* box = *it;
 
2607
            box->computeOverflow(box->lineTop(), box->lineBottom(), textBoxDataMap);
 
2608
        }
 
2609
    } else {
 
2610
        for (RenderBox* box = firstChildBox(); box; box = box->nextSiblingBox()) {
 
2611
            if (!box->isOutOfFlowPositioned())
 
2612
                box->layoutIfNeeded();
 
2613
        }
 
2614
    }
 
2615
}
 
2616
 
 
2617
bool RenderBlock::simplifiedLayout()
 
2618
{
 
2619
    if ((!posChildNeedsLayout() && !needsSimplifiedNormalFlowLayout()) || normalChildNeedsLayout() || selfNeedsLayout())
 
2620
        return false;
 
2621
 
 
2622
    LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasColumns() || hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
 
2623
    
 
2624
    if (needsPositionedMovementLayout() && !tryLayoutDoingPositionedMovementOnly())
 
2625
        return false;
 
2626
 
 
2627
    // Lay out positioned descendants or objects that just need to recompute overflow.
 
2628
    if (needsSimplifiedNormalFlowLayout())
 
2629
        simplifiedNormalFlowLayout();
 
2630
 
 
2631
    // Lay out our positioned objects if our positioned child bit is set.
 
2632
    if (posChildNeedsLayout())
 
2633
        layoutPositionedObjects(false);
 
2634
 
 
2635
    // Recompute our overflow information.
 
2636
    // FIXME: We could do better here by computing a temporary overflow object from layoutPositionedObjects and only
 
2637
    // updating our overflow if we either used to have overflow or if the new temporary object has overflow.
 
2638
    // For now just always recompute overflow.  This is no worse performance-wise than the old code that called rightmostPosition and
 
2639
    // lowestPosition on every relayout so it's not a regression.
 
2640
    m_overflow.clear();
 
2641
    computeOverflow(clientLogicalBottom(), true);
 
2642
 
 
2643
    statePusher.pop();
 
2644
    
 
2645
    updateLayerTransform();
 
2646
 
 
2647
    updateScrollInfoAfterLayout();
 
2648
 
 
2649
    setNeedsLayout(false);
 
2650
    return true;
 
2651
}
 
2652
 
 
2653
void RenderBlock::layoutPositionedObjects(bool relayoutChildren)
 
2654
{
 
2655
    TrackedRendererListHashSet* positionedDescendants = positionedObjects();
 
2656
    if (!positionedDescendants)
 
2657
        return;
 
2658
        
 
2659
    if (hasColumns())
 
2660
        view()->layoutState()->clearPaginationInformation(); // Positioned objects are not part of the column flow, so they don't paginate with the columns.
 
2661
 
 
2662
    RenderBox* r;
 
2663
    TrackedRendererListHashSet::iterator end = positionedDescendants->end();
 
2664
    for (TrackedRendererListHashSet::iterator it = positionedDescendants->begin(); it != end; ++it) {
 
2665
        r = *it;
 
2666
        // When a non-positioned block element moves, it may have positioned children that are implicitly positioned relative to the
 
2667
        // non-positioned block.  Rather than trying to detect all of these movement cases, we just always lay out positioned
 
2668
        // objects that are positioned implicitly like this.  Such objects are rare, and so in typical DHTML menu usage (where everything is
 
2669
        // positioned explicitly) this should not incur a performance penalty.
 
2670
        if (relayoutChildren || (r->style()->hasStaticBlockPosition(isHorizontalWritingMode()) && r->parent() != this))
 
2671
            r->setChildNeedsLayout(true, MarkOnlyThis);
 
2672
            
 
2673
        // If relayoutChildren is set and the child has percentage padding or an embedded content box, we also need to invalidate the childs pref widths.
 
2674
        if (relayoutChildren && r->needsPreferredWidthsRecalculation())
 
2675
            r->setPreferredLogicalWidthsDirty(true, MarkOnlyThis);
 
2676
        
 
2677
        if (!r->needsLayout())
 
2678
            r->markForPaginationRelayoutIfNeeded();
 
2679
        
 
2680
        // We don't have to do a full layout.  We just have to update our position. Try that first. If we have shrink-to-fit width
 
2681
        // and we hit the available width constraint, the layoutIfNeeded() will catch it and do a full layout.
 
2682
        if (r->needsPositionedMovementLayoutOnly() && r->tryLayoutDoingPositionedMovementOnly())
 
2683
            r->setNeedsLayout(false);
 
2684
            
 
2685
        // If we are paginated or in a line grid, go ahead and compute a vertical position for our object now.
 
2686
        // If it's wrong we'll lay out again.
 
2687
        LayoutUnit oldLogicalTop = 0;
 
2688
        bool needsBlockDirectionLocationSetBeforeLayout = r->needsLayout() && view()->layoutState()->needsBlockDirectionLocationSetBeforeLayout(); 
 
2689
        if (needsBlockDirectionLocationSetBeforeLayout) {
 
2690
            if (isHorizontalWritingMode() == r->isHorizontalWritingMode())
 
2691
                r->updateLogicalHeight();
 
2692
            else
 
2693
                r->updateLogicalWidth();
 
2694
            oldLogicalTop = logicalTopForChild(r);
 
2695
        }
 
2696
        
 
2697
        r->layoutIfNeeded();
 
2698
 
 
2699
        // Lay out again if our estimate was wrong.
 
2700
        if (needsBlockDirectionLocationSetBeforeLayout && logicalTopForChild(r) != oldLogicalTop) {
 
2701
            r->setChildNeedsLayout(true, MarkOnlyThis);
 
2702
            r->layoutIfNeeded();
 
2703
        }
 
2704
    }
 
2705
    
 
2706
    if (hasColumns())
 
2707
        view()->layoutState()->m_columnInfo = columnInfo(); // FIXME: Kind of gross. We just put this back into the layout state so that pop() will work.
 
2708
}
 
2709
 
 
2710
void RenderBlock::markPositionedObjectsForLayout()
 
2711
{
 
2712
    TrackedRendererListHashSet* positionedDescendants = positionedObjects();
 
2713
    if (positionedDescendants) {
 
2714
        RenderBox* r;
 
2715
        TrackedRendererListHashSet::iterator end = positionedDescendants->end();
 
2716
        for (TrackedRendererListHashSet::iterator it = positionedDescendants->begin(); it != end; ++it) {
 
2717
            r = *it;
 
2718
            r->setChildNeedsLayout(true);
 
2719
        }
 
2720
    }
 
2721
}
 
2722
 
 
2723
void RenderBlock::markForPaginationRelayoutIfNeeded()
 
2724
{
 
2725
    ASSERT(!needsLayout());
 
2726
    if (needsLayout())
 
2727
        return;
 
2728
 
 
2729
    if (view()->layoutState()->pageLogicalHeightChanged() || (view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(this, logicalTop()) != pageLogicalOffset()))
 
2730
        setChildNeedsLayout(true, MarkOnlyThis);
 
2731
}
 
2732
 
 
2733
void RenderBlock::repaintOverhangingFloats(bool paintAllDescendants)
 
2734
{
 
2735
    // Repaint any overhanging floats (if we know we're the one to paint them).
 
2736
    // Otherwise, bail out.
 
2737
    if (!hasOverhangingFloats())
 
2738
        return;
 
2739
 
 
2740
    // FIXME: Avoid disabling LayoutState. At the very least, don't disable it for floats originating
 
2741
    // in this block. Better yet would be to push extra state for the containers of other floats.
 
2742
    LayoutStateDisabler layoutStateDisabler(view());
 
2743
    const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
 
2744
    FloatingObjectSetIterator end = floatingObjectSet.end();
 
2745
    for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
 
2746
        FloatingObject* r = *it;
 
2747
        // Only repaint the object if it is overhanging, is not in its own layer, and
 
2748
        // is our responsibility to paint (m_shouldPaint is set). When paintAllDescendants is true, the latter
 
2749
        // condition is replaced with being a descendant of us.
 
2750
        if (logicalBottomForFloat(r) > logicalHeight() && ((paintAllDescendants && r->m_renderer->isDescendantOf(this)) || r->shouldPaint()) && !r->m_renderer->hasSelfPaintingLayer()) {
 
2751
            r->m_renderer->repaint();
 
2752
            r->m_renderer->repaintOverhangingFloats();
 
2753
        }
 
2754
    }
 
2755
}
 
2756
 
 
2757
void RenderBlock::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
 
2758
{
 
2759
    LayoutPoint adjustedPaintOffset = paintOffset + location();
 
2760
    
 
2761
    PaintPhase phase = paintInfo.phase;
 
2762
 
 
2763
    // Check if we need to do anything at all.
 
2764
    // FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView
 
2765
    // paints the root's background.
 
2766
    if (!isRoot()) {
 
2767
        LayoutRect overflowBox = overflowRectForPaintRejection();
 
2768
        flipForWritingMode(overflowBox);
 
2769
        overflowBox.inflate(maximalOutlineSize(paintInfo.phase));
 
2770
        overflowBox.moveBy(adjustedPaintOffset);
 
2771
        if (!overflowBox.intersects(paintInfo.rect))
 
2772
            return;
 
2773
    }
 
2774
 
 
2775
    bool pushedClip = pushContentsClip(paintInfo, adjustedPaintOffset);
 
2776
    paintObject(paintInfo, adjustedPaintOffset);
 
2777
    if (pushedClip)
 
2778
        popContentsClip(paintInfo, phase, adjustedPaintOffset);
 
2779
 
 
2780
    // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
 
2781
    // z-index.  We paint after we painted the background/border, so that the scrollbars will
 
2782
    // sit above the background/border.
 
2783
    if (hasOverflowClip() && style()->visibility() == VISIBLE && (phase == PaintPhaseBlockBackground || phase == PaintPhaseChildBlockBackground) && paintInfo.shouldPaintWithinRoot(this))
 
2784
        layer()->paintOverflowControls(paintInfo.context, roundedIntPoint(adjustedPaintOffset), paintInfo.rect);
 
2785
}
 
2786
 
 
2787
void RenderBlock::paintColumnRules(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
 
2788
{
 
2789
    if (paintInfo.context->paintingDisabled())
 
2790
        return;
 
2791
 
 
2792
    const Color& ruleColor = style()->visitedDependentColor(CSSPropertyWebkitColumnRuleColor);
 
2793
    bool ruleTransparent = style()->columnRuleIsTransparent();
 
2794
    EBorderStyle ruleStyle = style()->columnRuleStyle();
 
2795
    LayoutUnit ruleThickness = style()->columnRuleWidth();
 
2796
    LayoutUnit colGap = columnGap();
 
2797
    bool renderRule = ruleStyle > BHIDDEN && !ruleTransparent && ruleThickness <= colGap;
 
2798
    if (!renderRule)
 
2799
        return;
 
2800
 
 
2801
    ColumnInfo* colInfo = columnInfo();
 
2802
    unsigned colCount = columnCount(colInfo);
 
2803
 
 
2804
    bool antialias = shouldAntialiasLines(paintInfo.context);
 
2805
 
 
2806
    if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) {
 
2807
        bool leftToRight = style()->isLeftToRightDirection() ^ colInfo->progressionIsReversed();
 
2808
        LayoutUnit currLogicalLeftOffset = leftToRight ? LayoutUnit() : contentLogicalWidth();
 
2809
        LayoutUnit ruleAdd = logicalLeftOffsetForContent();
 
2810
        LayoutUnit ruleLogicalLeft = leftToRight ? LayoutUnit() : contentLogicalWidth();
 
2811
        LayoutUnit inlineDirectionSize = colInfo->desiredColumnWidth();
 
2812
        BoxSide boxSide = isHorizontalWritingMode()
 
2813
            ? leftToRight ? BSLeft : BSRight
 
2814
            : leftToRight ? BSTop : BSBottom;
 
2815
 
 
2816
        for (unsigned i = 0; i < colCount; i++) {
 
2817
            // Move to the next position.
 
2818
            if (leftToRight) {
 
2819
                ruleLogicalLeft += inlineDirectionSize + colGap / 2;
 
2820
                currLogicalLeftOffset += inlineDirectionSize + colGap;
 
2821
            } else {
 
2822
                ruleLogicalLeft -= (inlineDirectionSize + colGap / 2);
 
2823
                currLogicalLeftOffset -= (inlineDirectionSize + colGap);
 
2824
            }
 
2825
           
 
2826
            // Now paint the column rule.
 
2827
            if (i < colCount - 1) {
 
2828
                LayoutUnit ruleLeft = isHorizontalWritingMode() ? paintOffset.x() + ruleLogicalLeft - ruleThickness / 2 + ruleAdd : paintOffset.x() + borderLeft() + paddingLeft();
 
2829
                LayoutUnit ruleRight = isHorizontalWritingMode() ? ruleLeft + ruleThickness : ruleLeft + contentWidth();
 
2830
                LayoutUnit ruleTop = isHorizontalWritingMode() ? paintOffset.y() + borderTop() + paddingTop() : paintOffset.y() + ruleLogicalLeft - ruleThickness / 2 + ruleAdd;
 
2831
                LayoutUnit ruleBottom = isHorizontalWritingMode() ? ruleTop + contentHeight() : ruleTop + ruleThickness;
 
2832
                IntRect pixelSnappedRuleRect = pixelSnappedIntRectFromEdges(ruleLeft, ruleTop, ruleRight, ruleBottom);
 
2833
                drawLineForBoxSide(paintInfo.context, pixelSnappedRuleRect.x(), pixelSnappedRuleRect.y(), pixelSnappedRuleRect.maxX(), pixelSnappedRuleRect.maxY(), boxSide, ruleColor, ruleStyle, 0, 0, antialias);
 
2834
            }
 
2835
            
 
2836
            ruleLogicalLeft = currLogicalLeftOffset;
 
2837
        }
 
2838
    } else {
 
2839
        bool topToBottom = !style()->isFlippedBlocksWritingMode() ^ colInfo->progressionIsReversed();
 
2840
        LayoutUnit ruleLeft = isHorizontalWritingMode()
 
2841
            ? borderLeft() + paddingLeft()
 
2842
            : colGap / 2 - colGap - ruleThickness / 2 + (!colInfo->progressionIsReversed() ? borderBefore() + paddingBefore() : borderAfter() + paddingAfter());
 
2843
        LayoutUnit ruleWidth = isHorizontalWritingMode() ? contentWidth() : ruleThickness;
 
2844
        LayoutUnit ruleTop = isHorizontalWritingMode()
 
2845
            ? colGap / 2 - colGap - ruleThickness / 2 + (!colInfo->progressionIsReversed() ? borderBefore() + paddingBefore() : borderAfter() + paddingAfter())
 
2846
            : borderStart() + paddingStart();
 
2847
        LayoutUnit ruleHeight = isHorizontalWritingMode() ? ruleThickness : contentHeight();
 
2848
        LayoutRect ruleRect(ruleLeft, ruleTop, ruleWidth, ruleHeight);
 
2849
 
 
2850
        if (!topToBottom) {
 
2851
            if (isHorizontalWritingMode())
 
2852
                ruleRect.setY(height() - ruleRect.maxY());
 
2853
            else
 
2854
                ruleRect.setX(width() - ruleRect.maxX());
 
2855
        }
 
2856
 
 
2857
        ruleRect.moveBy(paintOffset);
 
2858
 
 
2859
        BoxSide boxSide = isHorizontalWritingMode()
 
2860
            ? topToBottom ? BSTop : BSBottom
 
2861
            : topToBottom ? BSLeft : BSRight;
 
2862
 
 
2863
        LayoutSize step(0, topToBottom ? colInfo->columnHeight() + colGap : -(colInfo->columnHeight() + colGap));
 
2864
        if (!isHorizontalWritingMode())
 
2865
            step = step.transposedSize();
 
2866
 
 
2867
        for (unsigned i = 1; i < colCount; i++) {
 
2868
            ruleRect.move(step);
 
2869
            IntRect pixelSnappedRuleRect = pixelSnappedIntRect(ruleRect);
 
2870
            drawLineForBoxSide(paintInfo.context, pixelSnappedRuleRect.x(), pixelSnappedRuleRect.y(), pixelSnappedRuleRect.maxX(), pixelSnappedRuleRect.maxY(), boxSide, ruleColor, ruleStyle, 0, 0, antialias);
 
2871
        }
 
2872
    }
 
2873
}
 
2874
 
 
2875
void RenderBlock::paintColumnContents(PaintInfo& paintInfo, const LayoutPoint& paintOffset, bool paintingFloats)
 
2876
{
 
2877
    // We need to do multiple passes, breaking up our child painting into strips.
 
2878
    GraphicsContext* context = paintInfo.context;
 
2879
    ColumnInfo* colInfo = columnInfo();
 
2880
    unsigned colCount = columnCount(colInfo);
 
2881
    if (!colCount)
 
2882
        return;
 
2883
    LayoutUnit currLogicalTopOffset = 0;
 
2884
    LayoutUnit colGap = columnGap();
 
2885
    for (unsigned i = 0; i < colCount; i++) {
 
2886
        // For each rect, we clip to the rect, and then we adjust our coords.
 
2887
        LayoutRect colRect = columnRectAt(colInfo, i);
 
2888
        flipForWritingMode(colRect);
 
2889
        LayoutUnit logicalLeftOffset = (isHorizontalWritingMode() ? colRect.x() : colRect.y()) - logicalLeftOffsetForContent();
 
2890
        LayoutSize offset = isHorizontalWritingMode() ? LayoutSize(logicalLeftOffset, currLogicalTopOffset) : LayoutSize(currLogicalTopOffset, logicalLeftOffset);
 
2891
        if (colInfo->progressionAxis() == ColumnInfo::BlockAxis) {
 
2892
            if (isHorizontalWritingMode())
 
2893
                offset.expand(0, colRect.y() - borderTop() - paddingTop());
 
2894
            else
 
2895
                offset.expand(colRect.x() - borderLeft() - paddingLeft(), 0);
 
2896
        }
 
2897
        colRect.moveBy(paintOffset);
 
2898
        PaintInfo info(paintInfo);
 
2899
        info.rect.intersect(pixelSnappedIntRect(colRect));
 
2900
        
 
2901
        if (!info.rect.isEmpty()) {
 
2902
            GraphicsContextStateSaver stateSaver(*context);
 
2903
            LayoutRect clipRect(colRect);
 
2904
            
 
2905
            if (i < colCount - 1) {
 
2906
                if (isHorizontalWritingMode())
 
2907
                    clipRect.expand(colGap / 2, 0);
 
2908
                else
 
2909
                    clipRect.expand(0, colGap / 2);
 
2910
            }
 
2911
            // Each strip pushes a clip, since column boxes are specified as being
 
2912
            // like overflow:hidden.
 
2913
            // FIXME: Content and column rules that extend outside column boxes at the edges of the multi-column element
 
2914
            // are clipped according to the 'overflow' property.
 
2915
            context->clip(pixelSnappedIntRect(clipRect));
 
2916
 
 
2917
            // Adjust our x and y when painting.
 
2918
            LayoutPoint adjustedPaintOffset = paintOffset + offset;
 
2919
            if (paintingFloats)
 
2920
                paintFloats(info, adjustedPaintOffset, paintInfo.phase == PaintPhaseSelection || paintInfo.phase == PaintPhaseTextClip);
 
2921
            else
 
2922
                paintContents(info, adjustedPaintOffset);
 
2923
        }
 
2924
 
 
2925
        LayoutUnit blockDelta = (isHorizontalWritingMode() ? colRect.height() : colRect.width());
 
2926
        if (style()->isFlippedBlocksWritingMode())
 
2927
            currLogicalTopOffset += blockDelta;
 
2928
        else
 
2929
            currLogicalTopOffset -= blockDelta;
 
2930
    }
 
2931
}
 
2932
 
 
2933
void RenderBlock::paintContents(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
 
2934
{
 
2935
    // Avoid painting descendants of the root element when stylesheets haven't loaded.  This eliminates FOUC.
 
2936
    // It's ok not to draw, because later on, when all the stylesheets do load, updateStyleSelector on the Document
 
2937
    // will do a full repaint().
 
2938
    if (document()->didLayoutWithPendingStylesheets() && !isRenderView())
 
2939
        return;
 
2940
 
 
2941
    if (childrenInline())
 
2942
        m_lineBoxes.paint(this, paintInfo, paintOffset);
 
2943
    else {
 
2944
        PaintPhase newPhase = (paintInfo.phase == PaintPhaseChildOutlines) ? PaintPhaseOutline : paintInfo.phase;
 
2945
        newPhase = (newPhase == PaintPhaseChildBlockBackgrounds) ? PaintPhaseChildBlockBackground : newPhase;
 
2946
 
 
2947
        // We don't paint our own background, but we do let the kids paint their backgrounds.
 
2948
        PaintInfo paintInfoForChild(paintInfo);
 
2949
        paintInfoForChild.phase = newPhase;
 
2950
        paintInfoForChild.updatePaintingRootForChildren(this);
 
2951
 
 
2952
        // FIXME: Paint-time pagination is obsolete and is now only used by embedded WebViews inside AppKit
 
2953
        // NSViews. Do not add any more code for this.
 
2954
        bool usePrintRect = !view()->printRect().isEmpty();
 
2955
        paintChildren(paintInfo, paintOffset, paintInfoForChild, usePrintRect);
 
2956
    }
 
2957
}
 
2958
 
 
2959
void RenderBlock::paintChildren(PaintInfo& paintInfo, const LayoutPoint& paintOffset, PaintInfo& paintInfoForChild, bool usePrintRect)
 
2960
{
 
2961
    for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
 
2962
        if (!paintChild(child, paintInfo, paintOffset, paintInfoForChild, usePrintRect))
 
2963
            return;
 
2964
    }
 
2965
}
 
2966
 
 
2967
bool RenderBlock::paintChild(RenderBox* child, PaintInfo& paintInfo, const LayoutPoint& paintOffset, PaintInfo& paintInfoForChild, bool usePrintRect)
 
2968
{
 
2969
    // Check for page-break-before: always, and if it's set, break and bail.
 
2970
    bool checkBeforeAlways = !childrenInline() && (usePrintRect && child->style()->pageBreakBefore() == PBALWAYS);
 
2971
    LayoutUnit absoluteChildY = paintOffset.y() + child->y();
 
2972
    if (checkBeforeAlways
 
2973
        && absoluteChildY > paintInfo.rect.y()
 
2974
        && absoluteChildY < paintInfo.rect.maxY()) {
 
2975
        view()->setBestTruncatedAt(absoluteChildY, this, true);
 
2976
        return false;
 
2977
    }
 
2978
 
 
2979
    RenderView* renderView = view();
 
2980
    if (!child->isFloating() && child->isReplaced() && usePrintRect && child->height() <= renderView->printRect().height()) {
 
2981
        // Paginate block-level replaced elements.
 
2982
        if (absoluteChildY + child->height() > renderView->printRect().maxY()) {
 
2983
            if (absoluteChildY < renderView->truncatedAt())
 
2984
                renderView->setBestTruncatedAt(absoluteChildY, child);
 
2985
            // If we were able to truncate, don't paint.
 
2986
            if (absoluteChildY >= renderView->truncatedAt())
 
2987
                return false;
 
2988
        }
 
2989
    }
 
2990
 
 
2991
    LayoutPoint childPoint = flipForWritingModeForChild(child, paintOffset);
 
2992
    if (!child->hasSelfPaintingLayer() && !child->isFloating())
 
2993
        child->paint(paintInfoForChild, childPoint);
 
2994
 
 
2995
    // Check for page-break-after: always, and if it's set, break and bail.
 
2996
    bool checkAfterAlways = !childrenInline() && (usePrintRect && child->style()->pageBreakAfter() == PBALWAYS);
 
2997
    if (checkAfterAlways
 
2998
        && (absoluteChildY + child->height()) > paintInfo.rect.y()
 
2999
        && (absoluteChildY + child->height()) < paintInfo.rect.maxY()) {
 
3000
        view()->setBestTruncatedAt(absoluteChildY + child->height() + max<LayoutUnit>(0, child->collapsedMarginAfter()), this, true);
 
3001
        return false;
 
3002
    }
 
3003
    return true;
 
3004
}
 
3005
 
 
3006
 
 
3007
void RenderBlock::paintCaret(PaintInfo& paintInfo, const LayoutPoint& paintOffset, CaretType type)
 
3008
{
 
3009
    // Paint the caret if the FrameSelection says so or if caret browsing is enabled
 
3010
    bool caretBrowsing = frame()->settings() && frame()->settings()->caretBrowsingEnabled();
 
3011
    RenderObject* caretPainter;
 
3012
    bool isContentEditable;
 
3013
    if (type == CursorCaret) {
 
3014
        caretPainter = frame()->selection()->caretRenderer();
 
3015
        isContentEditable = frame()->selection()->rendererIsEditable();
 
3016
    } else {
 
3017
        caretPainter = frame()->page()->dragCaretController()->caretRenderer();
 
3018
        isContentEditable = frame()->page()->dragCaretController()->isContentEditable();
 
3019
    }
 
3020
 
 
3021
    if (caretPainter == this && (isContentEditable || caretBrowsing)) {
 
3022
        if (type == CursorCaret)
 
3023
            frame()->selection()->paintCaret(paintInfo.context, paintOffset, paintInfo.rect);
 
3024
        else
 
3025
            frame()->page()->dragCaretController()->paintDragCaret(frame(), paintInfo.context, paintOffset, paintInfo.rect);
 
3026
    }
 
3027
}
 
3028
 
 
3029
void RenderBlock::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
 
3030
{
 
3031
    PaintPhase paintPhase = paintInfo.phase;
 
3032
 
 
3033
    // 1. paint background, borders etc
 
3034
    if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && style()->visibility() == VISIBLE) {
 
3035
        if (hasBoxDecorations())
 
3036
            paintBoxDecorations(paintInfo, paintOffset);
 
3037
        if (hasColumns())
 
3038
            paintColumnRules(paintInfo, paintOffset);
 
3039
    }
 
3040
 
 
3041
    if (paintPhase == PaintPhaseMask && style()->visibility() == VISIBLE) {
 
3042
        paintMask(paintInfo, paintOffset);
 
3043
        return;
 
3044
    }
 
3045
 
 
3046
    // We're done.  We don't bother painting any children.
 
3047
    if (paintPhase == PaintPhaseBlockBackground)
 
3048
        return;
 
3049
 
 
3050
    // Adjust our painting position if we're inside a scrolled layer (e.g., an overflow:auto div).
 
3051
    LayoutPoint scrolledOffset = paintOffset;
 
3052
    if (hasOverflowClip())
 
3053
        scrolledOffset.move(-scrolledContentOffset());
 
3054
 
 
3055
    // 2. paint contents
 
3056
    if (paintPhase != PaintPhaseSelfOutline) {
 
3057
        if (hasColumns())
 
3058
            paintColumnContents(paintInfo, scrolledOffset);
 
3059
        else
 
3060
            paintContents(paintInfo, scrolledOffset);
 
3061
    }
 
3062
 
 
3063
    // 3. paint selection
 
3064
    // FIXME: Make this work with multi column layouts.  For now don't fill gaps.
 
3065
    bool isPrinting = document()->printing();
 
3066
    if (!isPrinting && !hasColumns())
 
3067
        paintSelection(paintInfo, scrolledOffset); // Fill in gaps in selection on lines and between blocks.
 
3068
 
 
3069
    // 4. paint floats.
 
3070
    if (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip) {
 
3071
        if (hasColumns())
 
3072
            paintColumnContents(paintInfo, scrolledOffset, true);
 
3073
        else
 
3074
            paintFloats(paintInfo, scrolledOffset, paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip);
 
3075
    }
 
3076
 
 
3077
    // 5. paint outline.
 
3078
    if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && hasOutline() && style()->visibility() == VISIBLE)
 
3079
        paintOutline(paintInfo.context, LayoutRect(paintOffset, size()));
 
3080
 
 
3081
    // 6. paint continuation outlines.
 
3082
    if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseChildOutlines)) {
 
3083
        RenderInline* inlineCont = inlineElementContinuation();
 
3084
        // FIXME: For now, do not add continuations for outline painting by our containing block if we are a relative positioned
 
3085
        // anonymous block (i.e. have our own layer). This is because a block depends on renderers in its continuation table being
 
3086
        // in the same layer. 
 
3087
        if (inlineCont && inlineCont->hasOutline() && inlineCont->style()->visibility() == VISIBLE && !hasLayer()) {
 
3088
            RenderInline* inlineRenderer = toRenderInline(inlineCont->node()->renderer());
 
3089
            RenderBlock* cb = containingBlock();
 
3090
 
 
3091
            bool inlineEnclosedInSelfPaintingLayer = false;
 
3092
            for (RenderBoxModelObject* box = inlineRenderer; box != cb; box = box->parent()->enclosingBoxModelObject()) {
 
3093
                if (box->hasSelfPaintingLayer()) {
 
3094
                    inlineEnclosedInSelfPaintingLayer = true;
 
3095
                    break;
 
3096
                }
 
3097
            }
 
3098
 
 
3099
            if (!inlineEnclosedInSelfPaintingLayer)
 
3100
                cb->addContinuationWithOutline(inlineRenderer);
 
3101
            else if (!inlineRenderer->firstLineBox())
 
3102
                inlineRenderer->paintOutline(paintInfo.context, paintOffset - locationOffset() + inlineRenderer->containingBlock()->location());
 
3103
        }
 
3104
        paintContinuationOutlines(paintInfo, paintOffset);
 
3105
    }
 
3106
 
 
3107
    // 7. paint caret.
 
3108
    // If the caret's node's render object's containing block is this block, and the paint action is PaintPhaseForeground,
 
3109
    // then paint the caret.
 
3110
    if (paintPhase == PaintPhaseForeground) {        
 
3111
        paintCaret(paintInfo, paintOffset, CursorCaret);
 
3112
        paintCaret(paintInfo, paintOffset, DragCaret);
 
3113
    }
 
3114
}
 
3115
 
 
3116
LayoutPoint RenderBlock::flipFloatForWritingModeForChild(const FloatingObject* child, const LayoutPoint& point) const
 
3117
{
 
3118
    if (!style()->isFlippedBlocksWritingMode())
 
3119
        return point;
 
3120
    
 
3121
    // This is similar to RenderBox::flipForWritingModeForChild. We have to subtract out our left/top offsets twice, since
 
3122
    // it's going to get added back in. We hide this complication here so that the calling code looks normal for the unflipped
 
3123
    // case.
 
3124
    if (isHorizontalWritingMode())
 
3125
        return LayoutPoint(point.x(), point.y() + height() - child->renderer()->height() - 2 * yPositionForFloatIncludingMargin(child));
 
3126
    return LayoutPoint(point.x() + width() - child->width() - 2 * xPositionForFloatIncludingMargin(child), point.y());
 
3127
}
 
3128
 
 
3129
void RenderBlock::paintFloats(PaintInfo& paintInfo, const LayoutPoint& paintOffset, bool preservePhase)
 
3130
{
 
3131
    if (!m_floatingObjects)
 
3132
        return;
 
3133
 
 
3134
    const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
 
3135
    FloatingObjectSetIterator end = floatingObjectSet.end();
 
3136
    for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
 
3137
        FloatingObject* r = *it;
 
3138
        // Only paint the object if our m_shouldPaint flag is set.
 
3139
        if (r->shouldPaint() && !r->m_renderer->hasSelfPaintingLayer()) {
 
3140
            PaintInfo currentPaintInfo(paintInfo);
 
3141
            currentPaintInfo.phase = preservePhase ? paintInfo.phase : PaintPhaseBlockBackground;
 
3142
            LayoutPoint childPoint = flipFloatForWritingModeForChild(r, LayoutPoint(paintOffset.x() + xPositionForFloatIncludingMargin(r) - r->m_renderer->x(), paintOffset.y() + yPositionForFloatIncludingMargin(r) - r->m_renderer->y()));
 
3143
            r->m_renderer->paint(currentPaintInfo, childPoint);
 
3144
            if (!preservePhase) {
 
3145
                currentPaintInfo.phase = PaintPhaseChildBlockBackgrounds;
 
3146
                r->m_renderer->paint(currentPaintInfo, childPoint);
 
3147
                currentPaintInfo.phase = PaintPhaseFloat;
 
3148
                r->m_renderer->paint(currentPaintInfo, childPoint);
 
3149
                currentPaintInfo.phase = PaintPhaseForeground;
 
3150
                r->m_renderer->paint(currentPaintInfo, childPoint);
 
3151
                currentPaintInfo.phase = PaintPhaseOutline;
 
3152
                r->m_renderer->paint(currentPaintInfo, childPoint);
 
3153
            }
 
3154
        }
 
3155
    }
 
3156
}
 
3157
 
 
3158
RenderInline* RenderBlock::inlineElementContinuation() const
 
3159
 
3160
    RenderBoxModelObject* continuation = this->continuation();
 
3161
    return continuation && continuation->isInline() ? toRenderInline(continuation) : 0;
 
3162
}
 
3163
 
 
3164
RenderBlock* RenderBlock::blockElementContinuation() const
 
3165
{
 
3166
    RenderBoxModelObject* currentContinuation = continuation();
 
3167
    if (!currentContinuation || currentContinuation->isInline())
 
3168
        return 0;
 
3169
    RenderBlock* nextContinuation = toRenderBlock(currentContinuation);
 
3170
    if (nextContinuation->isAnonymousBlock())
 
3171
        return nextContinuation->blockElementContinuation();
 
3172
    return nextContinuation;
 
3173
}
 
3174
    
 
3175
static ContinuationOutlineTableMap* continuationOutlineTable()
 
3176
{
 
3177
    DEFINE_STATIC_LOCAL(ContinuationOutlineTableMap, table, ());
 
3178
    return &table;
 
3179
}
 
3180
 
 
3181
void RenderBlock::addContinuationWithOutline(RenderInline* flow)
 
3182
{
 
3183
    // We can't make this work if the inline is in a layer.  We'll just rely on the broken
 
3184
    // way of painting.
 
3185
    ASSERT(!flow->layer() && !flow->isInlineElementContinuation());
 
3186
    
 
3187
    ContinuationOutlineTableMap* table = continuationOutlineTable();
 
3188
    ListHashSet<RenderInline*>* continuations = table->get(this);
 
3189
    if (!continuations) {
 
3190
        continuations = new ListHashSet<RenderInline*>;
 
3191
        table->set(this, continuations);
 
3192
    }
 
3193
    
 
3194
    continuations->add(flow);
 
3195
}
 
3196
 
 
3197
bool RenderBlock::paintsContinuationOutline(RenderInline* flow)
 
3198
{
 
3199
    ContinuationOutlineTableMap* table = continuationOutlineTable();
 
3200
    if (table->isEmpty())
 
3201
        return false;
 
3202
        
 
3203
    ListHashSet<RenderInline*>* continuations = table->get(this);
 
3204
    if (!continuations)
 
3205
        return false;
 
3206
 
 
3207
    return continuations->contains(flow);
 
3208
}
 
3209
 
 
3210
void RenderBlock::paintContinuationOutlines(PaintInfo& info, const LayoutPoint& paintOffset)
 
3211
{
 
3212
    ContinuationOutlineTableMap* table = continuationOutlineTable();
 
3213
    if (table->isEmpty())
 
3214
        return;
 
3215
        
 
3216
    ListHashSet<RenderInline*>* continuations = table->get(this);
 
3217
    if (!continuations)
 
3218
        return;
 
3219
 
 
3220
    LayoutPoint accumulatedPaintOffset = paintOffset;
 
3221
    // Paint each continuation outline.
 
3222
    ListHashSet<RenderInline*>::iterator end = continuations->end();
 
3223
    for (ListHashSet<RenderInline*>::iterator it = continuations->begin(); it != end; ++it) {
 
3224
        // Need to add in the coordinates of the intervening blocks.
 
3225
        RenderInline* flow = *it;
 
3226
        RenderBlock* block = flow->containingBlock();
 
3227
        for ( ; block && block != this; block = block->containingBlock())
 
3228
            accumulatedPaintOffset.moveBy(block->location());
 
3229
        ASSERT(block);   
 
3230
        flow->paintOutline(info.context, accumulatedPaintOffset);
 
3231
    }
 
3232
    
 
3233
    // Delete
 
3234
    delete continuations;
 
3235
    table->remove(this);
 
3236
}
 
3237
 
 
3238
bool RenderBlock::shouldPaintSelectionGaps() const
 
3239
{
 
3240
    return selectionState() != SelectionNone && style()->visibility() == VISIBLE && isSelectionRoot();
 
3241
}
 
3242
 
 
3243
bool RenderBlock::isSelectionRoot() const
 
3244
{
 
3245
    if (!node())
 
3246
        return false;
 
3247
        
 
3248
    // FIXME: Eventually tables should have to learn how to fill gaps between cells, at least in simple non-spanning cases.
 
3249
    if (isTable())
 
3250
        return false;
 
3251
        
 
3252
    if (isBody() || isRoot() || hasOverflowClip()
 
3253
        || isPositioned() || isFloating()
 
3254
        || isTableCell() || isInlineBlockOrInlineTable()
 
3255
        || hasTransform() || hasReflection() || hasMask() || isWritingModeRoot()
 
3256
        || isRenderFlowThread())
 
3257
        return true;
 
3258
    
 
3259
    if (view() && view()->selectionStart()) {
 
3260
        Node* startElement = view()->selectionStart()->node();
 
3261
        if (startElement && startElement->rootEditableElement() == node())
 
3262
            return true;
 
3263
    }
 
3264
    
 
3265
    return false;
 
3266
}
 
3267
 
 
3268
GapRects RenderBlock::selectionGapRectsForRepaint(const RenderLayerModelObject* repaintContainer)
 
3269
{
 
3270
    ASSERT(!needsLayout());
 
3271
 
 
3272
    if (!shouldPaintSelectionGaps())
 
3273
        return GapRects();
 
3274
 
 
3275
    // FIXME: this is broken with transforms
 
3276
    TransformState transformState(TransformState::ApplyTransformDirection, FloatPoint());
 
3277
    mapLocalToContainer(repaintContainer, transformState);
 
3278
    LayoutPoint offsetFromRepaintContainer = roundedLayoutPoint(transformState.mappedPoint());
 
3279
 
 
3280
    if (hasOverflowClip())
 
3281
        offsetFromRepaintContainer -= scrolledContentOffset();
 
3282
 
 
3283
    LayoutUnit lastTop = 0;
 
3284
    LayoutUnit lastLeft = logicalLeftSelectionOffset(this, lastTop);
 
3285
    LayoutUnit lastRight = logicalRightSelectionOffset(this, lastTop);
 
3286
    
 
3287
    return selectionGaps(this, offsetFromRepaintContainer, IntSize(), lastTop, lastLeft, lastRight);
 
3288
}
 
3289
 
 
3290
void RenderBlock::paintSelection(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
 
3291
{
 
3292
    if (shouldPaintSelectionGaps() && paintInfo.phase == PaintPhaseForeground) {
 
3293
        LayoutUnit lastTop = 0;
 
3294
        LayoutUnit lastLeft = logicalLeftSelectionOffset(this, lastTop);
 
3295
        LayoutUnit lastRight = logicalRightSelectionOffset(this, lastTop);
 
3296
        GraphicsContextStateSaver stateSaver(*paintInfo.context);
 
3297
 
 
3298
        LayoutRect gapRectsBounds = selectionGaps(this, paintOffset, LayoutSize(), lastTop, lastLeft, lastRight, &paintInfo);
 
3299
        if (!gapRectsBounds.isEmpty()) {
 
3300
            if (RenderLayer* layer = enclosingLayer()) {
 
3301
                gapRectsBounds.moveBy(-paintOffset);
 
3302
                if (!hasLayer()) {
 
3303
                    LayoutRect localBounds(gapRectsBounds);
 
3304
                    flipForWritingMode(localBounds);
 
3305
                    gapRectsBounds = localToContainerQuad(FloatRect(localBounds), layer->renderer()).enclosingBoundingBox();
 
3306
                    if (layer->renderer()->hasOverflowClip())
 
3307
                        gapRectsBounds.move(layer->renderBox()->scrolledContentOffset());
 
3308
                }
 
3309
                layer->addBlockSelectionGapsBounds(gapRectsBounds);
 
3310
            }
 
3311
        }
 
3312
    }
 
3313
}
 
3314
 
 
3315
static void clipOutPositionedObjects(const PaintInfo* paintInfo, const LayoutPoint& offset, TrackedRendererListHashSet* positionedObjects)
 
3316
{
 
3317
    if (!positionedObjects)
 
3318
        return;
 
3319
    
 
3320
    TrackedRendererListHashSet::const_iterator end = positionedObjects->end();
 
3321
    for (TrackedRendererListHashSet::const_iterator it = positionedObjects->begin(); it != end; ++it) {
 
3322
        RenderBox* r = *it;
 
3323
        paintInfo->context->clipOut(IntRect(offset.x() + r->x(), offset.y() + r->y(), r->width(), r->height()));
 
3324
    }
 
3325
}
 
3326
 
 
3327
static LayoutUnit blockDirectionOffset(RenderBlock* rootBlock, const LayoutSize& offsetFromRootBlock)
 
3328
{
 
3329
    return rootBlock->isHorizontalWritingMode() ? offsetFromRootBlock.height() : offsetFromRootBlock.width();
 
3330
}
 
3331
 
 
3332
static LayoutUnit inlineDirectionOffset(RenderBlock* rootBlock, const LayoutSize& offsetFromRootBlock)
 
3333
{
 
3334
    return rootBlock->isHorizontalWritingMode() ? offsetFromRootBlock.width() : offsetFromRootBlock.height();
 
3335
}
 
3336
 
 
3337
LayoutRect RenderBlock::logicalRectToPhysicalRect(const LayoutPoint& rootBlockPhysicalPosition, const LayoutRect& logicalRect)
 
3338
{
 
3339
    LayoutRect result;
 
3340
    if (isHorizontalWritingMode())
 
3341
        result = logicalRect;
 
3342
    else
 
3343
        result = LayoutRect(logicalRect.y(), logicalRect.x(), logicalRect.height(), logicalRect.width());
 
3344
    flipForWritingMode(result);
 
3345
    result.moveBy(rootBlockPhysicalPosition);
 
3346
    return result;
 
3347
}
 
3348
 
 
3349
GapRects RenderBlock::selectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
 
3350
                                    LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo* paintInfo)
 
3351
{
 
3352
    // IMPORTANT: Callers of this method that intend for painting to happen need to do a save/restore.
 
3353
    // Clip out floating and positioned objects when painting selection gaps.
 
3354
    if (paintInfo) {
 
3355
        // Note that we don't clip out overflow for positioned objects.  We just stick to the border box.
 
3356
        LayoutRect flippedBlockRect(offsetFromRootBlock.width(), offsetFromRootBlock.height(), width(), height());
 
3357
        rootBlock->flipForWritingMode(flippedBlockRect);
 
3358
        flippedBlockRect.moveBy(rootBlockPhysicalPosition);
 
3359
        clipOutPositionedObjects(paintInfo, flippedBlockRect.location(), positionedObjects());
 
3360
        if (isBody() || isRoot()) // The <body> must make sure to examine its containingBlock's positioned objects.
 
3361
            for (RenderBlock* cb = containingBlock(); cb && !cb->isRenderView(); cb = cb->containingBlock())
 
3362
                clipOutPositionedObjects(paintInfo, LayoutPoint(cb->x(), cb->y()), cb->positionedObjects()); // FIXME: Not right for flipped writing modes.
 
3363
        if (m_floatingObjects) {
 
3364
            const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
 
3365
            FloatingObjectSetIterator end = floatingObjectSet.end();
 
3366
            for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
 
3367
                FloatingObject* r = *it;
 
3368
                LayoutRect floatBox(offsetFromRootBlock.width() + xPositionForFloatIncludingMargin(r),
 
3369
                                    offsetFromRootBlock.height() + yPositionForFloatIncludingMargin(r),
 
3370
                                    r->m_renderer->width(), r->m_renderer->height());
 
3371
                rootBlock->flipForWritingMode(floatBox);
 
3372
                floatBox.move(rootBlockPhysicalPosition.x(), rootBlockPhysicalPosition.y());
 
3373
                paintInfo->context->clipOut(pixelSnappedIntRect(floatBox));
 
3374
            }
 
3375
        }
 
3376
    }
 
3377
 
 
3378
    // FIXME: overflow: auto/scroll regions need more math here, since painting in the border box is different from painting in the padding box (one is scrolled, the other is
 
3379
    // fixed).
 
3380
    GapRects result;
 
3381
    if (!isBlockFlow()) // FIXME: Make multi-column selection gap filling work someday.
 
3382
        return result;
 
3383
 
 
3384
    if (hasColumns() || hasTransform() || style()->columnSpan()) {
 
3385
        // FIXME: We should learn how to gap fill multiple columns and transforms eventually.
 
3386
        lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalHeight();
 
3387
        lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, logicalHeight());
 
3388
        lastLogicalRight = logicalRightSelectionOffset(rootBlock, logicalHeight());
 
3389
        return result;
 
3390
    }
 
3391
 
 
3392
    if (childrenInline())
 
3393
        result = inlineSelectionGaps(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, paintInfo);
 
3394
    else
 
3395
        result = blockSelectionGaps(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, paintInfo);
 
3396
 
 
3397
    // Go ahead and fill the vertical gap all the way to the bottom of our block if the selection extends past our block.
 
3398
    if (rootBlock == this && (selectionState() != SelectionBoth && selectionState() != SelectionEnd))
 
3399
        result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, 
 
3400
                                             logicalHeight(), paintInfo));
 
3401
    return result;
 
3402
}
 
3403
 
 
3404
GapRects RenderBlock::inlineSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
 
3405
                                          LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo* paintInfo)
 
3406
{
 
3407
    GapRects result;
 
3408
 
 
3409
    bool containsStart = selectionState() == SelectionStart || selectionState() == SelectionBoth;
 
3410
 
 
3411
    if (!firstLineBox()) {
 
3412
        if (containsStart) {
 
3413
            // Go ahead and update our lastLogicalTop to be the bottom of the block.  <hr>s or empty blocks with height can trip this
 
3414
            // case.
 
3415
            lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalHeight();
 
3416
            lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, logicalHeight());
 
3417
            lastLogicalRight = logicalRightSelectionOffset(rootBlock, logicalHeight());
 
3418
        }
 
3419
        return result;
 
3420
    }
 
3421
 
 
3422
    RootInlineBox* lastSelectedLine = 0;
 
3423
    RootInlineBox* curr;
 
3424
    for (curr = firstRootBox(); curr && !curr->hasSelectedChildren(); curr = curr->nextRootBox()) { }
 
3425
 
 
3426
    // Now paint the gaps for the lines.
 
3427
    for (; curr && curr->hasSelectedChildren(); curr = curr->nextRootBox()) {
 
3428
        LayoutUnit selTop =  curr->selectionTopAdjustedForPrecedingBlock();
 
3429
        LayoutUnit selHeight = curr->selectionHeightAdjustedForPrecedingBlock();
 
3430
 
 
3431
        if (!containsStart && !lastSelectedLine &&
 
3432
            selectionState() != SelectionStart && selectionState() != SelectionBoth)
 
3433
            result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, 
 
3434
                                                 selTop, paintInfo));
 
3435
        
 
3436
        LayoutRect logicalRect(curr->logicalLeft(), selTop, curr->logicalWidth(), selTop + selHeight);
 
3437
        logicalRect.move(isHorizontalWritingMode() ? offsetFromRootBlock : offsetFromRootBlock.transposedSize());
 
3438
        LayoutRect physicalRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, logicalRect);
 
3439
        if (!paintInfo || (isHorizontalWritingMode() && physicalRect.y() < paintInfo->rect.maxY() && physicalRect.maxY() > paintInfo->rect.y())
 
3440
            || (!isHorizontalWritingMode() && physicalRect.x() < paintInfo->rect.maxX() && physicalRect.maxX() > paintInfo->rect.x()))
 
3441
            result.unite(curr->lineSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, selTop, selHeight, paintInfo));
 
3442
 
 
3443
        lastSelectedLine = curr;
 
3444
    }
 
3445
 
 
3446
    if (containsStart && !lastSelectedLine)
 
3447
        // VisibleSelection must start just after our last line.
 
3448
        lastSelectedLine = lastRootBox();
 
3449
 
 
3450
    if (lastSelectedLine && selectionState() != SelectionEnd && selectionState() != SelectionBoth) {
 
3451
        // Go ahead and update our lastY to be the bottom of the last selected line.
 
3452
        lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + lastSelectedLine->selectionBottom();
 
3453
        lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, lastSelectedLine->selectionBottom());
 
3454
        lastLogicalRight = logicalRightSelectionOffset(rootBlock, lastSelectedLine->selectionBottom());
 
3455
    }
 
3456
    return result;
 
3457
}
 
3458
 
 
3459
GapRects RenderBlock::blockSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
 
3460
                                         LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo* paintInfo)
 
3461
{
 
3462
    GapRects result;
 
3463
 
 
3464
    // Go ahead and jump right to the first block child that contains some selected objects.
 
3465
    RenderBox* curr;
 
3466
    for (curr = firstChildBox(); curr && curr->selectionState() == SelectionNone; curr = curr->nextSiblingBox()) { }
 
3467
 
 
3468
    for (bool sawSelectionEnd = false; curr && !sawSelectionEnd; curr = curr->nextSiblingBox()) {
 
3469
        SelectionState childState = curr->selectionState();
 
3470
        if (childState == SelectionBoth || childState == SelectionEnd)
 
3471
            sawSelectionEnd = true;
 
3472
 
 
3473
        if (curr->isFloatingOrOutOfFlowPositioned())
 
3474
            continue; // We must be a normal flow object in order to even be considered.
 
3475
 
 
3476
        if (curr->isInFlowPositioned() && curr->hasLayer()) {
 
3477
            // If the relposition offset is anything other than 0, then treat this just like an absolute positioned element.
 
3478
            // Just disregard it completely.
 
3479
            LayoutSize relOffset = curr->layer()->offsetForInFlowPosition();
 
3480
            if (relOffset.width() || relOffset.height())
 
3481
                continue;
 
3482
        }
 
3483
 
 
3484
        bool paintsOwnSelection = curr->shouldPaintSelectionGaps() || curr->isTable(); // FIXME: Eventually we won't special-case table like this.
 
3485
        bool fillBlockGaps = paintsOwnSelection || (curr->canBeSelectionLeaf() && childState != SelectionNone);
 
3486
        if (fillBlockGaps) {
 
3487
            // We need to fill the vertical gap above this object.
 
3488
            if (childState == SelectionEnd || childState == SelectionInside)
 
3489
                // Fill the gap above the object.
 
3490
                result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, 
 
3491
                                                     curr->logicalTop(), paintInfo));
 
3492
 
 
3493
            // Only fill side gaps for objects that paint their own selection if we know for sure the selection is going to extend all the way *past*
 
3494
            // our object.  We know this if the selection did not end inside our object.
 
3495
            if (paintsOwnSelection && (childState == SelectionStart || sawSelectionEnd))
 
3496
                childState = SelectionNone;
 
3497
 
 
3498
            // Fill side gaps on this object based off its state.
 
3499
            bool leftGap, rightGap;
 
3500
            getSelectionGapInfo(childState, leftGap, rightGap);
 
3501
 
 
3502
            if (leftGap)
 
3503
                result.uniteLeft(logicalLeftSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, this, curr->logicalLeft(), curr->logicalTop(), curr->logicalHeight(), paintInfo));
 
3504
            if (rightGap)
 
3505
                result.uniteRight(logicalRightSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, this, curr->logicalRight(), curr->logicalTop(), curr->logicalHeight(), paintInfo));
 
3506
 
 
3507
            // Update lastLogicalTop to be just underneath the object.  lastLogicalLeft and lastLogicalRight extend as far as
 
3508
            // they can without bumping into floating or positioned objects.  Ideally they will go right up
 
3509
            // to the border of the root selection block.
 
3510
            lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + curr->logicalBottom();
 
3511
            lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, curr->logicalBottom());
 
3512
            lastLogicalRight = logicalRightSelectionOffset(rootBlock, curr->logicalBottom());
 
3513
        } else if (childState != SelectionNone)
 
3514
            // We must be a block that has some selected object inside it.  Go ahead and recur.
 
3515
            result.unite(toRenderBlock(curr)->selectionGaps(rootBlock, rootBlockPhysicalPosition, LayoutSize(offsetFromRootBlock.width() + curr->x(), offsetFromRootBlock.height() + curr->y()), 
 
3516
                                                            lastLogicalTop, lastLogicalLeft, lastLogicalRight, paintInfo));
 
3517
    }
 
3518
    return result;
 
3519
}
 
3520
 
 
3521
LayoutRect RenderBlock::blockSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
 
3522
                                          LayoutUnit lastLogicalTop, LayoutUnit lastLogicalLeft, LayoutUnit lastLogicalRight, LayoutUnit logicalBottom, const PaintInfo* paintInfo)
 
3523
{
 
3524
    LayoutUnit logicalTop = lastLogicalTop;
 
3525
    LayoutUnit logicalHeight = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalBottom - logicalTop;
 
3526
    if (logicalHeight <= 0)
 
3527
        return LayoutRect();
 
3528
 
 
3529
    // Get the selection offsets for the bottom of the gap
 
3530
    LayoutUnit logicalLeft = max(lastLogicalLeft, logicalLeftSelectionOffset(rootBlock, logicalBottom));
 
3531
    LayoutUnit logicalRight = min(lastLogicalRight, logicalRightSelectionOffset(rootBlock, logicalBottom));
 
3532
    LayoutUnit logicalWidth = logicalRight - logicalLeft;
 
3533
    if (logicalWidth <= 0)
 
3534
        return LayoutRect();
 
3535
 
 
3536
    LayoutRect gapRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, LayoutRect(logicalLeft, logicalTop, logicalWidth, logicalHeight));
 
3537
    if (paintInfo)
 
3538
        paintInfo->context->fillRect(pixelSnappedIntRect(gapRect), selectionBackgroundColor(), style()->colorSpace());
 
3539
    return gapRect;
 
3540
}
 
3541
 
 
3542
LayoutRect RenderBlock::logicalLeftSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
 
3543
                                                RenderObject* selObj, LayoutUnit logicalLeft, LayoutUnit logicalTop, LayoutUnit logicalHeight, const PaintInfo* paintInfo)
 
3544
{
 
3545
    LayoutUnit rootBlockLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalTop;
 
3546
    LayoutUnit rootBlockLogicalLeft = max(logicalLeftSelectionOffset(rootBlock, logicalTop), logicalLeftSelectionOffset(rootBlock, logicalTop + logicalHeight));
 
3547
    LayoutUnit rootBlockLogicalRight = min(inlineDirectionOffset(rootBlock, offsetFromRootBlock) + floorToInt(logicalLeft), min(logicalRightSelectionOffset(rootBlock, logicalTop), logicalRightSelectionOffset(rootBlock, logicalTop + logicalHeight)));
 
3548
    LayoutUnit rootBlockLogicalWidth = rootBlockLogicalRight - rootBlockLogicalLeft;
 
3549
    if (rootBlockLogicalWidth <= 0)
 
3550
        return LayoutRect();
 
3551
 
 
3552
    LayoutRect gapRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, LayoutRect(rootBlockLogicalLeft, rootBlockLogicalTop, rootBlockLogicalWidth, logicalHeight));
 
3553
    if (paintInfo)
 
3554
        paintInfo->context->fillRect(pixelSnappedIntRect(gapRect), selObj->selectionBackgroundColor(), selObj->style()->colorSpace());
 
3555
    return gapRect;
 
3556
}
 
3557
 
 
3558
LayoutRect RenderBlock::logicalRightSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
 
3559
                                                 RenderObject* selObj, LayoutUnit logicalRight, LayoutUnit logicalTop, LayoutUnit logicalHeight, const PaintInfo* paintInfo)
 
3560
{
 
3561
    LayoutUnit rootBlockLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalTop;
 
3562
    LayoutUnit rootBlockLogicalLeft = max(inlineDirectionOffset(rootBlock, offsetFromRootBlock) + floorToInt(logicalRight), max(logicalLeftSelectionOffset(rootBlock, logicalTop), logicalLeftSelectionOffset(rootBlock, logicalTop + logicalHeight)));
 
3563
    LayoutUnit rootBlockLogicalRight = min(logicalRightSelectionOffset(rootBlock, logicalTop), logicalRightSelectionOffset(rootBlock, logicalTop + logicalHeight));
 
3564
    LayoutUnit rootBlockLogicalWidth = rootBlockLogicalRight - rootBlockLogicalLeft;
 
3565
    if (rootBlockLogicalWidth <= 0)
 
3566
        return LayoutRect();
 
3567
 
 
3568
    LayoutRect gapRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, LayoutRect(rootBlockLogicalLeft, rootBlockLogicalTop, rootBlockLogicalWidth, logicalHeight));
 
3569
    if (paintInfo)
 
3570
        paintInfo->context->fillRect(pixelSnappedIntRect(gapRect), selObj->selectionBackgroundColor(), selObj->style()->colorSpace());
 
3571
    return gapRect;
 
3572
}
 
3573
 
 
3574
void RenderBlock::getSelectionGapInfo(SelectionState state, bool& leftGap, bool& rightGap)
 
3575
{
 
3576
    bool ltr = style()->isLeftToRightDirection();
 
3577
    leftGap = (state == RenderObject::SelectionInside) ||
 
3578
              (state == RenderObject::SelectionEnd && ltr) ||
 
3579
              (state == RenderObject::SelectionStart && !ltr);
 
3580
    rightGap = (state == RenderObject::SelectionInside) ||
 
3581
               (state == RenderObject::SelectionStart && ltr) ||
 
3582
               (state == RenderObject::SelectionEnd && !ltr);
 
3583
}
 
3584
 
 
3585
LayoutUnit RenderBlock::logicalLeftSelectionOffset(RenderBlock* rootBlock, LayoutUnit position)
 
3586
{
 
3587
    LayoutUnit logicalLeft = logicalLeftOffsetForLine(position, false);
 
3588
    if (logicalLeft == logicalLeftOffsetForContent()) {
 
3589
        if (rootBlock != this)
 
3590
            // The border can potentially be further extended by our containingBlock().
 
3591
            return containingBlock()->logicalLeftSelectionOffset(rootBlock, position + logicalTop());
 
3592
        return logicalLeft;
 
3593
    } else {
 
3594
        RenderBlock* cb = this;
 
3595
        while (cb != rootBlock) {
 
3596
            logicalLeft += cb->logicalLeft();
 
3597
            cb = cb->containingBlock();
 
3598
        }
 
3599
    }
 
3600
    return logicalLeft;
 
3601
}
 
3602
 
 
3603
LayoutUnit RenderBlock::logicalRightSelectionOffset(RenderBlock* rootBlock, LayoutUnit position)
 
3604
{
 
3605
    LayoutUnit logicalRight = logicalRightOffsetForLine(position, false);
 
3606
    if (logicalRight == logicalRightOffsetForContent()) {
 
3607
        if (rootBlock != this)
 
3608
            // The border can potentially be further extended by our containingBlock().
 
3609
            return containingBlock()->logicalRightSelectionOffset(rootBlock, position + logicalTop());
 
3610
        return logicalRight;
 
3611
    } else {
 
3612
        RenderBlock* cb = this;
 
3613
        while (cb != rootBlock) {
 
3614
            logicalRight += cb->logicalLeft();
 
3615
            cb = cb->containingBlock();
 
3616
        }
 
3617
    }
 
3618
    return logicalRight;
 
3619
}
 
3620
 
 
3621
RenderBlock* RenderBlock::blockBeforeWithinSelectionRoot(LayoutSize& offset) const
 
3622
{
 
3623
    if (isSelectionRoot())
 
3624
        return 0;
 
3625
 
 
3626
    const RenderObject* object = this;
 
3627
    RenderObject* sibling;
 
3628
    do {
 
3629
        sibling = object->previousSibling();
 
3630
        while (sibling && (!sibling->isRenderBlock() || toRenderBlock(sibling)->isSelectionRoot()))
 
3631
            sibling = sibling->previousSibling();
 
3632
 
 
3633
        offset -= LayoutSize(toRenderBlock(object)->logicalLeft(), toRenderBlock(object)->logicalTop());
 
3634
        object = object->parent();
 
3635
    } while (!sibling && object && object->isRenderBlock() && !toRenderBlock(object)->isSelectionRoot());
 
3636
 
 
3637
    if (!sibling)
 
3638
        return 0;
 
3639
 
 
3640
    RenderBlock* beforeBlock = toRenderBlock(sibling);
 
3641
 
 
3642
    offset += LayoutSize(beforeBlock->logicalLeft(), beforeBlock->logicalTop());
 
3643
 
 
3644
    RenderObject* child = beforeBlock->lastChild();
 
3645
    while (child && child->isRenderBlock()) {
 
3646
        beforeBlock = toRenderBlock(child);
 
3647
        offset += LayoutSize(beforeBlock->logicalLeft(), beforeBlock->logicalTop());
 
3648
        child = beforeBlock->lastChild();
 
3649
    }
 
3650
    return beforeBlock;
 
3651
}
 
3652
 
 
3653
void RenderBlock::insertIntoTrackedRendererMaps(RenderBox* descendant, TrackedDescendantsMap*& descendantsMap, TrackedContainerMap*& containerMap)
 
3654
{
 
3655
    if (!descendantsMap) {
 
3656
        descendantsMap = new TrackedDescendantsMap;
 
3657
        containerMap = new TrackedContainerMap;
 
3658
    }
 
3659
    
 
3660
    TrackedRendererListHashSet* descendantSet = descendantsMap->get(this);
 
3661
    if (!descendantSet) {
 
3662
        descendantSet = new TrackedRendererListHashSet;
 
3663
        descendantsMap->set(this, descendantSet);
 
3664
    }
 
3665
    bool added = descendantSet->add(descendant).isNewEntry;
 
3666
    if (!added) {
 
3667
        ASSERT(containerMap->get(descendant));
 
3668
        ASSERT(containerMap->get(descendant)->contains(this));
 
3669
        return;
 
3670
    }
 
3671
    
 
3672
    HashSet<RenderBlock*>* containerSet = containerMap->get(descendant);
 
3673
    if (!containerSet) {
 
3674
        containerSet = new HashSet<RenderBlock*>;
 
3675
        containerMap->set(descendant, containerSet);
 
3676
    }
 
3677
    ASSERT(!containerSet->contains(this));
 
3678
    containerSet->add(this);
 
3679
}
 
3680
 
 
3681
void RenderBlock::removeFromTrackedRendererMaps(RenderBox* descendant, TrackedDescendantsMap*& descendantsMap, TrackedContainerMap*& containerMap)
 
3682
{
 
3683
    if (!descendantsMap)
 
3684
        return;
 
3685
    
 
3686
    HashSet<RenderBlock*>* containerSet = containerMap->take(descendant);
 
3687
    if (!containerSet)
 
3688
        return;
 
3689
    
 
3690
    HashSet<RenderBlock*>::iterator end = containerSet->end();
 
3691
    for (HashSet<RenderBlock*>::iterator it = containerSet->begin(); it != end; ++it) {
 
3692
        RenderBlock* container = *it;
 
3693
 
 
3694
        // FIXME: Disabling this assert temporarily until we fix the layout
 
3695
        // bugs associated with positioned objects not properly cleared from
 
3696
        // their ancestor chain before being moved. See webkit bug 93766.
 
3697
        // ASSERT(descendant->isDescendantOf(container));
 
3698
 
 
3699
        TrackedRendererListHashSet* descendantSet = descendantsMap->get(container);
 
3700
        ASSERT(descendantSet);
 
3701
        if (!descendantSet)
 
3702
            continue;
 
3703
        ASSERT(descendantSet->contains(descendant));
 
3704
        descendantSet->remove(descendant);
 
3705
        if (descendantSet->isEmpty()) {
 
3706
            descendantsMap->remove(container);
 
3707
            delete descendantSet;
 
3708
        }
 
3709
    }
 
3710
    
 
3711
    delete containerSet;
 
3712
}
 
3713
 
 
3714
TrackedRendererListHashSet* RenderBlock::positionedObjects() const
 
3715
{
 
3716
    if (gPositionedDescendantsMap)
 
3717
        return gPositionedDescendantsMap->get(this);
 
3718
    return 0;
 
3719
}
 
3720
 
 
3721
void RenderBlock::insertPositionedObject(RenderBox* o)
 
3722
{
 
3723
    ASSERT(!isAnonymousBlock());
 
3724
 
 
3725
    if (o->isRenderFlowThread())
 
3726
        return;
 
3727
    
 
3728
    insertIntoTrackedRendererMaps(o, gPositionedDescendantsMap, gPositionedContainerMap);
 
3729
}
 
3730
 
 
3731
void RenderBlock::removePositionedObject(RenderBox* o)
 
3732
{
 
3733
    removeFromTrackedRendererMaps(o, gPositionedDescendantsMap, gPositionedContainerMap);
 
3734
}
 
3735
 
 
3736
void RenderBlock::removePositionedObjects(RenderBlock* o, ContainingBlockState containingBlockState)
 
3737
{
 
3738
    TrackedRendererListHashSet* positionedDescendants = positionedObjects();
 
3739
    if (!positionedDescendants)
 
3740
        return;
 
3741
    
 
3742
    RenderBox* r;
 
3743
    
 
3744
    TrackedRendererListHashSet::iterator end = positionedDescendants->end();
 
3745
    
 
3746
    Vector<RenderBox*, 16> deadObjects;
 
3747
 
 
3748
    for (TrackedRendererListHashSet::iterator it = positionedDescendants->begin(); it != end; ++it) {
 
3749
        r = *it;
 
3750
        if (!o || r->isDescendantOf(o)) {
 
3751
            if (containingBlockState == NewContainingBlock)
 
3752
                r->setChildNeedsLayout(true, MarkOnlyThis);
 
3753
            
 
3754
            // It is parent blocks job to add positioned child to positioned objects list of its containing block
 
3755
            // Parent layout needs to be invalidated to ensure this happens.
 
3756
            RenderObject* p = r->parent();
 
3757
            while (p && !p->isRenderBlock())
 
3758
                p = p->parent();
 
3759
            if (p)
 
3760
                p->setChildNeedsLayout(true);
 
3761
            
 
3762
            deadObjects.append(r);
 
3763
        }
 
3764
    }
 
3765
    
 
3766
    for (unsigned i = 0; i < deadObjects.size(); i++)
 
3767
        removePositionedObject(deadObjects.at(i));
 
3768
}
 
3769
 
 
3770
void RenderBlock::removeFloatingObjects()
 
3771
{
 
3772
    if (!m_floatingObjects)
 
3773
        return;
 
3774
 
 
3775
    deleteAllValues(m_floatingObjects->set());
 
3776
    m_floatingObjects->clear();
 
3777
}
 
3778
 
 
3779
RenderBlock::FloatingObject* RenderBlock::insertFloatingObject(RenderBox* o)
 
3780
{
 
3781
    ASSERT(o->isFloating());
 
3782
 
 
3783
    // Create the list of special objects if we don't aleady have one
 
3784
    if (!m_floatingObjects)
 
3785
        m_floatingObjects = adoptPtr(new FloatingObjects(this, isHorizontalWritingMode()));
 
3786
    else {
 
3787
        // Don't insert the object again if it's already in the list
 
3788
        const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
 
3789
        FloatingObjectSetIterator it = floatingObjectSet.find<RenderBox*, FloatingObjectHashTranslator>(o);
 
3790
        if (it != floatingObjectSet.end())
 
3791
            return *it;
 
3792
    }
 
3793
 
 
3794
    // Create the special object entry & append it to the list
 
3795
 
 
3796
    FloatingObject* newObj = new FloatingObject(o->style()->floating());
 
3797
    
 
3798
    // Our location is irrelevant if we're unsplittable or no pagination is in effect.
 
3799
    // Just go ahead and lay out the float.
 
3800
    bool isChildRenderBlock = o->isRenderBlock();
 
3801
    if (isChildRenderBlock && !o->needsLayout() && view()->layoutState()->pageLogicalHeightChanged())
 
3802
        o->setChildNeedsLayout(true, MarkOnlyThis);
 
3803
            
 
3804
    bool needsBlockDirectionLocationSetBeforeLayout = isChildRenderBlock && view()->layoutState()->needsBlockDirectionLocationSetBeforeLayout();
 
3805
    if (!needsBlockDirectionLocationSetBeforeLayout || isWritingModeRoot()) // We are unsplittable if we're a block flow root.
 
3806
        o->layoutIfNeeded();
 
3807
    else {
 
3808
        o->updateLogicalWidth();
 
3809
        o->computeAndSetBlockDirectionMargins(this);
 
3810
    }
 
3811
    setLogicalWidthForFloat(newObj, logicalWidthForChild(o) + marginStartForChild(o) + marginEndForChild(o));
 
3812
 
 
3813
    newObj->setShouldPaint(!o->hasSelfPaintingLayer()); // If a layer exists, the float will paint itself. Otherwise someone else will.
 
3814
    newObj->setIsDescendant(true);
 
3815
    newObj->m_renderer = o;
 
3816
 
 
3817
    m_floatingObjects->add(newObj);
 
3818
    
 
3819
    return newObj;
 
3820
}
 
3821
 
 
3822
void RenderBlock::removeFloatingObject(RenderBox* o)
 
3823
{
 
3824
    if (m_floatingObjects) {
 
3825
        const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
 
3826
        FloatingObjectSetIterator it = floatingObjectSet.find<RenderBox*, FloatingObjectHashTranslator>(o);
 
3827
        if (it != floatingObjectSet.end()) {
 
3828
            FloatingObject* r = *it;
 
3829
            if (childrenInline()) {
 
3830
                LayoutUnit logicalTop = logicalTopForFloat(r);
 
3831
                LayoutUnit logicalBottom = logicalBottomForFloat(r);
 
3832
 
 
3833
                // Fix for https://bugs.webkit.org/show_bug.cgi?id=54995.
 
3834
                if (logicalBottom < 0 || logicalBottom < logicalTop || logicalTop == LayoutUnit::max())
 
3835
                    logicalBottom = LayoutUnit::max();
 
3836
                else {
 
3837
                    // Special-case zero- and less-than-zero-height floats: those don't touch
 
3838
                    // the line that they're on, but it still needs to be dirtied. This is
 
3839
                    // accomplished by pretending they have a height of 1.
 
3840
                    logicalBottom = max(logicalBottom, logicalTop + 1);
 
3841
                }
 
3842
                if (r->m_originatingLine) {
 
3843
                    if (!selfNeedsLayout()) {
 
3844
                        ASSERT(r->m_originatingLine->renderer() == this);
 
3845
                        r->m_originatingLine->markDirty();
 
3846
                    }
 
3847
#if !ASSERT_DISABLED
 
3848
                    r->m_originatingLine = 0;
 
3849
#endif
 
3850
                }
 
3851
                markLinesDirtyInBlockRange(0, logicalBottom);
 
3852
            }
 
3853
            m_floatingObjects->remove(r);
 
3854
            ASSERT(!r->m_originatingLine);
 
3855
            delete r;
 
3856
        }
 
3857
    }
 
3858
}
 
3859
 
 
3860
void RenderBlock::removeFloatingObjectsBelow(FloatingObject* lastFloat, int logicalOffset)
 
3861
{
 
3862
    if (!m_floatingObjects)
 
3863
        return;
 
3864
    
 
3865
    const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
 
3866
    FloatingObject* curr = floatingObjectSet.last();
 
3867
    while (curr != lastFloat && (!curr->isPlaced() || logicalTopForFloat(curr) >= logicalOffset)) {
 
3868
        m_floatingObjects->remove(curr);
 
3869
        ASSERT(!curr->m_originatingLine);
 
3870
        delete curr;
 
3871
        if (floatingObjectSet.isEmpty())
 
3872
            break;
 
3873
        curr = floatingObjectSet.last();
 
3874
    }
 
3875
}
 
3876
 
 
3877
LayoutPoint RenderBlock::computeLogicalLocationForFloat(const FloatingObject* floatingObject, LayoutUnit logicalTopOffset) const
 
3878
{
 
3879
    RenderBox* childBox = floatingObject->renderer();
 
3880
    LayoutUnit logicalRightOffset = logicalRightOffsetForContent(logicalTopOffset); // Constant part of right offset.
 
3881
    LayoutUnit logicalLeftOffset = logicalLeftOffsetForContent(logicalTopOffset); // Constant part of left offset.
 
3882
    LayoutUnit floatLogicalWidth = min(logicalWidthForFloat(floatingObject), logicalRightOffset - logicalLeftOffset); // The width we look for.
 
3883
 
 
3884
    LayoutUnit floatLogicalLeft;
 
3885
 
 
3886
    if (childBox->style()->floating() == LeftFloat) {
 
3887
        LayoutUnit heightRemainingLeft = 1;
 
3888
        LayoutUnit heightRemainingRight = 1;
 
3889
        floatLogicalLeft = logicalLeftOffsetForLine(logicalTopOffset, logicalLeftOffset, false, &heightRemainingLeft);
 
3890
        // FIXME: LayoutUnit::epsilon is probably only necessary here due to lost precision elsewhere https://bugs.webkit.org/show_bug.cgi?id=94000
 
3891
        while (logicalRightOffsetForLine(logicalTopOffset, logicalRightOffset, false, &heightRemainingRight) - floatLogicalLeft + LayoutUnit::epsilon() < floatLogicalWidth) {
 
3892
            logicalTopOffset += min(heightRemainingLeft, heightRemainingRight);
 
3893
            floatLogicalLeft = logicalLeftOffsetForLine(logicalTopOffset, logicalLeftOffset, false, &heightRemainingLeft);
 
3894
            if (inRenderFlowThread()) {
 
3895
                // Have to re-evaluate all of our offsets, since they may have changed.
 
3896
                logicalRightOffset = logicalRightOffsetForContent(logicalTopOffset); // Constant part of right offset.
 
3897
                logicalLeftOffset = logicalLeftOffsetForContent(logicalTopOffset); // Constant part of left offset.
 
3898
                floatLogicalWidth = min(logicalWidthForFloat(floatingObject), logicalRightOffset - logicalLeftOffset);
 
3899
            }
 
3900
        }
 
3901
        floatLogicalLeft = max(logicalLeftOffset - borderAndPaddingLogicalLeft(), floatLogicalLeft);
 
3902
    } else {
 
3903
        LayoutUnit heightRemainingLeft = 1;
 
3904
        LayoutUnit heightRemainingRight = 1;
 
3905
        floatLogicalLeft = logicalRightOffsetForLine(logicalTopOffset, logicalRightOffset, false, &heightRemainingRight);
 
3906
        // FIXME: LayoutUnit::epsilon is probably only necessary here due to lost precision elsewhere https://bugs.webkit.org/show_bug.cgi?id=94000
 
3907
        while (floatLogicalLeft - logicalLeftOffsetForLine(logicalTopOffset, logicalLeftOffset, false, &heightRemainingLeft) + LayoutUnit::epsilon() < floatLogicalWidth) {
 
3908
            logicalTopOffset += min(heightRemainingLeft, heightRemainingRight);
 
3909
            floatLogicalLeft = logicalRightOffsetForLine(logicalTopOffset, logicalRightOffset, false, &heightRemainingRight);
 
3910
            if (inRenderFlowThread()) {
 
3911
                // Have to re-evaluate all of our offsets, since they may have changed.
 
3912
                logicalRightOffset = logicalRightOffsetForContent(logicalTopOffset); // Constant part of right offset.
 
3913
                logicalLeftOffset = logicalLeftOffsetForContent(logicalTopOffset); // Constant part of left offset.
 
3914
                floatLogicalWidth = min(logicalWidthForFloat(floatingObject), logicalRightOffset - logicalLeftOffset);
 
3915
            }
 
3916
        }
 
3917
        floatLogicalLeft -= logicalWidthForFloat(floatingObject); // Use the original width of the float here, since the local variable
 
3918
                                                                  // |floatLogicalWidth| was capped to the available line width.
 
3919
                                                                  // See fast/block/float/clamped-right-float.html.
 
3920
    }
 
3921
    
 
3922
    return LayoutPoint(floatLogicalLeft, logicalTopOffset);
 
3923
}
 
3924
 
 
3925
bool RenderBlock::positionNewFloats()
 
3926
{
 
3927
    if (!m_floatingObjects)
 
3928
        return false;
 
3929
 
 
3930
    const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
 
3931
    if (floatingObjectSet.isEmpty())
 
3932
        return false;
 
3933
 
 
3934
    // If all floats have already been positioned, then we have no work to do.
 
3935
    if (floatingObjectSet.last()->isPlaced())
 
3936
        return false;
 
3937
 
 
3938
    // Move backwards through our floating object list until we find a float that has
 
3939
    // already been positioned.  Then we'll be able to move forward, positioning all of
 
3940
    // the new floats that need it.
 
3941
    FloatingObjectSetIterator it = floatingObjectSet.end();
 
3942
    --it; // Go to last item.
 
3943
    FloatingObjectSetIterator begin = floatingObjectSet.begin();
 
3944
    FloatingObject* lastPlacedFloatingObject = 0;
 
3945
    while (it != begin) {
 
3946
        --it;
 
3947
        if ((*it)->isPlaced()) {
 
3948
            lastPlacedFloatingObject = *it;
 
3949
            ++it;
 
3950
            break;
 
3951
        }
 
3952
    }
 
3953
 
 
3954
    LayoutUnit logicalTop = logicalHeight();
 
3955
    
 
3956
    // The float cannot start above the top position of the last positioned float.
 
3957
    if (lastPlacedFloatingObject)
 
3958
        logicalTop = max(logicalTopForFloat(lastPlacedFloatingObject), logicalTop);
 
3959
 
 
3960
    FloatingObjectSetIterator end = floatingObjectSet.end();
 
3961
    // Now walk through the set of unpositioned floats and place them.
 
3962
    for (; it != end; ++it) {
 
3963
        FloatingObject* floatingObject = *it;
 
3964
        // The containing block is responsible for positioning floats, so if we have floats in our
 
3965
        // list that come from somewhere else, do not attempt to position them.
 
3966
        if (floatingObject->renderer()->containingBlock() != this)
 
3967
            continue;
 
3968
 
 
3969
        RenderBox* childBox = floatingObject->renderer();
 
3970
        LayoutUnit childLogicalLeftMargin = style()->isLeftToRightDirection() ? marginStartForChild(childBox) : marginEndForChild(childBox);
 
3971
 
 
3972
        LayoutRect oldRect = childBox->frameRect();
 
3973
 
 
3974
        if (childBox->style()->clear() & CLEFT)
 
3975
            logicalTop = max(lowestFloatLogicalBottom(FloatingObject::FloatLeft), logicalTop);
 
3976
        if (childBox->style()->clear() & CRIGHT)
 
3977
            logicalTop = max(lowestFloatLogicalBottom(FloatingObject::FloatRight), logicalTop);
 
3978
 
 
3979
        LayoutPoint floatLogicalLocation = computeLogicalLocationForFloat(floatingObject, logicalTop);
 
3980
 
 
3981
        setLogicalLeftForFloat(floatingObject, floatLogicalLocation.x());
 
3982
        setLogicalLeftForChild(childBox, floatLogicalLocation.x() + childLogicalLeftMargin);
 
3983
        setLogicalTopForChild(childBox, floatLogicalLocation.y() + marginBeforeForChild(childBox));
 
3984
 
 
3985
        LayoutState* layoutState = view()->layoutState();
 
3986
        bool isPaginated = layoutState->isPaginated();
 
3987
        if (isPaginated && !childBox->needsLayout())
 
3988
            childBox->markForPaginationRelayoutIfNeeded();
 
3989
        
 
3990
        childBox->layoutIfNeeded();
 
3991
 
 
3992
        if (isPaginated) {
 
3993
            // If we are unsplittable and don't fit, then we need to move down.
 
3994
            // We include our margins as part of the unsplittable area.
 
3995
            LayoutUnit newLogicalTop = adjustForUnsplittableChild(childBox, floatLogicalLocation.y(), true);
 
3996
            
 
3997
            // See if we have a pagination strut that is making us move down further.
 
3998
            // Note that an unsplittable child can't also have a pagination strut, so this is
 
3999
            // exclusive with the case above.
 
4000
            RenderBlock* childBlock = childBox->isRenderBlock() ? toRenderBlock(childBox) : 0;
 
4001
            if (childBlock && childBlock->paginationStrut()) {
 
4002
                newLogicalTop += childBlock->paginationStrut();
 
4003
                childBlock->setPaginationStrut(0);
 
4004
            }
 
4005
            
 
4006
            if (newLogicalTop != floatLogicalLocation.y()) {
 
4007
                floatingObject->m_paginationStrut = newLogicalTop - floatLogicalLocation.y();
 
4008
 
 
4009
                floatLogicalLocation = computeLogicalLocationForFloat(floatingObject, newLogicalTop);
 
4010
                setLogicalLeftForFloat(floatingObject, floatLogicalLocation.x());
 
4011
                setLogicalLeftForChild(childBox, floatLogicalLocation.x() + childLogicalLeftMargin);
 
4012
                setLogicalTopForChild(childBox, floatLogicalLocation.y() + marginBeforeForChild(childBox));
 
4013
        
 
4014
                if (childBlock)
 
4015
                    childBlock->setChildNeedsLayout(true, MarkOnlyThis);
 
4016
                childBox->layoutIfNeeded();
 
4017
            }
 
4018
        }
 
4019
 
 
4020
        setLogicalTopForFloat(floatingObject, floatLogicalLocation.y());
 
4021
        setLogicalHeightForFloat(floatingObject, logicalHeightForChild(childBox) + marginBeforeForChild(childBox) + marginAfterForChild(childBox));
 
4022
 
 
4023
        m_floatingObjects->addPlacedObject(floatingObject);
 
4024
 
 
4025
        // If the child moved, we have to repaint it.
 
4026
        if (childBox->checkForRepaintDuringLayout())
 
4027
            childBox->repaintDuringLayoutIfMoved(oldRect);
 
4028
    }
 
4029
    return true;
 
4030
}
 
4031
 
 
4032
void RenderBlock::newLine(EClear clear)
 
4033
{
 
4034
    positionNewFloats();
 
4035
    // set y position
 
4036
    LayoutUnit newY = 0;
 
4037
    switch (clear)
 
4038
    {
 
4039
        case CLEFT:
 
4040
            newY = lowestFloatLogicalBottom(FloatingObject::FloatLeft);
 
4041
            break;
 
4042
        case CRIGHT:
 
4043
            newY = lowestFloatLogicalBottom(FloatingObject::FloatRight);
 
4044
            break;
 
4045
        case CBOTH:
 
4046
            newY = lowestFloatLogicalBottom();
 
4047
        default:
 
4048
            break;
 
4049
    }
 
4050
    if (height() < newY)
 
4051
        setLogicalHeight(newY);
 
4052
}
 
4053
 
 
4054
void RenderBlock::addPercentHeightDescendant(RenderBox* descendant)
 
4055
{
 
4056
    insertIntoTrackedRendererMaps(descendant, gPercentHeightDescendantsMap, gPercentHeightContainerMap);
 
4057
}
 
4058
 
 
4059
void RenderBlock::removePercentHeightDescendant(RenderBox* descendant)
 
4060
{
 
4061
    removeFromTrackedRendererMaps(descendant, gPercentHeightDescendantsMap, gPercentHeightContainerMap);
 
4062
}
 
4063
 
 
4064
TrackedRendererListHashSet* RenderBlock::percentHeightDescendants() const
 
4065
{
 
4066
    return gPercentHeightDescendantsMap ? gPercentHeightDescendantsMap->get(this) : 0;
 
4067
}
 
4068
 
 
4069
bool RenderBlock::hasPercentHeightContainerMap()
 
4070
{
 
4071
    return gPercentHeightContainerMap;
 
4072
}
 
4073
 
 
4074
bool RenderBlock::hasPercentHeightDescendant(RenderBox* descendant)
 
4075
{
 
4076
    // We don't null check gPercentHeightContainerMap since the caller
 
4077
    // already ensures this and we need to call this function on every
 
4078
    // descendant in clearPercentHeightDescendantsFrom().
 
4079
    ASSERT(gPercentHeightContainerMap);
 
4080
    return gPercentHeightContainerMap->contains(descendant);
 
4081
}
 
4082
 
 
4083
void RenderBlock::removePercentHeightDescendantIfNeeded(RenderBox* descendant)
 
4084
{
 
4085
    // We query the map directly, rather than looking at style's
 
4086
    // logicalHeight()/logicalMinHeight()/logicalMaxHeight() since those
 
4087
    // can change with writing mode/directional changes.
 
4088
    if (!hasPercentHeightContainerMap())
 
4089
        return;
 
4090
 
 
4091
    if (!hasPercentHeightDescendant(descendant))
 
4092
        return;
 
4093
 
 
4094
    removePercentHeightDescendant(descendant);
 
4095
}
 
4096
 
 
4097
void RenderBlock::clearPercentHeightDescendantsFrom(RenderBox* parent)
 
4098
{
 
4099
    ASSERT(gPercentHeightContainerMap);
 
4100
    for (RenderObject* curr = parent->firstChild(); curr; curr = curr->nextInPreOrder(parent)) {
 
4101
        if (!curr->isBox())
 
4102
            continue;
 
4103
 
 
4104
        RenderBox* box = toRenderBox(curr);
 
4105
        if (!hasPercentHeightDescendant(box))
 
4106
            continue;
 
4107
 
 
4108
        removePercentHeightDescendant(box);
 
4109
    }
 
4110
}
 
4111
 
 
4112
static bool rangesIntersect(int floatTop, int floatBottom, int objectTop, int objectBottom)
 
4113
{
 
4114
    if (objectTop >= floatBottom || objectBottom < floatTop)
 
4115
        return false;
 
4116
 
 
4117
    // The top of the object overlaps the float
 
4118
    if (objectTop >= floatTop)
 
4119
        return true;
 
4120
 
 
4121
    // The object encloses the float
 
4122
    if (objectTop < floatTop && objectBottom > floatBottom)
 
4123
        return true;
 
4124
 
 
4125
    // The bottom of the object overlaps the float
 
4126
    if (objectBottom > objectTop && objectBottom > floatTop && objectBottom <= floatBottom)
 
4127
        return true;
 
4128
 
 
4129
    return false;
 
4130
}
 
4131
 
 
4132
template <RenderBlock::FloatingObject::Type FloatTypeValue>
 
4133
inline void RenderBlock::FloatIntervalSearchAdapter<FloatTypeValue>::collectIfNeeded(const IntervalType& interval) const
 
4134
{
 
4135
    const FloatingObject* r = interval.data();
 
4136
    if (r->type() != FloatTypeValue || !rangesIntersect(interval.low(), interval.high(), m_lowValue, m_highValue))
 
4137
        return;
 
4138
 
 
4139
    // All the objects returned from the tree should be already placed.
 
4140
    ASSERT(r->isPlaced() && rangesIntersect(m_renderer->pixelSnappedLogicalTopForFloat(r), m_renderer->pixelSnappedLogicalBottomForFloat(r), m_lowValue, m_highValue));
 
4141
 
 
4142
    if (FloatTypeValue == FloatingObject::FloatLeft 
 
4143
        && m_renderer->logicalRightForFloat(r) > m_offset) {
 
4144
        m_offset = m_renderer->logicalRightForFloat(r);
 
4145
        if (m_heightRemaining)
 
4146
            *m_heightRemaining = m_renderer->logicalBottomForFloat(r) - m_lowValue;
 
4147
    }
 
4148
 
 
4149
    if (FloatTypeValue == FloatingObject::FloatRight
 
4150
        && m_renderer->logicalLeftForFloat(r) < m_offset) {
 
4151
        m_offset = m_renderer->logicalLeftForFloat(r);
 
4152
        if (m_heightRemaining)
 
4153
            *m_heightRemaining = m_renderer->logicalBottomForFloat(r) - m_lowValue;
 
4154
    }
 
4155
}
 
4156
 
 
4157
LayoutUnit RenderBlock::textIndentOffset() const
 
4158
{
 
4159
    LayoutUnit cw = 0;
 
4160
    RenderView* renderView = 0;
 
4161
    if (style()->textIndent().isPercent())
 
4162
        cw = containingBlock()->availableLogicalWidth();
 
4163
    else if (style()->textIndent().isViewportPercentage())
 
4164
        renderView = view();
 
4165
    return minimumValueForLength(style()->textIndent(), cw, renderView);
 
4166
}
 
4167
 
 
4168
LayoutUnit RenderBlock::logicalLeftOffsetForContent(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const
 
4169
{
 
4170
    LayoutUnit logicalLeftOffset = style()->isHorizontalWritingMode() ? borderLeft() + paddingLeft() : borderTop() + paddingTop();
 
4171
    if (!inRenderFlowThread())
 
4172
        return logicalLeftOffset;
 
4173
    LayoutRect boxRect = borderBoxRectInRegion(region, offsetFromLogicalTopOfFirstPage);
 
4174
    return logicalLeftOffset + (isHorizontalWritingMode() ? boxRect.x() : boxRect.y());
 
4175
}
 
4176
 
 
4177
LayoutUnit RenderBlock::logicalRightOffsetForContent(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const
 
4178
{
 
4179
    LayoutUnit logicalRightOffset = style()->isHorizontalWritingMode() ? borderLeft() + paddingLeft() : borderTop() + paddingTop();
 
4180
    logicalRightOffset += availableLogicalWidth();
 
4181
    if (!inRenderFlowThread())
 
4182
        return logicalRightOffset;
 
4183
    LayoutRect boxRect = borderBoxRectInRegion(region, offsetFromLogicalTopOfFirstPage);
 
4184
    return logicalRightOffset - (logicalWidth() - (isHorizontalWritingMode() ? boxRect.maxX() : boxRect.maxY()));
 
4185
}
 
4186
 
 
4187
LayoutUnit RenderBlock::logicalLeftOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* heightRemaining, LayoutUnit logicalHeight) const
 
4188
{
 
4189
    LayoutUnit left = fixedOffset;
 
4190
    if (m_floatingObjects && m_floatingObjects->hasLeftObjects()) {
 
4191
        if (heightRemaining)
 
4192
            *heightRemaining = 1;
 
4193
 
 
4194
        FloatIntervalSearchAdapter<FloatingObject::FloatLeft> adapter(this, roundToInt(logicalTop), roundToInt(logicalTop + logicalHeight), left, heightRemaining);
 
4195
        m_floatingObjects->placedFloatsTree().allOverlapsWithAdapter(adapter);
 
4196
    }
 
4197
 
 
4198
    if (applyTextIndent && style()->isLeftToRightDirection())
 
4199
        left += textIndentOffset();
 
4200
 
 
4201
    if (style()->lineAlign() == LineAlignNone)
 
4202
        return left;
 
4203
    
 
4204
    // Push in our left offset so that it is aligned with the character grid.
 
4205
    LayoutState* layoutState = view()->layoutState();
 
4206
    if (!layoutState)
 
4207
        return left;
 
4208
 
 
4209
    RenderBlock* lineGrid = layoutState->lineGrid();
 
4210
    if (!lineGrid || lineGrid->style()->writingMode() != style()->writingMode())
 
4211
        return left;
 
4212
 
 
4213
    // FIXME: Should letter-spacing apply? This is complicated since it doesn't apply at the edge?
 
4214
    float maxCharWidth = lineGrid->style()->font().primaryFont()->maxCharWidth();
 
4215
    if (!maxCharWidth)
 
4216
        return left;
 
4217
 
 
4218
    LayoutUnit lineGridOffset = lineGrid->isHorizontalWritingMode() ? layoutState->lineGridOffset().width(): layoutState->lineGridOffset().height();
 
4219
    LayoutUnit layoutOffset = lineGrid->isHorizontalWritingMode() ? layoutState->layoutOffset().width() : layoutState->layoutOffset().height();
 
4220
    
 
4221
    // Push in to the nearest character width (truncated so that we pixel snap left).
 
4222
    // FIXME: Should be patched when subpixel layout lands, since this calculation doesn't have to pixel snap
 
4223
    // any more (https://bugs.webkit.org/show_bug.cgi?id=79946).
 
4224
    // FIXME: This is wrong for RTL (https://bugs.webkit.org/show_bug.cgi?id=79945).
 
4225
    // FIXME: This doesn't work with columns or regions (https://bugs.webkit.org/show_bug.cgi?id=79942).
 
4226
    // FIXME: This doesn't work when the inline position of the object isn't set ahead of time.
 
4227
    // FIXME: Dynamic changes to the font or to the inline position need to result in a deep relayout.
 
4228
    // (https://bugs.webkit.org/show_bug.cgi?id=79944)
 
4229
    float remainder = fmodf(maxCharWidth - fmodf(left + layoutOffset - lineGridOffset, maxCharWidth), maxCharWidth);
 
4230
    left += remainder;
 
4231
    return left;
 
4232
}
 
4233
 
 
4234
LayoutUnit RenderBlock::logicalRightOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* heightRemaining, LayoutUnit logicalHeight) const
 
4235
{
 
4236
    LayoutUnit right = fixedOffset;
 
4237
    if (m_floatingObjects && m_floatingObjects->hasRightObjects()) {
 
4238
        if (heightRemaining)
 
4239
            *heightRemaining = 1;
 
4240
 
 
4241
        LayoutUnit rightFloatOffset = fixedOffset;
 
4242
        FloatIntervalSearchAdapter<FloatingObject::FloatRight> adapter(this, roundToInt(logicalTop), roundToInt(logicalTop + logicalHeight), rightFloatOffset, heightRemaining);
 
4243
        m_floatingObjects->placedFloatsTree().allOverlapsWithAdapter(adapter);
 
4244
        right = min(right, rightFloatOffset);
 
4245
    }
 
4246
    
 
4247
    if (applyTextIndent && !style()->isLeftToRightDirection())
 
4248
        right -= textIndentOffset();
 
4249
    
 
4250
    if (style()->lineAlign() == LineAlignNone)
 
4251
        return right;
 
4252
    
 
4253
    // Push in our right offset so that it is aligned with the character grid.
 
4254
    LayoutState* layoutState = view()->layoutState();
 
4255
    if (!layoutState)
 
4256
        return right;
 
4257
 
 
4258
    RenderBlock* lineGrid = layoutState->lineGrid();
 
4259
    if (!lineGrid || lineGrid->style()->writingMode() != style()->writingMode())
 
4260
        return right;
 
4261
 
 
4262
    // FIXME: Should letter-spacing apply? This is complicated since it doesn't apply at the edge?
 
4263
    float maxCharWidth = lineGrid->style()->font().primaryFont()->maxCharWidth();
 
4264
    if (!maxCharWidth)
 
4265
        return right;
 
4266
 
 
4267
    LayoutUnit lineGridOffset = lineGrid->isHorizontalWritingMode() ? layoutState->lineGridOffset().width(): layoutState->lineGridOffset().height();
 
4268
    LayoutUnit layoutOffset = lineGrid->isHorizontalWritingMode() ? layoutState->layoutOffset().width() : layoutState->layoutOffset().height();
 
4269
    
 
4270
    // Push in to the nearest character width (truncated so that we pixel snap right).
 
4271
    // FIXME: Should be patched when subpixel layout lands, since this calculation doesn't have to pixel snap
 
4272
    // any more (https://bugs.webkit.org/show_bug.cgi?id=79946).
 
4273
    // FIXME: This is wrong for RTL (https://bugs.webkit.org/show_bug.cgi?id=79945).
 
4274
    // FIXME: This doesn't work with columns or regions (https://bugs.webkit.org/show_bug.cgi?id=79942).
 
4275
    // FIXME: This doesn't work when the inline position of the object isn't set ahead of time.
 
4276
    // FIXME: Dynamic changes to the font or to the inline position need to result in a deep relayout.
 
4277
    // (https://bugs.webkit.org/show_bug.cgi?id=79944)
 
4278
    float remainder = fmodf(fmodf(right + layoutOffset - lineGridOffset, maxCharWidth), maxCharWidth);
 
4279
    right -= ceilf(remainder);
 
4280
    return right;
 
4281
}
 
4282
 
 
4283
LayoutUnit RenderBlock::nextFloatLogicalBottomBelow(LayoutUnit logicalHeight) const
 
4284
{
 
4285
    if (!m_floatingObjects)
 
4286
        return logicalHeight;
 
4287
 
 
4288
    LayoutUnit bottom = LayoutUnit::max();
 
4289
    const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
 
4290
    FloatingObjectSetIterator end = floatingObjectSet.end();
 
4291
    for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
 
4292
        FloatingObject* r = *it;
 
4293
        LayoutUnit floatBottom = logicalBottomForFloat(r);
 
4294
        if (floatBottom > logicalHeight)
 
4295
            bottom = min(floatBottom, bottom);
 
4296
    }
 
4297
 
 
4298
    return bottom == LayoutUnit::max() ? LayoutUnit() : bottom;
 
4299
}
 
4300
 
 
4301
LayoutUnit RenderBlock::lowestFloatLogicalBottom(FloatingObject::Type floatType) const
 
4302
{
 
4303
    if (!m_floatingObjects)
 
4304
        return 0;
 
4305
    LayoutUnit lowestFloatBottom = 0;
 
4306
    const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
 
4307
    FloatingObjectSetIterator end = floatingObjectSet.end();
 
4308
    for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
 
4309
        FloatingObject* r = *it;
 
4310
        if (r->isPlaced() && r->type() & floatType)
 
4311
            lowestFloatBottom = max(lowestFloatBottom, logicalBottomForFloat(r));
 
4312
    }
 
4313
    return lowestFloatBottom;
 
4314
}
 
4315
 
 
4316
void RenderBlock::markLinesDirtyInBlockRange(LayoutUnit logicalTop, LayoutUnit logicalBottom, RootInlineBox* highest)
 
4317
{
 
4318
    if (logicalTop >= logicalBottom)
 
4319
        return;
 
4320
 
 
4321
    RootInlineBox* lowestDirtyLine = lastRootBox();
 
4322
    RootInlineBox* afterLowest = lowestDirtyLine;
 
4323
    while (lowestDirtyLine && lowestDirtyLine->lineBottomWithLeading() >= logicalBottom && logicalBottom < LayoutUnit::max()) {
 
4324
        afterLowest = lowestDirtyLine;
 
4325
        lowestDirtyLine = lowestDirtyLine->prevRootBox();
 
4326
    }
 
4327
 
 
4328
    while (afterLowest && afterLowest != highest && (afterLowest->lineBottomWithLeading() >= logicalTop || afterLowest->lineBottomWithLeading() < 0)) {
 
4329
        afterLowest->markDirty();
 
4330
        afterLowest = afterLowest->prevRootBox();
 
4331
    }
 
4332
}
 
4333
 
 
4334
void RenderBlock::clearFloats()
 
4335
{
 
4336
    if (m_floatingObjects)
 
4337
        m_floatingObjects->setHorizontalWritingMode(isHorizontalWritingMode());
 
4338
 
 
4339
    HashSet<RenderBox*> oldIntrudingFloatSet;
 
4340
    if (!childrenInline() && m_floatingObjects) {
 
4341
        const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
 
4342
        FloatingObjectSetIterator end = floatingObjectSet.end();
 
4343
        for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
 
4344
            FloatingObject* floatingObject = *it;
 
4345
            if (!floatingObject->isDescendant())
 
4346
                oldIntrudingFloatSet.add(floatingObject->m_renderer);
 
4347
        }
 
4348
    }
 
4349
 
 
4350
    // Inline blocks are covered by the isReplaced() check in the avoidFloats method.
 
4351
    if (avoidsFloats() || isRoot() || isRenderView() || isFloatingOrOutOfFlowPositioned() || isTableCell()) {
 
4352
        if (m_floatingObjects) {
 
4353
            deleteAllValues(m_floatingObjects->set());
 
4354
            m_floatingObjects->clear();
 
4355
        }
 
4356
        if (!oldIntrudingFloatSet.isEmpty())
 
4357
            markAllDescendantsWithFloatsForLayout();
 
4358
        return;
 
4359
    }
 
4360
 
 
4361
    typedef HashMap<RenderObject*, FloatingObject*> RendererToFloatInfoMap;
 
4362
    RendererToFloatInfoMap floatMap;
 
4363
 
 
4364
    if (m_floatingObjects) {
 
4365
        const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
 
4366
        if (childrenInline()) {
 
4367
            FloatingObjectSetIterator end = floatingObjectSet.end();
 
4368
            for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
 
4369
                FloatingObject* f = *it;
 
4370
                floatMap.add(f->m_renderer, f);
 
4371
            }
 
4372
        } else
 
4373
            deleteAllValues(floatingObjectSet);
 
4374
        m_floatingObjects->clear();
 
4375
    }
 
4376
 
 
4377
    // We should not process floats if the parent node is not a RenderBlock. Otherwise, we will add 
 
4378
    // floats in an invalid context. This will cause a crash arising from a bad cast on the parent.
 
4379
    // See <rdar://problem/8049753>, where float property is applied on a text node in a SVG.
 
4380
    if (!parent() || !parent()->isRenderBlock())
 
4381
        return;
 
4382
 
 
4383
    // Attempt to locate a previous sibling with overhanging floats.  We skip any elements that are
 
4384
    // out of flow (like floating/positioned elements), and we also skip over any objects that may have shifted
 
4385
    // to avoid floats.
 
4386
    RenderBlock* parentBlock = toRenderBlock(parent());
 
4387
    bool parentHasFloats = false;
 
4388
    RenderObject* prev = previousSibling();
 
4389
    while (prev && (prev->isFloatingOrOutOfFlowPositioned() || !prev->isBox() || !prev->isRenderBlock() || toRenderBlock(prev)->avoidsFloats())) {
 
4390
        if (prev->isFloating())
 
4391
            parentHasFloats = true;
 
4392
        prev = prev->previousSibling();
 
4393
    }
 
4394
 
 
4395
    // First add in floats from the parent.
 
4396
    LayoutUnit logicalTopOffset = logicalTop();
 
4397
    if (parentHasFloats)
 
4398
        addIntrudingFloats(parentBlock, parentBlock->logicalLeftOffsetForContent(), logicalTopOffset);
 
4399
    
 
4400
    LayoutUnit logicalLeftOffset = 0;
 
4401
    if (prev)
 
4402
        logicalTopOffset -= toRenderBox(prev)->logicalTop();
 
4403
    else {
 
4404
        prev = parentBlock;
 
4405
        logicalLeftOffset += parentBlock->logicalLeftOffsetForContent();
 
4406
    }
 
4407
 
 
4408
    // Add overhanging floats from the previous RenderBlock, but only if it has a float that intrudes into our space.    
 
4409
    RenderBlock* block = toRenderBlock(prev);
 
4410
    if (block->m_floatingObjects && block->lowestFloatLogicalBottom() > logicalTopOffset)
 
4411
        addIntrudingFloats(block, logicalLeftOffset, logicalTopOffset);
 
4412
 
 
4413
    if (childrenInline()) {
 
4414
        LayoutUnit changeLogicalTop = LayoutUnit::max();
 
4415
        LayoutUnit changeLogicalBottom = LayoutUnit::min();
 
4416
        if (m_floatingObjects) {
 
4417
            const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
 
4418
            FloatingObjectSetIterator end = floatingObjectSet.end();
 
4419
            for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
 
4420
                FloatingObject* f = *it;
 
4421
                FloatingObject* oldFloatingObject = floatMap.get(f->m_renderer);
 
4422
                LayoutUnit logicalBottom = logicalBottomForFloat(f);
 
4423
                if (oldFloatingObject) {
 
4424
                    LayoutUnit oldLogicalBottom = logicalBottomForFloat(oldFloatingObject);
 
4425
                    if (logicalWidthForFloat(f) != logicalWidthForFloat(oldFloatingObject) || logicalLeftForFloat(f) != logicalLeftForFloat(oldFloatingObject)) {
 
4426
                        changeLogicalTop = 0;
 
4427
                        changeLogicalBottom = max(changeLogicalBottom, max(logicalBottom, oldLogicalBottom));
 
4428
                    } else {
 
4429
                        if (logicalBottom != oldLogicalBottom) {
 
4430
                            changeLogicalTop = min(changeLogicalTop, min(logicalBottom, oldLogicalBottom));
 
4431
                            changeLogicalBottom = max(changeLogicalBottom, max(logicalBottom, oldLogicalBottom));
 
4432
                        }
 
4433
                        LayoutUnit logicalTop = logicalTopForFloat(f);
 
4434
                        LayoutUnit oldLogicalTop = logicalTopForFloat(oldFloatingObject);
 
4435
                        if (logicalTop != oldLogicalTop) {
 
4436
                            changeLogicalTop = min(changeLogicalTop, min(logicalTop, oldLogicalTop));
 
4437
                            changeLogicalBottom = max(changeLogicalBottom, max(logicalTop, oldLogicalTop));
 
4438
                        }
 
4439
                    }
 
4440
 
 
4441
                    floatMap.remove(f->m_renderer);
 
4442
                    if (oldFloatingObject->m_originatingLine && !selfNeedsLayout()) {
 
4443
                        ASSERT(oldFloatingObject->m_originatingLine->renderer() == this);
 
4444
                        oldFloatingObject->m_originatingLine->markDirty();
 
4445
                    }
 
4446
                    delete oldFloatingObject;
 
4447
                } else {
 
4448
                    changeLogicalTop = 0;
 
4449
                    changeLogicalBottom = max(changeLogicalBottom, logicalBottom);
 
4450
                }
 
4451
            }
 
4452
        }
 
4453
 
 
4454
        RendererToFloatInfoMap::iterator end = floatMap.end();
 
4455
        for (RendererToFloatInfoMap::iterator it = floatMap.begin(); it != end; ++it) {
 
4456
            FloatingObject* floatingObject = (*it).value;
 
4457
            if (!floatingObject->isDescendant()) {
 
4458
                changeLogicalTop = 0;
 
4459
                changeLogicalBottom = max(changeLogicalBottom, logicalBottomForFloat(floatingObject));
 
4460
            }
 
4461
        }
 
4462
        deleteAllValues(floatMap);
 
4463
 
 
4464
        markLinesDirtyInBlockRange(changeLogicalTop, changeLogicalBottom);
 
4465
    } else if (!oldIntrudingFloatSet.isEmpty()) {
 
4466
        // If there are previously intruding floats that no longer intrude, then children with floats
 
4467
        // should also get layout because they might need their floating object lists cleared.
 
4468
        if (m_floatingObjects->set().size() < oldIntrudingFloatSet.size())
 
4469
            markAllDescendantsWithFloatsForLayout();
 
4470
        else {
 
4471
            const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
 
4472
            FloatingObjectSetIterator end = floatingObjectSet.end();
 
4473
            for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end && !oldIntrudingFloatSet.isEmpty(); ++it)
 
4474
                oldIntrudingFloatSet.remove((*it)->m_renderer);
 
4475
            if (!oldIntrudingFloatSet.isEmpty())
 
4476
                markAllDescendantsWithFloatsForLayout();
 
4477
        }
 
4478
    }
 
4479
}
 
4480
 
 
4481
LayoutUnit RenderBlock::addOverhangingFloats(RenderBlock* child, bool makeChildPaintOtherFloats)
 
4482
{
 
4483
    // Prevent floats from being added to the canvas by the root element, e.g., <html>.
 
4484
    if (child->hasOverflowClip() || !child->containsFloats() || child->isRoot() || child->hasColumns() || child->isWritingModeRoot())
 
4485
        return 0;
 
4486
 
 
4487
    LayoutUnit childLogicalTop = child->logicalTop();
 
4488
    LayoutUnit childLogicalLeft = child->logicalLeft();
 
4489
    LayoutUnit lowestFloatLogicalBottom = 0;
 
4490
 
 
4491
    // Floats that will remain the child's responsibility to paint should factor into its
 
4492
    // overflow.
 
4493
    FloatingObjectSetIterator childEnd = child->m_floatingObjects->set().end();
 
4494
    for (FloatingObjectSetIterator childIt = child->m_floatingObjects->set().begin(); childIt != childEnd; ++childIt) {
 
4495
        FloatingObject* r = *childIt;
 
4496
        LayoutUnit logicalBottomForFloat = min(this->logicalBottomForFloat(r), LayoutUnit::max() - childLogicalTop);
 
4497
        LayoutUnit logicalBottom = childLogicalTop + logicalBottomForFloat;
 
4498
        lowestFloatLogicalBottom = max(lowestFloatLogicalBottom, logicalBottom);
 
4499
 
 
4500
        if (logicalBottom > logicalHeight()) {
 
4501
            // If the object is not in the list, we add it now.
 
4502
            if (!containsFloat(r->m_renderer)) {
 
4503
                LayoutSize offset = isHorizontalWritingMode() ? LayoutSize(-childLogicalLeft, -childLogicalTop) : LayoutSize(-childLogicalTop, -childLogicalLeft);
 
4504
                FloatingObject* floatingObj = new FloatingObject(r->type(), LayoutRect(r->frameRect().location() - offset, r->frameRect().size()));
 
4505
                floatingObj->m_renderer = r->m_renderer;
 
4506
 
 
4507
                // The nearest enclosing layer always paints the float (so that zindex and stacking
 
4508
                // behaves properly).  We always want to propagate the desire to paint the float as
 
4509
                // far out as we can, to the outermost block that overlaps the float, stopping only
 
4510
                // if we hit a self-painting layer boundary.
 
4511
                if (r->m_renderer->enclosingFloatPaintingLayer() == enclosingFloatPaintingLayer())
 
4512
                    r->setShouldPaint(false);
 
4513
                else
 
4514
                    floatingObj->setShouldPaint(false);
 
4515
 
 
4516
                floatingObj->setIsDescendant(true);
 
4517
 
 
4518
                // We create the floating object list lazily.
 
4519
                if (!m_floatingObjects)
 
4520
                    m_floatingObjects = adoptPtr(new FloatingObjects(this, isHorizontalWritingMode()));
 
4521
 
 
4522
                m_floatingObjects->add(floatingObj);
 
4523
            }
 
4524
        } else {
 
4525
            if (makeChildPaintOtherFloats && !r->shouldPaint() && !r->m_renderer->hasSelfPaintingLayer()
 
4526
                && r->m_renderer->isDescendantOf(child) && r->m_renderer->enclosingFloatPaintingLayer() == child->enclosingFloatPaintingLayer()) {
 
4527
                // The float is not overhanging from this block, so if it is a descendant of the child, the child should
 
4528
                // paint it (the other case is that it is intruding into the child), unless it has its own layer or enclosing
 
4529
                // layer.
 
4530
                // If makeChildPaintOtherFloats is false, it means that the child must already know about all the floats
 
4531
                // it should paint.
 
4532
                r->setShouldPaint(true);
 
4533
            }
 
4534
            
 
4535
            // Since the float doesn't overhang, it didn't get put into our list.  We need to go ahead and add its overflow in to the
 
4536
            // child now.
 
4537
            if (r->isDescendant())
 
4538
                child->addOverflowFromChild(r->m_renderer, LayoutSize(xPositionForFloatIncludingMargin(r), yPositionForFloatIncludingMargin(r)));
 
4539
        }
 
4540
    }
 
4541
    return lowestFloatLogicalBottom;
 
4542
}
 
4543
 
 
4544
bool RenderBlock::hasOverhangingFloat(RenderBox* renderer)
 
4545
{
 
4546
    if (!m_floatingObjects || hasColumns() || !parent())
 
4547
        return false;
 
4548
 
 
4549
    const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
 
4550
    FloatingObjectSetIterator it = floatingObjectSet.find<RenderBox*, FloatingObjectHashTranslator>(renderer);
 
4551
    if (it == floatingObjectSet.end())
 
4552
        return false;
 
4553
 
 
4554
    return logicalBottomForFloat(*it) > logicalHeight();
 
4555
}
 
4556
 
 
4557
void RenderBlock::addIntrudingFloats(RenderBlock* prev, LayoutUnit logicalLeftOffset, LayoutUnit logicalTopOffset)
 
4558
{
 
4559
    ASSERT(!avoidsFloats());
 
4560
 
 
4561
    // If the parent or previous sibling doesn't have any floats to add, don't bother.
 
4562
    if (!prev->m_floatingObjects)
 
4563
        return;
 
4564
 
 
4565
    logicalLeftOffset += marginLogicalLeft();
 
4566
 
 
4567
    const FloatingObjectSet& prevSet = prev->m_floatingObjects->set();
 
4568
    FloatingObjectSetIterator prevEnd = prevSet.end();
 
4569
    for (FloatingObjectSetIterator prevIt = prevSet.begin(); prevIt != prevEnd; ++prevIt) {
 
4570
        FloatingObject* r = *prevIt;
 
4571
        if (logicalBottomForFloat(r) > logicalTopOffset) {
 
4572
            if (!m_floatingObjects || !m_floatingObjects->set().contains(r)) {
 
4573
                LayoutSize offset = isHorizontalWritingMode() ? LayoutSize(logicalLeftOffset, logicalTopOffset) : LayoutSize(logicalTopOffset, logicalLeftOffset);
 
4574
                FloatingObject* floatingObj = new FloatingObject(r->type(), LayoutRect(r->frameRect().location() - offset, r->frameRect().size()));
 
4575
 
 
4576
                // Applying the child's margin makes no sense in the case where the child was passed in.
 
4577
                // since this margin was added already through the modification of the |logicalLeftOffset| variable
 
4578
                // above.  |logicalLeftOffset| will equal the margin in this case, so it's already been taken
 
4579
                // into account.  Only apply this code if prev is the parent, since otherwise the left margin
 
4580
                // will get applied twice.
 
4581
                if (prev != parent()) {
 
4582
                    if (isHorizontalWritingMode())
 
4583
                        floatingObj->setX(floatingObj->x() + prev->marginLeft());
 
4584
                    else
 
4585
                        floatingObj->setY(floatingObj->y() + prev->marginTop());
 
4586
                }
 
4587
               
 
4588
                floatingObj->setShouldPaint(false); // We are not in the direct inheritance chain for this float. We will never paint it.
 
4589
                floatingObj->m_renderer = r->m_renderer;
 
4590
                
 
4591
                // We create the floating object list lazily.
 
4592
                if (!m_floatingObjects)
 
4593
                    m_floatingObjects = adoptPtr(new FloatingObjects(this, isHorizontalWritingMode()));
 
4594
                m_floatingObjects->add(floatingObj);
 
4595
            }
 
4596
        }
 
4597
    }
 
4598
}
 
4599
 
 
4600
bool RenderBlock::avoidsFloats() const
 
4601
{
 
4602
    // Floats can't intrude into our box if we have a non-auto column count or width.
 
4603
    return RenderBox::avoidsFloats() || !style()->hasAutoColumnCount() || !style()->hasAutoColumnWidth();
 
4604
}
 
4605
 
 
4606
bool RenderBlock::containsFloat(RenderBox* renderer) const
 
4607
{
 
4608
    return m_floatingObjects && m_floatingObjects->set().contains<RenderBox*, FloatingObjectHashTranslator>(renderer);
 
4609
}
 
4610
 
 
4611
void RenderBlock::markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove, bool inLayout)
 
4612
{
 
4613
    if (!everHadLayout())
 
4614
        return;
 
4615
 
 
4616
    MarkingBehavior markParents = inLayout ? MarkOnlyThis : MarkContainingBlockChain;
 
4617
    setChildNeedsLayout(true, markParents);
 
4618
 
 
4619
    if (floatToRemove)
 
4620
        removeFloatingObject(floatToRemove);
 
4621
 
 
4622
    // Iterate over our children and mark them as needed.
 
4623
    if (!childrenInline()) {
 
4624
        for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
 
4625
            if ((!floatToRemove && child->isFloatingOrOutOfFlowPositioned()) || !child->isRenderBlock())
 
4626
                continue;
 
4627
            RenderBlock* childBlock = toRenderBlock(child);
 
4628
            if ((floatToRemove ? childBlock->containsFloat(floatToRemove) : childBlock->containsFloats()) || childBlock->shrinkToAvoidFloats())
 
4629
                childBlock->markAllDescendantsWithFloatsForLayout(floatToRemove, inLayout);
 
4630
        }
 
4631
    }
 
4632
}
 
4633
 
 
4634
void RenderBlock::markSiblingsWithFloatsForLayout(RenderBox* floatToRemove)
 
4635
{
 
4636
    if (!m_floatingObjects)
 
4637
        return;
 
4638
 
 
4639
    const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
 
4640
    FloatingObjectSetIterator end = floatingObjectSet.end();
 
4641
 
 
4642
    for (RenderObject* next = nextSibling(); next; next = next->nextSibling()) {
 
4643
        if (!next->isRenderBlock() || next->isFloatingOrOutOfFlowPositioned() || toRenderBlock(next)->avoidsFloats())
 
4644
            continue;
 
4645
 
 
4646
        RenderBlock* nextBlock = toRenderBlock(next);
 
4647
        for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
 
4648
            RenderBox* floatingBox = (*it)->renderer();
 
4649
            if (floatToRemove && floatingBox != floatToRemove)
 
4650
                continue;
 
4651
            if (nextBlock->containsFloat(floatingBox))
 
4652
                nextBlock->markAllDescendantsWithFloatsForLayout(floatingBox);
 
4653
        }
 
4654
    }
 
4655
}
 
4656
 
 
4657
LayoutUnit RenderBlock::getClearDelta(RenderBox* child, LayoutUnit logicalTop)
 
4658
{
 
4659
    // There is no need to compute clearance if we have no floats.
 
4660
    if (!containsFloats())
 
4661
        return 0;
 
4662
    
 
4663
    // At least one float is present.  We need to perform the clearance computation.
 
4664
    bool clearSet = child->style()->clear() != CNONE;
 
4665
    LayoutUnit logicalBottom = 0;
 
4666
    switch (child->style()->clear()) {
 
4667
        case CNONE:
 
4668
            break;
 
4669
        case CLEFT:
 
4670
            logicalBottom = lowestFloatLogicalBottom(FloatingObject::FloatLeft);
 
4671
            break;
 
4672
        case CRIGHT:
 
4673
            logicalBottom = lowestFloatLogicalBottom(FloatingObject::FloatRight);
 
4674
            break;
 
4675
        case CBOTH:
 
4676
            logicalBottom = lowestFloatLogicalBottom();
 
4677
            break;
 
4678
    }
 
4679
 
 
4680
    // We also clear floats if we are too big to sit on the same line as a float (and wish to avoid floats by default).
 
4681
    LayoutUnit result = clearSet ? max<LayoutUnit>(0, logicalBottom - logicalTop) : LayoutUnit();
 
4682
    if (!result && child->avoidsFloats()) {
 
4683
        LayoutUnit newLogicalTop = logicalTop;
 
4684
        while (true) {
 
4685
            LayoutUnit availableLogicalWidthAtNewLogicalTopOffset = availableLogicalWidthForLine(newLogicalTop, false, logicalHeightForChild(child));
 
4686
            if (availableLogicalWidthAtNewLogicalTopOffset == availableLogicalWidthForContent(newLogicalTop))
 
4687
                return newLogicalTop - logicalTop;
 
4688
 
 
4689
            RenderRegion* region = regionAtBlockOffset(logicalTopForChild(child));
 
4690
            LayoutRect borderBox = child->borderBoxRectInRegion(region, offsetFromLogicalTopOfFirstPage() + logicalTopForChild(child), DoNotCacheRenderBoxRegionInfo);
 
4691
            LayoutUnit childLogicalWidthAtOldLogicalTopOffset = isHorizontalWritingMode() ? borderBox.width() : borderBox.height();
 
4692
 
 
4693
            // FIXME: None of this is right for perpendicular writing-mode children.
 
4694
            LayoutUnit childOldLogicalWidth = child->logicalWidth();
 
4695
            LayoutUnit childOldMarginLeft = child->marginLeft();
 
4696
            LayoutUnit childOldMarginRight = child->marginRight();
 
4697
            LayoutUnit childOldLogicalTop = child->logicalTop();
 
4698
 
 
4699
            child->setLogicalTop(newLogicalTop);
 
4700
            child->updateLogicalWidth();
 
4701
            region = regionAtBlockOffset(logicalTopForChild(child));
 
4702
            borderBox = child->borderBoxRectInRegion(region, offsetFromLogicalTopOfFirstPage() + logicalTopForChild(child), DoNotCacheRenderBoxRegionInfo);
 
4703
            LayoutUnit childLogicalWidthAtNewLogicalTopOffset = isHorizontalWritingMode() ? borderBox.width() : borderBox.height();
 
4704
 
 
4705
            child->setLogicalTop(childOldLogicalTop);
 
4706
            child->setLogicalWidth(childOldLogicalWidth);
 
4707
            child->setMarginLeft(childOldMarginLeft);
 
4708
            child->setMarginRight(childOldMarginRight);
 
4709
            
 
4710
            if (childLogicalWidthAtNewLogicalTopOffset <= availableLogicalWidthAtNewLogicalTopOffset) {
 
4711
                // Even though we may not be moving, if the logical width did shrink because of the presence of new floats, then
 
4712
                // we need to force a relayout as though we shifted. This happens because of the dynamic addition of overhanging floats
 
4713
                // from previous siblings when negative margins exist on a child (see the addOverhangingFloats call at the end of collapseMargins).
 
4714
                if (childLogicalWidthAtOldLogicalTopOffset != childLogicalWidthAtNewLogicalTopOffset)
 
4715
                    child->setChildNeedsLayout(true, MarkOnlyThis);
 
4716
                return newLogicalTop - logicalTop;
 
4717
            }
 
4718
 
 
4719
            newLogicalTop = nextFloatLogicalBottomBelow(newLogicalTop);
 
4720
            ASSERT(newLogicalTop >= logicalTop);
 
4721
            if (newLogicalTop < logicalTop)
 
4722
                break;
 
4723
        }
 
4724
        ASSERT_NOT_REACHED();
 
4725
    }
 
4726
    return result;
 
4727
}
 
4728
 
 
4729
bool RenderBlock::isPointInOverflowControl(HitTestResult& result, const LayoutPoint& locationInContainer, const LayoutPoint& accumulatedOffset)
 
4730
{
 
4731
    if (!scrollsOverflow())
 
4732
        return false;
 
4733
 
 
4734
    return layer()->hitTestOverflowControls(result, roundedIntPoint(locationInContainer - toLayoutSize(accumulatedOffset)));
 
4735
}
 
4736
 
 
4737
Node* RenderBlock::nodeForHitTest() const
 
4738
{
 
4739
    // If we are in the margins of block elements that are part of a
 
4740
    // continuation we're actually still inside the enclosing element
 
4741
    // that was split. Use the appropriate inner node.
 
4742
    return isAnonymousBlockContinuation() ? continuation()->node() : node();
 
4743
}
 
4744
 
 
4745
bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
 
4746
{
 
4747
    LayoutPoint adjustedLocation(accumulatedOffset + location());
 
4748
    LayoutSize localOffset = toLayoutSize(adjustedLocation);
 
4749
 
 
4750
    if (!isRenderView()) {
 
4751
        // Check if we need to do anything at all.
 
4752
        LayoutRect overflowBox = visualOverflowRect();
 
4753
        flipForWritingMode(overflowBox);
 
4754
        overflowBox.moveBy(adjustedLocation);
 
4755
        if (!locationInContainer.intersects(overflowBox))
 
4756
            return false;
 
4757
    }
 
4758
 
 
4759
    if ((hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground) && isPointInOverflowControl(result, locationInContainer.point(), adjustedLocation)) {
 
4760
        updateHitTestResult(result, locationInContainer.point() - localOffset);
 
4761
        // FIXME: isPointInOverflowControl() doesn't handle rect-based tests yet.
 
4762
        if (!result.addNodeToRectBasedTestResult(nodeForHitTest(), request, locationInContainer))
 
4763
           return true;
 
4764
    }
 
4765
 
 
4766
    // If we have clipping, then we can't have any spillout.
 
4767
    bool useOverflowClip = hasOverflowClip() && !hasSelfPaintingLayer();
 
4768
    bool useClip = (hasControlClip() || useOverflowClip);
 
4769
    bool checkChildren = !useClip || (hasControlClip() ? locationInContainer.intersects(controlClipRect(adjustedLocation)) : locationInContainer.intersects(overflowClipRect(adjustedLocation, locationInContainer.region(), IncludeOverlayScrollbarSize)));
 
4770
    if (checkChildren) {
 
4771
        // Hit test descendants first.
 
4772
        LayoutSize scrolledOffset(localOffset);
 
4773
        if (hasOverflowClip())
 
4774
            scrolledOffset -= scrolledContentOffset();
 
4775
 
 
4776
        // Hit test contents if we don't have columns.
 
4777
        if (!hasColumns()) {
 
4778
            if (hitTestContents(request, result, locationInContainer, toLayoutPoint(scrolledOffset), hitTestAction)) {
 
4779
                updateHitTestResult(result, locationInContainer.point() - localOffset);
 
4780
                return true;
 
4781
            }
 
4782
            if (hitTestAction == HitTestFloat && hitTestFloats(request, result, locationInContainer, toLayoutPoint(scrolledOffset)))
 
4783
                return true;
 
4784
        } else if (hitTestColumns(request, result, locationInContainer, toLayoutPoint(scrolledOffset), hitTestAction)) {
 
4785
            updateHitTestResult(result, flipForWritingMode(locationInContainer.point() - localOffset));
 
4786
            return true;
 
4787
        }
 
4788
    }
 
4789
 
 
4790
    // Now hit test our background
 
4791
    if (hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground) {
 
4792
        LayoutRect boundsRect(adjustedLocation, size());
 
4793
        if (visibleToHitTesting() && locationInContainer.intersects(boundsRect)) {
 
4794
            updateHitTestResult(result, flipForWritingMode(locationInContainer.point() - localOffset));
 
4795
            if (!result.addNodeToRectBasedTestResult(nodeForHitTest(), request, locationInContainer, boundsRect))
 
4796
                return true;
 
4797
        }
 
4798
    }
 
4799
 
 
4800
    return false;
 
4801
}
 
4802
 
 
4803
bool RenderBlock::hitTestFloats(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset)
 
4804
{
 
4805
    if (!m_floatingObjects)
 
4806
        return false;
 
4807
 
 
4808
    LayoutPoint adjustedLocation = accumulatedOffset;
 
4809
    if (isRenderView()) {
 
4810
        adjustedLocation += toLayoutSize(toRenderView(this)->frameView()->scrollPosition());
 
4811
    }
 
4812
 
 
4813
    const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
 
4814
    FloatingObjectSetIterator begin = floatingObjectSet.begin();
 
4815
    for (FloatingObjectSetIterator it = floatingObjectSet.end(); it != begin;) {
 
4816
        --it;
 
4817
        FloatingObject* floatingObject = *it;
 
4818
        if (floatingObject->shouldPaint() && !floatingObject->m_renderer->hasSelfPaintingLayer()) {
 
4819
            LayoutUnit xOffset = xPositionForFloatIncludingMargin(floatingObject) - floatingObject->m_renderer->x();
 
4820
            LayoutUnit yOffset = yPositionForFloatIncludingMargin(floatingObject) - floatingObject->m_renderer->y();
 
4821
            LayoutPoint childPoint = flipFloatForWritingModeForChild(floatingObject, adjustedLocation + LayoutSize(xOffset, yOffset));
 
4822
            if (floatingObject->m_renderer->hitTest(request, result, locationInContainer, childPoint)) {
 
4823
                updateHitTestResult(result, locationInContainer.point() - toLayoutSize(childPoint));
 
4824
                return true;
 
4825
            }
 
4826
        }
 
4827
    }
 
4828
 
 
4829
    return false;
 
4830
}
 
4831
 
 
4832
class ColumnRectIterator {
 
4833
    WTF_MAKE_NONCOPYABLE(ColumnRectIterator);
 
4834
public:
 
4835
    ColumnRectIterator(const RenderBlock& block)
 
4836
        : m_block(block)
 
4837
        , m_colInfo(block.columnInfo())
 
4838
        , m_direction(m_block.style()->isFlippedBlocksWritingMode() ? 1 : -1)
 
4839
        , m_isHorizontal(block.isHorizontalWritingMode())
 
4840
        , m_logicalLeft(block.logicalLeftOffsetForContent())
 
4841
    {
 
4842
        int colCount = m_colInfo->columnCount();
 
4843
        m_colIndex = colCount - 1;
 
4844
        m_currLogicalTopOffset = colCount * m_colInfo->columnHeight() * m_direction;
 
4845
        update();
 
4846
    }
 
4847
 
 
4848
    void advance()
 
4849
    {
 
4850
        ASSERT(hasMore());
 
4851
        m_colIndex--;
 
4852
        update();
 
4853
    }
 
4854
 
 
4855
    LayoutRect columnRect() const { return m_colRect; }
 
4856
    bool hasMore() const { return m_colIndex >= 0; }
 
4857
 
 
4858
    void adjust(LayoutSize& offset) const
 
4859
    {
 
4860
        LayoutUnit currLogicalLeftOffset = (m_isHorizontal ? m_colRect.x() : m_colRect.y()) - m_logicalLeft;
 
4861
        offset += m_isHorizontal ? LayoutSize(currLogicalLeftOffset, m_currLogicalTopOffset) : LayoutSize(m_currLogicalTopOffset, currLogicalLeftOffset);
 
4862
        if (m_colInfo->progressionAxis() == ColumnInfo::BlockAxis) {
 
4863
            if (m_isHorizontal)
 
4864
                offset.expand(0, m_colRect.y() - m_block.borderTop() - m_block.paddingTop());
 
4865
            else
 
4866
                offset.expand(m_colRect.x() - m_block.borderLeft() - m_block.paddingLeft(), 0);
 
4867
        }
 
4868
    }
 
4869
 
 
4870
private:
 
4871
    void update()
 
4872
    {
 
4873
        if (m_colIndex < 0)
 
4874
            return;
 
4875
 
 
4876
        m_colRect = m_block.columnRectAt(const_cast<ColumnInfo*>(m_colInfo), m_colIndex);
 
4877
        m_block.flipForWritingMode(m_colRect);
 
4878
        m_currLogicalTopOffset -= (m_isHorizontal ? m_colRect.height() : m_colRect.width()) * m_direction;
 
4879
    }
 
4880
 
 
4881
    const RenderBlock& m_block;
 
4882
    const ColumnInfo* const m_colInfo;
 
4883
    const int m_direction;
 
4884
    const bool m_isHorizontal;
 
4885
    const LayoutUnit m_logicalLeft;
 
4886
    int m_colIndex;
 
4887
    LayoutUnit m_currLogicalTopOffset;
 
4888
    LayoutRect m_colRect;
 
4889
};
 
4890
 
 
4891
bool RenderBlock::hitTestColumns(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
 
4892
{
 
4893
    // We need to do multiple passes, breaking up our hit testing into strips.
 
4894
    if (!hasColumns())
 
4895
        return false;
 
4896
 
 
4897
    for (ColumnRectIterator it(*this); it.hasMore(); it.advance()) {
 
4898
        LayoutRect hitRect = locationInContainer.boundingBox();
 
4899
        LayoutRect colRect = it.columnRect();
 
4900
        colRect.moveBy(accumulatedOffset);
 
4901
        if (locationInContainer.intersects(colRect)) {
 
4902
            // The point is inside this column.
 
4903
            // Adjust accumulatedOffset to change where we hit test.
 
4904
            LayoutSize offset;
 
4905
            it.adjust(offset);
 
4906
            LayoutPoint finalLocation = accumulatedOffset + offset;
 
4907
            if (!result.isRectBasedTest() || colRect.contains(hitRect))
 
4908
                return hitTestContents(request, result, locationInContainer, finalLocation, hitTestAction) || (hitTestAction == HitTestFloat && hitTestFloats(request, result, locationInContainer, finalLocation));
 
4909
 
 
4910
            hitTestContents(request, result, locationInContainer, finalLocation, hitTestAction);
 
4911
        }
 
4912
    }
 
4913
 
 
4914
    return false;
 
4915
}
 
4916
 
 
4917
void RenderBlock::adjustForColumnRect(LayoutSize& offset, const LayoutPoint& locationInContainer) const
 
4918
{
 
4919
    for (ColumnRectIterator it(*this); it.hasMore(); it.advance()) {
 
4920
        LayoutRect colRect = it.columnRect();
 
4921
        if (colRect.contains(locationInContainer)) {
 
4922
            it.adjust(offset);
 
4923
            return;
 
4924
        }
 
4925
    }
 
4926
}
 
4927
 
 
4928
bool RenderBlock::hitTestContents(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
 
4929
{
 
4930
    if (childrenInline() && !isTable()) {
 
4931
        // We have to hit-test our line boxes.
 
4932
        if (m_lineBoxes.hitTest(this, request, result, locationInContainer, accumulatedOffset, hitTestAction))
 
4933
            return true;
 
4934
    } else {
 
4935
        // Hit test our children.
 
4936
        HitTestAction childHitTest = hitTestAction;
 
4937
        if (hitTestAction == HitTestChildBlockBackgrounds)
 
4938
            childHitTest = HitTestChildBlockBackground;
 
4939
        for (RenderBox* child = lastChildBox(); child; child = child->previousSiblingBox()) {
 
4940
            LayoutPoint childPoint = flipForWritingModeForChild(child, accumulatedOffset);
 
4941
            if (!child->hasSelfPaintingLayer() && !child->isFloating() && child->nodeAtPoint(request, result, locationInContainer, childPoint, childHitTest))
 
4942
                return true;
 
4943
        }
 
4944
    }
 
4945
 
 
4946
    return false;
 
4947
}
 
4948
 
 
4949
Position RenderBlock::positionForBox(InlineBox *box, bool start) const
 
4950
{
 
4951
    if (!box)
 
4952
        return Position();
 
4953
 
 
4954
    if (!box->renderer()->node())
 
4955
        return createLegacyEditingPosition(node(), start ? caretMinOffset() : caretMaxOffset());
 
4956
 
 
4957
    if (!box->isInlineTextBox())
 
4958
        return createLegacyEditingPosition(box->renderer()->node(), start ? box->renderer()->caretMinOffset() : box->renderer()->caretMaxOffset());
 
4959
 
 
4960
    InlineTextBox* textBox = toInlineTextBox(box);
 
4961
    return createLegacyEditingPosition(box->renderer()->node(), start ? textBox->start() : textBox->start() + textBox->len());
 
4962
}
 
4963
 
 
4964
static inline bool isEditingBoundary(RenderObject* ancestor, RenderObject* child)
 
4965
{
 
4966
    ASSERT(!ancestor || ancestor->node());
 
4967
    ASSERT(child && child->node());
 
4968
    return !ancestor || !ancestor->parent() || (ancestor->hasLayer() && ancestor->parent()->isRenderView())
 
4969
        || ancestor->node()->rendererIsEditable() == child->node()->rendererIsEditable();
 
4970
}
 
4971
 
 
4972
// FIXME: This function should go on RenderObject as an instance method. Then
 
4973
// all cases in which positionForPoint recurs could call this instead to
 
4974
// prevent crossing editable boundaries. This would require many tests.
 
4975
static VisiblePosition positionForPointRespectingEditingBoundaries(RenderBlock* parent, RenderBox* child, const LayoutPoint& pointInParentCoordinates)
 
4976
{
 
4977
    LayoutPoint childLocation = child->location();
 
4978
    if (child->isInFlowPositioned())
 
4979
        childLocation += child->offsetForInFlowPosition();
 
4980
 
 
4981
    // FIXME: This is wrong if the child's writing-mode is different from the parent's.
 
4982
    LayoutPoint pointInChildCoordinates(toLayoutPoint(pointInParentCoordinates - childLocation));
 
4983
 
 
4984
    // If this is an anonymous renderer, we just recur normally
 
4985
    Node* childNode = child->node();
 
4986
    if (!childNode)
 
4987
        return child->positionForPoint(pointInChildCoordinates);
 
4988
 
 
4989
    // Otherwise, first make sure that the editability of the parent and child agree.
 
4990
    // If they don't agree, then we return a visible position just before or after the child
 
4991
    RenderObject* ancestor = parent;
 
4992
    while (ancestor && !ancestor->node())
 
4993
        ancestor = ancestor->parent();
 
4994
 
 
4995
    // If we can't find an ancestor to check editability on, or editability is unchanged, we recur like normal
 
4996
    if (isEditingBoundary(ancestor, child))
 
4997
        return child->positionForPoint(pointInChildCoordinates);
 
4998
 
 
4999
    // Otherwise return before or after the child, depending on if the click was to the logical left or logical right of the child
 
5000
    LayoutUnit childMiddle = parent->logicalWidthForChild(child) / 2;
 
5001
    LayoutUnit logicalLeft = parent->isHorizontalWritingMode() ? pointInChildCoordinates.x() : pointInChildCoordinates.y();
 
5002
    if (logicalLeft < childMiddle)
 
5003
        return ancestor->createVisiblePosition(childNode->nodeIndex(), DOWNSTREAM);
 
5004
    return ancestor->createVisiblePosition(childNode->nodeIndex() + 1, UPSTREAM);
 
5005
}
 
5006
 
 
5007
VisiblePosition RenderBlock::positionForPointWithInlineChildren(const LayoutPoint& pointInLogicalContents)
 
5008
{
 
5009
    ASSERT(childrenInline());
 
5010
 
 
5011
    if (!firstRootBox())
 
5012
        return createVisiblePosition(0, DOWNSTREAM);
 
5013
 
 
5014
    bool linesAreFlipped = style()->isFlippedLinesWritingMode();
 
5015
    bool blocksAreFlipped = style()->isFlippedBlocksWritingMode();
 
5016
 
 
5017
    // look for the closest line box in the root box which is at the passed-in y coordinate
 
5018
    InlineBox* closestBox = 0;
 
5019
    RootInlineBox* firstRootBoxWithChildren = 0;
 
5020
    RootInlineBox* lastRootBoxWithChildren = 0;
 
5021
    for (RootInlineBox* root = firstRootBox(); root; root = root->nextRootBox()) {
 
5022
        if (!root->firstLeafChild())
 
5023
            continue;
 
5024
        if (!firstRootBoxWithChildren)
 
5025
            firstRootBoxWithChildren = root;
 
5026
 
 
5027
        if (!linesAreFlipped && root->isFirstAfterPageBreak() && (pointInLogicalContents.y() < root->lineTopWithLeading()
 
5028
            || (blocksAreFlipped && pointInLogicalContents.y() == root->lineTopWithLeading())))
 
5029
            break;
 
5030
 
 
5031
        lastRootBoxWithChildren = root;
 
5032
 
 
5033
        // check if this root line box is located at this y coordinate
 
5034
        if (pointInLogicalContents.y() < root->selectionBottom() || (blocksAreFlipped && pointInLogicalContents.y() == root->selectionBottom())) {
 
5035
            if (linesAreFlipped) {
 
5036
                RootInlineBox* nextRootBoxWithChildren = root->nextRootBox();
 
5037
                while (nextRootBoxWithChildren && !nextRootBoxWithChildren->firstLeafChild())
 
5038
                    nextRootBoxWithChildren = nextRootBoxWithChildren->nextRootBox();
 
5039
 
 
5040
                if (nextRootBoxWithChildren && nextRootBoxWithChildren->isFirstAfterPageBreak() && (pointInLogicalContents.y() > nextRootBoxWithChildren->lineTopWithLeading()
 
5041
                    || (!blocksAreFlipped && pointInLogicalContents.y() == nextRootBoxWithChildren->lineTopWithLeading())))
 
5042
                    continue;
 
5043
            }
 
5044
            closestBox = root->closestLeafChildForLogicalLeftPosition(pointInLogicalContents.x());
 
5045
            if (closestBox)
 
5046
                break;
 
5047
        }
 
5048
    }
 
5049
 
 
5050
    bool moveCaretToBoundary = document()->frame()->editor()->behavior().shouldMoveCaretToHorizontalBoundaryWhenPastTopOrBottom();
 
5051
 
 
5052
    if (!moveCaretToBoundary && !closestBox && lastRootBoxWithChildren) {
 
5053
        // y coordinate is below last root line box, pretend we hit it
 
5054
        closestBox = lastRootBoxWithChildren->closestLeafChildForLogicalLeftPosition(pointInLogicalContents.x());
 
5055
    }
 
5056
 
 
5057
    if (closestBox) {
 
5058
        if (moveCaretToBoundary) {
 
5059
            LayoutUnit firstRootBoxWithChildrenTop = min<LayoutUnit>(firstRootBoxWithChildren->selectionTop(), firstRootBoxWithChildren->logicalTop());
 
5060
            if (pointInLogicalContents.y() < firstRootBoxWithChildrenTop
 
5061
                || (blocksAreFlipped && pointInLogicalContents.y() == firstRootBoxWithChildrenTop)) {
 
5062
                InlineBox* box = firstRootBoxWithChildren->firstLeafChild();
 
5063
                if (box->isLineBreak()) {
 
5064
                    if (InlineBox* newBox = box->nextLeafChildIgnoringLineBreak())
 
5065
                        box = newBox;
 
5066
                }
 
5067
                // y coordinate is above first root line box, so return the start of the first
 
5068
                return VisiblePosition(positionForBox(box, true), DOWNSTREAM);
 
5069
            }
 
5070
        }
 
5071
 
 
5072
        // pass the box a top position that is inside it
 
5073
        LayoutPoint point(pointInLogicalContents.x(), closestBox->root()->blockDirectionPointInLine());
 
5074
        if (!isHorizontalWritingMode())
 
5075
            point = point.transposedPoint();
 
5076
        if (closestBox->renderer()->isReplaced())
 
5077
            return positionForPointRespectingEditingBoundaries(this, toRenderBox(closestBox->renderer()), point);
 
5078
        return closestBox->renderer()->positionForPoint(point);
 
5079
    }
 
5080
 
 
5081
    if (lastRootBoxWithChildren) {
 
5082
        // We hit this case for Mac behavior when the Y coordinate is below the last box.
 
5083
        ASSERT(moveCaretToBoundary);
 
5084
        InlineBox* logicallyLastBox;
 
5085
        if (lastRootBoxWithChildren->getLogicalEndBoxWithNode(logicallyLastBox))
 
5086
            return VisiblePosition(positionForBox(logicallyLastBox, false), DOWNSTREAM);
 
5087
    }
 
5088
 
 
5089
    // Can't reach this. We have a root line box, but it has no kids.
 
5090
    // FIXME: This should ASSERT_NOT_REACHED(), but clicking on placeholder text
 
5091
    // seems to hit this code path.
 
5092
    return createVisiblePosition(0, DOWNSTREAM);
 
5093
}
 
5094
 
 
5095
static inline bool isChildHitTestCandidate(RenderBox* box)
 
5096
{
 
5097
    return box->height() && box->style()->visibility() == VISIBLE && !box->isFloatingOrOutOfFlowPositioned();
 
5098
}
 
5099
 
 
5100
VisiblePosition RenderBlock::positionForPoint(const LayoutPoint& point)
 
5101
{
 
5102
    if (isTable())
 
5103
        return RenderBox::positionForPoint(point);
 
5104
 
 
5105
    if (isReplaced()) {
 
5106
        // FIXME: This seems wrong when the object's writing-mode doesn't match the line's writing-mode.
 
5107
        LayoutUnit pointLogicalLeft = isHorizontalWritingMode() ? point.x() : point.y();
 
5108
        LayoutUnit pointLogicalTop = isHorizontalWritingMode() ? point.y() : point.x();
 
5109
 
 
5110
        if (pointLogicalTop < 0 || (pointLogicalTop < logicalHeight() && pointLogicalLeft < 0))
 
5111
            return createVisiblePosition(caretMinOffset(), DOWNSTREAM);
 
5112
        if (pointLogicalTop >= logicalHeight() || (pointLogicalTop >= 0 && pointLogicalLeft >= logicalWidth()))
 
5113
            return createVisiblePosition(caretMaxOffset(), DOWNSTREAM);
 
5114
    } 
 
5115
 
 
5116
    LayoutPoint pointInContents = point;
 
5117
    offsetForContents(pointInContents);
 
5118
    LayoutPoint pointInLogicalContents(pointInContents);
 
5119
    if (!isHorizontalWritingMode())
 
5120
        pointInLogicalContents = pointInLogicalContents.transposedPoint();
 
5121
 
 
5122
    if (childrenInline())
 
5123
        return positionForPointWithInlineChildren(pointInLogicalContents);
 
5124
 
 
5125
    RenderBox* lastCandidateBox = lastChildBox();
 
5126
    while (lastCandidateBox && !isChildHitTestCandidate(lastCandidateBox))
 
5127
        lastCandidateBox = lastCandidateBox->previousSiblingBox();
 
5128
 
 
5129
    bool blocksAreFlipped = style()->isFlippedBlocksWritingMode();
 
5130
    if (lastCandidateBox) {
 
5131
        if (pointInLogicalContents.y() > logicalTopForChild(lastCandidateBox)
 
5132
            || (!blocksAreFlipped && pointInLogicalContents.y() == logicalTopForChild(lastCandidateBox)))
 
5133
            return positionForPointRespectingEditingBoundaries(this, lastCandidateBox, pointInContents);
 
5134
 
 
5135
        for (RenderBox* childBox = firstChildBox(); childBox; childBox = childBox->nextSiblingBox()) {
 
5136
            if (!isChildHitTestCandidate(childBox))
 
5137
                continue;
 
5138
            LayoutUnit childLogicalBottom = logicalTopForChild(childBox) + logicalHeightForChild(childBox);
 
5139
            // We hit child if our click is above the bottom of its padding box (like IE6/7 and FF3).
 
5140
            if (isChildHitTestCandidate(childBox) && (pointInLogicalContents.y() < childLogicalBottom
 
5141
                || (blocksAreFlipped && pointInLogicalContents.y() == childLogicalBottom)))
 
5142
                return positionForPointRespectingEditingBoundaries(this, childBox, pointInContents);
 
5143
        }
 
5144
    }
 
5145
 
 
5146
    // We only get here if there are no hit test candidate children below the click.
 
5147
    return RenderBox::positionForPoint(point);
 
5148
}
 
5149
 
 
5150
void RenderBlock::offsetForContents(LayoutPoint& offset) const
 
5151
{
 
5152
    offset = flipForWritingMode(offset);
 
5153
 
 
5154
    if (hasOverflowClip())
 
5155
        offset += scrolledContentOffset();
 
5156
 
 
5157
    if (hasColumns())
 
5158
        adjustPointToColumnContents(offset);
 
5159
 
 
5160
    offset = flipForWritingMode(offset);
 
5161
}
 
5162
 
 
5163
LayoutUnit RenderBlock::availableLogicalWidth() const
 
5164
{
 
5165
    // If we have multiple columns, then the available logical width is reduced to our column width.
 
5166
    if (hasColumns())
 
5167
        return desiredColumnWidth();
 
5168
    return RenderBox::availableLogicalWidth();
 
5169
}
 
5170
 
 
5171
int RenderBlock::columnGap() const
 
5172
{
 
5173
    if (style()->hasNormalColumnGap())
 
5174
        return style()->fontDescription().computedPixelSize(); // "1em" is recommended as the normal gap setting. Matches <p> margins.
 
5175
    return static_cast<int>(style()->columnGap());
 
5176
}
 
5177
 
 
5178
void RenderBlock::calcColumnWidth()
 
5179
{   
 
5180
    if (document()->regionBasedColumnsEnabled())
 
5181
        return;
 
5182
 
 
5183
    // Calculate our column width and column count.
 
5184
    // FIXME: Can overflow on fast/block/float/float-not-removed-from-next-sibling4.html, see https://bugs.webkit.org/show_bug.cgi?id=68744
 
5185
    unsigned desiredColumnCount = 1;
 
5186
    LayoutUnit desiredColumnWidth = contentLogicalWidth();
 
5187
    
 
5188
    // For now, we don't support multi-column layouts when printing, since we have to do a lot of work for proper pagination.
 
5189
    if (document()->paginated() || (style()->hasAutoColumnCount() && style()->hasAutoColumnWidth()) || !style()->hasInlineColumnAxis()) {
 
5190
        setDesiredColumnCountAndWidth(desiredColumnCount, desiredColumnWidth);
 
5191
        return;
 
5192
    }
 
5193
        
 
5194
    LayoutUnit availWidth = desiredColumnWidth;
 
5195
    LayoutUnit colGap = columnGap();
 
5196
    LayoutUnit colWidth = max<LayoutUnit>(1, LayoutUnit(style()->columnWidth()));
 
5197
    int colCount = max<int>(1, style()->columnCount());
 
5198
 
 
5199
    if (style()->hasAutoColumnWidth() && !style()->hasAutoColumnCount()) {
 
5200
        desiredColumnCount = colCount;
 
5201
        desiredColumnWidth = max<LayoutUnit>(0, (availWidth - ((desiredColumnCount - 1) * colGap)) / desiredColumnCount);
 
5202
    } else if (!style()->hasAutoColumnWidth() && style()->hasAutoColumnCount()) {
 
5203
        desiredColumnCount = max<LayoutUnit>(1, (availWidth + colGap) / (colWidth + colGap));
 
5204
        desiredColumnWidth = ((availWidth + colGap) / desiredColumnCount) - colGap;
 
5205
    } else {
 
5206
        desiredColumnCount = max<LayoutUnit>(min<LayoutUnit>(colCount, (availWidth + colGap) / (colWidth + colGap)), 1);
 
5207
        desiredColumnWidth = ((availWidth + colGap) / desiredColumnCount) - colGap;
 
5208
    }
 
5209
    setDesiredColumnCountAndWidth(desiredColumnCount, desiredColumnWidth);
 
5210
}
 
5211
 
 
5212
bool RenderBlock::requiresColumns(int desiredColumnCount) const
 
5213
{
 
5214
    // If overflow-y is set to paged-x or paged-y on the body or html element, we'll handle the paginating
 
5215
    // in the RenderView instead.
 
5216
    bool isPaginated = (style()->overflowY() == OPAGEDX || style()->overflowY() == OPAGEDY) && !(isRoot() || isBody());
 
5217
 
 
5218
    return firstChild()
 
5219
        && (desiredColumnCount != 1 || !style()->hasAutoColumnWidth() || !style()->hasInlineColumnAxis() || isPaginated)
 
5220
        && !firstChild()->isAnonymousColumnsBlock()
 
5221
        && !firstChild()->isAnonymousColumnSpanBlock();
 
5222
}
 
5223
 
 
5224
void RenderBlock::setDesiredColumnCountAndWidth(int count, LayoutUnit width)
 
5225
{
 
5226
    bool destroyColumns = !requiresColumns(count);
 
5227
    if (destroyColumns) {
 
5228
        if (hasColumns()) {
 
5229
            delete gColumnInfoMap->take(this);
 
5230
            setHasColumns(false);
 
5231
        }
 
5232
    } else {
 
5233
        ColumnInfo* info;
 
5234
        if (hasColumns())
 
5235
            info = gColumnInfoMap->get(this);
 
5236
        else {
 
5237
            if (!gColumnInfoMap)
 
5238
                gColumnInfoMap = new ColumnInfoMap;
 
5239
            info = new ColumnInfo;
 
5240
            gColumnInfoMap->add(this, info);
 
5241
            setHasColumns(true);
 
5242
        }
 
5243
        info->setDesiredColumnCount(count);
 
5244
        info->setDesiredColumnWidth(width);
 
5245
        info->setProgressionAxis(style()->hasInlineColumnAxis() ? ColumnInfo::InlineAxis : ColumnInfo::BlockAxis);
 
5246
        info->setProgressionIsReversed(style()->columnProgression() == ReverseColumnProgression);
 
5247
    }
 
5248
}
 
5249
 
 
5250
void RenderBlock::updateColumnInfoFromStyle(RenderStyle* style)
 
5251
{
 
5252
    if (!hasColumns())
 
5253
        return;
 
5254
 
 
5255
    ColumnInfo* info = gColumnInfoMap->get(this);
 
5256
 
 
5257
    bool needsLayout = false;
 
5258
    ColumnInfo::Axis oldAxis = info->progressionAxis();
 
5259
    ColumnInfo::Axis newAxis = style->hasInlineColumnAxis() ? ColumnInfo::InlineAxis : ColumnInfo::BlockAxis;
 
5260
    if (oldAxis != newAxis) {
 
5261
        info->setProgressionAxis(newAxis);
 
5262
        needsLayout = true;
 
5263
    }
 
5264
 
 
5265
    bool oldProgressionIsReversed = info->progressionIsReversed();
 
5266
    bool newProgressionIsReversed = style->columnProgression() == ReverseColumnProgression;
 
5267
    if (oldProgressionIsReversed != newProgressionIsReversed) {
 
5268
        info->setProgressionIsReversed(newProgressionIsReversed);
 
5269
        needsLayout = true;
 
5270
    }
 
5271
 
 
5272
    if (needsLayout)
 
5273
        setNeedsLayoutAndPrefWidthsRecalc();
 
5274
}
 
5275
 
 
5276
LayoutUnit RenderBlock::desiredColumnWidth() const
 
5277
{
 
5278
    if (!hasColumns())
 
5279
        return contentLogicalWidth();
 
5280
    return gColumnInfoMap->get(this)->desiredColumnWidth();
 
5281
}
 
5282
 
 
5283
unsigned RenderBlock::desiredColumnCount() const
 
5284
{
 
5285
    if (!hasColumns())
 
5286
        return 1;
 
5287
    return gColumnInfoMap->get(this)->desiredColumnCount();
 
5288
}
 
5289
 
 
5290
ColumnInfo* RenderBlock::columnInfo() const
 
5291
{
 
5292
    if (!hasColumns())
 
5293
        return 0;
 
5294
    return gColumnInfoMap->get(this);    
 
5295
}
 
5296
 
 
5297
unsigned RenderBlock::columnCount(ColumnInfo* colInfo) const
 
5298
{
 
5299
    ASSERT(hasColumns());
 
5300
    ASSERT(gColumnInfoMap->get(this) == colInfo);
 
5301
    return colInfo->columnCount();
 
5302
}
 
5303
 
 
5304
LayoutRect RenderBlock::columnRectAt(ColumnInfo* colInfo, unsigned index) const
 
5305
{
 
5306
    ASSERT(hasColumns() && gColumnInfoMap->get(this) == colInfo);
 
5307
 
 
5308
    // Compute the appropriate rect based off our information.
 
5309
    LayoutUnit colLogicalWidth = colInfo->desiredColumnWidth();
 
5310
    LayoutUnit colLogicalHeight = colInfo->columnHeight();
 
5311
    LayoutUnit colLogicalTop = borderBefore() + paddingBefore();
 
5312
    LayoutUnit colLogicalLeft = logicalLeftOffsetForContent();
 
5313
    int colGap = columnGap();
 
5314
    if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) {
 
5315
        if (style()->isLeftToRightDirection() ^ colInfo->progressionIsReversed())
 
5316
            colLogicalLeft += index * (colLogicalWidth + colGap);
 
5317
        else
 
5318
            colLogicalLeft += contentLogicalWidth() - colLogicalWidth - index * (colLogicalWidth + colGap);
 
5319
    } else {
 
5320
        if (!colInfo->progressionIsReversed())
 
5321
            colLogicalTop += index * (colLogicalHeight + colGap);
 
5322
        else
 
5323
            colLogicalTop += contentLogicalHeight() - colLogicalHeight - index * (colLogicalHeight + colGap);
 
5324
    }
 
5325
 
 
5326
    if (isHorizontalWritingMode())
 
5327
        return LayoutRect(colLogicalLeft, colLogicalTop, colLogicalWidth, colLogicalHeight);
 
5328
    return LayoutRect(colLogicalTop, colLogicalLeft, colLogicalHeight, colLogicalWidth);
 
5329
}
 
5330
 
 
5331
bool RenderBlock::relayoutForPagination(bool hasSpecifiedPageLogicalHeight, LayoutUnit pageLogicalHeight, LayoutStateMaintainer& statePusher)
 
5332
{
 
5333
    if (!hasColumns())
 
5334
        return false;
 
5335
 
 
5336
    OwnPtr<RenderOverflow> savedOverflow = m_overflow.release();
 
5337
    if (childrenInline())
 
5338
        addOverflowFromInlineChildren();
 
5339
    else
 
5340
        addOverflowFromBlockChildren();
 
5341
    LayoutUnit layoutOverflowLogicalBottom = (isHorizontalWritingMode() ? layoutOverflowRect().maxY() : layoutOverflowRect().maxX()) - borderBefore() - paddingBefore();
 
5342
 
 
5343
    // FIXME: We don't balance properly at all in the presence of forced page breaks.  We need to understand what
 
5344
    // the distance between forced page breaks is so that we can avoid making the minimum column height too tall.
 
5345
    ColumnInfo* colInfo = columnInfo();
 
5346
    if (!hasSpecifiedPageLogicalHeight) {
 
5347
        LayoutUnit columnHeight = pageLogicalHeight;
 
5348
        int minColumnCount = colInfo->forcedBreaks() + 1;
 
5349
        int desiredColumnCount = colInfo->desiredColumnCount();
 
5350
        if (minColumnCount >= desiredColumnCount) {
 
5351
            // The forced page breaks are in control of the balancing.  Just set the column height to the
 
5352
            // maximum page break distance.
 
5353
            if (!pageLogicalHeight) {
 
5354
                LayoutUnit distanceBetweenBreaks = max<LayoutUnit>(colInfo->maximumDistanceBetweenForcedBreaks(),
 
5355
                                                                   view()->layoutState()->pageLogicalOffset(this, borderBefore() + paddingBefore() + layoutOverflowLogicalBottom) - colInfo->forcedBreakOffset());
 
5356
                columnHeight = max(colInfo->minimumColumnHeight(), distanceBetweenBreaks);
 
5357
            }
 
5358
        } else if (layoutOverflowLogicalBottom > boundedMultiply(pageLogicalHeight, desiredColumnCount)) {
 
5359
            // Now that we know the intrinsic height of the columns, we have to rebalance them.
 
5360
            columnHeight = max<LayoutUnit>(colInfo->minimumColumnHeight(), ceilf((float)layoutOverflowLogicalBottom / desiredColumnCount));
 
5361
        }
 
5362
        
 
5363
        if (columnHeight && columnHeight != pageLogicalHeight) {
 
5364
            statePusher.pop();
 
5365
            setEverHadLayout(true);
 
5366
            layoutBlock(false, columnHeight);
 
5367
            return true;
 
5368
        }
 
5369
    } 
 
5370
 
 
5371
    if (pageLogicalHeight)
 
5372
        colInfo->setColumnCountAndHeight(ceilf((float)layoutOverflowLogicalBottom / pageLogicalHeight), pageLogicalHeight);
 
5373
 
 
5374
    if (columnCount(colInfo)) {
 
5375
        setLogicalHeight(borderBefore() + paddingBefore() + colInfo->columnHeight() + borderAfter() + paddingAfter() + scrollbarLogicalHeight());
 
5376
        m_overflow.clear();
 
5377
    } else
 
5378
        m_overflow = savedOverflow.release();
 
5379
    
 
5380
    return false;
 
5381
}
 
5382
 
 
5383
void RenderBlock::adjustPointToColumnContents(LayoutPoint& point) const
 
5384
{
 
5385
    // Just bail if we have no columns.
 
5386
    if (!hasColumns())
 
5387
        return;
 
5388
    
 
5389
    ColumnInfo* colInfo = columnInfo();
 
5390
    if (!columnCount(colInfo))
 
5391
        return;
 
5392
 
 
5393
    // Determine which columns we intersect.
 
5394
    LayoutUnit colGap = columnGap();
 
5395
    LayoutUnit halfColGap = colGap / 2;
 
5396
    LayoutPoint columnPoint(columnRectAt(colInfo, 0).location());
 
5397
    LayoutUnit logicalOffset = 0;
 
5398
    for (unsigned i = 0; i < colInfo->columnCount(); i++) {
 
5399
        // Add in half the column gap to the left and right of the rect.
 
5400
        LayoutRect colRect = columnRectAt(colInfo, i);
 
5401
        flipForWritingMode(colRect);
 
5402
        if (isHorizontalWritingMode() == (colInfo->progressionAxis() == ColumnInfo::InlineAxis)) {
 
5403
            LayoutRect gapAndColumnRect(colRect.x() - halfColGap, colRect.y(), colRect.width() + colGap, colRect.height());
 
5404
            if (point.x() >= gapAndColumnRect.x() && point.x() < gapAndColumnRect.maxX()) {
 
5405
                if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) {
 
5406
                    // FIXME: The clamping that follows is not completely right for right-to-left
 
5407
                    // content.
 
5408
                    // Clamp everything above the column to its top left.
 
5409
                    if (point.y() < gapAndColumnRect.y())
 
5410
                        point = gapAndColumnRect.location();
 
5411
                    // Clamp everything below the column to the next column's top left. If there is
 
5412
                    // no next column, this still maps to just after this column.
 
5413
                    else if (point.y() >= gapAndColumnRect.maxY()) {
 
5414
                        point = gapAndColumnRect.location();
 
5415
                        point.move(0, gapAndColumnRect.height());
 
5416
                    }
 
5417
                } else {
 
5418
                    if (point.x() < colRect.x())
 
5419
                        point.setX(colRect.x());
 
5420
                    else if (point.x() >= colRect.maxX())
 
5421
                        point.setX(colRect.maxX() - 1);
 
5422
                }
 
5423
 
 
5424
                // We're inside the column.  Translate the x and y into our column coordinate space.
 
5425
                if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
 
5426
                    point.move(columnPoint.x() - colRect.x(), (!style()->isFlippedBlocksWritingMode() ? logicalOffset : -logicalOffset));
 
5427
                else
 
5428
                    point.move((!style()->isFlippedBlocksWritingMode() ? logicalOffset : -logicalOffset) - colRect.x() + borderLeft() + paddingLeft(), 0);
 
5429
                return;
 
5430
            }
 
5431
 
 
5432
            // Move to the next position.
 
5433
            logicalOffset += colInfo->progressionAxis() == ColumnInfo::InlineAxis ? colRect.height() : colRect.width();
 
5434
        } else {
 
5435
            LayoutRect gapAndColumnRect(colRect.x(), colRect.y() - halfColGap, colRect.width(), colRect.height() + colGap);
 
5436
            if (point.y() >= gapAndColumnRect.y() && point.y() < gapAndColumnRect.maxY()) {
 
5437
                if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) {
 
5438
                    // FIXME: The clamping that follows is not completely right for right-to-left
 
5439
                    // content.
 
5440
                    // Clamp everything above the column to its top left.
 
5441
                    if (point.x() < gapAndColumnRect.x())
 
5442
                        point = gapAndColumnRect.location();
 
5443
                    // Clamp everything below the column to the next column's top left. If there is
 
5444
                    // no next column, this still maps to just after this column.
 
5445
                    else if (point.x() >= gapAndColumnRect.maxX()) {
 
5446
                        point = gapAndColumnRect.location();
 
5447
                        point.move(gapAndColumnRect.width(), 0);
 
5448
                    }
 
5449
                } else {
 
5450
                    if (point.y() < colRect.y())
 
5451
                        point.setY(colRect.y());
 
5452
                    else if (point.y() >= colRect.maxY())
 
5453
                        point.setY(colRect.maxY() - 1);
 
5454
                }
 
5455
 
 
5456
                // We're inside the column.  Translate the x and y into our column coordinate space.
 
5457
                if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
 
5458
                    point.move((!style()->isFlippedBlocksWritingMode() ? logicalOffset : -logicalOffset), columnPoint.y() - colRect.y());
 
5459
                else
 
5460
                    point.move(0, (!style()->isFlippedBlocksWritingMode() ? logicalOffset : -logicalOffset) - colRect.y() + borderTop() + paddingTop());
 
5461
                return;
 
5462
            }
 
5463
 
 
5464
            // Move to the next position.
 
5465
            logicalOffset += colInfo->progressionAxis() == ColumnInfo::InlineAxis ? colRect.width() : colRect.height();
 
5466
        }
 
5467
    }
 
5468
}
 
5469
 
 
5470
void RenderBlock::adjustRectForColumns(LayoutRect& r) const
 
5471
{
 
5472
    // Just bail if we have no columns.
 
5473
    if (!hasColumns())
 
5474
        return;
 
5475
    
 
5476
    ColumnInfo* colInfo = columnInfo();
 
5477
    
 
5478
    // Determine which columns we intersect.
 
5479
    unsigned colCount = columnCount(colInfo);
 
5480
    if (!colCount)
 
5481
        return;
 
5482
 
 
5483
    // Begin with a result rect that is empty.
 
5484
    LayoutRect result;
 
5485
 
 
5486
    bool isHorizontal = isHorizontalWritingMode();
 
5487
    LayoutUnit beforeBorderPadding = borderBefore() + paddingBefore();
 
5488
    LayoutUnit colHeight = colInfo->columnHeight();
 
5489
    if (!colHeight)
 
5490
        return;
 
5491
 
 
5492
    LayoutUnit startOffset = max(isHorizontal ? r.y() : r.x(), beforeBorderPadding);
 
5493
    LayoutUnit endOffset = min<LayoutUnit>(isHorizontal ? r.maxY() : r.maxX(), beforeBorderPadding + colCount * colHeight);
 
5494
 
 
5495
    // FIXME: Can overflow on fast/block/float/float-not-removed-from-next-sibling4.html, see https://bugs.webkit.org/show_bug.cgi?id=68744
 
5496
    unsigned startColumn = (startOffset - beforeBorderPadding) / colHeight;
 
5497
    unsigned endColumn = (endOffset - beforeBorderPadding) / colHeight;
 
5498
 
 
5499
    if (startColumn == endColumn) {
 
5500
        // The rect is fully contained within one column. Adjust for our offsets
 
5501
        // and repaint only that portion.
 
5502
        LayoutUnit logicalLeftOffset = logicalLeftOffsetForContent();
 
5503
        LayoutRect colRect = columnRectAt(colInfo, startColumn);
 
5504
        LayoutRect repaintRect = r;
 
5505
 
 
5506
        if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) {
 
5507
            if (isHorizontal)
 
5508
                repaintRect.move(colRect.x() - logicalLeftOffset, - static_cast<int>(startColumn) * colHeight);
 
5509
            else
 
5510
                repaintRect.move(- static_cast<int>(startColumn) * colHeight, colRect.y() - logicalLeftOffset);
 
5511
        } else {
 
5512
            if (isHorizontal)
 
5513
                repaintRect.move(0, colRect.y() - startColumn * colHeight - beforeBorderPadding);
 
5514
            else
 
5515
                repaintRect.move(colRect.x() - startColumn * colHeight - beforeBorderPadding, 0);
 
5516
        }
 
5517
        repaintRect.intersect(colRect);
 
5518
        result.unite(repaintRect);
 
5519
    } else {
 
5520
        // We span multiple columns. We can just unite the start and end column to get the final
 
5521
        // repaint rect.
 
5522
        result.unite(columnRectAt(colInfo, startColumn));
 
5523
        result.unite(columnRectAt(colInfo, endColumn));
 
5524
    }
 
5525
 
 
5526
    r = result;
 
5527
}
 
5528
 
 
5529
LayoutPoint RenderBlock::flipForWritingModeIncludingColumns(const LayoutPoint& point) const
 
5530
{
 
5531
    ASSERT(hasColumns());
 
5532
    if (!hasColumns() || !style()->isFlippedBlocksWritingMode())
 
5533
        return point;
 
5534
    ColumnInfo* colInfo = columnInfo();
 
5535
    LayoutUnit columnLogicalHeight = colInfo->columnHeight();
 
5536
    LayoutUnit expandedLogicalHeight = borderBefore() + paddingBefore() + columnCount(colInfo) * columnLogicalHeight + borderAfter() + paddingAfter() + scrollbarLogicalHeight();
 
5537
    if (isHorizontalWritingMode())
 
5538
        return LayoutPoint(point.x(), expandedLogicalHeight - point.y());
 
5539
    return LayoutPoint(expandedLogicalHeight - point.x(), point.y());
 
5540
}
 
5541
 
 
5542
void RenderBlock::adjustStartEdgeForWritingModeIncludingColumns(LayoutRect& rect) const
 
5543
{
 
5544
    ASSERT(hasColumns());
 
5545
    if (!hasColumns() || !style()->isFlippedBlocksWritingMode())
 
5546
        return;
 
5547
    
 
5548
    ColumnInfo* colInfo = columnInfo();
 
5549
    LayoutUnit columnLogicalHeight = colInfo->columnHeight();
 
5550
    LayoutUnit expandedLogicalHeight = borderBefore() + paddingBefore() + columnCount(colInfo) * columnLogicalHeight + borderAfter() + paddingAfter() + scrollbarLogicalHeight();
 
5551
    
 
5552
    if (isHorizontalWritingMode())
 
5553
        rect.setY(expandedLogicalHeight - rect.maxY());
 
5554
    else
 
5555
        rect.setX(expandedLogicalHeight - rect.maxX());
 
5556
}
 
5557
 
 
5558
void RenderBlock::adjustForColumns(LayoutSize& offset, const LayoutPoint& point) const
 
5559
{
 
5560
    if (!hasColumns())
 
5561
        return;
 
5562
 
 
5563
    ColumnInfo* colInfo = columnInfo();
 
5564
 
 
5565
    LayoutUnit logicalLeft = logicalLeftOffsetForContent();
 
5566
    unsigned colCount = columnCount(colInfo);
 
5567
    LayoutUnit colLogicalWidth = colInfo->desiredColumnWidth();
 
5568
    LayoutUnit colLogicalHeight = colInfo->columnHeight();
 
5569
 
 
5570
    for (unsigned i = 0; i < colCount; ++i) {
 
5571
        // Compute the edges for a given column in the block progression direction.
 
5572
        LayoutRect sliceRect = LayoutRect(logicalLeft, borderBefore() + paddingBefore() + i * colLogicalHeight, colLogicalWidth, colLogicalHeight);
 
5573
        if (!isHorizontalWritingMode())
 
5574
            sliceRect = sliceRect.transposedRect();
 
5575
        
 
5576
        LayoutUnit logicalOffset = i * colLogicalHeight;
 
5577
 
 
5578
        // Now we're in the same coordinate space as the point.  See if it is inside the rectangle.
 
5579
        if (isHorizontalWritingMode()) {
 
5580
            if (point.y() >= sliceRect.y() && point.y() < sliceRect.maxY()) {
 
5581
                if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
 
5582
                    offset.expand(columnRectAt(colInfo, i).x() - logicalLeft, -logicalOffset);
 
5583
                else
 
5584
                    offset.expand(0, columnRectAt(colInfo, i).y() - logicalOffset - borderBefore() - paddingBefore());
 
5585
                return;
 
5586
            }
 
5587
        } else {
 
5588
            if (point.x() >= sliceRect.x() && point.x() < sliceRect.maxX()) {
 
5589
                if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
 
5590
                    offset.expand(-logicalOffset, columnRectAt(colInfo, i).y() - logicalLeft);
 
5591
                else
 
5592
                    offset.expand(columnRectAt(colInfo, i).x() - logicalOffset - borderBefore() - paddingBefore(), 0);
 
5593
                return;
 
5594
            }
 
5595
        }
 
5596
    }
 
5597
}
 
5598
 
 
5599
void RenderBlock::computePreferredLogicalWidths()
 
5600
{
 
5601
    ASSERT(preferredLogicalWidthsDirty());
 
5602
 
 
5603
    updateFirstLetter();
 
5604
 
 
5605
    RenderStyle* styleToUse = style();
 
5606
    if (!isTableCell() && styleToUse->logicalWidth().isFixed() && styleToUse->logicalWidth().value() >= 0 
 
5607
       && style()->marqueeBehavior() != MALTERNATE && !(isDeprecatedFlexItem() && !styleToUse->logicalWidth().intValue()))
 
5608
        m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalWidth().value());
 
5609
    else {
 
5610
        m_minPreferredLogicalWidth = 0;
 
5611
        m_maxPreferredLogicalWidth = 0;
 
5612
 
 
5613
        if (childrenInline())
 
5614
            computeInlinePreferredLogicalWidths();
 
5615
        else
 
5616
            computeBlockPreferredLogicalWidths();
 
5617
 
 
5618
        m_maxPreferredLogicalWidth = max(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
 
5619
 
 
5620
        if (!styleToUse->autoWrap() && childrenInline()) {
 
5621
            m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth;
 
5622
            
 
5623
            // A horizontal marquee with inline children has no minimum width.
 
5624
            if (layer() && layer()->marquee() && layer()->marquee()->isHorizontal())
 
5625
                m_minPreferredLogicalWidth = 0;
 
5626
        }
 
5627
 
 
5628
        int scrollbarWidth = 0;
 
5629
        // FIXME: This should only be done for horizontal writing mode.
 
5630
        // For vertical writing mode, this should check overflowX and use the horizontalScrollbarHeight.
 
5631
        if (hasOverflowClip() && styleToUse->overflowY() == OSCROLL) {
 
5632
            layer()->setHasVerticalScrollbar(true);
 
5633
            scrollbarWidth = verticalScrollbarWidth();
 
5634
            m_maxPreferredLogicalWidth += scrollbarWidth;
 
5635
        }
 
5636
 
 
5637
        if (isTableCell()) {
 
5638
            Length w = toRenderTableCell(this)->styleOrColLogicalWidth();
 
5639
            if (w.isFixed() && w.value() > 0) {
 
5640
                m_maxPreferredLogicalWidth = max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(w.value()));
 
5641
                scrollbarWidth = 0;
 
5642
            }
 
5643
        }
 
5644
        
 
5645
        m_minPreferredLogicalWidth += scrollbarWidth;
 
5646
    }
 
5647
    
 
5648
    if (styleToUse->logicalMinWidth().isFixed() && styleToUse->logicalMinWidth().value() > 0) {
 
5649
        m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMinWidth().value()));
 
5650
        m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMinWidth().value()));
 
5651
    }
 
5652
    
 
5653
    if (styleToUse->logicalMaxWidth().isFixed()) {
 
5654
        m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMaxWidth().value()));
 
5655
        m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMaxWidth().value()));
 
5656
    }
 
5657
    
 
5658
    // Table layout uses integers, ceil the preferred widths to ensure that they can contain the contents.
 
5659
    if (isTableCell()) {
 
5660
        m_minPreferredLogicalWidth = m_minPreferredLogicalWidth.ceil();
 
5661
        m_maxPreferredLogicalWidth = m_maxPreferredLogicalWidth.ceil();
 
5662
    }
 
5663
 
 
5664
    LayoutUnit borderAndPadding = borderAndPaddingLogicalWidth();
 
5665
    m_minPreferredLogicalWidth += borderAndPadding;
 
5666
    m_maxPreferredLogicalWidth += borderAndPadding;
 
5667
 
 
5668
    setPreferredLogicalWidthsDirty(false);
 
5669
}
 
5670
 
 
5671
struct InlineMinMaxIterator {
 
5672
/* InlineMinMaxIterator is a class that will iterate over all render objects that contribute to
 
5673
   inline min/max width calculations.  Note the following about the way it walks:
 
5674
   (1) Positioned content is skipped (since it does not contribute to min/max width of a block)
 
5675
   (2) We do not drill into the children of floats or replaced elements, since you can't break
 
5676
       in the middle of such an element.
 
5677
   (3) Inline flows (e.g., <a>, <span>, <i>) are walked twice, since each side can have
 
5678
       distinct borders/margin/padding that contribute to the min/max width.
 
5679
*/
 
5680
    RenderObject* parent;
 
5681
    RenderObject* current;
 
5682
    bool endOfInline;
 
5683
 
 
5684
    InlineMinMaxIterator(RenderObject* p, bool end = false)
 
5685
        :parent(p), current(p), endOfInline(end) {}
 
5686
 
 
5687
    RenderObject* next();
 
5688
};
 
5689
 
 
5690
RenderObject* InlineMinMaxIterator::next()
 
5691
{
 
5692
    RenderObject* result = 0;
 
5693
    bool oldEndOfInline = endOfInline;
 
5694
    endOfInline = false;
 
5695
    while (current || current == parent) {
 
5696
        if (!oldEndOfInline &&
 
5697
            (current == parent ||
 
5698
             (!current->isFloating() && !current->isReplaced() && !current->isOutOfFlowPositioned())))
 
5699
            result = current->firstChild();
 
5700
        if (!result) {
 
5701
            // We hit the end of our inline. (It was empty, e.g., <span></span>.)
 
5702
            if (!oldEndOfInline && current->isRenderInline()) {
 
5703
                result = current;
 
5704
                endOfInline = true;
 
5705
                break;
 
5706
            }
 
5707
 
 
5708
            while (current && current != parent) {
 
5709
                result = current->nextSibling();
 
5710
                if (result) break;
 
5711
                current = current->parent();
 
5712
                if (current && current != parent && current->isRenderInline()) {
 
5713
                    result = current;
 
5714
                    endOfInline = true;
 
5715
                    break;
 
5716
                }
 
5717
            }
 
5718
        }
 
5719
 
 
5720
        if (!result)
 
5721
            break;
 
5722
 
 
5723
        if (!result->isOutOfFlowPositioned() && (result->isText() || result->isFloating() || result->isReplaced() || result->isRenderInline()))
 
5724
             break;
 
5725
        
 
5726
        current = result;
 
5727
        result = 0;
 
5728
    }
 
5729
 
 
5730
    // Update our position.
 
5731
    current = result;
 
5732
    return current;
 
5733
}
 
5734
 
 
5735
static LayoutUnit getBPMWidth(LayoutUnit childValue, Length cssUnit)
 
5736
{
 
5737
    if (cssUnit.type() != Auto)
 
5738
        return (cssUnit.isFixed() ? static_cast<LayoutUnit>(cssUnit.value()) : childValue);
 
5739
    return 0;
 
5740
}
 
5741
 
 
5742
static LayoutUnit getBorderPaddingMargin(const RenderBoxModelObject* child, bool endOfInline)
 
5743
{
 
5744
    RenderStyle* childStyle = child->style();
 
5745
    if (endOfInline)
 
5746
        return getBPMWidth(child->marginEnd(), childStyle->marginEnd()) +
 
5747
               getBPMWidth(child->paddingEnd(), childStyle->paddingEnd()) +
 
5748
               child->borderEnd();
 
5749
    return getBPMWidth(child->marginStart(), childStyle->marginStart()) +
 
5750
               getBPMWidth(child->paddingStart(), childStyle->paddingStart()) +
 
5751
               child->borderStart();
 
5752
}
 
5753
 
 
5754
static inline void stripTrailingSpace(float& inlineMax, float& inlineMin,
 
5755
                                      RenderObject* trailingSpaceChild)
 
5756
{
 
5757
    if (trailingSpaceChild && trailingSpaceChild->isText()) {
 
5758
        // Collapse away the trailing space at the end of a block.
 
5759
        RenderText* t = toRenderText(trailingSpaceChild);
 
5760
        const UChar space = ' ';
 
5761
        const Font& font = t->style()->font(); // FIXME: This ignores first-line.
 
5762
        float spaceWidth = font.width(RenderBlock::constructTextRun(t, font, &space, 1, t->style()));
 
5763
        inlineMax -= spaceWidth + font.wordSpacing();
 
5764
        if (inlineMin > inlineMax)
 
5765
            inlineMin = inlineMax;
 
5766
    }
 
5767
}
 
5768
 
 
5769
static inline void updatePreferredWidth(LayoutUnit& preferredWidth, float& result)
 
5770
{
 
5771
    LayoutUnit snappedResult = ceiledLayoutUnit(result);
 
5772
    preferredWidth = max(snappedResult, preferredWidth);
 
5773
}
 
5774
 
 
5775
// With sub-pixel enabled: When converting between floating point and LayoutUnits
 
5776
// we risk losing precision with each conversion. When this occurs while
 
5777
// accumulating our preferred widths, we can wind up with a line width that's
 
5778
// larger than our maxPreferredWidth due to pure float accumulation.
 
5779
//
 
5780
// With sub-pixel disabled: values from Lengths or the render tree aren't subject
 
5781
// to the same loss of precision, as they're always truncated and stored as
 
5782
// integers. We mirror that behavior here to prevent over-allocating our preferred
 
5783
// width.
 
5784
static inline LayoutUnit adjustFloatForSubPixelLayout(float value)
 
5785
{
 
5786
#if ENABLE(SUBPIXEL_LAYOUT)
 
5787
    return ceiledLayoutUnit(value);
 
5788
#else
 
5789
    return static_cast<int>(value);
 
5790
#endif
 
5791
}
 
5792
 
 
5793
 
 
5794
void RenderBlock::computeInlinePreferredLogicalWidths()
 
5795
{
 
5796
    float inlineMax = 0;
 
5797
    float inlineMin = 0;
 
5798
 
 
5799
    RenderStyle* styleToUse = style();
 
5800
    RenderBlock* containingBlock = this->containingBlock();
 
5801
    LayoutUnit cw = containingBlock ? containingBlock->contentLogicalWidth() : LayoutUnit();
 
5802
 
 
5803
    // If we are at the start of a line, we want to ignore all white-space.
 
5804
    // Also strip spaces if we previously had text that ended in a trailing space.
 
5805
    bool stripFrontSpaces = true;
 
5806
    RenderObject* trailingSpaceChild = 0;
 
5807
 
 
5808
    // Firefox and Opera will allow a table cell to grow to fit an image inside it under
 
5809
    // very specific cirucumstances (in order to match common WinIE renderings). 
 
5810
    // Not supporting the quirk has caused us to mis-render some real sites. (See Bugzilla 10517.) 
 
5811
    bool allowImagesToBreak = !document()->inQuirksMode() || !isTableCell() || !styleToUse->logicalWidth().isIntrinsicOrAuto();
 
5812
 
 
5813
    bool autoWrap, oldAutoWrap;
 
5814
    autoWrap = oldAutoWrap = styleToUse->autoWrap();
 
5815
 
 
5816
    InlineMinMaxIterator childIterator(this);
 
5817
    bool addedTextIndent = false; // Only gets added in once.
 
5818
    LayoutUnit textIndent = minimumValueForLength(styleToUse->textIndent(), cw, view());
 
5819
    RenderObject* prevFloat = 0;
 
5820
    bool isPrevChildInlineFlow = false;
 
5821
    bool shouldBreakLineAfterText = false;
 
5822
    while (RenderObject* child = childIterator.next()) {
 
5823
        autoWrap = child->isReplaced() ? child->parent()->style()->autoWrap() : 
 
5824
            child->style()->autoWrap();
 
5825
 
 
5826
        if (!child->isBR()) {
 
5827
            // Step One: determine whether or not we need to go ahead and
 
5828
            // terminate our current line.  Each discrete chunk can become
 
5829
            // the new min-width, if it is the widest chunk seen so far, and
 
5830
            // it can also become the max-width.
 
5831
 
 
5832
            // Children fall into three categories:
 
5833
            // (1) An inline flow object.  These objects always have a min/max of 0,
 
5834
            // and are included in the iteration solely so that their margins can
 
5835
            // be added in.
 
5836
            //
 
5837
            // (2) An inline non-text non-flow object, e.g., an inline replaced element.
 
5838
            // These objects can always be on a line by themselves, so in this situation
 
5839
            // we need to go ahead and break the current line, and then add in our own
 
5840
            // margins and min/max width on its own line, and then terminate the line.
 
5841
            //
 
5842
            // (3) A text object.  Text runs can have breakable characters at the start,
 
5843
            // the middle or the end.  They may also lose whitespace off the front if
 
5844
            // we're already ignoring whitespace.  In order to compute accurate min-width
 
5845
            // information, we need three pieces of information.
 
5846
            // (a) the min-width of the first non-breakable run.  Should be 0 if the text string
 
5847
            // starts with whitespace.
 
5848
            // (b) the min-width of the last non-breakable run. Should be 0 if the text string
 
5849
            // ends with whitespace.
 
5850
            // (c) the min/max width of the string (trimmed for whitespace).
 
5851
            //
 
5852
            // If the text string starts with whitespace, then we need to go ahead and
 
5853
            // terminate our current line (unless we're already in a whitespace stripping
 
5854
            // mode.
 
5855
            //
 
5856
            // If the text string has a breakable character in the middle, but didn't start
 
5857
            // with whitespace, then we add the width of the first non-breakable run and
 
5858
            // then end the current line.  We then need to use the intermediate min/max width
 
5859
            // values (if any of them are larger than our current min/max).  We then look at
 
5860
            // the width of the last non-breakable run and use that to start a new line
 
5861
            // (unless we end in whitespace).
 
5862
            RenderStyle* childStyle = child->style();
 
5863
            float childMin = 0;
 
5864
            float childMax = 0;
 
5865
 
 
5866
            if (!child->isText()) {
 
5867
                // Case (1) and (2).  Inline replaced and inline flow elements.
 
5868
                if (child->isRenderInline()) {
 
5869
                    // Add in padding/border/margin from the appropriate side of
 
5870
                    // the element.
 
5871
                    float bpm = getBorderPaddingMargin(toRenderInline(child), childIterator.endOfInline);
 
5872
                    childMin += bpm;
 
5873
                    childMax += bpm;
 
5874
 
 
5875
                    inlineMin += childMin;
 
5876
                    inlineMax += childMax;
 
5877
                    
 
5878
                    child->setPreferredLogicalWidthsDirty(false);
 
5879
                } else {
 
5880
                    // Inline replaced elts add in their margins to their min/max values.
 
5881
                    LayoutUnit margins = 0;
 
5882
                    Length startMargin = childStyle->marginStart();
 
5883
                    Length endMargin = childStyle->marginEnd();
 
5884
                    if (startMargin.isFixed())
 
5885
                        margins += adjustFloatForSubPixelLayout(startMargin.value());
 
5886
                    if (endMargin.isFixed())
 
5887
                        margins += adjustFloatForSubPixelLayout(endMargin.value());
 
5888
                    childMin += margins.ceilToFloat();
 
5889
                    childMax += margins.ceilToFloat();
 
5890
                }
 
5891
            }
 
5892
 
 
5893
            if (!child->isRenderInline() && !child->isText()) {
 
5894
                // Case (2). Inline replaced elements and floats.
 
5895
                // Go ahead and terminate the current line as far as
 
5896
                // minwidth is concerned.
 
5897
                childMin += child->minPreferredLogicalWidth().ceilToFloat();
 
5898
                childMax += child->maxPreferredLogicalWidth().ceilToFloat();
 
5899
 
 
5900
                bool clearPreviousFloat;
 
5901
                if (child->isFloating()) {
 
5902
                    clearPreviousFloat = (prevFloat
 
5903
                        && ((prevFloat->style()->floating() == LeftFloat && (childStyle->clear() & CLEFT))
 
5904
                            || (prevFloat->style()->floating() == RightFloat && (childStyle->clear() & CRIGHT))));
 
5905
                    prevFloat = child;
 
5906
                } else
 
5907
                    clearPreviousFloat = false;
 
5908
 
 
5909
                bool canBreakReplacedElement = !child->isImage() || allowImagesToBreak;
 
5910
                if ((canBreakReplacedElement && (autoWrap || oldAutoWrap) && (!isPrevChildInlineFlow || shouldBreakLineAfterText)) || clearPreviousFloat) {
 
5911
                    updatePreferredWidth(m_minPreferredLogicalWidth, inlineMin);
 
5912
                    inlineMin = 0;
 
5913
                }
 
5914
 
 
5915
                // If we're supposed to clear the previous float, then terminate maxwidth as well.
 
5916
                if (clearPreviousFloat) {
 
5917
                    updatePreferredWidth(m_maxPreferredLogicalWidth, inlineMax);
 
5918
                    inlineMax = 0;
 
5919
                }
 
5920
 
 
5921
                // Add in text-indent.  This is added in only once.
 
5922
                LayoutUnit ti = 0;
 
5923
                if (!addedTextIndent) {
 
5924
                    ti = textIndent;
 
5925
                    childMin += ti.ceilToFloat();
 
5926
                    childMax += ti.ceilToFloat();
 
5927
 
 
5928
                    if (childMin < 0)
 
5929
                        textIndent = adjustFloatForSubPixelLayout(childMin);
 
5930
                    else
 
5931
                        addedTextIndent = true;
 
5932
                }
 
5933
 
 
5934
                // Add our width to the max.
 
5935
                inlineMax += max<float>(0, childMax);
 
5936
 
 
5937
                if (!autoWrap || !canBreakReplacedElement || (isPrevChildInlineFlow && !shouldBreakLineAfterText)) {
 
5938
                    if (child->isFloating())
 
5939
                        updatePreferredWidth(m_minPreferredLogicalWidth, childMin);
 
5940
                    else
 
5941
                        inlineMin += childMin;
 
5942
                } else {
 
5943
                    // Now check our line.
 
5944
                    updatePreferredWidth(m_minPreferredLogicalWidth, childMin);
 
5945
 
 
5946
                    // Now start a new line.
 
5947
                    inlineMin = 0;
 
5948
                }
 
5949
 
 
5950
                if (autoWrap && canBreakReplacedElement && isPrevChildInlineFlow) {
 
5951
                    updatePreferredWidth(m_minPreferredLogicalWidth, inlineMin);
 
5952
                    inlineMin = 0;
 
5953
                }
 
5954
 
 
5955
                // We are no longer stripping whitespace at the start of
 
5956
                // a line.
 
5957
                if (!child->isFloating()) {
 
5958
                    stripFrontSpaces = false;
 
5959
                    trailingSpaceChild = 0;
 
5960
                }
 
5961
            } else if (child->isText()) {
 
5962
                // Case (3). Text.
 
5963
                RenderText* t = toRenderText(child);
 
5964
 
 
5965
                if (t->isWordBreak()) {
 
5966
                    updatePreferredWidth(m_minPreferredLogicalWidth, inlineMin);
 
5967
                    inlineMin = 0;
 
5968
                    continue;
 
5969
                }
 
5970
 
 
5971
                if (t->style()->hasTextCombine() && t->isCombineText())
 
5972
                    toRenderCombineText(t)->combineText();
 
5973
 
 
5974
                // Determine if we have a breakable character.  Pass in
 
5975
                // whether or not we should ignore any spaces at the front
 
5976
                // of the string.  If those are going to be stripped out,
 
5977
                // then they shouldn't be considered in the breakable char
 
5978
                // check.
 
5979
                bool hasBreakableChar, hasBreak;
 
5980
                float beginMin, endMin;
 
5981
                bool beginWS, endWS;
 
5982
                float beginMax, endMax;
 
5983
                t->trimmedPrefWidths(inlineMax, beginMin, beginWS, endMin, endWS,
 
5984
                                     hasBreakableChar, hasBreak, beginMax, endMax,
 
5985
                                     childMin, childMax, stripFrontSpaces);
 
5986
 
 
5987
                // This text object will not be rendered, but it may still provide a breaking opportunity.
 
5988
                if (!hasBreak && childMax == 0) {
 
5989
                    if (autoWrap && (beginWS || endWS)) {
 
5990
                        updatePreferredWidth(m_minPreferredLogicalWidth, inlineMin);
 
5991
                        inlineMin = 0;
 
5992
                    }
 
5993
                    continue;
 
5994
                }
 
5995
                
 
5996
                if (stripFrontSpaces)
 
5997
                    trailingSpaceChild = child;
 
5998
                else
 
5999
                    trailingSpaceChild = 0;
 
6000
 
 
6001
                // Add in text-indent.  This is added in only once.
 
6002
                float ti = 0;
 
6003
                if (!addedTextIndent) {
 
6004
                    ti = textIndent.ceilToFloat();
 
6005
                    
 
6006
                    childMin += ti;
 
6007
                    childMax += ti;
 
6008
                    beginMin += ti;
 
6009
                    beginMax += ti;
 
6010
                    
 
6011
                    if (childMin < 0)
 
6012
                        textIndent = childMin;
 
6013
                    else
 
6014
                        addedTextIndent = true;
 
6015
                }
 
6016
                
 
6017
                // If we have no breakable characters at all,
 
6018
                // then this is the easy case. We add ourselves to the current
 
6019
                // min and max and continue.
 
6020
                if (!hasBreakableChar) {
 
6021
                    inlineMin += childMin;
 
6022
                } else {
 
6023
                    // We have a breakable character.  Now we need to know if
 
6024
                    // we start and end with whitespace.
 
6025
                    if (beginWS)
 
6026
                        // Go ahead and end the current line.
 
6027
                        updatePreferredWidth(m_minPreferredLogicalWidth, inlineMin);
 
6028
                    else {
 
6029
                        inlineMin += beginMin;
 
6030
                        updatePreferredWidth(m_minPreferredLogicalWidth, inlineMin);
 
6031
                        childMin -= ti;
 
6032
                    }
 
6033
 
 
6034
                    inlineMin = childMin;
 
6035
 
 
6036
                    if (endWS) {
 
6037
                        // We end in whitespace, which means we can go ahead
 
6038
                        // and end our current line.
 
6039
                        updatePreferredWidth(m_minPreferredLogicalWidth, inlineMin);
 
6040
                        inlineMin = 0;
 
6041
                        shouldBreakLineAfterText = false;
 
6042
                    } else {
 
6043
                        updatePreferredWidth(m_minPreferredLogicalWidth, inlineMin);
 
6044
                        inlineMin = endMin;
 
6045
                        shouldBreakLineAfterText = true;
 
6046
                    }
 
6047
                }
 
6048
 
 
6049
                if (hasBreak) {
 
6050
                    inlineMax += beginMax;
 
6051
                    updatePreferredWidth(m_maxPreferredLogicalWidth, inlineMax);
 
6052
                    updatePreferredWidth(m_maxPreferredLogicalWidth, childMax);
 
6053
                    inlineMax = endMax;
 
6054
                    addedTextIndent = true;
 
6055
                } else
 
6056
                    inlineMax += max<float>(0, childMax);
 
6057
            }
 
6058
 
 
6059
            // Ignore spaces after a list marker.
 
6060
            if (child->isListMarker())
 
6061
                stripFrontSpaces = true;
 
6062
        } else {
 
6063
            updatePreferredWidth(m_minPreferredLogicalWidth, inlineMin);
 
6064
            updatePreferredWidth(m_maxPreferredLogicalWidth, inlineMax);
 
6065
            inlineMin = inlineMax = 0;
 
6066
            stripFrontSpaces = true;
 
6067
            trailingSpaceChild = 0;
 
6068
            addedTextIndent = true;
 
6069
        }
 
6070
 
 
6071
        if (!child->isText() && child->isRenderInline())
 
6072
            isPrevChildInlineFlow = true;
 
6073
        else
 
6074
            isPrevChildInlineFlow = false;
 
6075
 
 
6076
        oldAutoWrap = autoWrap;
 
6077
    }
 
6078
 
 
6079
    if (styleToUse->collapseWhiteSpace())
 
6080
        stripTrailingSpace(inlineMax, inlineMin, trailingSpaceChild);
 
6081
 
 
6082
    updatePreferredWidth(m_minPreferredLogicalWidth, inlineMin);
 
6083
    updatePreferredWidth(m_maxPreferredLogicalWidth, inlineMax);
 
6084
}
 
6085
 
 
6086
void RenderBlock::computeBlockPreferredLogicalWidths()
 
6087
{
 
6088
    RenderStyle* styleToUse = style();
 
6089
    bool nowrap = styleToUse->whiteSpace() == NOWRAP;
 
6090
 
 
6091
    RenderObject* child = firstChild();
 
6092
    RenderBlock* containingBlock = this->containingBlock();
 
6093
    LayoutUnit floatLeftWidth = 0, floatRightWidth = 0;
 
6094
    while (child) {
 
6095
        // Positioned children don't affect the min/max width
 
6096
        if (child->isOutOfFlowPositioned()) {
 
6097
            child = child->nextSibling();
 
6098
            continue;
 
6099
        }
 
6100
 
 
6101
        RenderStyle* childStyle = child->style();
 
6102
        if (child->isFloating() || (child->isBox() && toRenderBox(child)->avoidsFloats())) {
 
6103
            LayoutUnit floatTotalWidth = floatLeftWidth + floatRightWidth;
 
6104
            if (childStyle->clear() & CLEFT) {
 
6105
                m_maxPreferredLogicalWidth = max(floatTotalWidth, m_maxPreferredLogicalWidth);
 
6106
                floatLeftWidth = 0;
 
6107
            }
 
6108
            if (childStyle->clear() & CRIGHT) {
 
6109
                m_maxPreferredLogicalWidth = max(floatTotalWidth, m_maxPreferredLogicalWidth);
 
6110
                floatRightWidth = 0;
 
6111
            }
 
6112
        }
 
6113
 
 
6114
        // A margin basically has three types: fixed, percentage, and auto (variable).
 
6115
        // Auto and percentage margins simply become 0 when computing min/max width.
 
6116
        // Fixed margins can be added in as is.
 
6117
        Length startMarginLength = childStyle->marginStartUsing(styleToUse);
 
6118
        Length endMarginLength = childStyle->marginEndUsing(styleToUse);
 
6119
        LayoutUnit margin = 0;
 
6120
        LayoutUnit marginStart = 0;
 
6121
        LayoutUnit marginEnd = 0;
 
6122
        if (startMarginLength.isFixed())
 
6123
            marginStart += startMarginLength.value();
 
6124
        if (endMarginLength.isFixed())
 
6125
            marginEnd += endMarginLength.value();
 
6126
        margin = marginStart + marginEnd;
 
6127
 
 
6128
        LayoutUnit childMinPreferredLogicalWidth, childMaxPreferredLogicalWidth;
 
6129
        if (child->isBox() && child->isHorizontalWritingMode() != isHorizontalWritingMode()) {
 
6130
            RenderBox* childBox = toRenderBox(child);
 
6131
            LogicalExtentComputedValues computedValues;
 
6132
            childBox->computeLogicalHeight(childBox->borderAndPaddingLogicalHeight(), 0, computedValues);
 
6133
            childMinPreferredLogicalWidth = childMaxPreferredLogicalWidth = computedValues.m_extent;
 
6134
        } else {
 
6135
            childMinPreferredLogicalWidth = child->minPreferredLogicalWidth();
 
6136
            childMaxPreferredLogicalWidth = child->maxPreferredLogicalWidth();
 
6137
        }
 
6138
 
 
6139
        LayoutUnit w = childMinPreferredLogicalWidth + margin;
 
6140
        m_minPreferredLogicalWidth = max(w, m_minPreferredLogicalWidth);
 
6141
        
 
6142
        // IE ignores tables for calculation of nowrap. Makes some sense.
 
6143
        if (nowrap && !child->isTable())
 
6144
            m_maxPreferredLogicalWidth = max(w, m_maxPreferredLogicalWidth);
 
6145
 
 
6146
        w = childMaxPreferredLogicalWidth + margin;
 
6147
 
 
6148
        if (!child->isFloating()) {
 
6149
            if (child->isBox() && toRenderBox(child)->avoidsFloats()) {
 
6150
                // Determine a left and right max value based off whether or not the floats can fit in the
 
6151
                // margins of the object.  For negative margins, we will attempt to overlap the float if the negative margin
 
6152
                // is smaller than the float width.
 
6153
                bool ltr = containingBlock ? containingBlock->style()->isLeftToRightDirection() : styleToUse->isLeftToRightDirection();
 
6154
                LayoutUnit marginLogicalLeft = ltr ? marginStart : marginEnd;
 
6155
                LayoutUnit marginLogicalRight = ltr ? marginEnd : marginStart;
 
6156
                LayoutUnit maxLeft = marginLogicalLeft > 0 ? max(floatLeftWidth, marginLogicalLeft) : floatLeftWidth + marginLogicalLeft;
 
6157
                LayoutUnit maxRight = marginLogicalRight > 0 ? max(floatRightWidth, marginLogicalRight) : floatRightWidth + marginLogicalRight;
 
6158
                w = childMaxPreferredLogicalWidth + maxLeft + maxRight;
 
6159
                w = max(w, floatLeftWidth + floatRightWidth);
 
6160
            }
 
6161
            else
 
6162
                m_maxPreferredLogicalWidth = max(floatLeftWidth + floatRightWidth, m_maxPreferredLogicalWidth);
 
6163
            floatLeftWidth = floatRightWidth = 0;
 
6164
        }
 
6165
        
 
6166
        if (child->isFloating()) {
 
6167
            if (styleToUse->floating() == LeftFloat)
 
6168
                floatLeftWidth += w;
 
6169
            else
 
6170
                floatRightWidth += w;
 
6171
        } else
 
6172
            m_maxPreferredLogicalWidth = max(w, m_maxPreferredLogicalWidth);
 
6173
        
 
6174
        child = child->nextSibling();
 
6175
    }
 
6176
 
 
6177
    // Always make sure these values are non-negative.
 
6178
    m_minPreferredLogicalWidth = max<LayoutUnit>(0, m_minPreferredLogicalWidth);
 
6179
    m_maxPreferredLogicalWidth = max<LayoutUnit>(0, m_maxPreferredLogicalWidth);
 
6180
 
 
6181
    m_maxPreferredLogicalWidth = max(floatLeftWidth + floatRightWidth, m_maxPreferredLogicalWidth);
 
6182
}
 
6183
 
 
6184
bool RenderBlock::hasLineIfEmpty() const
 
6185
{
 
6186
    if (!node())
 
6187
        return false;
 
6188
    
 
6189
    if (node()->isRootEditableElement())
 
6190
        return true;
 
6191
    
 
6192
    if (node()->isShadowRoot() && toShadowRoot(node())->host()->hasTagName(inputTag))
 
6193
        return true;
 
6194
    
 
6195
    return false;
 
6196
}
 
6197
 
 
6198
LayoutUnit RenderBlock::lineHeight(bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
 
6199
{
 
6200
    // Inline blocks are replaced elements. Otherwise, just pass off to
 
6201
    // the base class.  If we're being queried as though we're the root line
 
6202
    // box, then the fact that we're an inline-block is irrelevant, and we behave
 
6203
    // just like a block.
 
6204
    if (isReplaced() && linePositionMode == PositionOnContainingLine)
 
6205
        return RenderBox::lineHeight(firstLine, direction, linePositionMode);
 
6206
 
 
6207
    if (firstLine && document()->styleSheetCollection()->usesFirstLineRules()) {
 
6208
        RenderStyle* s = style(firstLine);
 
6209
        if (s != style())
 
6210
            return s->computedLineHeight(view());
 
6211
    }
 
6212
    
 
6213
    if (m_lineHeight == -1)
 
6214
        m_lineHeight = style()->computedLineHeight(view());
 
6215
 
 
6216
    return m_lineHeight;
 
6217
}
 
6218
 
 
6219
int RenderBlock::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
 
6220
{
 
6221
    // Inline blocks are replaced elements. Otherwise, just pass off to
 
6222
    // the base class.  If we're being queried as though we're the root line
 
6223
    // box, then the fact that we're an inline-block is irrelevant, and we behave
 
6224
    // just like a block.
 
6225
    if (isReplaced() && linePositionMode == PositionOnContainingLine) {
 
6226
        // For "leaf" theme objects, let the theme decide what the baseline position is.
 
6227
        // FIXME: Might be better to have a custom CSS property instead, so that if the theme
 
6228
        // is turned off, checkboxes/radios will still have decent baselines.
 
6229
        // FIXME: Need to patch form controls to deal with vertical lines.
 
6230
        if (style()->hasAppearance() && !theme()->isControlContainer(style()->appearance()))
 
6231
            return theme()->baselinePosition(this);
 
6232
            
 
6233
        // CSS2.1 states that the baseline of an inline block is the baseline of the last line box in
 
6234
        // the normal flow.  We make an exception for marquees, since their baselines are meaningless
 
6235
        // (the content inside them moves).  This matches WinIE as well, which just bottom-aligns them.
 
6236
        // We also give up on finding a baseline if we have a vertical scrollbar, or if we are scrolled
 
6237
        // vertically (e.g., an overflow:hidden block that has had scrollTop moved) or if the baseline is outside
 
6238
        // of our content box.
 
6239
        bool ignoreBaseline = (layer() && (layer()->marquee() || (direction == HorizontalLine ? (layer()->verticalScrollbar() || layer()->scrollYOffset() != 0)
 
6240
            : (layer()->horizontalScrollbar() || layer()->scrollXOffset() != 0)))) || (isWritingModeRoot() && !isRubyRun());
 
6241
        
 
6242
        int baselinePos = ignoreBaseline ? -1 : inlineBlockBaseline(direction);
 
6243
        
 
6244
        LayoutUnit bottomOfContent = direction == HorizontalLine ? borderTop() + paddingTop() + contentHeight() : borderRight() + paddingRight() + contentWidth();
 
6245
        if (baselinePos != -1 && baselinePos <= bottomOfContent)
 
6246
            return direction == HorizontalLine ? marginTop() + baselinePos : marginRight() + baselinePos;
 
6247
            
 
6248
        return RenderBox::baselinePosition(baselineType, firstLine, direction, linePositionMode);
 
6249
    }
 
6250
 
 
6251
    const FontMetrics& fontMetrics = style(firstLine)->fontMetrics();
 
6252
    return fontMetrics.ascent(baselineType) + (lineHeight(firstLine, direction, linePositionMode) - fontMetrics.height()) / 2;
 
6253
}
 
6254
 
 
6255
int RenderBlock::firstLineBoxBaseline() const
 
6256
{
 
6257
    if (!isBlockFlow() || (isWritingModeRoot() && !isRubyRun()))
 
6258
        return -1;
 
6259
 
 
6260
    if (childrenInline()) {
 
6261
        if (firstLineBox())
 
6262
            return firstLineBox()->logicalTop() + style(true)->fontMetrics().ascent(firstRootBox()->baselineType());
 
6263
        else
 
6264
            return -1;
 
6265
    }
 
6266
    else {
 
6267
        for (RenderBox* curr = firstChildBox(); curr; curr = curr->nextSiblingBox()) {
 
6268
            if (!curr->isFloatingOrOutOfFlowPositioned()) {
 
6269
                int result = curr->firstLineBoxBaseline();
 
6270
                if (result != -1)
 
6271
                    return curr->logicalTop() + result; // Translate to our coordinate space.
 
6272
            }
 
6273
        }
 
6274
    }
 
6275
 
 
6276
    return -1;
 
6277
}
 
6278
 
 
6279
int RenderBlock::inlineBlockBaseline(LineDirectionMode direction) const
 
6280
{
 
6281
    return lastLineBoxBaseline(direction);
 
6282
}
 
6283
 
 
6284
int RenderBlock::lastLineBoxBaseline(LineDirectionMode lineDirection) const
 
6285
{
 
6286
    if (!isBlockFlow() || (isWritingModeRoot() && !isRubyRun()))
 
6287
        return -1;
 
6288
 
 
6289
    if (childrenInline()) {
 
6290
        if (!firstLineBox() && hasLineIfEmpty()) {
 
6291
            const FontMetrics& fontMetrics = firstLineStyle()->fontMetrics();
 
6292
            return fontMetrics.ascent()
 
6293
                 + (lineHeight(true, lineDirection, PositionOfInteriorLineBoxes) - fontMetrics.height()) / 2
 
6294
                 + (lineDirection == HorizontalLine ? borderTop() + paddingTop() : borderRight() + paddingRight());
 
6295
        }
 
6296
        if (lastLineBox())
 
6297
            return lastLineBox()->logicalTop() + style(lastLineBox() == firstLineBox())->fontMetrics().ascent(lastRootBox()->baselineType());
 
6298
        return -1;
 
6299
    } else {
 
6300
        bool haveNormalFlowChild = false;
 
6301
        for (RenderBox* curr = lastChildBox(); curr; curr = curr->previousSiblingBox()) {
 
6302
            if (!curr->isFloatingOrOutOfFlowPositioned()) {
 
6303
                haveNormalFlowChild = true;
 
6304
                int result = curr->inlineBlockBaseline(lineDirection);
 
6305
                if (result != -1)
 
6306
                    return curr->logicalTop() + result; // Translate to our coordinate space.
 
6307
            }
 
6308
        }
 
6309
        if (!haveNormalFlowChild && hasLineIfEmpty()) {
 
6310
            const FontMetrics& fontMetrics = firstLineStyle()->fontMetrics();
 
6311
            return fontMetrics.ascent()
 
6312
                 + (lineHeight(true, lineDirection, PositionOfInteriorLineBoxes) - fontMetrics.height()) / 2
 
6313
                 + (lineDirection == HorizontalLine ? borderTop() + paddingTop() : borderRight() + paddingRight());
 
6314
        }
 
6315
    }
 
6316
 
 
6317
    return -1;
 
6318
}
 
6319
 
 
6320
bool RenderBlock::containsNonZeroBidiLevel() const
 
6321
{
 
6322
    for (RootInlineBox* root = firstRootBox(); root; root = root->nextRootBox()) {
 
6323
        for (InlineBox* box = root->firstLeafChild(); box; box = box->nextLeafChild()) {
 
6324
            if (box->bidiLevel())
 
6325
                return true;
 
6326
        }
 
6327
    }
 
6328
    return false;
 
6329
}
 
6330
 
 
6331
RenderBlock* RenderBlock::firstLineBlock() const
 
6332
{
 
6333
    RenderBlock* firstLineBlock = const_cast<RenderBlock*>(this);
 
6334
    bool hasPseudo = false;
 
6335
    while (true) {
 
6336
        hasPseudo = firstLineBlock->style()->hasPseudoStyle(FIRST_LINE);
 
6337
        if (hasPseudo)
 
6338
            break;
 
6339
        RenderObject* parentBlock = firstLineBlock->parent();
 
6340
        if (firstLineBlock->isReplaced() || firstLineBlock->isFloating() || 
 
6341
            !parentBlock || parentBlock->firstChild() != firstLineBlock || !parentBlock->isBlockFlow())
 
6342
            break;
 
6343
        ASSERT(parentBlock->isRenderBlock());
 
6344
        firstLineBlock = toRenderBlock(parentBlock);
 
6345
    } 
 
6346
    
 
6347
    if (!hasPseudo)
 
6348
        return 0;
 
6349
    
 
6350
    return firstLineBlock;
 
6351
}
 
6352
 
 
6353
static RenderStyle* styleForFirstLetter(RenderObject* firstLetterBlock, RenderObject* firstLetterContainer)
 
6354
{
 
6355
    RenderStyle* pseudoStyle = firstLetterBlock->getCachedPseudoStyle(FIRST_LETTER, firstLetterContainer->firstLineStyle());
 
6356
    // Force inline display (except for floating first-letters).
 
6357
    pseudoStyle->setDisplay(pseudoStyle->isFloating() ? BLOCK : INLINE);
 
6358
    // CSS2 says first-letter can't be positioned.
 
6359
    pseudoStyle->setPosition(StaticPosition);
 
6360
    return pseudoStyle;
 
6361
}
 
6362
 
 
6363
// CSS 2.1 http://www.w3.org/TR/CSS21/selector.html#first-letter
 
6364
// "Punctuation (i.e, characters defined in Unicode [UNICODE] in the "open" (Ps), "close" (Pe),
 
6365
// "initial" (Pi). "final" (Pf) and "other" (Po) punctuation classes), that precedes or follows the first letter should be included"
 
6366
static inline bool isPunctuationForFirstLetter(UChar c)
 
6367
{
 
6368
    CharCategory charCategory = category(c);
 
6369
    return charCategory == Punctuation_Open
 
6370
        || charCategory == Punctuation_Close
 
6371
        || charCategory == Punctuation_InitialQuote
 
6372
        || charCategory == Punctuation_FinalQuote
 
6373
        || charCategory == Punctuation_Other;
 
6374
}
 
6375
 
 
6376
static inline bool shouldSkipForFirstLetter(UChar c)
 
6377
{
 
6378
    return isSpaceOrNewline(c) || c == noBreakSpace || isPunctuationForFirstLetter(c);
 
6379
}
 
6380
 
 
6381
static inline RenderObject* findFirstLetterBlock(RenderBlock* start)
 
6382
{
 
6383
    RenderObject* firstLetterBlock = start;
 
6384
    while (true) {
 
6385
        bool canHaveFirstLetterRenderer = firstLetterBlock->style()->hasPseudoStyle(FIRST_LETTER)
 
6386
            && firstLetterBlock->canHaveGeneratedChildren();
 
6387
        if (canHaveFirstLetterRenderer)
 
6388
            return firstLetterBlock;
 
6389
 
 
6390
        RenderObject* parentBlock = firstLetterBlock->parent();
 
6391
        if (firstLetterBlock->isReplaced() || !parentBlock || parentBlock->firstChild() != firstLetterBlock || 
 
6392
            !parentBlock->isBlockFlow())
 
6393
            return 0;
 
6394
        firstLetterBlock = parentBlock;
 
6395
    } 
 
6396
 
 
6397
    return 0;
 
6398
}
 
6399
 
 
6400
void RenderBlock::updateFirstLetterStyle(RenderObject* firstLetterBlock, RenderObject* currentChild)
 
6401
{
 
6402
    RenderObject* firstLetter = currentChild->parent();
 
6403
    RenderObject* firstLetterContainer = firstLetter->parent();
 
6404
    RenderStyle* pseudoStyle = styleForFirstLetter(firstLetterBlock, firstLetterContainer);
 
6405
    ASSERT(firstLetter->isFloating() || firstLetter->isInline());
 
6406
 
 
6407
    if (Node::diff(firstLetter->style(), pseudoStyle, document()) == Node::Detach) {
 
6408
        // The first-letter renderer needs to be replaced. Create a new renderer of the right type.
 
6409
        RenderObject* newFirstLetter;
 
6410
        if (pseudoStyle->display() == INLINE)
 
6411
            newFirstLetter = new (renderArena()) RenderInline(document());
 
6412
        else
 
6413
            newFirstLetter = new (renderArena()) RenderBlock(document());
 
6414
        newFirstLetter->setStyle(pseudoStyle);
 
6415
 
 
6416
        // Move the first letter into the new renderer.
 
6417
        LayoutStateDisabler layoutStateDisabler(view());
 
6418
        while (RenderObject* child = firstLetter->firstChild()) {
 
6419
            if (child->isText())
 
6420
                toRenderText(child)->removeAndDestroyTextBoxes();
 
6421
            firstLetter->removeChild(child);
 
6422
            newFirstLetter->addChild(child, 0);
 
6423
        }
 
6424
 
 
6425
        RenderTextFragment* remainingText = 0;
 
6426
        RenderObject* nextSibling = firstLetter->nextSibling();
 
6427
        RenderObject* remainingTextObject = toRenderBoxModelObject(firstLetter)->firstLetterRemainingText();
 
6428
        if (remainingTextObject && remainingTextObject->isText() && toRenderText(remainingTextObject)->isTextFragment())
 
6429
            remainingText = toRenderTextFragment(remainingTextObject);
 
6430
        if (remainingText) {
 
6431
            ASSERT(remainingText->isAnonymous() || remainingText->node()->renderer() == remainingText);
 
6432
            // Replace the old renderer with the new one.
 
6433
            remainingText->setFirstLetter(newFirstLetter);
 
6434
            toRenderBoxModelObject(newFirstLetter)->setFirstLetterRemainingText(remainingText);
 
6435
        }
 
6436
        // To prevent removal of single anonymous block in RenderBlock::removeChild and causing
 
6437
        // |nextSibling| to go stale, we remove the old first letter using removeChildNode first.
 
6438
        firstLetterContainer->virtualChildren()->removeChildNode(firstLetterContainer, firstLetter);
 
6439
        firstLetter->destroy();
 
6440
        firstLetter = newFirstLetter;
 
6441
        firstLetterContainer->addChild(firstLetter, nextSibling);
 
6442
    } else
 
6443
        firstLetter->setStyle(pseudoStyle);
 
6444
 
 
6445
    for (RenderObject* genChild = firstLetter->firstChild(); genChild; genChild = genChild->nextSibling()) {
 
6446
        if (genChild->isText())
 
6447
            genChild->setStyle(pseudoStyle);
 
6448
    }
 
6449
}
 
6450
 
 
6451
void RenderBlock::createFirstLetterRenderer(RenderObject* firstLetterBlock, RenderObject* currentChild)
 
6452
{
 
6453
    RenderObject* firstLetterContainer = currentChild->parent();
 
6454
    RenderStyle* pseudoStyle = styleForFirstLetter(firstLetterBlock, firstLetterContainer);
 
6455
    RenderObject* firstLetter = 0;
 
6456
    if (pseudoStyle->display() == INLINE)
 
6457
        firstLetter = new (renderArena()) RenderInline(document());
 
6458
    else
 
6459
        firstLetter = new (renderArena()) RenderBlock(document());
 
6460
    firstLetter->setStyle(pseudoStyle);
 
6461
    firstLetterContainer->addChild(firstLetter, currentChild);
 
6462
 
 
6463
    RenderText* textObj = toRenderText(currentChild);
 
6464
 
 
6465
    // The original string is going to be either a generated content string or a DOM node's
 
6466
    // string.  We want the original string before it got transformed in case first-letter has
 
6467
    // no text-transform or a different text-transform applied to it.
 
6468
    RefPtr<StringImpl> oldText = textObj->originalText();
 
6469
    ASSERT(oldText);
 
6470
 
 
6471
    if (oldText && oldText->length() > 0) {
 
6472
        unsigned length = 0;
 
6473
 
 
6474
        // Account for leading spaces and punctuation.
 
6475
        while (length < oldText->length() && shouldSkipForFirstLetter((*oldText)[length]))
 
6476
            length++;
 
6477
 
 
6478
        // Account for first letter.
 
6479
        length++;
 
6480
        
 
6481
        // Keep looking for whitespace and allowed punctuation, but avoid
 
6482
        // accumulating just whitespace into the :first-letter.
 
6483
        for (unsigned scanLength = length; scanLength < oldText->length(); ++scanLength) {
 
6484
            UChar c = (*oldText)[scanLength]; 
 
6485
            
 
6486
            if (!shouldSkipForFirstLetter(c))
 
6487
                break;
 
6488
 
 
6489
            if (isPunctuationForFirstLetter(c))
 
6490
                length = scanLength + 1;
 
6491
         }
 
6492
         
 
6493
        // Construct a text fragment for the text after the first letter.
 
6494
        // This text fragment might be empty.
 
6495
        RenderTextFragment* remainingText = 
 
6496
            new (renderArena()) RenderTextFragment(textObj->node() ? textObj->node() : textObj->document(), oldText.get(), length, oldText->length() - length);
 
6497
        remainingText->setStyle(textObj->style());
 
6498
        if (remainingText->node())
 
6499
            remainingText->node()->setRenderer(remainingText);
 
6500
 
 
6501
        firstLetterContainer->addChild(remainingText, textObj);
 
6502
        firstLetterContainer->removeChild(textObj);
 
6503
        remainingText->setFirstLetter(firstLetter);
 
6504
        toRenderBoxModelObject(firstLetter)->setFirstLetterRemainingText(remainingText);
 
6505
        
 
6506
        // construct text fragment for the first letter
 
6507
        RenderTextFragment* letter = 
 
6508
            new (renderArena()) RenderTextFragment(remainingText->node() ? remainingText->node() : remainingText->document(), oldText.get(), 0, length);
 
6509
        letter->setStyle(pseudoStyle);
 
6510
        firstLetter->addChild(letter);
 
6511
 
 
6512
        textObj->destroy();
 
6513
    }
 
6514
}
 
6515
 
 
6516
void RenderBlock::updateFirstLetter()
 
6517
{
 
6518
    if (!document()->styleSheetCollection()->usesFirstLetterRules())
 
6519
        return;
 
6520
    // Don't recur
 
6521
    if (style()->styleType() == FIRST_LETTER)
 
6522
        return;
 
6523
 
 
6524
    // FIXME: We need to destroy the first-letter object if it is no longer the first child. Need to find
 
6525
    // an efficient way to check for that situation though before implementing anything.
 
6526
    RenderObject* firstLetterBlock = findFirstLetterBlock(this);
 
6527
    if (!firstLetterBlock)
 
6528
        return;
 
6529
 
 
6530
    // Drill into inlines looking for our first text child.
 
6531
    RenderObject* currChild = firstLetterBlock->firstChild();
 
6532
    while (currChild) {
 
6533
        if (currChild->isText())
 
6534
            break;
 
6535
        if (currChild->isListMarker())
 
6536
            currChild = currChild->nextSibling();
 
6537
        else if (currChild->isFloatingOrOutOfFlowPositioned()) {
 
6538
            if (currChild->style()->styleType() == FIRST_LETTER) {
 
6539
                currChild = currChild->firstChild();
 
6540
                break;
 
6541
            }
 
6542
            currChild = currChild->nextSibling();
 
6543
        } else if (currChild->isReplaced() || currChild->isRenderButton() || currChild->isMenuList())
 
6544
            break;
 
6545
        else if (currChild->style()->hasPseudoStyle(FIRST_LETTER) && currChild->canHaveGeneratedChildren())  {
 
6546
            // We found a lower-level node with first-letter, which supersedes the higher-level style
 
6547
            firstLetterBlock = currChild;
 
6548
            currChild = currChild->firstChild();
 
6549
        } else
 
6550
            currChild = currChild->firstChild();
 
6551
    }
 
6552
 
 
6553
    if (!currChild)
 
6554
        return;
 
6555
 
 
6556
    // If the child already has style, then it has already been created, so we just want
 
6557
    // to update it.
 
6558
    if (currChild->parent()->style()->styleType() == FIRST_LETTER) {
 
6559
        updateFirstLetterStyle(firstLetterBlock, currChild);
 
6560
        return;
 
6561
    }
 
6562
 
 
6563
    if (!currChild->isText() || currChild->isBR())
 
6564
        return;
 
6565
 
 
6566
    // Our layout state is not valid for the repaints we are going to trigger by
 
6567
    // adding and removing children of firstLetterContainer.
 
6568
    LayoutStateDisabler layoutStateDisabler(view());
 
6569
 
 
6570
    createFirstLetterRenderer(firstLetterBlock, currChild);
 
6571
}
 
6572
 
 
6573
// Helper methods for obtaining the last line, computing line counts and heights for line counts
 
6574
// (crawling into blocks).
 
6575
static bool shouldCheckLines(RenderObject* obj)
 
6576
{
 
6577
    return !obj->isFloatingOrOutOfFlowPositioned() && !obj->isRunIn()
 
6578
            && obj->isBlockFlow() && obj->style()->height().isAuto()
 
6579
            && (!obj->isDeprecatedFlexibleBox() || obj->style()->boxOrient() == VERTICAL);
 
6580
}
 
6581
 
 
6582
static RootInlineBox* getLineAtIndex(RenderBlock* block, int i, int& count)
 
6583
{
 
6584
    if (block->style()->visibility() == VISIBLE) {
 
6585
        if (block->childrenInline()) {
 
6586
            for (RootInlineBox* box = block->firstRootBox(); box; box = box->nextRootBox()) {
 
6587
                if (count++ == i)
 
6588
                    return box;
 
6589
            }
 
6590
        }
 
6591
        else {
 
6592
            for (RenderObject* obj = block->firstChild(); obj; obj = obj->nextSibling()) {
 
6593
                if (shouldCheckLines(obj)) {
 
6594
                    RootInlineBox *box = getLineAtIndex(toRenderBlock(obj), i, count);
 
6595
                    if (box)
 
6596
                        return box;
 
6597
                }
 
6598
            }
 
6599
        }
 
6600
    }
 
6601
    return 0;
 
6602
}
 
6603
 
 
6604
static int getHeightForLineCount(RenderBlock* block, int l, bool includeBottom, int& count)
 
6605
{
 
6606
    if (block->style()->visibility() == VISIBLE) {
 
6607
        if (block->childrenInline()) {
 
6608
            for (RootInlineBox* box = block->firstRootBox(); box; box = box->nextRootBox()) {
 
6609
                if (++count == l)
 
6610
                    return box->lineBottom() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : LayoutUnit());
 
6611
            }
 
6612
        }
 
6613
        else {
 
6614
            RenderBox* normalFlowChildWithoutLines = 0;
 
6615
            for (RenderBox* obj = block->firstChildBox(); obj; obj = obj->nextSiblingBox()) {
 
6616
                if (shouldCheckLines(obj)) {
 
6617
                    int result = getHeightForLineCount(toRenderBlock(obj), l, false, count);
 
6618
                    if (result != -1)
 
6619
                        return result + obj->y() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : LayoutUnit());
 
6620
                } else if (!obj->isFloatingOrOutOfFlowPositioned() && !obj->isRunIn())
 
6621
                    normalFlowChildWithoutLines = obj;
 
6622
            }
 
6623
            if (normalFlowChildWithoutLines && l == 0)
 
6624
                return normalFlowChildWithoutLines->y() + normalFlowChildWithoutLines->height();
 
6625
        }
 
6626
    }
 
6627
    
 
6628
    return -1;
 
6629
}
 
6630
 
 
6631
RootInlineBox* RenderBlock::lineAtIndex(int i)
 
6632
{
 
6633
    int count = 0;
 
6634
    return getLineAtIndex(this, i, count);
 
6635
}
 
6636
 
 
6637
int RenderBlock::lineCount()
 
6638
{
 
6639
    int count = 0;
 
6640
    if (style()->visibility() == VISIBLE) {
 
6641
        if (childrenInline())
 
6642
            for (RootInlineBox* box = firstRootBox(); box; box = box->nextRootBox())
 
6643
                count++;
 
6644
        else
 
6645
            for (RenderObject* obj = firstChild(); obj; obj = obj->nextSibling())
 
6646
                if (shouldCheckLines(obj))
 
6647
                    count += toRenderBlock(obj)->lineCount();
 
6648
    }
 
6649
    return count;
 
6650
}
 
6651
 
 
6652
int RenderBlock::heightForLineCount(int l)
 
6653
{
 
6654
    int count = 0;
 
6655
    return getHeightForLineCount(this, l, true, count);
 
6656
}
 
6657
 
 
6658
void RenderBlock::adjustForBorderFit(LayoutUnit x, LayoutUnit& left, LayoutUnit& right) const
 
6659
{
 
6660
    // We don't deal with relative positioning.  Our assumption is that you shrink to fit the lines without accounting
 
6661
    // for either overflow or translations via relative positioning.
 
6662
    if (style()->visibility() == VISIBLE) {
 
6663
        if (childrenInline()) {
 
6664
            for (RootInlineBox* box = firstRootBox(); box; box = box->nextRootBox()) {
 
6665
                if (box->firstChild())
 
6666
                    left = min(left, x + static_cast<LayoutUnit>(box->firstChild()->x()));
 
6667
                if (box->lastChild())
 
6668
                    right = max(right, x + static_cast<LayoutUnit>(ceilf(box->lastChild()->logicalRight())));
 
6669
            }
 
6670
        }
 
6671
        else {
 
6672
            for (RenderBox* obj = firstChildBox(); obj; obj = obj->nextSiblingBox()) {
 
6673
                if (!obj->isFloatingOrOutOfFlowPositioned()) {
 
6674
                    if (obj->isBlockFlow() && !obj->hasOverflowClip())
 
6675
                        toRenderBlock(obj)->adjustForBorderFit(x + obj->x(), left, right);
 
6676
                    else if (obj->style()->visibility() == VISIBLE) {
 
6677
                        // We are a replaced element or some kind of non-block-flow object.
 
6678
                        left = min(left, x + obj->x());
 
6679
                        right = max(right, x + obj->x() + obj->width());
 
6680
                    }
 
6681
                }
 
6682
            }
 
6683
        }
 
6684
        
 
6685
        if (m_floatingObjects) {
 
6686
            const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
 
6687
            FloatingObjectSetIterator end = floatingObjectSet.end();
 
6688
            for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
 
6689
                FloatingObject* r = *it;
 
6690
                // Only examine the object if our m_shouldPaint flag is set.
 
6691
                if (r->shouldPaint()) {
 
6692
                    LayoutUnit floatLeft = xPositionForFloatIncludingMargin(r) - r->m_renderer->x();
 
6693
                    LayoutUnit floatRight = floatLeft + r->m_renderer->width();
 
6694
                    left = min(left, floatLeft);
 
6695
                    right = max(right, floatRight);
 
6696
                }
 
6697
            }
 
6698
        }
 
6699
    }
 
6700
}
 
6701
 
 
6702
void RenderBlock::borderFitAdjust(LayoutRect& rect) const
 
6703
{
 
6704
    if (style()->borderFit() == BorderFitBorder)
 
6705
        return;
 
6706
 
 
6707
    // Walk any normal flow lines to snugly fit.
 
6708
    LayoutUnit left = LayoutUnit::max();
 
6709
    LayoutUnit right = LayoutUnit::min();
 
6710
    LayoutUnit oldWidth = rect.width();
 
6711
    adjustForBorderFit(0, left, right);
 
6712
    if (left != LayoutUnit::max()) {
 
6713
        left = min(left, oldWidth - (borderRight() + paddingRight()));
 
6714
 
 
6715
        left -= (borderLeft() + paddingLeft());
 
6716
        if (left > 0) {
 
6717
            rect.move(left, 0);
 
6718
            rect.expand(-left, 0);
 
6719
        }
 
6720
    }
 
6721
    if (right != LayoutUnit::min()) {
 
6722
        right = max(right, borderLeft() + paddingLeft());
 
6723
 
 
6724
        right += (borderRight() + paddingRight());
 
6725
        if (right < oldWidth)
 
6726
            rect.expand(-(oldWidth - right), 0);
 
6727
    }
 
6728
}
 
6729
 
 
6730
void RenderBlock::clearTruncation()
 
6731
{
 
6732
    if (style()->visibility() == VISIBLE) {
 
6733
        if (childrenInline() && hasMarkupTruncation()) {
 
6734
            setHasMarkupTruncation(false);
 
6735
            for (RootInlineBox* box = firstRootBox(); box; box = box->nextRootBox())
 
6736
                box->clearTruncation();
 
6737
        } else {
 
6738
            for (RenderObject* obj = firstChild(); obj; obj = obj->nextSibling()) {
 
6739
                if (shouldCheckLines(obj))
 
6740
                    toRenderBlock(obj)->clearTruncation();
 
6741
            }
 
6742
        }
 
6743
    }
 
6744
}
 
6745
 
 
6746
void RenderBlock::setMaxMarginBeforeValues(LayoutUnit pos, LayoutUnit neg)
 
6747
{
 
6748
    if (!m_rareData) {
 
6749
        if (pos == RenderBlockRareData::positiveMarginBeforeDefault(this) && neg == RenderBlockRareData::negativeMarginBeforeDefault(this))
 
6750
            return;
 
6751
        m_rareData = adoptPtr(new RenderBlockRareData(this));
 
6752
    }
 
6753
    m_rareData->m_margins.setPositiveMarginBefore(pos);
 
6754
    m_rareData->m_margins.setNegativeMarginBefore(neg);
 
6755
}
 
6756
 
 
6757
void RenderBlock::setMaxMarginAfterValues(LayoutUnit pos, LayoutUnit neg)
 
6758
{
 
6759
    if (!m_rareData) {
 
6760
        if (pos == RenderBlockRareData::positiveMarginAfterDefault(this) && neg == RenderBlockRareData::negativeMarginAfterDefault(this))
 
6761
            return;
 
6762
        m_rareData = adoptPtr(new RenderBlockRareData(this));
 
6763
    }
 
6764
    m_rareData->m_margins.setPositiveMarginAfter(pos);
 
6765
    m_rareData->m_margins.setNegativeMarginAfter(neg);
 
6766
}
 
6767
 
 
6768
void RenderBlock::setPaginationStrut(LayoutUnit strut)
 
6769
{
 
6770
    if (!m_rareData) {
 
6771
        if (!strut)
 
6772
            return;
 
6773
        m_rareData = adoptPtr(new RenderBlockRareData(this));
 
6774
    }
 
6775
    m_rareData->m_paginationStrut = strut;
 
6776
}
 
6777
 
 
6778
void RenderBlock::setPageLogicalOffset(LayoutUnit logicalOffset)
 
6779
{
 
6780
    if (!m_rareData) {
 
6781
        if (!logicalOffset)
 
6782
            return;
 
6783
        m_rareData = adoptPtr(new RenderBlockRareData(this));
 
6784
    }
 
6785
    m_rareData->m_pageLogicalOffset = logicalOffset;
 
6786
}
 
6787
 
 
6788
void RenderBlock::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
 
6789
{
 
6790
    // For blocks inside inlines, we go ahead and include margins so that we run right up to the
 
6791
    // inline boxes above and below us (thus getting merged with them to form a single irregular
 
6792
    // shape).
 
6793
    if (isAnonymousBlockContinuation()) {
 
6794
        // FIXME: This is wrong for block-flows that are horizontal.
 
6795
        // https://bugs.webkit.org/show_bug.cgi?id=46781
 
6796
        rects.append(pixelSnappedIntRect(accumulatedOffset.x(), accumulatedOffset.y() - collapsedMarginBefore(),
 
6797
                                width(), height() + collapsedMarginBefore() + collapsedMarginAfter()));
 
6798
        continuation()->absoluteRects(rects, accumulatedOffset - toLayoutSize(location() +
 
6799
                inlineElementContinuation()->containingBlock()->location()));
 
6800
    } else
 
6801
        rects.append(pixelSnappedIntRect(accumulatedOffset, size()));
 
6802
}
 
6803
 
 
6804
void RenderBlock::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
 
6805
{
 
6806
    // For blocks inside inlines, we go ahead and include margins so that we run right up to the
 
6807
    // inline boxes above and below us (thus getting merged with them to form a single irregular
 
6808
    // shape).
 
6809
    if (isAnonymousBlockContinuation()) {
 
6810
        // FIXME: This is wrong for block-flows that are horizontal.
 
6811
        // https://bugs.webkit.org/show_bug.cgi?id=46781
 
6812
        FloatRect localRect(0, -collapsedMarginBefore(),
 
6813
                            width(), height() + collapsedMarginBefore() + collapsedMarginAfter());
 
6814
        quads.append(localToAbsoluteQuad(localRect, 0 /* mode */, wasFixed));
 
6815
        continuation()->absoluteQuads(quads, wasFixed);
 
6816
    } else
 
6817
        quads.append(RenderBox::localToAbsoluteQuad(FloatRect(0, 0, width(), height()), 0 /* mode */, wasFixed));
 
6818
}
 
6819
 
 
6820
LayoutRect RenderBlock::rectWithOutlineForRepaint(const RenderLayerModelObject* repaintContainer, LayoutUnit outlineWidth) const
 
6821
{
 
6822
    LayoutRect r(RenderBox::rectWithOutlineForRepaint(repaintContainer, outlineWidth));
 
6823
    if (isAnonymousBlockContinuation())
 
6824
        r.inflateY(collapsedMarginBefore()); // FIXME: This is wrong for block-flows that are horizontal.
 
6825
    return r;
 
6826
}
 
6827
 
 
6828
RenderObject* RenderBlock::hoverAncestor() const
 
6829
{
 
6830
    return isAnonymousBlockContinuation() ? continuation() : RenderBox::hoverAncestor();
 
6831
}
 
6832
 
 
6833
void RenderBlock::updateDragState(bool dragOn)
 
6834
{
 
6835
    RenderBox::updateDragState(dragOn);
 
6836
    if (continuation())
 
6837
        continuation()->updateDragState(dragOn);
 
6838
}
 
6839
 
 
6840
RenderStyle* RenderBlock::outlineStyleForRepaint() const
 
6841
{
 
6842
    return isAnonymousBlockContinuation() ? continuation()->style() : style();
 
6843
}
 
6844
 
 
6845
void RenderBlock::childBecameNonInline(RenderObject*)
 
6846
{
 
6847
    makeChildrenNonInline();
 
6848
    if (isAnonymousBlock() && parent() && parent()->isRenderBlock())
 
6849
        toRenderBlock(parent())->removeLeftoverAnonymousBlock(this);
 
6850
    // |this| may be dead here
 
6851
}
 
6852
 
 
6853
void RenderBlock::updateHitTestResult(HitTestResult& result, const LayoutPoint& point)
 
6854
{
 
6855
    if (result.innerNode())
 
6856
        return;
 
6857
 
 
6858
    if (Node* n = nodeForHitTest()) {
 
6859
        result.setInnerNode(n);
 
6860
        if (!result.innerNonSharedNode())
 
6861
            result.setInnerNonSharedNode(n);
 
6862
        result.setLocalPoint(point);
 
6863
    }
 
6864
}
 
6865
 
 
6866
LayoutRect RenderBlock::localCaretRect(InlineBox* inlineBox, int caretOffset, LayoutUnit* extraWidthToEndOfLine)
 
6867
{
 
6868
    // Do the normal calculation in most cases.
 
6869
    if (firstChild())
 
6870
        return RenderBox::localCaretRect(inlineBox, caretOffset, extraWidthToEndOfLine);
 
6871
 
 
6872
    LayoutRect caretRect = localCaretRectForEmptyElement(width(), textIndentOffset());
 
6873
 
 
6874
    if (extraWidthToEndOfLine) {
 
6875
        if (isRenderBlock()) {
 
6876
            *extraWidthToEndOfLine = width() - caretRect.maxX();
 
6877
        } else {
 
6878
            // FIXME: This code looks wrong.
 
6879
            // myRight and containerRight are set up, but then clobbered.
 
6880
            // So *extraWidthToEndOfLine will always be 0 here.
 
6881
 
 
6882
            LayoutUnit myRight = caretRect.maxX();
 
6883
            // FIXME: why call localToAbsoluteForContent() twice here, too?
 
6884
            FloatPoint absRightPoint = localToAbsolute(FloatPoint(myRight, 0));
 
6885
 
 
6886
            LayoutUnit containerRight = containingBlock()->x() + containingBlockLogicalWidthForContent();
 
6887
            FloatPoint absContainerPoint = localToAbsolute(FloatPoint(containerRight, 0));
 
6888
 
 
6889
            *extraWidthToEndOfLine = absContainerPoint.x() - absRightPoint.x();
 
6890
        }
 
6891
    }
 
6892
 
 
6893
    return caretRect;
 
6894
}
 
6895
 
 
6896
void RenderBlock::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint& additionalOffset)
 
6897
{
 
6898
    // For blocks inside inlines, we go ahead and include margins so that we run right up to the
 
6899
    // inline boxes above and below us (thus getting merged with them to form a single irregular
 
6900
    // shape).
 
6901
    if (inlineElementContinuation()) {
 
6902
        // FIXME: This check really isn't accurate. 
 
6903
        bool nextInlineHasLineBox = inlineElementContinuation()->firstLineBox();
 
6904
        // FIXME: This is wrong. The principal renderer may not be the continuation preceding this block.
 
6905
        // FIXME: This is wrong for block-flows that are horizontal.
 
6906
        // https://bugs.webkit.org/show_bug.cgi?id=46781
 
6907
        bool prevInlineHasLineBox = toRenderInline(inlineElementContinuation()->node()->renderer())->firstLineBox(); 
 
6908
        float topMargin = prevInlineHasLineBox ? collapsedMarginBefore() : LayoutUnit();
 
6909
        float bottomMargin = nextInlineHasLineBox ? collapsedMarginAfter() : LayoutUnit();
 
6910
        LayoutRect rect(additionalOffset.x(), additionalOffset.y() - topMargin, width(), height() + topMargin + bottomMargin);
 
6911
        if (!rect.isEmpty())
 
6912
            rects.append(pixelSnappedIntRect(rect));
 
6913
    } else if (width() && height())
 
6914
        rects.append(pixelSnappedIntRect(additionalOffset, size()));
 
6915
 
 
6916
    if (!hasOverflowClip() && !hasControlClip()) {
 
6917
        for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
 
6918
            LayoutUnit top = max<LayoutUnit>(curr->lineTop(), curr->top());
 
6919
            LayoutUnit bottom = min<LayoutUnit>(curr->lineBottom(), curr->top() + curr->height());
 
6920
            LayoutRect rect(additionalOffset.x() + curr->x(), additionalOffset.y() + top, curr->width(), bottom - top);
 
6921
            if (!rect.isEmpty())
 
6922
                rects.append(pixelSnappedIntRect(rect));
 
6923
        }
 
6924
 
 
6925
        for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
 
6926
            if (!curr->isText() && !curr->isListMarker() && curr->isBox()) {
 
6927
                RenderBox* box = toRenderBox(curr);
 
6928
                FloatPoint pos;
 
6929
                // FIXME: This doesn't work correctly with transforms.
 
6930
                if (box->layer()) 
 
6931
                    pos = curr->localToAbsolute();
 
6932
                else
 
6933
                    pos = FloatPoint(additionalOffset.x() + box->x(), additionalOffset.y() + box->y());
 
6934
                box->addFocusRingRects(rects, flooredLayoutPoint(pos));
 
6935
            }
 
6936
        }
 
6937
    }
 
6938
 
 
6939
    if (inlineElementContinuation())
 
6940
        inlineElementContinuation()->addFocusRingRects(rects, flooredLayoutPoint(additionalOffset + inlineElementContinuation()->containingBlock()->location() - location()));
 
6941
}
 
6942
 
 
6943
RenderBox* RenderBlock::createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const
 
6944
{
 
6945
    if (isAnonymousColumnsBlock())
 
6946
        return createAnonymousColumnsWithParentRenderer(parent);
 
6947
    if (isAnonymousColumnSpanBlock())
 
6948
        return createAnonymousColumnSpanWithParentRenderer(parent);
 
6949
    return createAnonymousWithParentRendererAndDisplay(parent, style()->display());
 
6950
}
 
6951
 
 
6952
bool RenderBlock::hasNextPage(LayoutUnit logicalOffset, PageBoundaryRule pageBoundaryRule) const
 
6953
{
 
6954
    ASSERT(view()->layoutState() && view()->layoutState()->isPaginated());
 
6955
 
 
6956
    if (!inRenderFlowThread())
 
6957
        return true; // Printing and multi-column both make new pages to accommodate content.
 
6958
 
 
6959
    // See if we're in the last region.
 
6960
    LayoutUnit pageOffset = offsetFromLogicalTopOfFirstPage() + logicalOffset;
 
6961
    RenderRegion* region = enclosingRenderFlowThread()->regionAtBlockOffset(pageOffset, this);
 
6962
    if (!region)
 
6963
        return false;
 
6964
    if (region->isLastRegion())
 
6965
        return region->isRenderRegionSet() || region->style()->regionOverflow() == BreakRegionOverflow
 
6966
            || (pageBoundaryRule == IncludePageBoundary && pageOffset == region->logicalTopForFlowThreadContent());
 
6967
    return true;
 
6968
}
 
6969
 
 
6970
LayoutUnit RenderBlock::nextPageLogicalTop(LayoutUnit logicalOffset, PageBoundaryRule pageBoundaryRule) const
 
6971
{
 
6972
    LayoutUnit pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset);
 
6973
    if (!pageLogicalHeight)
 
6974
        return logicalOffset;
 
6975
    
 
6976
    // The logicalOffset is in our coordinate space.  We can add in our pushed offset.
 
6977
    LayoutUnit remainingLogicalHeight = pageRemainingLogicalHeightForOffset(logicalOffset);
 
6978
    if (pageBoundaryRule == ExcludePageBoundary)
 
6979
        return logicalOffset + (remainingLogicalHeight ? remainingLogicalHeight : pageLogicalHeight);
 
6980
    return logicalOffset + remainingLogicalHeight;
 
6981
}
 
6982
 
 
6983
static bool inNormalFlow(RenderBox* child)
 
6984
{
 
6985
    RenderBlock* curr = child->containingBlock();
 
6986
    RenderView* renderView = child->view();
 
6987
    while (curr && curr != renderView) {
 
6988
        if (curr->hasColumns() || curr->isRenderFlowThread())
 
6989
            return true;
 
6990
        if (curr->isFloatingOrOutOfFlowPositioned())
 
6991
            return false;
 
6992
        curr = curr->containingBlock();
 
6993
    }
 
6994
    return true;
 
6995
}
 
6996
 
 
6997
ColumnInfo::PaginationUnit RenderBlock::paginationUnit() const
 
6998
{
 
6999
    return ColumnInfo::Column;
 
7000
}
 
7001
 
 
7002
LayoutUnit RenderBlock::applyBeforeBreak(RenderBox* child, LayoutUnit logicalOffset)
 
7003
{
 
7004
    // FIXME: Add page break checking here when we support printing.
 
7005
    bool checkColumnBreaks = view()->layoutState()->isPaginatingColumns();
 
7006
    bool checkPageBreaks = !checkColumnBreaks && view()->layoutState()->m_pageLogicalHeight; // FIXME: Once columns can print we have to check this.
 
7007
    bool checkRegionBreaks = inRenderFlowThread();
 
7008
    bool checkBeforeAlways = (checkColumnBreaks && child->style()->columnBreakBefore() == PBALWAYS) || (checkPageBreaks && child->style()->pageBreakBefore() == PBALWAYS)
 
7009
                             || (checkRegionBreaks && child->style()->regionBreakBefore() == PBALWAYS);
 
7010
    if (checkBeforeAlways && inNormalFlow(child) && hasNextPage(logicalOffset, IncludePageBoundary)) {
 
7011
        if (checkColumnBreaks)
 
7012
            view()->layoutState()->addForcedColumnBreak(child, logicalOffset);
 
7013
        if (checkRegionBreaks) {
 
7014
            LayoutUnit offsetBreakAdjustment = 0;
 
7015
            if (enclosingRenderFlowThread()->addForcedRegionBreak(offsetFromLogicalTopOfFirstPage() + logicalOffset, child, true, &offsetBreakAdjustment))
 
7016
                return logicalOffset + offsetBreakAdjustment;
 
7017
        }
 
7018
        return nextPageLogicalTop(logicalOffset, IncludePageBoundary);
 
7019
    }
 
7020
    return logicalOffset;
 
7021
}
 
7022
 
 
7023
LayoutUnit RenderBlock::applyAfterBreak(RenderBox* child, LayoutUnit logicalOffset, MarginInfo& marginInfo)
 
7024
{
 
7025
    // FIXME: Add page break checking here when we support printing.
 
7026
    bool checkColumnBreaks = view()->layoutState()->isPaginatingColumns();
 
7027
    bool checkPageBreaks = !checkColumnBreaks && view()->layoutState()->m_pageLogicalHeight; // FIXME: Once columns can print we have to check this.
 
7028
    bool checkRegionBreaks = inRenderFlowThread();
 
7029
    bool checkAfterAlways = (checkColumnBreaks && child->style()->columnBreakAfter() == PBALWAYS) || (checkPageBreaks && child->style()->pageBreakAfter() == PBALWAYS)
 
7030
                            || (checkRegionBreaks && child->style()->regionBreakAfter() == PBALWAYS);
 
7031
    if (checkAfterAlways && inNormalFlow(child) && hasNextPage(logicalOffset, IncludePageBoundary)) {
 
7032
        marginInfo.setMarginAfterQuirk(true); // Cause margins to be discarded for any following content.
 
7033
        if (checkColumnBreaks)
 
7034
            view()->layoutState()->addForcedColumnBreak(child, logicalOffset);
 
7035
        if (checkRegionBreaks) {
 
7036
            LayoutUnit marginOffset = marginInfo.canCollapseWithMarginBefore() ? LayoutUnit() : marginInfo.margin();
 
7037
            LayoutUnit offsetBreakAdjustment = 0;
 
7038
            if (enclosingRenderFlowThread()->addForcedRegionBreak(offsetFromLogicalTopOfFirstPage() + logicalOffset + marginOffset, child, false, &offsetBreakAdjustment))
 
7039
                return logicalOffset + offsetBreakAdjustment;
 
7040
        }
 
7041
        return nextPageLogicalTop(logicalOffset, IncludePageBoundary);
 
7042
    }
 
7043
    return logicalOffset;
 
7044
}
 
7045
 
 
7046
LayoutUnit RenderBlock::pageLogicalTopForOffset(LayoutUnit offset) const
 
7047
{
 
7048
    RenderView* renderView = view();
 
7049
    LayoutUnit firstPageLogicalTop = isHorizontalWritingMode() ? renderView->layoutState()->m_pageOffset.height() : renderView->layoutState()->m_pageOffset.width();
 
7050
    LayoutUnit blockLogicalTop = isHorizontalWritingMode() ? renderView->layoutState()->m_layoutOffset.height() : renderView->layoutState()->m_layoutOffset.width();
 
7051
 
 
7052
    LayoutUnit cumulativeOffset = offset + blockLogicalTop;
 
7053
    if (!inRenderFlowThread()) {
 
7054
        LayoutUnit pageLogicalHeight = renderView->layoutState()->pageLogicalHeight();
 
7055
        if (!pageLogicalHeight)
 
7056
            return 0;
 
7057
        return cumulativeOffset - roundToInt(cumulativeOffset - firstPageLogicalTop) % roundToInt(pageLogicalHeight);
 
7058
    }
 
7059
    return enclosingRenderFlowThread()->pageLogicalTopForOffset(cumulativeOffset);
 
7060
}
 
7061
 
 
7062
LayoutUnit RenderBlock::pageLogicalHeightForOffset(LayoutUnit offset) const
 
7063
{
 
7064
    RenderView* renderView = view();
 
7065
    if (!inRenderFlowThread())
 
7066
        return renderView->layoutState()->m_pageLogicalHeight;
 
7067
    return enclosingRenderFlowThread()->pageLogicalHeightForOffset(offset + offsetFromLogicalTopOfFirstPage());
 
7068
}
 
7069
 
 
7070
LayoutUnit RenderBlock::pageRemainingLogicalHeightForOffset(LayoutUnit offset, PageBoundaryRule pageBoundaryRule) const
 
7071
{
 
7072
    RenderView* renderView = view();
 
7073
    offset += offsetFromLogicalTopOfFirstPage();
 
7074
    
 
7075
    if (!inRenderFlowThread()) {
 
7076
        LayoutUnit pageLogicalHeight = renderView->layoutState()->m_pageLogicalHeight;
 
7077
        LayoutUnit remainingHeight = pageLogicalHeight - intMod(offset, pageLogicalHeight);
 
7078
        if (pageBoundaryRule == IncludePageBoundary) {
 
7079
            // If includeBoundaryPoint is true the line exactly on the top edge of a
 
7080
            // column will act as being part of the previous column.
 
7081
            remainingHeight = intMod(remainingHeight, pageLogicalHeight);
 
7082
        }
 
7083
        return remainingHeight;
 
7084
    }
 
7085
    
 
7086
    return enclosingRenderFlowThread()->pageRemainingLogicalHeightForOffset(offset, pageBoundaryRule);
 
7087
}
 
7088
 
 
7089
LayoutUnit RenderBlock::adjustForUnsplittableChild(RenderBox* child, LayoutUnit logicalOffset, bool includeMargins)
 
7090
{
 
7091
    bool checkColumnBreaks = view()->layoutState()->isPaginatingColumns();
 
7092
    bool checkPageBreaks = !checkColumnBreaks && view()->layoutState()->m_pageLogicalHeight;
 
7093
    bool checkRegionBreaks = inRenderFlowThread();
 
7094
    bool isUnsplittable = child->isUnsplittableForPagination() || (checkColumnBreaks && child->style()->columnBreakInside() == PBAVOID)
 
7095
        || (checkPageBreaks && child->style()->pageBreakInside() == PBAVOID)
 
7096
        || (checkRegionBreaks && child->style()->regionBreakInside() == PBAVOID);
 
7097
    if (!isUnsplittable)
 
7098
        return logicalOffset;
 
7099
    LayoutUnit childLogicalHeight = logicalHeightForChild(child) + (includeMargins ? marginBeforeForChild(child) + marginAfterForChild(child) : LayoutUnit());
 
7100
    LayoutState* layoutState = view()->layoutState();
 
7101
    if (layoutState->m_columnInfo)
 
7102
        layoutState->m_columnInfo->updateMinimumColumnHeight(childLogicalHeight);
 
7103
    LayoutUnit pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset);
 
7104
    bool hasUniformPageLogicalHeight = !inRenderFlowThread() || enclosingRenderFlowThread()->regionsHaveUniformLogicalHeight();
 
7105
    if (!pageLogicalHeight || (hasUniformPageLogicalHeight && childLogicalHeight > pageLogicalHeight)
 
7106
        || !hasNextPage(logicalOffset))
 
7107
        return logicalOffset;
 
7108
    LayoutUnit remainingLogicalHeight = pageRemainingLogicalHeightForOffset(logicalOffset, ExcludePageBoundary);
 
7109
    if (remainingLogicalHeight < childLogicalHeight) {
 
7110
        if (!hasUniformPageLogicalHeight && !pushToNextPageWithMinimumLogicalHeight(remainingLogicalHeight, logicalOffset, childLogicalHeight))
 
7111
            return logicalOffset;
 
7112
        return logicalOffset + remainingLogicalHeight;
 
7113
    }
 
7114
    return logicalOffset;
 
7115
}
 
7116
 
 
7117
bool RenderBlock::pushToNextPageWithMinimumLogicalHeight(LayoutUnit& adjustment, LayoutUnit logicalOffset, LayoutUnit minimumLogicalHeight) const
 
7118
{
 
7119
    bool checkRegion = false;
 
7120
    for (LayoutUnit pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset + adjustment); pageLogicalHeight;
 
7121
        pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset + adjustment)) {
 
7122
        if (minimumLogicalHeight <= pageLogicalHeight)
 
7123
            return true;
 
7124
        if (!hasNextPage(logicalOffset + adjustment))
 
7125
            return false;
 
7126
        adjustment += pageLogicalHeight;
 
7127
        checkRegion = true;
 
7128
    }
 
7129
    return !checkRegion;
 
7130
}
 
7131
 
 
7132
void RenderBlock::adjustLinePositionForPagination(RootInlineBox* lineBox, LayoutUnit& delta)
 
7133
{
 
7134
    // FIXME: For now we paginate using line overflow.  This ensures that lines don't overlap at all when we
 
7135
    // put a strut between them for pagination purposes.  However, this really isn't the desired rendering, since
 
7136
    // the line on the top of the next page will appear too far down relative to the same kind of line at the top
 
7137
    // of the first column.
 
7138
    //
 
7139
    // The rendering we would like to see is one where the lineTopWithLeading is at the top of the column, and any line overflow
 
7140
    // simply spills out above the top of the column.  This effect would match what happens at the top of the first column.
 
7141
    // We can't achieve this rendering, however, until we stop columns from clipping to the column bounds (thus allowing
 
7142
    // for overflow to occur), and then cache visible overflow for each column rect.
 
7143
    //
 
7144
    // Furthermore, the paint we have to do when a column has overflow has to be special.  We need to exclude
 
7145
    // content that paints in a previous column (and content that paints in the following column).
 
7146
    //
 
7147
    // For now we'll at least honor the lineTopWithLeading when paginating if it is above the logical top overflow. This will
 
7148
    // at least make positive leading work in typical cases.
 
7149
    //
 
7150
    // FIXME: Another problem with simply moving lines is that the available line width may change (because of floats).
 
7151
    // Technically if the location we move the line to has a different line width than our old position, then we need to dirty the
 
7152
    // line and all following lines.
 
7153
    LayoutRect logicalVisualOverflow = lineBox->logicalVisualOverflowRect(lineBox->lineTop(), lineBox->lineBottom());
 
7154
    LayoutUnit logicalOffset = min(lineBox->lineTopWithLeading(), logicalVisualOverflow.y());
 
7155
    LayoutUnit lineHeight = max(lineBox->lineBottomWithLeading(), logicalVisualOverflow.maxY()) - logicalOffset;
 
7156
    RenderView* renderView = view();
 
7157
    LayoutState* layoutState = renderView->layoutState();
 
7158
    if (layoutState->m_columnInfo)
 
7159
        layoutState->m_columnInfo->updateMinimumColumnHeight(lineHeight);
 
7160
    logicalOffset += delta;
 
7161
    lineBox->setPaginationStrut(0);
 
7162
    lineBox->setIsFirstAfterPageBreak(false);
 
7163
    LayoutUnit pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset);
 
7164
    bool hasUniformPageLogicalHeight = !inRenderFlowThread() || enclosingRenderFlowThread()->regionsHaveUniformLogicalHeight();
 
7165
    // If lineHeight is greater than pageLogicalHeight, but logicalVisualOverflow.height() still fits, we are
 
7166
    // still going to add a strut, so that the visible overflow fits on a single page.
 
7167
    if (!pageLogicalHeight || (hasUniformPageLogicalHeight && logicalVisualOverflow.height() > pageLogicalHeight)
 
7168
        || !hasNextPage(logicalOffset))
 
7169
        return;
 
7170
    LayoutUnit remainingLogicalHeight = pageRemainingLogicalHeightForOffset(logicalOffset, ExcludePageBoundary);
 
7171
    if (remainingLogicalHeight < lineHeight) {
 
7172
        // If we have a non-uniform page height, then we have to shift further possibly.
 
7173
        if (!hasUniformPageLogicalHeight && !pushToNextPageWithMinimumLogicalHeight(remainingLogicalHeight, logicalOffset, lineHeight))
 
7174
            return;
 
7175
        if (lineHeight > pageLogicalHeight) {
 
7176
            // Split the top margin in order to avoid splitting the visible part of the line.
 
7177
            remainingLogicalHeight -= min(lineHeight - pageLogicalHeight, max<LayoutUnit>(0, logicalVisualOverflow.y() - lineBox->lineTopWithLeading()));
 
7178
        }
 
7179
        LayoutUnit totalLogicalHeight = lineHeight + max<LayoutUnit>(0, logicalOffset);
 
7180
        LayoutUnit pageLogicalHeightAtNewOffset = hasUniformPageLogicalHeight ? pageLogicalHeight : pageLogicalHeightForOffset(logicalOffset + remainingLogicalHeight);
 
7181
        if (lineBox == firstRootBox() && totalLogicalHeight < pageLogicalHeightAtNewOffset && !isOutOfFlowPositioned() && !isTableCell())
 
7182
            setPaginationStrut(remainingLogicalHeight + max<LayoutUnit>(0, logicalOffset));
 
7183
        else {
 
7184
            delta += remainingLogicalHeight;
 
7185
            lineBox->setPaginationStrut(remainingLogicalHeight);
 
7186
            lineBox->setIsFirstAfterPageBreak(true);
 
7187
        }
 
7188
    } else if (remainingLogicalHeight == pageLogicalHeight && lineBox != firstRootBox())
 
7189
        lineBox->setIsFirstAfterPageBreak(true);
 
7190
}
 
7191
 
 
7192
LayoutUnit RenderBlock::adjustBlockChildForPagination(LayoutUnit logicalTopAfterClear, LayoutUnit estimateWithoutPagination, RenderBox* child, bool atBeforeSideOfBlock)
 
7193
{
 
7194
    RenderBlock* childRenderBlock = child->isRenderBlock() ? toRenderBlock(child) : 0;
 
7195
 
 
7196
    if (estimateWithoutPagination != logicalTopAfterClear) {
 
7197
        // Our guess prior to pagination movement was wrong. Before we attempt to paginate, let's try again at the new
 
7198
        // position.
 
7199
        setLogicalHeight(logicalTopAfterClear);
 
7200
        setLogicalTopForChild(child, logicalTopAfterClear, ApplyLayoutDelta);
 
7201
 
 
7202
        if (child->shrinkToAvoidFloats()) {
 
7203
            // The child's width depends on the line width.
 
7204
            // When the child shifts to clear an item, its width can
 
7205
            // change (because it has more available line width).
 
7206
            // So go ahead and mark the item as dirty.
 
7207
            child->setChildNeedsLayout(true, MarkOnlyThis);
 
7208
        }
 
7209
        
 
7210
        if (childRenderBlock) {
 
7211
            if (!child->avoidsFloats() && childRenderBlock->containsFloats())
 
7212
                childRenderBlock->markAllDescendantsWithFloatsForLayout();
 
7213
            if (!child->needsLayout())
 
7214
                child->markForPaginationRelayoutIfNeeded();
 
7215
        }
 
7216
 
 
7217
        // Our guess was wrong. Make the child lay itself out again.
 
7218
        child->layoutIfNeeded();
 
7219
    }
 
7220
 
 
7221
    LayoutUnit oldTop = logicalTopAfterClear;
 
7222
 
 
7223
    // If the object has a page or column break value of "before", then we should shift to the top of the next page.
 
7224
    LayoutUnit result = applyBeforeBreak(child, logicalTopAfterClear);
 
7225
 
 
7226
    // For replaced elements and scrolled elements, we want to shift them to the next page if they don't fit on the current one.
 
7227
    LayoutUnit logicalTopBeforeUnsplittableAdjustment = result;
 
7228
    LayoutUnit logicalTopAfterUnsplittableAdjustment = adjustForUnsplittableChild(child, result);
 
7229
    
 
7230
    LayoutUnit paginationStrut = 0;
 
7231
    LayoutUnit unsplittableAdjustmentDelta = logicalTopAfterUnsplittableAdjustment - logicalTopBeforeUnsplittableAdjustment;
 
7232
    if (unsplittableAdjustmentDelta)
 
7233
        paginationStrut = unsplittableAdjustmentDelta;
 
7234
    else if (childRenderBlock && childRenderBlock->paginationStrut())
 
7235
        paginationStrut = childRenderBlock->paginationStrut();
 
7236
 
 
7237
    if (paginationStrut) {
 
7238
        // We are willing to propagate out to our parent block as long as we were at the top of the block prior
 
7239
        // to collapsing our margins, and as long as we didn't clear or move as a result of other pagination.
 
7240
        if (atBeforeSideOfBlock && oldTop == result && !isOutOfFlowPositioned() && !isTableCell()) {
 
7241
            // FIXME: Should really check if we're exceeding the page height before propagating the strut, but we don't
 
7242
            // have all the information to do so (the strut only has the remaining amount to push). Gecko gets this wrong too
 
7243
            // and pushes to the next page anyway, so not too concerned about it.
 
7244
            setPaginationStrut(result + paginationStrut);
 
7245
            if (childRenderBlock)
 
7246
                childRenderBlock->setPaginationStrut(0);
 
7247
        } else
 
7248
            result += paginationStrut;
 
7249
    }
 
7250
 
 
7251
    // Similar to how we apply clearance. Go ahead and boost height() to be the place where we're going to position the child.
 
7252
    setLogicalHeight(logicalHeight() + (result - oldTop));
 
7253
    
 
7254
    // Return the final adjusted logical top.
 
7255
    return result;
 
7256
}
 
7257
 
 
7258
bool RenderBlock::lineWidthForPaginatedLineChanged(RootInlineBox* rootBox, LayoutUnit lineDelta) const
 
7259
{
 
7260
    if (!inRenderFlowThread())
 
7261
        return false;
 
7262
 
 
7263
    RenderRegion* currentRegion = regionAtBlockOffset(rootBox->lineTopWithLeading() + lineDelta);
 
7264
    // Just bail if we still don't have a region.
 
7265
    if (!rootBox->hasContainingRegion() && !currentRegion)
 
7266
        return false;
 
7267
    // Just bail if the region didn't change.
 
7268
    if (rootBox->hasContainingRegion() && rootBox->containingRegion() == currentRegion)
 
7269
        return false;
 
7270
    return rootBox->paginatedLineWidth() != availableLogicalWidthForContent(currentRegion, offsetFromLogicalTopOfFirstPage());
 
7271
}
 
7272
 
 
7273
LayoutUnit RenderBlock::offsetFromLogicalTopOfFirstPage() const
 
7274
{
 
7275
    LayoutState* layoutState = view()->layoutState();
 
7276
    if (layoutState && !layoutState->isPaginated())
 
7277
        return 0;
 
7278
    if (layoutState) {
 
7279
        // FIXME: Sanity check that the renderer in the layout state is ours, since otherwise the computation will be off.
 
7280
        // Right now this assert gets hit inside computeLogicalHeight for percentage margins, since they're computed using
 
7281
        // widths which can vary in each region. Until we patch that, we can't have this assert.
 
7282
        // ASSERT(layoutState->m_renderer == this);
 
7283
 
 
7284
        LayoutSize offsetDelta = layoutState->m_layoutOffset - layoutState->m_pageOffset;
 
7285
        return isHorizontalWritingMode() ? offsetDelta.height() : offsetDelta.width();
 
7286
    }
 
7287
    // FIXME: Right now, this assert is hit outside layout, from logicalLeftSelectionOffset in selectionGapRectsForRepaint (called from FrameSelection::selectAll).
 
7288
    // ASSERT(inRenderFlowThread());
 
7289
 
 
7290
    // FIXME: This is a slower path that doesn't use layout state and relies on getting your logical top inside the enclosing flow thread. It doesn't
 
7291
    // work with columns or pages currently, but it should once they have been switched over to using flow threads.
 
7292
    if (!inRenderFlowThread())
 
7293
        return 0;
 
7294
 
 
7295
    const RenderBlock* currentBlock = this;
 
7296
    LayoutRect blockRect(0, 0, width(), height());
 
7297
 
 
7298
    while (currentBlock && !currentBlock->isRenderFlowThread()) {
 
7299
        RenderBlock* containerBlock = currentBlock->containingBlock();
 
7300
        ASSERT(containerBlock);
 
7301
        if (!containerBlock)
 
7302
            return 0;
 
7303
        LayoutPoint currentBlockLocation = currentBlock->location();
 
7304
 
 
7305
        if (containerBlock->style()->writingMode() != currentBlock->style()->writingMode()) {
 
7306
            // We have to put the block rect in container coordinates
 
7307
            // and we have to take into account both the container and current block flipping modes
 
7308
            if (containerBlock->style()->isFlippedBlocksWritingMode()) {
 
7309
                if (containerBlock->isHorizontalWritingMode())
 
7310
                    blockRect.setY(currentBlock->height() - blockRect.maxY());
 
7311
                else
 
7312
                    blockRect.setX(currentBlock->width() - blockRect.maxX());
 
7313
            }
 
7314
            currentBlock->flipForWritingMode(blockRect);
 
7315
        }
 
7316
        blockRect.moveBy(currentBlockLocation);
 
7317
        currentBlock = containerBlock;
 
7318
    };
 
7319
    return currentBlock->isHorizontalWritingMode() ? blockRect.y() : blockRect.x();
 
7320
}
 
7321
 
 
7322
RenderRegion* RenderBlock::regionAtBlockOffset(LayoutUnit blockOffset) const
 
7323
{
 
7324
    if (!inRenderFlowThread())
 
7325
        return 0;
 
7326
 
 
7327
    RenderFlowThread* flowThread = enclosingRenderFlowThread();
 
7328
    if (!flowThread || !flowThread->hasValidRegionInfo())
 
7329
        return 0;
 
7330
 
 
7331
    return flowThread->regionAtBlockOffset(offsetFromLogicalTopOfFirstPage() + blockOffset, true);
 
7332
}
 
7333
 
 
7334
void RenderBlock::setStaticInlinePositionForChild(RenderBox* child, LayoutUnit blockOffset, LayoutUnit inlinePosition)
 
7335
{
 
7336
    if (inRenderFlowThread()) {
 
7337
        // Shift the inline position to exclude the region offset.
 
7338
        inlinePosition += startOffsetForContent() - startOffsetForContent(blockOffset);
 
7339
    }
 
7340
    child->layer()->setStaticInlinePosition(inlinePosition);
 
7341
}
 
7342
 
 
7343
bool RenderBlock::logicalWidthChangedInRegions() const
 
7344
{
 
7345
    if (!inRenderFlowThread())
 
7346
        return false;
 
7347
    
 
7348
    RenderFlowThread* flowThread = enclosingRenderFlowThread();
 
7349
    if (!flowThread || !flowThread->hasValidRegionInfo())
 
7350
        return 0;
 
7351
    
 
7352
    return flowThread->logicalWidthChangedInRegions(this, offsetFromLogicalTopOfFirstPage());
 
7353
}
 
7354
 
 
7355
RenderRegion* RenderBlock::clampToStartAndEndRegions(RenderRegion* region) const
 
7356
{
 
7357
    ASSERT(region && inRenderFlowThread());
 
7358
    
 
7359
    // We need to clamp to the block, since we want any lines or blocks that overflow out of the
 
7360
    // logical top or logical bottom of the block to size as though the border box in the first and
 
7361
    // last regions extended infinitely. Otherwise the lines are going to size according to the regions
 
7362
    // they overflow into, which makes no sense when this block doesn't exist in |region| at all.
 
7363
    RenderRegion* startRegion;
 
7364
    RenderRegion* endRegion;
 
7365
    enclosingRenderFlowThread()->getRegionRangeForBox(this, startRegion, endRegion);
 
7366
    
 
7367
    if (startRegion && region->logicalTopForFlowThreadContent() < startRegion->logicalTopForFlowThreadContent())
 
7368
        return startRegion;
 
7369
    if (endRegion && region->logicalTopForFlowThreadContent() > endRegion->logicalTopForFlowThreadContent())
 
7370
        return endRegion;
 
7371
    
 
7372
    return region;
 
7373
}
 
7374
 
 
7375
LayoutUnit RenderBlock::collapsedMarginBeforeForChild(const RenderBox* child) const
 
7376
{
 
7377
    // If the child has the same directionality as we do, then we can just return its
 
7378
    // collapsed margin.
 
7379
    if (!child->isWritingModeRoot())
 
7380
        return child->collapsedMarginBefore();
 
7381
    
 
7382
    // The child has a different directionality.  If the child is parallel, then it's just
 
7383
    // flipped relative to us.  We can use the collapsed margin for the opposite edge.
 
7384
    if (child->isHorizontalWritingMode() == isHorizontalWritingMode())
 
7385
        return child->collapsedMarginAfter();
 
7386
    
 
7387
    // The child is perpendicular to us, which means its margins don't collapse but are on the
 
7388
    // "logical left/right" sides of the child box.  We can just return the raw margin in this case.  
 
7389
    return marginBeforeForChild(child);
 
7390
}
 
7391
 
 
7392
LayoutUnit RenderBlock::collapsedMarginAfterForChild(const  RenderBox* child) const
 
7393
{
 
7394
    // If the child has the same directionality as we do, then we can just return its
 
7395
    // collapsed margin.
 
7396
    if (!child->isWritingModeRoot())
 
7397
        return child->collapsedMarginAfter();
 
7398
    
 
7399
    // The child has a different directionality.  If the child is parallel, then it's just
 
7400
    // flipped relative to us.  We can use the collapsed margin for the opposite edge.
 
7401
    if (child->isHorizontalWritingMode() == isHorizontalWritingMode())
 
7402
        return child->collapsedMarginBefore();
 
7403
    
 
7404
    // The child is perpendicular to us, which means its margins don't collapse but are on the
 
7405
    // "logical left/right" side of the child box.  We can just return the raw margin in this case.  
 
7406
    return marginAfterForChild(child);
 
7407
}
 
7408
 
 
7409
RenderBlock::MarginValues RenderBlock::marginValuesForChild(RenderBox* child) const
 
7410
{
 
7411
    LayoutUnit childBeforePositive = 0;
 
7412
    LayoutUnit childBeforeNegative = 0;
 
7413
    LayoutUnit childAfterPositive = 0;
 
7414
    LayoutUnit childAfterNegative = 0;
 
7415
 
 
7416
    LayoutUnit beforeMargin = 0;
 
7417
    LayoutUnit afterMargin = 0;
 
7418
 
 
7419
    RenderBlock* childRenderBlock = child->isRenderBlock() ? toRenderBlock(child) : 0;
 
7420
    
 
7421
    // If the child has the same directionality as we do, then we can just return its
 
7422
    // margins in the same direction.
 
7423
    if (!child->isWritingModeRoot()) {
 
7424
        if (childRenderBlock) {
 
7425
            childBeforePositive = childRenderBlock->maxPositiveMarginBefore();
 
7426
            childBeforeNegative = childRenderBlock->maxNegativeMarginBefore();
 
7427
            childAfterPositive = childRenderBlock->maxPositiveMarginAfter();
 
7428
            childAfterNegative = childRenderBlock->maxNegativeMarginAfter();
 
7429
        } else {
 
7430
            beforeMargin = child->marginBefore();
 
7431
            afterMargin = child->marginAfter();
 
7432
        }
 
7433
    } else if (child->isHorizontalWritingMode() == isHorizontalWritingMode()) {
 
7434
        // The child has a different directionality.  If the child is parallel, then it's just
 
7435
        // flipped relative to us.  We can use the margins for the opposite edges.
 
7436
        if (childRenderBlock) {
 
7437
            childBeforePositive = childRenderBlock->maxPositiveMarginAfter();
 
7438
            childBeforeNegative = childRenderBlock->maxNegativeMarginAfter();
 
7439
            childAfterPositive = childRenderBlock->maxPositiveMarginBefore();
 
7440
            childAfterNegative = childRenderBlock->maxNegativeMarginBefore();
 
7441
        } else {
 
7442
            beforeMargin = child->marginAfter();
 
7443
            afterMargin = child->marginBefore();
 
7444
        }
 
7445
    } else {
 
7446
        // The child is perpendicular to us, which means its margins don't collapse but are on the
 
7447
        // "logical left/right" sides of the child box.  We can just return the raw margin in this case.
 
7448
        beforeMargin = marginBeforeForChild(child);
 
7449
        afterMargin = marginAfterForChild(child);
 
7450
    }
 
7451
 
 
7452
    // Resolve uncollapsing margins into their positive/negative buckets.
 
7453
    if (beforeMargin) {
 
7454
        if (beforeMargin > 0)
 
7455
            childBeforePositive = beforeMargin;
 
7456
        else
 
7457
            childBeforeNegative = -beforeMargin;
 
7458
    }
 
7459
    if (afterMargin) {
 
7460
        if (afterMargin > 0)
 
7461
            childAfterPositive = afterMargin;
 
7462
        else
 
7463
            childAfterNegative = -afterMargin;
 
7464
    }
 
7465
 
 
7466
    return MarginValues(childBeforePositive, childBeforeNegative, childAfterPositive, childAfterNegative);
 
7467
}
 
7468
 
 
7469
const char* RenderBlock::renderName() const
 
7470
{
 
7471
    if (isBody())
 
7472
        return "RenderBody"; // FIXME: Temporary hack until we know that the regression tests pass.
 
7473
    
 
7474
    if (isFloating())
 
7475
        return "RenderBlock (floating)";
 
7476
    if (isOutOfFlowPositioned())
 
7477
        return "RenderBlock (positioned)";
 
7478
    if (isAnonymousColumnsBlock())
 
7479
        return "RenderBlock (anonymous multi-column)";
 
7480
    if (isAnonymousColumnSpanBlock())
 
7481
        return "RenderBlock (anonymous multi-column span)";
 
7482
    if (isAnonymousBlock())
 
7483
        return "RenderBlock (anonymous)";
 
7484
    else if (isAnonymous())
 
7485
        return "RenderBlock (generated)";
 
7486
    if (isRelPositioned())
 
7487
        return "RenderBlock (relative positioned)";
 
7488
    if (isStickyPositioned())
 
7489
        return "RenderBlock (sticky positioned)";
 
7490
    if (isRunIn())
 
7491
        return "RenderBlock (run-in)";
 
7492
    return "RenderBlock";
 
7493
}
 
7494
 
 
7495
inline void RenderBlock::FloatingObjects::clear()
 
7496
{
 
7497
    m_set.clear();
 
7498
    m_placedFloatsTree.clear();
 
7499
    m_leftObjectsCount = 0;
 
7500
    m_rightObjectsCount = 0;
 
7501
}
 
7502
 
 
7503
inline void RenderBlock::FloatingObjects::increaseObjectsCount(FloatingObject::Type type)
 
7504
{    
 
7505
    if (type == FloatingObject::FloatLeft)
 
7506
        m_leftObjectsCount++;
 
7507
    else 
 
7508
        m_rightObjectsCount++;
 
7509
}
 
7510
 
 
7511
inline void RenderBlock::FloatingObjects::decreaseObjectsCount(FloatingObject::Type type)
 
7512
{
 
7513
    if (type == FloatingObject::FloatLeft)
 
7514
        m_leftObjectsCount--;
 
7515
    else
 
7516
        m_rightObjectsCount--;
 
7517
}
 
7518
 
 
7519
inline RenderBlock::FloatingObjectInterval RenderBlock::FloatingObjects::intervalForFloatingObject(FloatingObject* floatingObject)
 
7520
{
 
7521
    if (m_horizontalWritingMode)
 
7522
        return RenderBlock::FloatingObjectInterval(floatingObject->frameRect().pixelSnappedY(), floatingObject->frameRect().pixelSnappedMaxY(), floatingObject);
 
7523
    return RenderBlock::FloatingObjectInterval(floatingObject->frameRect().pixelSnappedX(), floatingObject->frameRect().pixelSnappedMaxX(), floatingObject);
 
7524
}
 
7525
 
 
7526
void RenderBlock::FloatingObjects::addPlacedObject(FloatingObject* floatingObject)
 
7527
{
 
7528
    ASSERT(!floatingObject->isInPlacedTree());
 
7529
 
 
7530
    floatingObject->setIsPlaced(true);
 
7531
    if (m_placedFloatsTree.isInitialized())
 
7532
        m_placedFloatsTree.add(intervalForFloatingObject(floatingObject));
 
7533
 
 
7534
#ifndef NDEBUG
 
7535
    floatingObject->setIsInPlacedTree(true);      
 
7536
#endif
 
7537
}
 
7538
 
 
7539
void RenderBlock::FloatingObjects::removePlacedObject(FloatingObject* floatingObject)
 
7540
{
 
7541
    ASSERT(floatingObject->isPlaced() && floatingObject->isInPlacedTree());
 
7542
 
 
7543
    if (m_placedFloatsTree.isInitialized()) {
 
7544
        bool removed = m_placedFloatsTree.remove(intervalForFloatingObject(floatingObject));
 
7545
        ASSERT_UNUSED(removed, removed);
 
7546
    }
 
7547
    
 
7548
    floatingObject->setIsPlaced(false);
 
7549
#ifndef NDEBUG
 
7550
    floatingObject->setIsInPlacedTree(false);
 
7551
#endif
 
7552
}
 
7553
 
 
7554
inline void RenderBlock::FloatingObjects::add(FloatingObject* floatingObject)
 
7555
{
 
7556
    increaseObjectsCount(floatingObject->type());
 
7557
    m_set.add(floatingObject);
 
7558
    if (floatingObject->isPlaced())
 
7559
        addPlacedObject(floatingObject);
 
7560
}
 
7561
 
 
7562
inline void RenderBlock::FloatingObjects::remove(FloatingObject* floatingObject)
 
7563
{
 
7564
    decreaseObjectsCount(floatingObject->type());
 
7565
    m_set.remove(floatingObject);
 
7566
    ASSERT(floatingObject->isPlaced() || !floatingObject->isInPlacedTree());
 
7567
    if (floatingObject->isPlaced())
 
7568
        removePlacedObject(floatingObject);
 
7569
}
 
7570
 
 
7571
void RenderBlock::FloatingObjects::computePlacedFloatsTree()
 
7572
{
 
7573
    ASSERT(!m_placedFloatsTree.isInitialized());
 
7574
    if (m_set.isEmpty())
 
7575
        return;
 
7576
    m_placedFloatsTree.initIfNeeded(m_renderer->view()->intervalArena());
 
7577
    FloatingObjectSetIterator it = m_set.begin();
 
7578
    FloatingObjectSetIterator end = m_set.end();
 
7579
    for (; it != end; ++it) {
 
7580
        FloatingObject* floatingObject = *it;
 
7581
        if (floatingObject->isPlaced())
 
7582
            m_placedFloatsTree.add(intervalForFloatingObject(floatingObject));
 
7583
    }
 
7584
}
 
7585
 
 
7586
template <typename CharacterType>
 
7587
static inline TextRun constructTextRunInternal(RenderObject* context, const Font& font, const CharacterType* characters, int length, RenderStyle* style, TextRun::ExpansionBehavior expansion)
 
7588
{
 
7589
    ASSERT(style);
 
7590
 
 
7591
    TextDirection textDirection = LTR;
 
7592
    bool directionalOverride = style->rtlOrdering() == VisualOrder;
 
7593
 
 
7594
    TextRun run(characters, length, 0, 0, expansion, textDirection, directionalOverride);
 
7595
    if (textRunNeedsRenderingContext(font))
 
7596
        run.setRenderingContext(SVGTextRunRenderingContext::create(context));
 
7597
 
 
7598
    return run;
 
7599
}
 
7600
 
 
7601
template <typename CharacterType>
 
7602
static inline TextRun constructTextRunInternal(RenderObject* context, const Font& font, const CharacterType* characters, int length, RenderStyle* style, TextRun::ExpansionBehavior expansion, TextRunFlags flags)
 
7603
{
 
7604
    ASSERT(style);
 
7605
 
 
7606
    TextDirection textDirection = LTR;
 
7607
    bool directionalOverride = style->rtlOrdering() == VisualOrder;
 
7608
    if (flags != DefaultTextRunFlags) {
 
7609
        if (flags & RespectDirection)
 
7610
            textDirection = style->direction();
 
7611
        if (flags & RespectDirectionOverride)
 
7612
            directionalOverride |= isOverride(style->unicodeBidi());
 
7613
    }
 
7614
    TextRun run(characters, length, 0, 0, expansion, textDirection, directionalOverride);
 
7615
    if (textRunNeedsRenderingContext(font))
 
7616
        run.setRenderingContext(SVGTextRunRenderingContext::create(context));
 
7617
 
 
7618
    return run;
 
7619
}
 
7620
 
 
7621
#if ENABLE(8BIT_TEXTRUN)
 
7622
TextRun RenderBlock::constructTextRun(RenderObject* context, const Font& font, const LChar* characters, int length, RenderStyle* style, TextRun::ExpansionBehavior expansion)
 
7623
{
 
7624
    return constructTextRunInternal(context, font, characters, length, style, expansion);
 
7625
}
 
7626
#endif
 
7627
 
 
7628
TextRun RenderBlock::constructTextRun(RenderObject* context, const Font& font, const UChar* characters, int length, RenderStyle* style, TextRun::ExpansionBehavior expansion)
 
7629
{
 
7630
    return constructTextRunInternal(context, font, characters, length, style, expansion);
 
7631
}
 
7632
 
 
7633
TextRun RenderBlock::constructTextRun(RenderObject* context, const Font& font, const RenderText* text, RenderStyle* style, TextRun::ExpansionBehavior expansion)
 
7634
{
 
7635
#if ENABLE(8BIT_TEXTRUN)
 
7636
    if (text->is8Bit())
 
7637
        return constructTextRunInternal(context, font, text->characters8(), text->textLength(), style, expansion);
 
7638
    return constructTextRunInternal(context, font, text->characters16(), text->textLength(), style, expansion);
 
7639
#else
 
7640
    return constructTextRunInternal(context, font, text->characters(), text->textLength(), style, expansion);
 
7641
#endif
 
7642
}
 
7643
 
 
7644
TextRun RenderBlock::constructTextRun(RenderObject* context, const Font& font, const RenderText* text, unsigned offset, unsigned length, RenderStyle* style, TextRun::ExpansionBehavior expansion)
 
7645
{
 
7646
    ASSERT(offset + length <= text->textLength());
 
7647
#if ENABLE(8BIT_TEXTRUN)
 
7648
    if (text->is8Bit())
 
7649
        return constructTextRunInternal(context, font, text->characters8() + offset, length, style, expansion);
 
7650
    return constructTextRunInternal(context, font, text->characters16() + offset, length, style, expansion);
 
7651
#else
 
7652
    return constructTextRunInternal(context, font, text->characters() + offset, length, style, expansion);
 
7653
#endif
 
7654
}
 
7655
 
 
7656
TextRun RenderBlock::constructTextRun(RenderObject* context, const Font& font, const String& string, RenderStyle* style, TextRun::ExpansionBehavior expansion, TextRunFlags flags)
 
7657
{
 
7658
    unsigned length = string.length();
 
7659
 
 
7660
#if ENABLE(8BIT_TEXTRUN)
 
7661
    if (length && string.is8Bit())
 
7662
        return constructTextRunInternal(context, font, string.characters8(), length, style, expansion, flags);
 
7663
    return constructTextRunInternal(context, font, string.characters(), length, style, expansion, flags);
 
7664
#else
 
7665
    return constructTextRunInternal(context, font, string.characters(), length, style, expansion, flags);
 
7666
#endif
 
7667
}
 
7668
 
 
7669
RenderBlock* RenderBlock::createAnonymousWithParentRendererAndDisplay(const RenderObject* parent, EDisplay display)
 
7670
{
 
7671
    // FIXME: Do we need to cover the new flex box here ?
 
7672
    // FIXME: Do we need to convert all our inline displays to block-type in the anonymous logic ?
 
7673
    EDisplay newDisplay;
 
7674
    RenderBlock* newBox = 0;
 
7675
    if (display == BOX || display == INLINE_BOX) {
 
7676
        newBox = new (parent->renderArena()) RenderDeprecatedFlexibleBox(parent->document() /* anonymous box */);
 
7677
        newDisplay = BOX;
 
7678
    } else {
 
7679
        newBox = new (parent->renderArena()) RenderBlock(parent->document() /* anonymous box */);
 
7680
        newDisplay = BLOCK;
 
7681
    }
 
7682
 
 
7683
    RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parent->style(), newDisplay);
 
7684
    newBox->setStyle(newStyle.release());
 
7685
    return newBox;
 
7686
}
 
7687
 
 
7688
RenderBlock* RenderBlock::createAnonymousColumnsWithParentRenderer(const RenderObject* parent)
 
7689
{
 
7690
    RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parent->style(), BLOCK);
 
7691
    newStyle->inheritColumnPropertiesFrom(parent->style());
 
7692
 
 
7693
    RenderBlock* newBox = new (parent->renderArena()) RenderBlock(parent->document() /* anonymous box */);
 
7694
    newBox->setStyle(newStyle.release());
 
7695
    return newBox;
 
7696
}
 
7697
 
 
7698
RenderBlock* RenderBlock::createAnonymousColumnSpanWithParentRenderer(const RenderObject* parent)
 
7699
{
 
7700
    RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parent->style(), BLOCK);
 
7701
    newStyle->setColumnSpan(ColumnSpanAll);
 
7702
 
 
7703
    RenderBlock* newBox = new (parent->renderArena()) RenderBlock(parent->document() /* anonymous box */);
 
7704
    newBox->setStyle(newStyle.release());
 
7705
    return newBox;
 
7706
}
 
7707
 
 
7708
#ifndef NDEBUG
 
7709
void RenderBlock::checkPositionedObjectsNeedLayout()
 
7710
{
 
7711
    if (!gPositionedDescendantsMap)
 
7712
        return;
 
7713
 
 
7714
    if (TrackedRendererListHashSet* positionedDescendantSet = positionedObjects()) {
 
7715
        TrackedRendererListHashSet::const_iterator end = positionedDescendantSet->end();
 
7716
        for (TrackedRendererListHashSet::const_iterator it = positionedDescendantSet->begin(); it != end; ++it) {
 
7717
            RenderBox* currBox = *it;
 
7718
            ASSERT(!currBox->needsLayout());
 
7719
        }
 
7720
    }
 
7721
}
 
7722
 
 
7723
void RenderBlock::showLineTreeAndMark(const InlineBox* markedBox1, const char* markedLabel1, const InlineBox* markedBox2, const char* markedLabel2, const RenderObject* obj) const
 
7724
{
 
7725
    showRenderObject();
 
7726
    for (const RootInlineBox* root = firstRootBox(); root; root = root->nextRootBox())
 
7727
        root->showLineTreeAndMark(markedBox1, markedLabel1, markedBox2, markedLabel2, obj, 1);
 
7728
}
 
7729
 
 
7730
// These helpers are only used by the PODIntervalTree for debugging purposes.
 
7731
String ValueToString<int>::string(const int value)
 
7732
{
 
7733
    return String::number(value);
 
7734
}
 
7735
 
 
7736
String ValueToString<RenderBlock::FloatingObject*>::string(const RenderBlock::FloatingObject* floatingObject)
 
7737
{
 
7738
    return String::format("%p (%dx%d %dx%d)", floatingObject, floatingObject->frameRect().pixelSnappedX(), floatingObject->frameRect().pixelSnappedY(), floatingObject->frameRect().pixelSnappedMaxX(), floatingObject->frameRect().pixelSnappedMaxY());
 
7739
}
 
7740
 
 
7741
#endif
 
7742
 
 
7743
} // namespace WebCore