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 "Document.h"
29#include "Editor.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 "HTMLInputElement.h"
37#include "HTMLNames.h"
38#include "HitTestLocation.h"
39#include "HitTestResult.h"
40#include "InlineElementBox.h"
41#include "InlineIterator.h"
42#include "InlineTextBox.h"
43#include "LayoutRepainter.h"
44#include "LogicalSelectionOffsetCaches.h"
45#include "OverflowEvent.h"
46#include "Page.h"
47#include "PaintInfo.h"
48#include "RenderBlockFlow.h"
49#include "RenderBoxRegionInfo.h"
50#include "RenderCombineText.h"
51#include "RenderDeprecatedFlexibleBox.h"
52#include "RenderFlexibleBox.h"
53#include "RenderInline.h"
54#include "RenderIterator.h"
55#include "RenderLayer.h"
56#include "RenderNamedFlowFragment.h"
57#include "RenderNamedFlowThread.h"
58#include "RenderRegion.h"
59#include "RenderTableCell.h"
60#include "RenderTextFragment.h"
61#include "RenderTheme.h"
62#include "RenderView.h"
63#include "SVGTextRunRenderingContext.h"
64#include "Settings.h"
65#include "ShadowRoot.h"
66#include "TransformState.h"
67#include <wtf/NeverDestroyed.h>
68#include <wtf/StackStats.h>
69#include <wtf/TemporaryChange.h>
70
71#if ENABLE(CSS_SHAPES)
72#include "ShapeOutsideInfo.h"
73#endif
74
75using namespace WTF;
76using namespace Unicode;
77
78namespace WebCore {
79
80using namespace HTMLNames;
81
82struct SameSizeAsRenderBlock : public RenderBox {
83    uint32_t bitfields;
84};
85
86COMPILE_ASSERT(sizeof(RenderBlock) == sizeof(SameSizeAsRenderBlock), RenderBlock_should_stay_small);
87
88static TrackedDescendantsMap* gPositionedDescendantsMap = 0;
89static TrackedDescendantsMap* gPercentHeightDescendantsMap = 0;
90
91static TrackedContainerMap* gPositionedContainerMap = 0;
92static TrackedContainerMap* gPercentHeightContainerMap = 0;
93
94typedef HashMap<RenderBlock*, std::unique_ptr<ListHashSet<RenderInline*>>> ContinuationOutlineTableMap;
95
96struct UpdateScrollInfoAfterLayoutTransaction {
97    UpdateScrollInfoAfterLayoutTransaction(const RenderView& view)
98        : nestedCount(0)
99        , view(&view)
100    {
101    }
102
103    int nestedCount;
104    const RenderView* view;
105    HashSet<RenderBlock*> blocks;
106};
107
108typedef Vector<UpdateScrollInfoAfterLayoutTransaction> DelayedUpdateScrollInfoStack;
109static std::unique_ptr<DelayedUpdateScrollInfoStack>& updateScrollInfoAfterLayoutTransactionStack()
110{
111    static NeverDestroyed<std::unique_ptr<DelayedUpdateScrollInfoStack>> delayedUpdatedScrollInfoStack;
112    return delayedUpdatedScrollInfoStack;
113}
114
115// Allocated only when some of these fields have non-default values
116
117struct RenderBlockRareData {
118    WTF_MAKE_NONCOPYABLE(RenderBlockRareData); WTF_MAKE_FAST_ALLOCATED;
119public:
120    RenderBlockRareData()
121        : m_paginationStrut(0)
122        , m_pageLogicalOffset(0)
123    {
124    }
125
126    LayoutUnit m_paginationStrut;
127    LayoutUnit m_pageLogicalOffset;
128};
129
130typedef HashMap<const RenderBlock*, std::unique_ptr<RenderBlockRareData>> RenderBlockRareDataMap;
131static RenderBlockRareDataMap* gRareDataMap = 0;
132
133// This class helps dispatching the 'overflow' event on layout change. overflow can be set on RenderBoxes, yet the existing code
134// only works on RenderBlocks. If this change, this class should be shared with other RenderBoxes.
135class OverflowEventDispatcher {
136    WTF_MAKE_NONCOPYABLE(OverflowEventDispatcher);
137public:
138    OverflowEventDispatcher(const RenderBlock* block)
139        : m_block(block)
140        , m_hadHorizontalLayoutOverflow(false)
141        , m_hadVerticalLayoutOverflow(false)
142    {
143        m_shouldDispatchEvent = !m_block->isAnonymous() && m_block->hasOverflowClip() && m_block->document().hasListenerType(Document::OVERFLOWCHANGED_LISTENER);
144        if (m_shouldDispatchEvent) {
145            m_hadHorizontalLayoutOverflow = m_block->hasHorizontalLayoutOverflow();
146            m_hadVerticalLayoutOverflow = m_block->hasVerticalLayoutOverflow();
147        }
148    }
149
150    ~OverflowEventDispatcher()
151    {
152        if (!m_shouldDispatchEvent)
153            return;
154
155        bool hasHorizontalLayoutOverflow = m_block->hasHorizontalLayoutOverflow();
156        bool hasVerticalLayoutOverflow = m_block->hasVerticalLayoutOverflow();
157
158        bool horizontalLayoutOverflowChanged = hasHorizontalLayoutOverflow != m_hadHorizontalLayoutOverflow;
159        bool verticalLayoutOverflowChanged = hasVerticalLayoutOverflow != m_hadVerticalLayoutOverflow;
160        if (!horizontalLayoutOverflowChanged && !verticalLayoutOverflowChanged)
161            return;
162
163        RefPtr<OverflowEvent> overflowEvent = OverflowEvent::create(horizontalLayoutOverflowChanged, hasHorizontalLayoutOverflow, verticalLayoutOverflowChanged, hasVerticalLayoutOverflow);
164        overflowEvent->setTarget(m_block->element());
165        m_block->document().enqueueOverflowEvent(overflowEvent.release());
166    }
167
168private:
169    const RenderBlock* m_block;
170    bool m_shouldDispatchEvent;
171    bool m_hadHorizontalLayoutOverflow;
172    bool m_hadVerticalLayoutOverflow;
173};
174
175RenderBlock::RenderBlock(Element& element, PassRef<RenderStyle> style, unsigned baseTypeFlags)
176    : RenderBox(element, WTF::move(style), baseTypeFlags | RenderBlockFlag)
177    , m_lineHeight(-1)
178    , m_hasMarginBeforeQuirk(false)
179    , m_hasMarginAfterQuirk(false)
180    , m_beingDestroyed(false)
181    , m_hasMarkupTruncation(false)
182    , m_hasBorderOrPaddingLogicalWidthChanged(false)
183    , m_lineLayoutPath(UndeterminedPath)
184{
185}
186
187RenderBlock::RenderBlock(Document& document, PassRef<RenderStyle> style, unsigned baseTypeFlags)
188    : RenderBox(document, WTF::move(style), baseTypeFlags | RenderBlockFlag)
189    , m_lineHeight(-1)
190    , m_hasMarginBeforeQuirk(false)
191    , m_hasMarginAfterQuirk(false)
192    , m_beingDestroyed(false)
193    , m_hasMarkupTruncation(false)
194    , m_hasBorderOrPaddingLogicalWidthChanged(false)
195    , m_lineLayoutPath(UndeterminedPath)
196{
197}
198
199static void removeBlockFromDescendantAndContainerMaps(RenderBlock* block, TrackedDescendantsMap*& descendantMap, TrackedContainerMap*& containerMap)
200{
201    if (std::unique_ptr<TrackedRendererListHashSet> descendantSet = descendantMap->take(block)) {
202        TrackedRendererListHashSet::iterator end = descendantSet->end();
203        for (TrackedRendererListHashSet::iterator descendant = descendantSet->begin(); descendant != end; ++descendant) {
204            TrackedContainerMap::iterator it = containerMap->find(*descendant);
205            ASSERT(it != containerMap->end());
206            if (it == containerMap->end())
207                continue;
208            HashSet<RenderBlock*>* containerSet = it->value.get();
209            ASSERT(containerSet->contains(block));
210            containerSet->remove(block);
211            if (containerSet->isEmpty())
212                containerMap->remove(it);
213        }
214    }
215}
216
217RenderBlock::~RenderBlock()
218{
219    if (gRareDataMap)
220        gRareDataMap->remove(this);
221    if (gPercentHeightDescendantsMap)
222        removeBlockFromDescendantAndContainerMaps(this, gPercentHeightDescendantsMap, gPercentHeightContainerMap);
223    if (gPositionedDescendantsMap)
224        removeBlockFromDescendantAndContainerMaps(this, gPositionedDescendantsMap, gPositionedContainerMap);
225}
226
227bool RenderBlock::hasRareData() const
228{
229    return gRareDataMap ? gRareDataMap->contains(this) : false;
230}
231
232void RenderBlock::willBeDestroyed()
233{
234    // Mark as being destroyed to avoid trouble with merges in removeChild().
235    m_beingDestroyed = true;
236
237    // Make sure to destroy anonymous children first while they are still connected to the rest of the tree, so that they will
238    // properly dirty line boxes that they are removed from. Effects that do :before/:after only on hover could crash otherwise.
239    destroyLeftoverChildren();
240
241    // Destroy our continuation before anything other than anonymous children.
242    // The reason we don't destroy it before anonymous children is that they may
243    // have continuations of their own that are anonymous children of our continuation.
244    RenderBoxModelObject* continuation = this->continuation();
245    if (continuation) {
246        continuation->destroy();
247        setContinuation(0);
248    }
249
250    if (!documentBeingDestroyed()) {
251        if (parent())
252            parent()->dirtyLinesFromChangedChild(this);
253    }
254
255    removeFromUpdateScrollInfoAfterLayoutTransaction();
256
257    RenderBox::willBeDestroyed();
258}
259
260void RenderBlock::styleWillChange(StyleDifference diff, const RenderStyle& newStyle)
261{
262    const RenderStyle* oldStyle = hasInitializedStyle() ? &style() : nullptr;
263
264    setReplaced(newStyle.isDisplayInlineType());
265
266    if (oldStyle && parent() && diff == StyleDifferenceLayout && oldStyle->position() != newStyle.position()) {
267        if (newStyle.position() == StaticPosition)
268            // Clear our positioned objects list. Our absolutely positioned descendants will be
269            // inserted into our containing block's positioned objects list during layout.
270            removePositionedObjects(0, NewContainingBlock);
271        else if (oldStyle->position() == StaticPosition) {
272            // Remove our absolutely positioned descendants from their current containing block.
273            // They will be inserted into our positioned objects list during layout.
274            auto cb = parent();
275            while (cb && (cb->style().position() == StaticPosition || (cb->isInline() && !cb->isReplaced())) && !cb->isRenderView()) {
276                if (cb->style().position() == RelativePosition && cb->isInline() && !cb->isReplaced()) {
277                    cb = cb->containingBlock();
278                    break;
279                }
280                cb = cb->parent();
281            }
282
283            if (cb->isRenderBlock())
284                toRenderBlock(cb)->removePositionedObjects(this, NewContainingBlock);
285        }
286    }
287
288    RenderBox::styleWillChange(diff, newStyle);
289}
290
291static bool borderOrPaddingLogicalWidthChanged(const RenderStyle* oldStyle, const RenderStyle* newStyle)
292{
293    if (newStyle->isHorizontalWritingMode())
294        return oldStyle->borderLeftWidth() != newStyle->borderLeftWidth()
295            || oldStyle->borderRightWidth() != newStyle->borderRightWidth()
296            || oldStyle->paddingLeft() != newStyle->paddingLeft()
297            || oldStyle->paddingRight() != newStyle->paddingRight();
298
299    return oldStyle->borderTopWidth() != newStyle->borderTopWidth()
300        || oldStyle->borderBottomWidth() != newStyle->borderBottomWidth()
301        || oldStyle->paddingTop() != newStyle->paddingTop()
302        || oldStyle->paddingBottom() != newStyle->paddingBottom();
303}
304
305void RenderBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
306{
307    RenderBox::styleDidChange(diff, oldStyle);
308
309    RenderStyle& newStyle = style();
310
311    if (!isAnonymousBlock()) {
312        // Ensure that all of our continuation blocks pick up the new style.
313        for (RenderBlock* currCont = blockElementContinuation(); currCont; currCont = currCont->blockElementContinuation()) {
314            RenderBoxModelObject* nextCont = currCont->continuation();
315            currCont->setContinuation(0);
316            currCont->setStyle(newStyle);
317            currCont->setContinuation(nextCont);
318        }
319    }
320
321    propagateStyleToAnonymousChildren(PropagateToBlockChildrenOnly);
322    m_lineHeight = -1;
323
324    // It's possible for our border/padding to change, but for the overall logical width of the block to
325    // end up being the same. We keep track of this change so in layoutBlock, we can know to set relayoutChildren=true.
326    m_hasBorderOrPaddingLogicalWidthChanged = oldStyle && diff == StyleDifferenceLayout && needsLayout() && borderOrPaddingLogicalWidthChanged(oldStyle, &newStyle);
327}
328
329RenderBlock* RenderBlock::continuationBefore(RenderObject* beforeChild)
330{
331    if (beforeChild && beforeChild->parent() == this)
332        return this;
333
334    RenderBlock* curr = toRenderBlock(continuation());
335    RenderBlock* nextToLast = this;
336    RenderBlock* last = this;
337    while (curr) {
338        if (beforeChild && beforeChild->parent() == curr) {
339            if (curr->firstChild() == beforeChild)
340                return last;
341            return curr;
342        }
343
344        nextToLast = last;
345        last = curr;
346        curr = toRenderBlock(curr->continuation());
347    }
348
349    if (!beforeChild && !last->firstChild())
350        return nextToLast;
351    return last;
352}
353
354void RenderBlock::addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild)
355{
356    RenderBlock* flow = continuationBefore(beforeChild);
357    ASSERT(!beforeChild || beforeChild->parent()->isRenderBlock());
358    RenderBoxModelObject* beforeChildParent = 0;
359    if (beforeChild)
360        beforeChildParent = toRenderBoxModelObject(beforeChild->parent());
361    else {
362        RenderBoxModelObject* cont = flow->continuation();
363        if (cont)
364            beforeChildParent = cont;
365        else
366            beforeChildParent = flow;
367    }
368
369    if (newChild->isFloatingOrOutOfFlowPositioned()) {
370        beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
371        return;
372    }
373
374    bool childIsNormal = newChild->isInline() || !newChild->style().columnSpan();
375    bool bcpIsNormal = beforeChildParent->isInline() || !beforeChildParent->style().columnSpan();
376    bool flowIsNormal = flow->isInline() || !flow->style().columnSpan();
377
378    if (flow == beforeChildParent) {
379        flow->addChildIgnoringContinuation(newChild, beforeChild);
380        return;
381    }
382
383    // The goal here is to match up if we can, so that we can coalesce and create the
384    // minimal # of continuations needed for the inline.
385    if (childIsNormal == bcpIsNormal) {
386        beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
387        return;
388    }
389    if (flowIsNormal == childIsNormal) {
390        flow->addChildIgnoringContinuation(newChild, 0); // Just treat like an append.
391        return;
392    }
393    beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
394}
395
396RenderPtr<RenderBlock> RenderBlock::clone() const
397{
398    RenderPtr<RenderBlock> cloneBlock;
399    if (isAnonymousBlock()) {
400        cloneBlock = RenderPtr<RenderBlock>(createAnonymousBlock());
401        cloneBlock->setChildrenInline(childrenInline());
402    } else {
403        cloneBlock = static_pointer_cast<RenderBlock>(element()->createElementRenderer(style()));
404        cloneBlock->initializeStyle();
405
406        // This takes care of setting the right value of childrenInline in case
407        // generated content is added to cloneBlock and 'this' does not have
408        // generated content added yet.
409        cloneBlock->setChildrenInline(cloneBlock->firstChild() ? cloneBlock->firstChild()->isInline() : childrenInline());
410    }
411    cloneBlock->setFlowThreadState(flowThreadState());
412    return cloneBlock;
413}
414
415void RenderBlock::splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock,
416                              RenderBlock* middleBlock,
417                              RenderObject* beforeChild, RenderBoxModelObject* oldCont)
418{
419    // Create a clone of this inline.
420    RenderPtr<RenderBlock> cloneBlock = clone();
421    if (!isAnonymousBlock())
422        cloneBlock->setContinuation(oldCont);
423
424    if (!beforeChild && isAfterContent(lastChild()))
425        beforeChild = lastChild();
426
427    // If we are moving inline children from |this| to cloneBlock, then we need
428    // to clear our line box tree.
429    if (beforeChild && childrenInline())
430        deleteLines();
431
432    // Now take all of the children from beforeChild to the end and remove
433    // them from |this| and place them in the clone.
434    moveChildrenTo(cloneBlock.get(), beforeChild, 0, true);
435
436    // Hook |clone| up as the continuation of the middle block.
437    if (!cloneBlock->isAnonymousBlock())
438        middleBlock->setContinuation(cloneBlock.get());
439
440    // We have been reparented and are now under the fromBlock.  We need
441    // to walk up our block parent chain until we hit the containing anonymous columns block.
442    // Once we hit the anonymous columns block we're done.
443    RenderBoxModelObject* curr = toRenderBoxModelObject(parent());
444    RenderBoxModelObject* currChild = this;
445    RenderObject* currChildNextSibling = currChild->nextSibling();
446
447    while (curr && curr->isDescendantOf(fromBlock) && curr != fromBlock) {
448        RenderBlock* blockCurr = toRenderBlock(curr);
449
450        // Create a new clone.
451        RenderPtr<RenderBlock> cloneChild = WTF::move(cloneBlock);
452        cloneBlock = blockCurr->clone();
453
454        // Insert our child clone as the first child.
455        cloneBlock->addChildIgnoringContinuation(cloneChild.leakPtr(), 0);
456
457        // Hook the clone up as a continuation of |curr|.  Note we do encounter
458        // anonymous blocks possibly as we walk up the block chain.  When we split an
459        // anonymous block, there's no need to do any continuation hookup, since we haven't
460        // actually split a real element.
461        if (!blockCurr->isAnonymousBlock()) {
462            oldCont = blockCurr->continuation();
463            blockCurr->setContinuation(cloneBlock.get());
464            cloneBlock->setContinuation(oldCont);
465        }
466
467        // Now we need to take all of the children starting from the first child
468        // *after* currChild and append them all to the clone.
469        blockCurr->moveChildrenTo(cloneBlock.get(), currChildNextSibling, 0, true);
470
471        // Keep walking up the chain.
472        currChild = curr;
473        currChildNextSibling = currChild->nextSibling();
474        curr = toRenderBoxModelObject(curr->parent());
475    }
476
477    // Now we are at the columns block level. We need to put the clone into the toBlock.
478    toBlock->insertChildInternal(cloneBlock.leakPtr(), nullptr, NotifyChildren);
479
480    // Now take all the children after currChild and remove them from the fromBlock
481    // and put them in the toBlock.
482    if (currChildNextSibling && currChildNextSibling->parent() == fromBlock)
483        fromBlock->moveChildrenTo(toBlock, currChildNextSibling, 0, true);
484}
485
486void RenderBlock::addChild(RenderObject* newChild, RenderObject* beforeChild)
487{
488    if (continuation() && !isAnonymousBlock())
489        addChildToContinuation(newChild, beforeChild);
490    else
491        addChildIgnoringContinuation(newChild, beforeChild);
492}
493
494void RenderBlock::addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild)
495{
496    if (beforeChild && beforeChild->parent() != this) {
497        RenderElement* beforeChildContainer = beforeChild->parent();
498        while (beforeChildContainer->parent() != this)
499            beforeChildContainer = beforeChildContainer->parent();
500        ASSERT(beforeChildContainer);
501
502        if (beforeChildContainer->isAnonymous()) {
503            // If the requested beforeChild is not one of our children, then this is because
504            // there is an anonymous container within this object that contains the beforeChild.
505            RenderElement* beforeChildAnonymousContainer = beforeChildContainer;
506            if (beforeChildAnonymousContainer->isAnonymousBlock()
507#if ENABLE(FULLSCREEN_API)
508                // Full screen renderers and full screen placeholders act as anonymous blocks, not tables:
509                || beforeChildAnonymousContainer->isRenderFullScreen()
510                || beforeChildAnonymousContainer->isRenderFullScreenPlaceholder()
511#endif
512                ) {
513                // Insert the child into the anonymous block box instead of here.
514                if (newChild->isInline() || beforeChild->parent()->firstChild() != beforeChild)
515                    beforeChild->parent()->addChild(newChild, beforeChild);
516                else
517                    addChild(newChild, beforeChild->parent());
518                return;
519            }
520
521            ASSERT(beforeChildAnonymousContainer->isTable());
522            if (newChild->isTablePart()) {
523                // Insert into the anonymous table.
524                beforeChildAnonymousContainer->addChild(newChild, beforeChild);
525                return;
526            }
527
528            beforeChild = splitAnonymousBoxesAroundChild(beforeChild);
529
530            ASSERT(beforeChild->parent() == this);
531            if (beforeChild->parent() != this) {
532                // We should never reach here. If we do, we need to use the
533                // safe fallback to use the topmost beforeChild container.
534                beforeChild = beforeChildContainer;
535            }
536        }
537    }
538
539    bool madeBoxesNonInline = false;
540
541    // A block has to either have all of its children inline, or all of its children as blocks.
542    // So, if our children are currently inline and a block child has to be inserted, we move all our
543    // inline children into anonymous block boxes.
544    if (childrenInline() && !newChild->isInline() && !newChild->isFloatingOrOutOfFlowPositioned()) {
545        // This is a block with inline content. Wrap the inline content in anonymous blocks.
546        makeChildrenNonInline(beforeChild);
547        madeBoxesNonInline = true;
548
549        if (beforeChild && beforeChild->parent() != this) {
550            beforeChild = beforeChild->parent();
551            ASSERT(beforeChild->isAnonymousBlock());
552            ASSERT(beforeChild->parent() == this);
553        }
554    } else if (!childrenInline() && (newChild->isFloatingOrOutOfFlowPositioned() || newChild->isInline())) {
555        // If we're inserting an inline child but all of our children are blocks, then we have to make sure
556        // it is put into an anomyous block box. We try to use an existing anonymous box if possible, otherwise
557        // a new one is created and inserted into our list of children in the appropriate position.
558        RenderObject* afterChild = beforeChild ? beforeChild->previousSibling() : lastChild();
559
560        if (afterChild && afterChild->isAnonymousBlock()) {
561            toRenderBlock(afterChild)->addChild(newChild);
562            return;
563        }
564
565        if (newChild->isInline()) {
566            // No suitable existing anonymous box - create a new one.
567            RenderBlock* newBox = createAnonymousBlock();
568            RenderBox::addChild(newBox, beforeChild);
569            newBox->addChild(newChild);
570            return;
571        }
572    }
573
574    invalidateLineLayoutPath();
575
576    RenderBox::addChild(newChild, beforeChild);
577
578    if (madeBoxesNonInline && parent() && isAnonymousBlock() && parent()->isRenderBlock())
579        toRenderBlock(parent())->removeLeftoverAnonymousBlock(this);
580    // this object may be dead here
581}
582
583static void getInlineRun(RenderObject* start, RenderObject* boundary,
584                         RenderObject*& inlineRunStart,
585                         RenderObject*& inlineRunEnd)
586{
587    // Beginning at |start| we find the largest contiguous run of inlines that
588    // we can.  We denote the run with start and end points, |inlineRunStart|
589    // and |inlineRunEnd|.  Note that these two values may be the same if
590    // we encounter only one inline.
591    //
592    // We skip any non-inlines we encounter as long as we haven't found any
593    // inlines yet.
594    //
595    // |boundary| indicates a non-inclusive boundary point.  Regardless of whether |boundary|
596    // is inline or not, we will not include it in a run with inlines before it.  It's as though we encountered
597    // a non-inline.
598
599    // Start by skipping as many non-inlines as we can.
600    RenderObject * curr = start;
601    bool sawInline;
602    do {
603        while (curr && !(curr->isInline() || curr->isFloatingOrOutOfFlowPositioned()))
604            curr = curr->nextSibling();
605
606        inlineRunStart = inlineRunEnd = curr;
607
608        if (!curr)
609            return; // No more inline children to be found.
610
611        sawInline = curr->isInline();
612
613        curr = curr->nextSibling();
614        while (curr && (curr->isInline() || curr->isFloatingOrOutOfFlowPositioned()) && (curr != boundary)) {
615            inlineRunEnd = curr;
616            if (curr->isInline())
617                sawInline = true;
618            curr = curr->nextSibling();
619        }
620    } while (!sawInline);
621}
622
623void RenderBlock::deleteLines()
624{
625    if (AXObjectCache* cache = document().existingAXObjectCache())
626        cache->recomputeIsIgnored(this);
627}
628
629void RenderBlock::makeChildrenNonInline(RenderObject* insertionPoint)
630{
631    // makeChildrenNonInline takes a block whose children are *all* inline and it
632    // makes sure that inline children are coalesced under anonymous
633    // blocks.  If |insertionPoint| is defined, then it represents the insertion point for
634    // the new block child that is causing us to have to wrap all the inlines.  This
635    // means that we cannot coalesce inlines before |insertionPoint| with inlines following
636    // |insertionPoint|, because the new child is going to be inserted in between the inlines,
637    // splitting them.
638    ASSERT(isInlineBlockOrInlineTable() || !isInline());
639    ASSERT(!insertionPoint || insertionPoint->parent() == this);
640
641    setChildrenInline(false);
642
643    RenderObject* child = firstChild();
644    if (!child)
645        return;
646
647    deleteLines();
648
649    while (child) {
650        RenderObject* inlineRunStart;
651        RenderObject* inlineRunEnd;
652        getInlineRun(child, insertionPoint, inlineRunStart, inlineRunEnd);
653
654        if (!inlineRunStart)
655            break;
656
657        child = inlineRunEnd->nextSibling();
658
659        RenderBlock* block = createAnonymousBlock();
660        insertChildInternal(block, inlineRunStart, NotifyChildren);
661        moveChildrenTo(block, inlineRunStart, child);
662    }
663
664#ifndef NDEBUG
665    for (RenderObject* c = firstChild(); c; c = c->nextSibling())
666        ASSERT(!c->isInline());
667#endif
668
669    repaint();
670}
671
672void RenderBlock::removeLeftoverAnonymousBlock(RenderBlock* child)
673{
674    ASSERT(child->isAnonymousBlock());
675    ASSERT(!child->childrenInline());
676
677    if (child->continuation())
678        return;
679
680    RenderObject* firstAnChild = child->firstChild();
681    RenderObject* lastAnChild = child->lastChild();
682    if (firstAnChild) {
683        RenderObject* o = firstAnChild;
684        while (o) {
685            o->setParent(this);
686            o = o->nextSibling();
687        }
688        firstAnChild->setPreviousSibling(child->previousSibling());
689        lastAnChild->setNextSibling(child->nextSibling());
690        if (child->previousSibling())
691            child->previousSibling()->setNextSibling(firstAnChild);
692        if (child->nextSibling())
693            child->nextSibling()->setPreviousSibling(lastAnChild);
694
695        if (child == firstChild())
696            setFirstChild(firstAnChild);
697        if (child == lastChild())
698            setLastChild(lastAnChild);
699    } else {
700        if (child == firstChild())
701            setFirstChild(child->nextSibling());
702        if (child == lastChild())
703            setLastChild(child->previousSibling());
704
705        if (child->previousSibling())
706            child->previousSibling()->setNextSibling(child->nextSibling());
707        if (child->nextSibling())
708            child->nextSibling()->setPreviousSibling(child->previousSibling());
709    }
710
711    child->setFirstChild(0);
712    child->m_next = 0;
713
714    // Remove all the information in the flow thread associated with the leftover anonymous block.
715    child->removeFromRenderFlowThread();
716
717    child->setParent(0);
718    child->setPreviousSibling(0);
719    child->setNextSibling(0);
720
721    child->destroy();
722}
723
724static bool canMergeAnonymousBlock(RenderBlock* anonymousBlock)
725{
726    if (anonymousBlock->beingDestroyed() || anonymousBlock->continuation())
727        return false;
728    if (anonymousBlock->isRubyRun() || anonymousBlock->isRubyBase())
729        return false;
730    return true;
731}
732
733static bool canMergeContiguousAnonymousBlocks(RenderObject& oldChild, RenderObject* previous, RenderObject* next)
734{
735    if (oldChild.documentBeingDestroyed() || oldChild.isInline() || oldChild.virtualContinuation())
736        return false;
737
738    if (previous) {
739        if (!previous->isAnonymousBlock())
740            return false;
741        RenderBlock* previousAnonymousBlock = toRenderBlock(previous);
742        if (!canMergeAnonymousBlock(previousAnonymousBlock))
743            return false;
744    }
745    if (next) {
746        if (!next->isAnonymousBlock())
747            return false;
748        RenderBlock* nextAnonymousBlock = toRenderBlock(next);
749        if (!canMergeAnonymousBlock(nextAnonymousBlock))
750            return false;
751    }
752    return true;
753}
754
755void RenderBlock::collapseAnonymousBoxChild(RenderBlock* parent, RenderBlock* child)
756{
757    parent->setNeedsLayoutAndPrefWidthsRecalc();
758    parent->setChildrenInline(child->childrenInline());
759    RenderObject* nextSibling = child->nextSibling();
760
761    RenderFlowThread* childFlowThread = child->flowThreadContainingBlock();
762    CurrentRenderFlowThreadMaintainer flowThreadMaintainer(childFlowThread);
763    if (childFlowThread && childFlowThread->isRenderNamedFlowThread())
764        toRenderNamedFlowThread(childFlowThread)->removeFlowChildInfo(child);
765
766    parent->removeChildInternal(*child, child->hasLayer() ? NotifyChildren : DontNotifyChildren);
767    child->moveAllChildrenTo(parent, nextSibling, child->hasLayer());
768    // Delete the now-empty block's lines and nuke it.
769    child->deleteLines();
770    child->destroy();
771}
772
773RenderObject* RenderBlock::removeChild(RenderObject& oldChild)
774{
775    // No need to waste time in merging or removing empty anonymous blocks.
776    // We can just bail out if our document is getting destroyed.
777    if (documentBeingDestroyed())
778        return RenderBox::removeChild(oldChild);
779
780    // If this child is a block, and if our previous and next siblings are
781    // both anonymous blocks with inline content, then we can go ahead and
782    // fold the inline content back together.
783    RenderObject* prev = oldChild.previousSibling();
784    RenderObject* next = oldChild.nextSibling();
785    bool canMergeAnonymousBlocks = canMergeContiguousAnonymousBlocks(oldChild, prev, next);
786    if (canMergeAnonymousBlocks && prev && next) {
787        prev->setNeedsLayoutAndPrefWidthsRecalc();
788        RenderBlock* nextBlock = toRenderBlock(next);
789        RenderBlock* prevBlock = toRenderBlock(prev);
790
791        if (prev->childrenInline() != next->childrenInline()) {
792            RenderBlock* inlineChildrenBlock = prev->childrenInline() ? prevBlock : nextBlock;
793            RenderBlock* blockChildrenBlock = prev->childrenInline() ? nextBlock : prevBlock;
794
795            // Place the inline children block inside of the block children block instead of deleting it.
796            // In order to reuse it, we have to reset it to just be a generic anonymous block.  Make sure
797            // to clear out inherited column properties by just making a new style, and to also clear the
798            // column span flag if it is set.
799            ASSERT(!inlineChildrenBlock->continuation());
800            // Cache this value as it might get changed in setStyle() call.
801            bool inlineChildrenBlockHasLayer = inlineChildrenBlock->hasLayer();
802            inlineChildrenBlock->setStyle(RenderStyle::createAnonymousStyleWithDisplay(&style(), BLOCK));
803            removeChildInternal(*inlineChildrenBlock, inlineChildrenBlockHasLayer ? NotifyChildren : DontNotifyChildren);
804
805            // Now just put the inlineChildrenBlock inside the blockChildrenBlock.
806            RenderObject* beforeChild = prev == inlineChildrenBlock ? blockChildrenBlock->firstChild() : nullptr;
807            blockChildrenBlock->insertChildInternal(inlineChildrenBlock, beforeChild,
808                (inlineChildrenBlockHasLayer || blockChildrenBlock->hasLayer()) ? NotifyChildren : DontNotifyChildren);
809            next->setNeedsLayoutAndPrefWidthsRecalc();
810
811            // inlineChildrenBlock got reparented to blockChildrenBlock, so it is no longer a child
812            // of "this". we null out prev or next so that is not used later in the function.
813            if (inlineChildrenBlock == prevBlock)
814                prev = 0;
815            else
816                next = 0;
817        } else {
818            // Take all the children out of the |next| block and put them in
819            // the |prev| block.
820            nextBlock->moveAllChildrenIncludingFloatsTo(prevBlock, nextBlock->hasLayer() || prevBlock->hasLayer());
821
822            // Delete the now-empty block's lines and nuke it.
823            nextBlock->deleteLines();
824            nextBlock->destroy();
825            next = 0;
826        }
827    }
828
829    invalidateLineLayoutPath();
830
831    RenderObject* nextSibling = RenderBox::removeChild(oldChild);
832
833    RenderObject* child = prev ? prev : next;
834    if (canMergeAnonymousBlocks && child && !child->previousSibling() && !child->nextSibling() && canCollapseAnonymousBlockChild()) {
835        // The removal has knocked us down to containing only a single anonymous
836        // box.  We can go ahead and pull the content right back up into our
837        // box.
838        collapseAnonymousBoxChild(this, toRenderBlock(child));
839        nextSibling = nullptr;
840    } else if (((prev && prev->isAnonymousBlock()) || (next && next->isAnonymousBlock())) && canCollapseAnonymousBlockChild()) {
841        // It's possible that the removal has knocked us down to a single anonymous
842        // block with pseudo-style element siblings (e.g. first-letter). If these
843        // are floating, then we need to pull the content up also.
844        RenderBlock* anonBlock = toRenderBlock((prev && prev->isAnonymousBlock()) ? prev : next);
845        if ((anonBlock->previousSibling() || anonBlock->nextSibling())
846            && (!anonBlock->previousSibling() || (anonBlock->previousSibling()->style().styleType() != NOPSEUDO && anonBlock->previousSibling()->isFloating() && !anonBlock->previousSibling()->previousSibling()))
847            && (!anonBlock->nextSibling() || (anonBlock->nextSibling()->style().styleType() != NOPSEUDO && anonBlock->nextSibling()->isFloating() && !anonBlock->nextSibling()->nextSibling()))) {
848            collapseAnonymousBoxChild(this, anonBlock);
849            nextSibling = nullptr;
850        }
851    }
852
853    if (!firstChild()) {
854        nextSibling = nullptr;
855
856        // If this was our last child be sure to clear out our line boxes.
857        if (childrenInline())
858            deleteLines();
859
860        // If we are an empty anonymous block in the continuation chain,
861        // we need to remove ourself and fix the continuation chain.
862        if (!beingDestroyed() && isAnonymousBlockContinuation() && !oldChild.isListMarker()) {
863            auto containingBlockIgnoringAnonymous = containingBlock();
864            while (containingBlockIgnoringAnonymous && containingBlockIgnoringAnonymous->isAnonymousBlock())
865                containingBlockIgnoringAnonymous = containingBlockIgnoringAnonymous->containingBlock();
866            for (RenderObject* curr = this; curr; curr = curr->previousInPreOrder(containingBlockIgnoringAnonymous)) {
867                if (curr->virtualContinuation() != this)
868                    continue;
869
870                // Found our previous continuation. We just need to point it to
871                // |this|'s next continuation.
872                RenderBoxModelObject* nextContinuation = continuation();
873                if (curr->isRenderInline())
874                    toRenderInline(curr)->setContinuation(nextContinuation);
875                else if (curr->isRenderBlock())
876                    toRenderBlock(curr)->setContinuation(nextContinuation);
877                else
878                    ASSERT_NOT_REACHED();
879
880                break;
881            }
882            setContinuation(0);
883            destroy();
884        }
885    }
886
887    return nextSibling;
888}
889
890bool RenderBlock::isSelfCollapsingBlock() const
891{
892    // We are not self-collapsing if we
893    // (a) have a non-zero height according to layout (an optimization to avoid wasting time)
894    // (b) are a table,
895    // (c) have border/padding,
896    // (d) have a min-height
897    // (e) have specified that one of our margins can't collapse using a CSS extension
898    if (logicalHeight() > 0
899        || isTable() || borderAndPaddingLogicalHeight()
900        || style().logicalMinHeight().isPositive()
901        || style().marginBeforeCollapse() == MSEPARATE || style().marginAfterCollapse() == MSEPARATE)
902        return false;
903
904    Length logicalHeightLength = style().logicalHeight();
905    bool hasAutoHeight = logicalHeightLength.isAuto();
906    if (logicalHeightLength.isPercent() && !document().inQuirksMode()) {
907        hasAutoHeight = true;
908        for (RenderBlock* cb = containingBlock(); !cb->isRenderView(); cb = cb->containingBlock()) {
909            if (cb->style().logicalHeight().isFixed() || cb->isTableCell())
910                hasAutoHeight = false;
911        }
912    }
913
914    // If the height is 0 or auto, then whether or not we are a self-collapsing block depends
915    // on whether we have content that is all self-collapsing or not.
916    if (hasAutoHeight || ((logicalHeightLength.isFixed() || logicalHeightLength.isPercent()) && logicalHeightLength.isZero())) {
917        // If the block has inline children, see if we generated any line boxes.  If we have any
918        // line boxes, then we can't be self-collapsing, since we have content.
919        if (childrenInline())
920            return !hasLines();
921
922        // Whether or not we collapse is dependent on whether all our normal flow children
923        // are also self-collapsing.
924        for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
925            if (child->isFloatingOrOutOfFlowPositioned())
926                continue;
927            if (!child->isSelfCollapsingBlock())
928                return false;
929        }
930        return true;
931    }
932    return false;
933}
934
935static inline UpdateScrollInfoAfterLayoutTransaction* currentUpdateScrollInfoAfterLayoutTransaction()
936{
937    if (!updateScrollInfoAfterLayoutTransactionStack())
938        return nullptr;
939    return &updateScrollInfoAfterLayoutTransactionStack()->last();
940}
941
942void RenderBlock::beginUpdateScrollInfoAfterLayoutTransaction()
943{
944    if (!updateScrollInfoAfterLayoutTransactionStack())
945        updateScrollInfoAfterLayoutTransactionStack() = std::make_unique<DelayedUpdateScrollInfoStack>();
946    if (updateScrollInfoAfterLayoutTransactionStack()->isEmpty() || currentUpdateScrollInfoAfterLayoutTransaction()->view != &view())
947        updateScrollInfoAfterLayoutTransactionStack()->append(UpdateScrollInfoAfterLayoutTransaction(view()));
948    ++currentUpdateScrollInfoAfterLayoutTransaction()->nestedCount;
949}
950
951void RenderBlock::endAndCommitUpdateScrollInfoAfterLayoutTransaction()
952{
953    UpdateScrollInfoAfterLayoutTransaction* transaction = currentUpdateScrollInfoAfterLayoutTransaction();
954    ASSERT(transaction);
955    ASSERT(transaction->view == &view());
956    if (--transaction->nestedCount)
957        return;
958
959    // Calling RenderLayer::updateScrollInfoAfterLayout() may cause its associated block to layout again and
960    // updates its scroll info (i.e. call RenderBlock::updateScrollInfoAfterLayout()). We remove |transaction|
961    // from the transaction stack to ensure that all subsequent calls to RenderBlock::updateScrollInfoAfterLayout()
962    // are dispatched immediately. That is, to ensure that such subsequent calls aren't added to |transaction|
963    // while we are processing it.
964    Vector<RenderBlock*> blocksToUpdate;
965    copyToVector(transaction->blocks, blocksToUpdate);
966    updateScrollInfoAfterLayoutTransactionStack()->removeLast();
967    if (updateScrollInfoAfterLayoutTransactionStack()->isEmpty())
968        updateScrollInfoAfterLayoutTransactionStack() = nullptr;
969
970    for (auto* block : blocksToUpdate) {
971        ASSERT(block->hasOverflowClip());
972        block->layer()->updateScrollInfoAfterLayout();
973        block->clearLayoutOverflow();
974    }
975}
976
977void RenderBlock::removeFromUpdateScrollInfoAfterLayoutTransaction()
978{
979    if (UNLIKELY(updateScrollInfoAfterLayoutTransactionStack().get() != 0)) {
980        UpdateScrollInfoAfterLayoutTransaction* transaction = currentUpdateScrollInfoAfterLayoutTransaction();
981        ASSERT(transaction);
982        ASSERT(transaction->view == &view());
983        transaction->blocks.remove(this);
984    }
985}
986
987void RenderBlock::updateScrollInfoAfterLayout()
988{
989    if (hasOverflowClip()) {
990        if (style().isFlippedBlocksWritingMode()) {
991            // FIXME: https://bugs.webkit.org/show_bug.cgi?id=97937
992            // Workaround for now. We cannot delay the scroll info for overflow
993            // for items with opposite writing directions, as the contents needs
994            // to overflow in that direction
995            layer()->updateScrollInfoAfterLayout();
996            return;
997        }
998
999        UpdateScrollInfoAfterLayoutTransaction* transaction = currentUpdateScrollInfoAfterLayoutTransaction();
1000        if (transaction && transaction->view == &view()) {
1001            transaction->blocks.add(this);
1002            return;
1003        }
1004        layer()->updateScrollInfoAfterLayout();
1005    }
1006}
1007
1008void RenderBlock::layout()
1009{
1010    StackStats::LayoutCheckPoint layoutCheckPoint;
1011    OverflowEventDispatcher dispatcher(this);
1012
1013    // Update our first letter info now.
1014    updateFirstLetter();
1015
1016    // Table cells call layoutBlock directly, so don't add any logic here.  Put code into
1017    // layoutBlock().
1018    layoutBlock(false);
1019
1020    // It's safe to check for control clip here, since controls can never be table cells.
1021    // If we have a lightweight clip, there can never be any overflow from children.
1022    UpdateScrollInfoAfterLayoutTransaction* transaction = currentUpdateScrollInfoAfterLayoutTransaction();
1023    bool isDelayingUpdateScrollInfoAfterLayoutInView = transaction && transaction->view == &view();
1024    if (hasControlClip() && m_overflow && !isDelayingUpdateScrollInfoAfterLayoutInView)
1025        clearLayoutOverflow();
1026
1027    invalidateBackgroundObscurationStatus();
1028}
1029
1030static RenderBlockRareData* getRareData(const RenderBlock* block)
1031{
1032    return gRareDataMap ? gRareDataMap->get(block) : 0;
1033}
1034
1035static RenderBlockRareData& ensureRareData(const RenderBlock* block)
1036{
1037    if (!gRareDataMap)
1038        gRareDataMap = new RenderBlockRareDataMap;
1039
1040    auto& rareData = gRareDataMap->add(block, nullptr).iterator->value;
1041    if (!rareData)
1042        rareData = std::make_unique<RenderBlockRareData>();
1043    return *rareData.get();
1044}
1045
1046#if ENABLE(CSS_SHAPES)
1047void RenderBlock::imageChanged(WrappedImagePtr image, const IntRect*)
1048{
1049    RenderBox::imageChanged(image);
1050
1051    if (!parent() || !everHadLayout())
1052        return;
1053}
1054#endif
1055
1056void RenderBlock::preparePaginationBeforeBlockLayout(bool& relayoutChildren)
1057{
1058    // Regions changing widths can force us to relayout our children.
1059    RenderFlowThread* flowThread = flowThreadContainingBlock();
1060    if (flowThread)
1061        flowThread->logicalWidthChangedInRegionsForBlock(this, relayoutChildren);
1062}
1063
1064bool RenderBlock::recomputeLogicalWidth()
1065{
1066    LayoutUnit oldWidth = logicalWidth();
1067
1068    updateLogicalWidth();
1069
1070    bool hasBorderOrPaddingLogicalWidthChanged = m_hasBorderOrPaddingLogicalWidthChanged;
1071    m_hasBorderOrPaddingLogicalWidthChanged = false;
1072
1073    return oldWidth != logicalWidth() || hasBorderOrPaddingLogicalWidthChanged;
1074}
1075
1076void RenderBlock::layoutBlock(bool, LayoutUnit)
1077{
1078    ASSERT_NOT_REACHED();
1079    clearNeedsLayout();
1080}
1081
1082void RenderBlock::addOverflowFromChildren()
1083{
1084    if (childrenInline())
1085        addOverflowFromInlineChildren();
1086    else
1087        addOverflowFromBlockChildren();
1088
1089    // If this block is flowed inside a flow thread, make sure its overflow is propagated to the containing regions.
1090    if (m_overflow) {
1091        if (RenderFlowThread* containingFlowThread = flowThreadContainingBlock())
1092            containingFlowThread->addRegionsVisualOverflow(this, m_overflow->visualOverflowRect());
1093    }
1094}
1095
1096void RenderBlock::computeOverflow(LayoutUnit oldClientAfterEdge, bool)
1097{
1098    clearOverflow();
1099
1100    // Add overflow from children.
1101    addOverflowFromChildren();
1102
1103    // Add in the overflow from positioned objects.
1104    addOverflowFromPositionedObjects();
1105
1106    if (hasOverflowClip()) {
1107        // When we have overflow clip, propagate the original spillout since it will include collapsed bottom margins
1108        // and bottom padding.  Set the axis we don't care about to be 1, since we want this overflow to always
1109        // be considered reachable.
1110        LayoutRect clientRect(flippedClientBoxRect());
1111        LayoutRect rectToApply;
1112        if (isHorizontalWritingMode())
1113            rectToApply = LayoutRect(clientRect.x(), clientRect.y(), 1, std::max<LayoutUnit>(0, oldClientAfterEdge - clientRect.y()));
1114        else
1115            rectToApply = LayoutRect(clientRect.x(), clientRect.y(), std::max<LayoutUnit>(0, oldClientAfterEdge - clientRect.x()), 1);
1116        addLayoutOverflow(rectToApply);
1117        if (hasRenderOverflow())
1118            m_overflow->setLayoutClientAfterEdge(oldClientAfterEdge);
1119    }
1120
1121    // Add visual overflow from box-shadow and border-image-outset.
1122    addVisualEffectOverflow();
1123
1124    // Add visual overflow from theme.
1125    addVisualOverflowFromTheme();
1126}
1127
1128void RenderBlock::clearLayoutOverflow()
1129{
1130    if (!m_overflow)
1131        return;
1132
1133    if (visualOverflowRect() == borderBoxRect()) {
1134        // FIXME: Implement complete solution for regions overflow.
1135        clearOverflow();
1136        return;
1137    }
1138
1139    m_overflow->setLayoutOverflow(borderBoxRect());
1140}
1141
1142void RenderBlock::addOverflowFromBlockChildren()
1143{
1144    for (auto child = firstChildBox(); child; child = child->nextSiblingBox()) {
1145        if (!child->isFloatingOrOutOfFlowPositioned())
1146            addOverflowFromChild(child);
1147    }
1148}
1149
1150void RenderBlock::addOverflowFromPositionedObjects()
1151{
1152    TrackedRendererListHashSet* positionedDescendants = positionedObjects();
1153    if (!positionedDescendants)
1154        return;
1155
1156    for (auto it = positionedDescendants->begin(), end = positionedDescendants->end(); it != end; ++it) {
1157        RenderBox* positionedObject = *it;
1158
1159        // Fixed positioned elements don't contribute to layout overflow, since they don't scroll with the content.
1160        if (positionedObject->style().position() != FixedPosition) {
1161            LayoutUnit x = positionedObject->x();
1162            if (style().shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
1163                x -= verticalScrollbarWidth();
1164            addOverflowFromChild(positionedObject, LayoutSize(x, positionedObject->y()));
1165        }
1166    }
1167}
1168
1169void RenderBlock::addVisualOverflowFromTheme()
1170{
1171    if (!style().hasAppearance())
1172        return;
1173
1174    FloatRect inflatedRect = borderBoxRect();
1175    theme().adjustRepaintRect(*this, inflatedRect);
1176    addVisualOverflow(pixelSnappedIntRect(LayoutRect(inflatedRect)));
1177
1178    if (RenderFlowThread* flowThread = flowThreadContainingBlock())
1179        flowThread->addRegionsVisualOverflowFromTheme(this);
1180}
1181
1182bool RenderBlock::expandsToEncloseOverhangingFloats() const
1183{
1184    return isInlineBlockOrInlineTable() || isFloatingOrOutOfFlowPositioned() || hasOverflowClip() || (parent() && parent()->isFlexibleBoxIncludingDeprecated())
1185        || isTableCell() || isTableCaption() || isFieldset() || isWritingModeRoot() || isRoot() || isRenderFlowThread();
1186}
1187
1188LayoutUnit RenderBlock::computeStartPositionDeltaForChildAvoidingFloats(const RenderBox& child, LayoutUnit childMarginStart, RenderRegion* region)
1189{
1190    LayoutUnit startPosition = startOffsetForContent(region);
1191
1192    // Add in our start margin.
1193    LayoutUnit oldPosition = startPosition + childMarginStart;
1194    LayoutUnit newPosition = oldPosition;
1195
1196    LayoutUnit blockOffset = logicalTopForChild(child);
1197    if (region)
1198        blockOffset = std::max(blockOffset, blockOffset + (region->logicalTopForFlowThreadContent() - offsetFromLogicalTopOfFirstPage()));
1199
1200    LayoutUnit startOff = startOffsetForLineInRegion(blockOffset, false, region, logicalHeightForChild(child));
1201
1202    if (style().textAlign() != WEBKIT_CENTER && !child.style().marginStartUsing(&style()).isAuto()) {
1203        if (childMarginStart < 0)
1204            startOff += childMarginStart;
1205        newPosition = std::max(newPosition, startOff); // Let the float sit in the child's margin if it can fit.
1206    } else if (startOff != startPosition)
1207        newPosition = startOff + childMarginStart;
1208
1209    return newPosition - oldPosition;
1210}
1211
1212void RenderBlock::setLogicalLeftForChild(RenderBox& child, LayoutUnit logicalLeft, ApplyLayoutDeltaMode applyDelta)
1213{
1214    if (isHorizontalWritingMode()) {
1215        if (applyDelta == ApplyLayoutDelta)
1216            view().addLayoutDelta(LayoutSize(child.x() - logicalLeft, 0));
1217        child.setX(logicalLeft);
1218    } else {
1219        if (applyDelta == ApplyLayoutDelta)
1220            view().addLayoutDelta(LayoutSize(0, child.y() - logicalLeft));
1221        child.setY(logicalLeft);
1222    }
1223}
1224
1225void RenderBlock::setLogicalTopForChild(RenderBox& child, LayoutUnit logicalTop, ApplyLayoutDeltaMode applyDelta)
1226{
1227    if (isHorizontalWritingMode()) {
1228        if (applyDelta == ApplyLayoutDelta)
1229            view().addLayoutDelta(LayoutSize(0, child.y() - logicalTop));
1230        child.setY(logicalTop);
1231    } else {
1232        if (applyDelta == ApplyLayoutDelta)
1233            view().addLayoutDelta(LayoutSize(child.x() - logicalTop, 0));
1234        child.setX(logicalTop);
1235    }
1236}
1237
1238void RenderBlock::updateBlockChildDirtyBitsBeforeLayout(bool relayoutChildren, RenderBox& child)
1239{
1240    // FIXME: Technically percentage height objects only need a relayout if their percentage isn't going to be turned into
1241    // an auto value. Add a method to determine this, so that we can avoid the relayout.
1242    if (relayoutChildren || (child.hasRelativeLogicalHeight() && !isRenderView()))
1243        child.setChildNeedsLayout(MarkOnlyThis);
1244
1245    // If relayoutChildren is set and the child has percentage padding or an embedded content box, we also need to invalidate the childs pref widths.
1246    if (relayoutChildren && child.needsPreferredWidthsRecalculation())
1247        child.setPreferredLogicalWidthsDirty(true, MarkOnlyThis);
1248}
1249
1250void RenderBlock::dirtyForLayoutFromPercentageHeightDescendants()
1251{
1252    if (!gPercentHeightDescendantsMap)
1253        return;
1254
1255    TrackedRendererListHashSet* descendants = gPercentHeightDescendantsMap->get(this);
1256    if (!descendants)
1257        return;
1258
1259    for (auto it = descendants->begin(), end = descendants->end(); it != end; ++it) {
1260        RenderBox* box = *it;
1261        while (box != this) {
1262            if (box->normalChildNeedsLayout())
1263                break;
1264            box->setChildNeedsLayout(MarkOnlyThis);
1265
1266            // If the width of an image is affected by the height of a child (e.g., an image with an aspect ratio),
1267            // then we have to dirty preferred widths, since even enclosing blocks can become dirty as a result.
1268            // (A horizontal flexbox that contains an inline image wrapped in an anonymous block for example.)
1269            if (box->hasAspectRatio())
1270                box->setPreferredLogicalWidthsDirty(true);
1271
1272            box = box->containingBlock();
1273            ASSERT(box);
1274            if (!box)
1275                break;
1276        }
1277    }
1278}
1279
1280void RenderBlock::simplifiedNormalFlowLayout()
1281{
1282    if (childrenInline()) {
1283        ListHashSet<RootInlineBox*> lineBoxes;
1284        for (InlineWalker walker(*this); !walker.atEnd(); walker.advance()) {
1285            RenderObject* o = walker.current();
1286            if (!o->isOutOfFlowPositioned() && (o->isReplaced() || o->isFloating())) {
1287                RenderBox& box = toRenderBox(*o);
1288                box.layoutIfNeeded();
1289                if (box.inlineBoxWrapper())
1290                    lineBoxes.add(&box.inlineBoxWrapper()->root());
1291            } else if (o->isText() || (o->isRenderInline() && !walker.atEndOfInline()))
1292                o->clearNeedsLayout();
1293        }
1294
1295        // FIXME: Glyph overflow will get lost in this case, but not really a big deal.
1296        // FIXME: Find a way to invalidate the knownToHaveNoOverflow flag on the InlineBoxes.
1297        GlyphOverflowAndFallbackFontsMap textBoxDataMap;
1298        for (auto it = lineBoxes.begin(), end = lineBoxes.end(); it != end; ++it) {
1299            RootInlineBox* box = *it;
1300            box->computeOverflow(box->lineTop(), box->lineBottom(), textBoxDataMap);
1301        }
1302    } else {
1303        for (auto box = firstChildBox(); box; box = box->nextSiblingBox()) {
1304            if (!box->isOutOfFlowPositioned())
1305                box->layoutIfNeeded();
1306        }
1307    }
1308}
1309
1310bool RenderBlock::simplifiedLayout()
1311{
1312    if ((!posChildNeedsLayout() && !needsSimplifiedNormalFlowLayout()) || normalChildNeedsLayout() || selfNeedsLayout())
1313        return false;
1314
1315    LayoutStateMaintainer statePusher(view(), *this, locationOffset(), hasTransform() || hasReflection() || style().isFlippedBlocksWritingMode());
1316
1317    if (needsPositionedMovementLayout() && !tryLayoutDoingPositionedMovementOnly())
1318        return false;
1319
1320    // Lay out positioned descendants or objects that just need to recompute overflow.
1321    if (needsSimplifiedNormalFlowLayout())
1322        simplifiedNormalFlowLayout();
1323
1324    // Make sure a forced break is applied after the content if we are a flow thread in a simplified layout.
1325    // This ensures the size information is correctly computed for the last auto-height region receiving content.
1326    if (isRenderFlowThread())
1327        toRenderFlowThread(this)->applyBreakAfterContent(clientLogicalBottom());
1328
1329    // Lay out our positioned objects if our positioned child bit is set.
1330    // Also, if an absolute position element inside a relative positioned container moves, and the absolute element has a fixed position
1331    // child, neither the fixed element nor its container learn of the movement since posChildNeedsLayout() is only marked as far as the
1332    // relative positioned container. So if we can have fixed pos objects in our positioned objects list check if any of them
1333    // are statically positioned and thus need to move with their absolute ancestors.
1334    bool canContainFixedPosObjects = canContainFixedPositionObjects();
1335    if (posChildNeedsLayout() || canContainFixedPosObjects)
1336        layoutPositionedObjects(false, !posChildNeedsLayout() && canContainFixedPosObjects);
1337
1338    // Recompute our overflow information.
1339    // FIXME: We could do better here by computing a temporary overflow object from layoutPositionedObjects and only
1340    // updating our overflow if we either used to have overflow or if the new temporary object has overflow.
1341    // For now just always recompute overflow.  This is no worse performance-wise than the old code that called rightmostPosition and
1342    // lowestPosition on every relayout so it's not a regression.
1343    // computeOverflow expects the bottom edge before we clamp our height. Since this information isn't available during
1344    // simplifiedLayout, we cache the value in m_overflow.
1345    LayoutUnit oldClientAfterEdge = hasRenderOverflow() ? m_overflow->layoutClientAfterEdge() : clientLogicalBottom();
1346    computeOverflow(oldClientAfterEdge, true);
1347
1348    statePusher.pop();
1349
1350    updateLayerTransform();
1351
1352    updateScrollInfoAfterLayout();
1353
1354    clearNeedsLayout();
1355    return true;
1356}
1357
1358void RenderBlock::markFixedPositionObjectForLayoutIfNeeded(RenderObject& child)
1359{
1360    if (child.style().position() != FixedPosition)
1361        return;
1362
1363    bool hasStaticBlockPosition = child.style().hasStaticBlockPosition(isHorizontalWritingMode());
1364    bool hasStaticInlinePosition = child.style().hasStaticInlinePosition(isHorizontalWritingMode());
1365    if (!hasStaticBlockPosition && !hasStaticInlinePosition)
1366        return;
1367
1368    auto o = child.parent();
1369    while (o && !o->isRenderView() && o->style().position() != AbsolutePosition)
1370        o = o->parent();
1371    if (o->style().position() != AbsolutePosition)
1372        return;
1373
1374    RenderBox& box = toRenderBox(child);
1375    if (hasStaticInlinePosition) {
1376        LogicalExtentComputedValues computedValues;
1377        box.computeLogicalWidthInRegion(computedValues);
1378        LayoutUnit newLeft = computedValues.m_position;
1379        if (newLeft != box.logicalLeft())
1380            box.setChildNeedsLayout(MarkOnlyThis);
1381    } else if (hasStaticBlockPosition) {
1382        LayoutUnit oldTop = box.logicalTop();
1383        box.updateLogicalHeight();
1384        if (box.logicalTop() != oldTop)
1385            box.setChildNeedsLayout(MarkOnlyThis);
1386    }
1387}
1388
1389LayoutUnit RenderBlock::marginIntrinsicLogicalWidthForChild(RenderBox& child) const
1390{
1391    // A margin has three types: fixed, percentage, and auto (variable).
1392    // Auto and percentage margins become 0 when computing min/max width.
1393    // Fixed margins can be added in as is.
1394    Length marginLeft = child.style().marginStartUsing(&style());
1395    Length marginRight = child.style().marginEndUsing(&style());
1396    LayoutUnit margin = 0;
1397    if (marginLeft.isFixed())
1398        margin += marginLeft.value();
1399    if (marginRight.isFixed())
1400        margin += marginRight.value();
1401    return margin;
1402}
1403
1404void RenderBlock::layoutPositionedObjects(bool relayoutChildren, bool fixedPositionObjectsOnly)
1405{
1406    TrackedRendererListHashSet* positionedDescendants = positionedObjects();
1407    if (!positionedDescendants)
1408        return;
1409
1410    for (auto it = positionedDescendants->begin(), end = positionedDescendants->end(); it != end; ++it) {
1411        RenderBox& r = **it;
1412
1413        estimateRegionRangeForBoxChild(r);
1414
1415        // A fixed position element with an absolute positioned ancestor has no way of knowing if the latter has changed position. So
1416        // if this is a fixed position element, mark it for layout if it has an abspos ancestor and needs to move with that ancestor, i.e.
1417        // it has static position.
1418        markFixedPositionObjectForLayoutIfNeeded(r);
1419        if (fixedPositionObjectsOnly) {
1420            r.layoutIfNeeded();
1421            continue;
1422        }
1423
1424        // When a non-positioned block element moves, it may have positioned children that are implicitly positioned relative to the
1425        // non-positioned block.  Rather than trying to detect all of these movement cases, we just always lay out positioned
1426        // objects that are positioned implicitly like this.  Such objects are rare, and so in typical DHTML menu usage (where everything is
1427        // positioned explicitly) this should not incur a performance penalty.
1428        if (relayoutChildren || (r.style().hasStaticBlockPosition(isHorizontalWritingMode()) && r.parent() != this))
1429            r.setChildNeedsLayout(MarkOnlyThis);
1430
1431        // If relayoutChildren is set and the child has percentage padding or an embedded content box, we also need to invalidate the childs pref widths.
1432        if (relayoutChildren && r.needsPreferredWidthsRecalculation())
1433            r.setPreferredLogicalWidthsDirty(true, MarkOnlyThis);
1434
1435        if (!r.needsLayout())
1436            r.markForPaginationRelayoutIfNeeded();
1437
1438        // 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
1439        // and we hit the available width constraint, the layoutIfNeeded() will catch it and do a full layout.
1440        if (r.needsPositionedMovementLayoutOnly() && r.tryLayoutDoingPositionedMovementOnly())
1441            r.clearNeedsLayout();
1442
1443        // If we are paginated or in a line grid, go ahead and compute a vertical position for our object now.
1444        // If it's wrong we'll lay out again.
1445        LayoutUnit oldLogicalTop = 0;
1446        bool needsBlockDirectionLocationSetBeforeLayout = r.needsLayout() && view().layoutState()->needsBlockDirectionLocationSetBeforeLayout();
1447        if (needsBlockDirectionLocationSetBeforeLayout) {
1448            if (isHorizontalWritingMode() == r.isHorizontalWritingMode())
1449                r.updateLogicalHeight();
1450            else
1451                r.updateLogicalWidth();
1452            oldLogicalTop = logicalTopForChild(r);
1453        }
1454
1455        r.layoutIfNeeded();
1456
1457        // Lay out again if our estimate was wrong.
1458        if (needsBlockDirectionLocationSetBeforeLayout && logicalTopForChild(r) != oldLogicalTop) {
1459            r.setChildNeedsLayout(MarkOnlyThis);
1460            r.layoutIfNeeded();
1461        }
1462
1463        if (updateRegionRangeForBoxChild(r)) {
1464            r.setNeedsLayout(MarkOnlyThis);
1465            r.layoutIfNeeded();
1466        }
1467    }
1468}
1469
1470void RenderBlock::markPositionedObjectsForLayout()
1471{
1472    TrackedRendererListHashSet* positionedDescendants = positionedObjects();
1473    if (!positionedDescendants)
1474        return;
1475
1476    for (auto it = positionedDescendants->begin(), end = positionedDescendants->end(); it != end; ++it) {
1477        RenderBox* r = *it;
1478        r->setChildNeedsLayout();
1479    }
1480}
1481
1482void RenderBlock::markForPaginationRelayoutIfNeeded()
1483{
1484    ASSERT(!needsLayout());
1485    if (needsLayout())
1486        return;
1487
1488    if (view().layoutState()->pageLogicalHeightChanged() || (view().layoutState()->pageLogicalHeight() && view().layoutState()->pageLogicalOffset(this, logicalTop()) != pageLogicalOffset()))
1489        setChildNeedsLayout(MarkOnlyThis);
1490}
1491
1492void RenderBlock::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
1493{
1494    LayoutPoint adjustedPaintOffset = paintOffset + location();
1495
1496    PaintPhase phase = paintInfo.phase;
1497
1498    RenderNamedFlowFragment* namedFlowFragment = currentRenderNamedFlowFragment();
1499    // Check our region range to make sure we need to be painting in this region.
1500    if (namedFlowFragment && !namedFlowFragment->flowThread()->objectShouldFragmentInFlowRegion(this, namedFlowFragment))
1501        return;
1502
1503    // Check if we need to do anything at all.
1504    // FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView
1505    // paints the root's background.
1506    if (!isRoot()) {
1507        LayoutRect overflowBox = overflowRectForPaintRejection(namedFlowFragment);
1508        flipForWritingMode(overflowBox);
1509        overflowBox.inflate(maximalOutlineSize(paintInfo.phase));
1510        overflowBox.moveBy(adjustedPaintOffset);
1511        if (!overflowBox.intersects(paintInfo.rect)
1512#if PLATFORM(IOS)
1513            // FIXME: This may be applicable to non-iOS ports.
1514            && (!hasLayer() || !layer()->isComposited())
1515#endif
1516        )
1517            return;
1518    }
1519
1520    bool pushedClip = pushContentsClip(paintInfo, adjustedPaintOffset);
1521    paintObject(paintInfo, adjustedPaintOffset);
1522    if (pushedClip)
1523        popContentsClip(paintInfo, phase, adjustedPaintOffset);
1524
1525    // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
1526    // z-index.  We paint after we painted the background/border, so that the scrollbars will
1527    // sit above the background/border.
1528    if (hasOverflowClip() && style().visibility() == VISIBLE && (phase == PaintPhaseBlockBackground || phase == PaintPhaseChildBlockBackground) && paintInfo.shouldPaintWithinRoot(*this) && !paintInfo.paintRootBackgroundOnly())
1529        layer()->paintOverflowControls(paintInfo.context, roundedIntPoint(adjustedPaintOffset), pixelSnappedIntRect(paintInfo.rect));
1530}
1531
1532void RenderBlock::paintContents(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
1533{
1534    // Avoid painting descendants of the root element when stylesheets haven't loaded.  This eliminates FOUC.
1535    // It's ok not to draw, because later on, when all the stylesheets do load, styleResolverChanged() on the Document
1536    // will do a full repaint.
1537    if (document().didLayoutWithPendingStylesheets() && !isRenderView())
1538        return;
1539
1540    if (childrenInline())
1541        paintInlineChildren(paintInfo, paintOffset);
1542    else {
1543        PaintPhase newPhase = (paintInfo.phase == PaintPhaseChildOutlines) ? PaintPhaseOutline : paintInfo.phase;
1544        newPhase = (newPhase == PaintPhaseChildBlockBackgrounds) ? PaintPhaseChildBlockBackground : newPhase;
1545
1546        // We don't paint our own background, but we do let the kids paint their backgrounds.
1547        PaintInfo paintInfoForChild(paintInfo);
1548        paintInfoForChild.phase = newPhase;
1549        paintInfoForChild.updateSubtreePaintRootForChildren(this);
1550
1551        // FIXME: Paint-time pagination is obsolete and is now only used by embedded WebViews inside AppKit
1552        // NSViews. Do not add any more code for this.
1553        bool usePrintRect = !view().printRect().isEmpty();
1554        paintChildren(paintInfo, paintOffset, paintInfoForChild, usePrintRect);
1555    }
1556}
1557
1558void RenderBlock::paintChildren(PaintInfo& paintInfo, const LayoutPoint& paintOffset, PaintInfo& paintInfoForChild, bool usePrintRect)
1559{
1560    for (auto child = firstChildBox(); child; child = child->nextSiblingBox()) {
1561        if (!paintChild(*child, paintInfo, paintOffset, paintInfoForChild, usePrintRect))
1562            return;
1563    }
1564}
1565
1566bool RenderBlock::paintChild(RenderBox& child, PaintInfo& paintInfo, const LayoutPoint& paintOffset, PaintInfo& paintInfoForChild, bool usePrintRect)
1567{
1568    // Check for page-break-before: always, and if it's set, break and bail.
1569    bool checkBeforeAlways = !childrenInline() && (usePrintRect && child.style().pageBreakBefore() == PBALWAYS);
1570    LayoutUnit absoluteChildY = paintOffset.y() + child.y();
1571    if (checkBeforeAlways
1572        && absoluteChildY > paintInfo.rect.y()
1573        && absoluteChildY < paintInfo.rect.maxY()) {
1574        view().setBestTruncatedAt(absoluteChildY, this, true);
1575        return false;
1576    }
1577
1578    if (!child.isFloating() && child.isReplaced() && usePrintRect && child.height() <= view().printRect().height()) {
1579        // Paginate block-level replaced elements.
1580        if (absoluteChildY + child.height() > view().printRect().maxY()) {
1581            if (absoluteChildY < view().truncatedAt())
1582                view().setBestTruncatedAt(absoluteChildY, &child);
1583            // If we were able to truncate, don't paint.
1584            if (absoluteChildY >= view().truncatedAt())
1585                return false;
1586        }
1587    }
1588
1589    LayoutPoint childPoint = flipForWritingModeForChild(&child, paintOffset);
1590    if (!child.hasSelfPaintingLayer() && !child.isFloating())
1591        child.paint(paintInfoForChild, childPoint);
1592
1593    // Check for page-break-after: always, and if it's set, break and bail.
1594    bool checkAfterAlways = !childrenInline() && (usePrintRect && child.style().pageBreakAfter() == PBALWAYS);
1595    if (checkAfterAlways
1596        && (absoluteChildY + child.height()) > paintInfo.rect.y()
1597        && (absoluteChildY + child.height()) < paintInfo.rect.maxY()) {
1598        view().setBestTruncatedAt(absoluteChildY + child.height() + std::max<LayoutUnit>(0, child.collapsedMarginAfter()), this, true);
1599        return false;
1600    }
1601
1602    return true;
1603}
1604
1605
1606void RenderBlock::paintCaret(PaintInfo& paintInfo, const LayoutPoint& paintOffset, CaretType type)
1607{
1608    // Paint the caret if the FrameSelection says so or if caret browsing is enabled
1609    bool caretBrowsing = frame().settings().caretBrowsingEnabled();
1610    RenderObject* caretPainter;
1611    bool isContentEditable;
1612    if (type == CursorCaret) {
1613        caretPainter = frame().selection().caretRendererWithoutUpdatingLayout();
1614        isContentEditable = frame().selection().selection().hasEditableStyle();
1615    } else {
1616        caretPainter = frame().page()->dragCaretController().caretRenderer();
1617        isContentEditable = frame().page()->dragCaretController().isContentEditable();
1618    }
1619
1620    if (caretPainter == this && (isContentEditable || caretBrowsing)) {
1621        if (type == CursorCaret)
1622            frame().selection().paintCaret(paintInfo.context, paintOffset, paintInfo.rect);
1623        else
1624            frame().page()->dragCaretController().paintDragCaret(&frame(), paintInfo.context, paintOffset, paintInfo.rect);
1625    }
1626}
1627
1628void RenderBlock::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
1629{
1630    PaintPhase paintPhase = paintInfo.phase;
1631
1632    // 1. paint background, borders etc
1633    if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && style().visibility() == VISIBLE) {
1634        if (hasBoxDecorations()) {
1635            bool didClipToRegion = false;
1636
1637            RenderNamedFlowFragment* namedFlowFragment = currentRenderNamedFlowFragment();
1638            if (paintInfo.paintContainer && namedFlowFragment && paintInfo.paintContainer->isRenderNamedFlowThread()) {
1639                // If this box goes beyond the current region, then make sure not to overflow the region.
1640                // This (overflowing region X altough also fragmented to region X+1) could happen when one of this box's children
1641                // overflows region X and is an unsplittable element (like an image).
1642                // The same applies for a box overflowing the top of region X when that box is also fragmented in region X-1.
1643
1644                paintInfo.context->save();
1645                didClipToRegion = true;
1646
1647                paintInfo.context->clip(toRenderNamedFlowThread(paintInfo.paintContainer)->decorationsClipRectForBoxInNamedFlowFragment(*this, *namedFlowFragment));
1648            }
1649
1650            paintBoxDecorations(paintInfo, paintOffset);
1651
1652            if (didClipToRegion)
1653                paintInfo.context->restore();
1654        }
1655    }
1656
1657    if (paintPhase == PaintPhaseMask && style().visibility() == VISIBLE) {
1658        paintMask(paintInfo, paintOffset);
1659        return;
1660    }
1661
1662    // If just painting the root background, then return.
1663    if (paintInfo.paintRootBackgroundOnly())
1664        return;
1665
1666    // Adjust our painting position if we're inside a scrolled layer (e.g., an overflow:auto div).
1667    LayoutPoint scrolledOffset = paintOffset;
1668    scrolledOffset.move(-scrolledContentOffset());
1669
1670    // Column rules need to account for scrolling and clipping.
1671    // FIXME: Clipping of column rules does not work. We will need a separate paint phase for column rules I suspect in order to get
1672    // clipping correct (since it has to paint as background but is still considered "contents").
1673    if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && style().visibility() == VISIBLE)
1674        paintColumnRules(paintInfo, scrolledOffset);
1675
1676    // Done with backgrounds, borders and column rules.
1677    if (paintPhase == PaintPhaseBlockBackground)
1678        return;
1679
1680    // 2. paint contents
1681    if (paintPhase != PaintPhaseSelfOutline)
1682        paintContents(paintInfo, scrolledOffset);
1683
1684    // 3. paint selection
1685    // FIXME: Make this work with multi column layouts.  For now don't fill gaps.
1686    bool isPrinting = document().printing();
1687    if (!isPrinting)
1688        paintSelection(paintInfo, scrolledOffset); // Fill in gaps in selection on lines and between blocks.
1689
1690    // 4. paint floats.
1691    if (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip)
1692        paintFloats(paintInfo, scrolledOffset, paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip);
1693
1694    // 5. paint outline.
1695    if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && hasOutline() && style().visibility() == VISIBLE)
1696        paintOutline(paintInfo, LayoutRect(paintOffset, size()));
1697
1698    // 6. paint continuation outlines.
1699    if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseChildOutlines)) {
1700        RenderInline* inlineCont = inlineElementContinuation();
1701        if (inlineCont && inlineCont->hasOutline() && inlineCont->style().visibility() == VISIBLE) {
1702            RenderInline* inlineRenderer = toRenderInline(inlineCont->element()->renderer());
1703            RenderBlock* cb = containingBlock();
1704
1705            bool inlineEnclosedInSelfPaintingLayer = false;
1706            for (RenderBoxModelObject* box = inlineRenderer; box != cb; box = &box->parent()->enclosingBoxModelObject()) {
1707                if (box->hasSelfPaintingLayer()) {
1708                    inlineEnclosedInSelfPaintingLayer = true;
1709                    break;
1710                }
1711            }
1712
1713            // Do not add continuations for outline painting by our containing block if we are a relative positioned
1714            // anonymous block (i.e. have our own layer), paint them straightaway instead. This is because a block depends on renderers in its continuation table being
1715            // in the same layer.
1716            if (!inlineEnclosedInSelfPaintingLayer && !hasLayer())
1717                cb->addContinuationWithOutline(inlineRenderer);
1718            else if (!inlineRenderer->firstLineBox() || (!inlineEnclosedInSelfPaintingLayer && hasLayer()))
1719                inlineRenderer->paintOutline(paintInfo, paintOffset - locationOffset() + inlineRenderer->containingBlock()->location());
1720        }
1721        paintContinuationOutlines(paintInfo, paintOffset);
1722    }
1723
1724    // 7. paint caret.
1725    // If the caret's node's render object's containing block is this block, and the paint action is PaintPhaseForeground,
1726    // then paint the caret.
1727    if (paintPhase == PaintPhaseForeground) {
1728        paintCaret(paintInfo, paintOffset, CursorCaret);
1729        paintCaret(paintInfo, paintOffset, DragCaret);
1730    }
1731}
1732
1733RenderInline* RenderBlock::inlineElementContinuation() const
1734{
1735    RenderBoxModelObject* continuation = this->continuation();
1736    return continuation && continuation->isRenderInline() ? toRenderInline(continuation) : 0;
1737}
1738
1739RenderBlock* RenderBlock::blockElementContinuation() const
1740{
1741    RenderBoxModelObject* currentContinuation = continuation();
1742    if (!currentContinuation || currentContinuation->isInline())
1743        return 0;
1744    RenderBlock* nextContinuation = toRenderBlock(currentContinuation);
1745    if (nextContinuation->isAnonymousBlock())
1746        return nextContinuation->blockElementContinuation();
1747    return nextContinuation;
1748}
1749
1750static ContinuationOutlineTableMap* continuationOutlineTable()
1751{
1752    DEPRECATED_DEFINE_STATIC_LOCAL(ContinuationOutlineTableMap, table, ());
1753    return &table;
1754}
1755
1756void RenderBlock::addContinuationWithOutline(RenderInline* flow)
1757{
1758    // We can't make this work if the inline is in a layer.  We'll just rely on the broken
1759    // way of painting.
1760    ASSERT(!flow->layer() && !flow->isInlineElementContinuation());
1761
1762    ContinuationOutlineTableMap* table = continuationOutlineTable();
1763    ListHashSet<RenderInline*>* continuations = table->get(this);
1764    if (!continuations) {
1765        continuations = new ListHashSet<RenderInline*>;
1766        table->set(this, std::unique_ptr<ListHashSet<RenderInline*>>(continuations));
1767    }
1768
1769    continuations->add(flow);
1770}
1771
1772bool RenderBlock::paintsContinuationOutline(RenderInline* flow)
1773{
1774    ContinuationOutlineTableMap* table = continuationOutlineTable();
1775    if (table->isEmpty())
1776        return false;
1777
1778    ListHashSet<RenderInline*>* continuations = table->get(this);
1779    if (!continuations)
1780        return false;
1781
1782    return continuations->contains(flow);
1783}
1784
1785void RenderBlock::paintContinuationOutlines(PaintInfo& info, const LayoutPoint& paintOffset)
1786{
1787    ContinuationOutlineTableMap* table = continuationOutlineTable();
1788    if (table->isEmpty())
1789        return;
1790
1791    std::unique_ptr<ListHashSet<RenderInline*>> continuations = table->take(this);
1792    if (!continuations)
1793        return;
1794
1795    LayoutPoint accumulatedPaintOffset = paintOffset;
1796    // Paint each continuation outline.
1797    ListHashSet<RenderInline*>::iterator end = continuations->end();
1798    for (ListHashSet<RenderInline*>::iterator it = continuations->begin(); it != end; ++it) {
1799        // Need to add in the coordinates of the intervening blocks.
1800        RenderInline* flow = *it;
1801        RenderBlock* block = flow->containingBlock();
1802        for ( ; block && block != this; block = block->containingBlock())
1803            accumulatedPaintOffset.moveBy(block->location());
1804        ASSERT(block);
1805        flow->paintOutline(info, accumulatedPaintOffset);
1806    }
1807}
1808
1809bool RenderBlock::shouldPaintSelectionGaps() const
1810{
1811    return selectionState() != SelectionNone && style().visibility() == VISIBLE && isSelectionRoot();
1812}
1813
1814bool RenderBlock::isSelectionRoot() const
1815{
1816    if (isPseudoElement())
1817        return false;
1818    ASSERT(element() || isAnonymous());
1819
1820    // FIXME: Eventually tables should have to learn how to fill gaps between cells, at least in simple non-spanning cases.
1821    if (isTable())
1822        return false;
1823
1824    if (isBody() || isRoot() || hasOverflowClip()
1825        || isPositioned() || isFloating()
1826        || isTableCell() || isInlineBlockOrInlineTable()
1827        || hasTransform() || hasReflection() || hasMask() || isWritingModeRoot()
1828        || isRenderFlowThread() || style().columnSpan() == ColumnSpanAll)
1829        return true;
1830
1831    if (view().selectionStart()) {
1832        Node* startElement = view().selectionStart()->node();
1833        if (startElement && startElement->rootEditableElement() == element())
1834            return true;
1835    }
1836
1837    return false;
1838}
1839
1840GapRects RenderBlock::selectionGapRectsForRepaint(const RenderLayerModelObject* repaintContainer)
1841{
1842    ASSERT(!needsLayout());
1843
1844    if (!shouldPaintSelectionGaps())
1845        return GapRects();
1846
1847    TransformState transformState(TransformState::ApplyTransformDirection, FloatPoint());
1848    mapLocalToContainer(repaintContainer, transformState, ApplyContainerFlip | UseTransforms);
1849    LayoutPoint offsetFromRepaintContainer = roundedLayoutPoint(transformState.mappedPoint()) - scrolledContentOffset();
1850
1851    LogicalSelectionOffsetCaches cache(*this);
1852    LayoutUnit lastTop = 0;
1853    LayoutUnit lastLeft = logicalLeftSelectionOffset(*this, lastTop, cache);
1854    LayoutUnit lastRight = logicalRightSelectionOffset(*this, lastTop, cache);
1855
1856    return selectionGaps(*this, offsetFromRepaintContainer, IntSize(), lastTop, lastLeft, lastRight, cache);
1857}
1858
1859void RenderBlock::paintSelection(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
1860{
1861#if ENABLE(TEXT_SELECTION)
1862    if (shouldPaintSelectionGaps() && paintInfo.phase == PaintPhaseForeground) {
1863        LogicalSelectionOffsetCaches cache(*this);
1864        LayoutUnit lastTop = 0;
1865        LayoutUnit lastLeft = logicalLeftSelectionOffset(*this, lastTop, cache);
1866        LayoutUnit lastRight = logicalRightSelectionOffset(*this, lastTop, cache);
1867        GraphicsContextStateSaver stateSaver(*paintInfo.context);
1868
1869        LayoutRect gapRectsBounds = selectionGaps(*this, paintOffset, LayoutSize(), lastTop, lastLeft, lastRight, cache, &paintInfo);
1870        if (!gapRectsBounds.isEmpty()) {
1871            if (RenderLayer* layer = enclosingLayer()) {
1872                gapRectsBounds.moveBy(-paintOffset);
1873                if (!hasLayer()) {
1874                    LayoutRect localBounds(gapRectsBounds);
1875                    flipForWritingMode(localBounds);
1876                    gapRectsBounds = localToContainerQuad(FloatRect(localBounds), &layer->renderer()).enclosingBoundingBox();
1877                    if (layer->renderer().isBox())
1878                        gapRectsBounds.move(layer->renderBox()->scrolledContentOffset());
1879                }
1880                layer->addBlockSelectionGapsBounds(gapRectsBounds);
1881            }
1882        }
1883    }
1884#else
1885    UNUSED_PARAM(paintInfo);
1886    UNUSED_PARAM(paintOffset);
1887#endif
1888}
1889
1890static void clipOutPositionedObjects(const PaintInfo* paintInfo, const LayoutPoint& offset, TrackedRendererListHashSet* positionedObjects)
1891{
1892    if (!positionedObjects)
1893        return;
1894
1895    TrackedRendererListHashSet::const_iterator end = positionedObjects->end();
1896    for (TrackedRendererListHashSet::const_iterator it = positionedObjects->begin(); it != end; ++it) {
1897        RenderBox* r = *it;
1898        paintInfo->context->clipOut(IntRect(offset.x() + r->x(), offset.y() + r->y(), r->width(), r->height()));
1899    }
1900}
1901
1902LayoutUnit blockDirectionOffset(RenderBlock& rootBlock, const LayoutSize& offsetFromRootBlock)
1903{
1904    return rootBlock.isHorizontalWritingMode() ? offsetFromRootBlock.height() : offsetFromRootBlock.width();
1905}
1906
1907LayoutUnit inlineDirectionOffset(RenderBlock& rootBlock, const LayoutSize& offsetFromRootBlock)
1908{
1909    return rootBlock.isHorizontalWritingMode() ? offsetFromRootBlock.width() : offsetFromRootBlock.height();
1910}
1911
1912LayoutRect RenderBlock::logicalRectToPhysicalRect(const LayoutPoint& rootBlockPhysicalPosition, const LayoutRect& logicalRect)
1913{
1914    LayoutRect result;
1915    if (isHorizontalWritingMode())
1916        result = logicalRect;
1917    else
1918        result = LayoutRect(logicalRect.y(), logicalRect.x(), logicalRect.height(), logicalRect.width());
1919    flipForWritingMode(result);
1920    result.moveBy(rootBlockPhysicalPosition);
1921    return result;
1922}
1923
1924GapRects RenderBlock::selectionGaps(RenderBlock& rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
1925    LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const LogicalSelectionOffsetCaches& cache, const PaintInfo* paintInfo)
1926{
1927    // IMPORTANT: Callers of this method that intend for painting to happen need to do a save/restore.
1928    // Clip out floating and positioned objects when painting selection gaps.
1929    if (paintInfo) {
1930        // Note that we don't clip out overflow for positioned objects.  We just stick to the border box.
1931        LayoutRect flippedBlockRect(offsetFromRootBlock.width(), offsetFromRootBlock.height(), width(), height());
1932        rootBlock.flipForWritingMode(flippedBlockRect);
1933        flippedBlockRect.moveBy(rootBlockPhysicalPosition);
1934        clipOutPositionedObjects(paintInfo, flippedBlockRect.location(), positionedObjects());
1935        if (isBody() || isRoot()) // The <body> must make sure to examine its containingBlock's positioned objects.
1936            for (RenderBlock* cb = containingBlock(); cb && !cb->isRenderView(); cb = cb->containingBlock())
1937                clipOutPositionedObjects(paintInfo, LayoutPoint(cb->x(), cb->y()), cb->positionedObjects()); // FIXME: Not right for flipped writing modes.
1938        clipOutFloatingObjects(rootBlock, paintInfo, rootBlockPhysicalPosition, offsetFromRootBlock);
1939    }
1940
1941    // 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
1942    // fixed).
1943    GapRects result;
1944    if (!isRenderBlockFlow()) // FIXME: Make multi-column selection gap filling work someday.
1945        return result;
1946
1947    if (hasTransform() || style().columnSpan() == ColumnSpanAll || isInFlowRenderFlowThread()) {
1948        // FIXME: We should learn how to gap fill multiple columns and transforms eventually.
1949        lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalHeight();
1950        lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, logicalHeight(), cache);
1951        lastLogicalRight = logicalRightSelectionOffset(rootBlock, logicalHeight(), cache);
1952        return result;
1953    }
1954
1955    RenderNamedFlowFragment* namedFlowFragment = currentRenderNamedFlowFragment();
1956    if (paintInfo && namedFlowFragment && paintInfo->paintContainer->isRenderFlowThread()) {
1957        // Make sure the current object is actually flowed into the region being painted.
1958        if (!toRenderFlowThread(paintInfo->paintContainer)->objectShouldFragmentInFlowRegion(this, namedFlowFragment))
1959            return result;
1960    }
1961
1962    if (childrenInline())
1963        result = inlineSelectionGaps(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, cache, paintInfo);
1964    else
1965        result = blockSelectionGaps(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, cache, paintInfo);
1966
1967    // Go ahead and fill the vertical gap all the way to the bottom of our block if the selection extends past our block.
1968    if (&rootBlock == this && (selectionState() != SelectionBoth && selectionState() != SelectionEnd)) {
1969        result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock,
1970            lastLogicalTop, lastLogicalLeft, lastLogicalRight, logicalHeight(), cache, paintInfo));
1971    }
1972
1973    return result;
1974}
1975
1976GapRects RenderBlock::inlineSelectionGaps(RenderBlock&, const LayoutPoint&, const LayoutSize&, LayoutUnit&, LayoutUnit&, LayoutUnit&, const LogicalSelectionOffsetCaches&, const PaintInfo*)
1977{
1978    ASSERT_NOT_REACHED();
1979    return GapRects();
1980}
1981
1982GapRects RenderBlock::blockSelectionGaps(RenderBlock& rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
1983    LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const LogicalSelectionOffsetCaches& cache, const PaintInfo* paintInfo)
1984{
1985    GapRects result;
1986
1987    // Go ahead and jump right to the first block child that contains some selected objects.
1988    RenderBox* curr;
1989    for (curr = firstChildBox(); curr && curr->selectionState() == SelectionNone; curr = curr->nextSiblingBox()) { }
1990
1991    if (!curr)
1992        return result;
1993
1994    LogicalSelectionOffsetCaches childCache(*this, cache);
1995
1996    for (bool sawSelectionEnd = false; curr && !sawSelectionEnd; curr = curr->nextSiblingBox()) {
1997        SelectionState childState = curr->selectionState();
1998        if (childState == SelectionBoth || childState == SelectionEnd)
1999            sawSelectionEnd = true;
2000
2001        if (curr->isFloatingOrOutOfFlowPositioned())
2002            continue; // We must be a normal flow object in order to even be considered.
2003
2004        if (curr->isInFlowPositioned() && curr->hasLayer()) {
2005            // If the relposition offset is anything other than 0, then treat this just like an absolute positioned element.
2006            // Just disregard it completely.
2007            LayoutSize relOffset = curr->layer()->offsetForInFlowPosition();
2008            if (relOffset.width() || relOffset.height())
2009                continue;
2010        }
2011
2012        bool paintsOwnSelection = curr->shouldPaintSelectionGaps() || curr->isTable(); // FIXME: Eventually we won't special-case table like this.
2013        bool fillBlockGaps = paintsOwnSelection || (curr->canBeSelectionLeaf() && childState != SelectionNone);
2014        if (fillBlockGaps) {
2015            // We need to fill the vertical gap above this object.
2016            if (childState == SelectionEnd || childState == SelectionInside) {
2017                // Fill the gap above the object.
2018                result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock,
2019                    lastLogicalTop, lastLogicalLeft, lastLogicalRight, curr->logicalTop(), cache, paintInfo));
2020            }
2021
2022            // 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*
2023            // our object.  We know this if the selection did not end inside our object.
2024            if (paintsOwnSelection && (childState == SelectionStart || sawSelectionEnd))
2025                childState = SelectionNone;
2026
2027            // Fill side gaps on this object based off its state.
2028            bool leftGap, rightGap;
2029            getSelectionGapInfo(childState, leftGap, rightGap);
2030
2031            if (leftGap)
2032                result.uniteLeft(logicalLeftSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, this, curr->logicalLeft(), curr->logicalTop(), curr->logicalHeight(), cache, paintInfo));
2033            if (rightGap)
2034                result.uniteRight(logicalRightSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, this, curr->logicalRight(), curr->logicalTop(), curr->logicalHeight(), cache, paintInfo));
2035
2036            // Update lastLogicalTop to be just underneath the object.  lastLogicalLeft and lastLogicalRight extend as far as
2037            // they can without bumping into floating or positioned objects.  Ideally they will go right up
2038            // to the border of the root selection block.
2039            lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + curr->logicalBottom();
2040            lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, curr->logicalBottom(), cache);
2041            lastLogicalRight = logicalRightSelectionOffset(rootBlock, curr->logicalBottom(), cache);
2042        } else if (childState != SelectionNone) {
2043            // We must be a block that has some selected object inside it.  Go ahead and recur.
2044            result.unite(toRenderBlock(curr)->selectionGaps(rootBlock, rootBlockPhysicalPosition, LayoutSize(offsetFromRootBlock.width() + curr->x(), offsetFromRootBlock.height() + curr->y()),
2045                lastLogicalTop, lastLogicalLeft, lastLogicalRight, childCache, paintInfo));
2046        }
2047    }
2048    return result;
2049}
2050
2051LayoutRect RenderBlock::blockSelectionGap(RenderBlock& rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
2052    LayoutUnit lastLogicalTop, LayoutUnit lastLogicalLeft, LayoutUnit lastLogicalRight, LayoutUnit logicalBottom, const LogicalSelectionOffsetCaches& cache, const PaintInfo* paintInfo)
2053{
2054    LayoutUnit logicalTop = lastLogicalTop;
2055    LayoutUnit logicalHeight = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalBottom - logicalTop;
2056    if (logicalHeight <= 0)
2057        return LayoutRect();
2058
2059    // Get the selection offsets for the bottom of the gap
2060    LayoutUnit logicalLeft = std::max(lastLogicalLeft, logicalLeftSelectionOffset(rootBlock, logicalBottom, cache));
2061    LayoutUnit logicalRight = std::min(lastLogicalRight, logicalRightSelectionOffset(rootBlock, logicalBottom, cache));
2062    LayoutUnit logicalWidth = logicalRight - logicalLeft;
2063    if (logicalWidth <= 0)
2064        return LayoutRect();
2065
2066    LayoutRect gapRect = rootBlock.logicalRectToPhysicalRect(rootBlockPhysicalPosition, LayoutRect(logicalLeft, logicalTop, logicalWidth, logicalHeight));
2067    if (paintInfo)
2068        paintInfo->context->fillRect(pixelSnappedForPainting(gapRect, document().deviceScaleFactor()), selectionBackgroundColor(), style().colorSpace());
2069    return gapRect;
2070}
2071
2072LayoutRect RenderBlock::logicalLeftSelectionGap(RenderBlock& rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
2073    RenderObject* selObj, LayoutUnit logicalLeft, LayoutUnit logicalTop, LayoutUnit logicalHeight, const LogicalSelectionOffsetCaches& cache, const PaintInfo* paintInfo)
2074{
2075    LayoutUnit rootBlockLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalTop;
2076    LayoutUnit rootBlockLogicalLeft = std::max(logicalLeftSelectionOffset(rootBlock, logicalTop, cache), logicalLeftSelectionOffset(rootBlock, logicalTop + logicalHeight, cache));
2077    LayoutUnit rootBlockLogicalRight = std::min(inlineDirectionOffset(rootBlock, offsetFromRootBlock) + logicalLeft,
2078        std::min(logicalRightSelectionOffset(rootBlock, logicalTop, cache), logicalRightSelectionOffset(rootBlock, logicalTop + logicalHeight, cache)));
2079    LayoutUnit rootBlockLogicalWidth = rootBlockLogicalRight - rootBlockLogicalLeft;
2080    if (rootBlockLogicalWidth <= 0)
2081        return LayoutRect();
2082
2083    LayoutRect gapRect = rootBlock.logicalRectToPhysicalRect(rootBlockPhysicalPosition, LayoutRect(rootBlockLogicalLeft, rootBlockLogicalTop, rootBlockLogicalWidth, logicalHeight));
2084    if (paintInfo)
2085        paintInfo->context->fillRect(pixelSnappedForPainting(gapRect, document().deviceScaleFactor()), selObj->selectionBackgroundColor(), selObj->style().colorSpace());
2086    return gapRect;
2087}
2088
2089LayoutRect RenderBlock::logicalRightSelectionGap(RenderBlock& rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
2090    RenderObject* selObj, LayoutUnit logicalRight, LayoutUnit logicalTop, LayoutUnit logicalHeight, const LogicalSelectionOffsetCaches& cache, const PaintInfo* paintInfo)
2091{
2092    LayoutUnit rootBlockLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalTop;
2093    LayoutUnit rootBlockLogicalLeft = std::max(inlineDirectionOffset(rootBlock, offsetFromRootBlock) + logicalRight,
2094        std::max(logicalLeftSelectionOffset(rootBlock, logicalTop, cache), logicalLeftSelectionOffset(rootBlock, logicalTop + logicalHeight, cache)));
2095    LayoutUnit rootBlockLogicalRight = std::min(logicalRightSelectionOffset(rootBlock, logicalTop, cache), logicalRightSelectionOffset(rootBlock, logicalTop + logicalHeight, cache));
2096    LayoutUnit rootBlockLogicalWidth = rootBlockLogicalRight - rootBlockLogicalLeft;
2097    if (rootBlockLogicalWidth <= 0)
2098        return LayoutRect();
2099
2100    LayoutRect gapRect = rootBlock.logicalRectToPhysicalRect(rootBlockPhysicalPosition, LayoutRect(rootBlockLogicalLeft, rootBlockLogicalTop, rootBlockLogicalWidth, logicalHeight));
2101    if (paintInfo)
2102        paintInfo->context->fillRect(pixelSnappedForPainting(gapRect, document().deviceScaleFactor()), selObj->selectionBackgroundColor(), selObj->style().colorSpace());
2103    return gapRect;
2104}
2105
2106void RenderBlock::getSelectionGapInfo(SelectionState state, bool& leftGap, bool& rightGap)
2107{
2108    bool ltr = style().isLeftToRightDirection();
2109    leftGap = (state == RenderObject::SelectionInside) ||
2110              (state == RenderObject::SelectionEnd && ltr) ||
2111              (state == RenderObject::SelectionStart && !ltr);
2112    rightGap = (state == RenderObject::SelectionInside) ||
2113               (state == RenderObject::SelectionStart && ltr) ||
2114               (state == RenderObject::SelectionEnd && !ltr);
2115}
2116
2117LayoutUnit RenderBlock::logicalLeftSelectionOffset(RenderBlock& rootBlock, LayoutUnit position, const LogicalSelectionOffsetCaches& cache)
2118{
2119    LayoutUnit logicalLeft = logicalLeftOffsetForLine(position, false);
2120    if (logicalLeft == logicalLeftOffsetForContent()) {
2121        if (&rootBlock != this) // The border can potentially be further extended by our containingBlock().
2122            return cache.containingBlockInfo(*this).logicalLeftSelectionOffset(rootBlock, position + logicalTop());
2123        return logicalLeft;
2124    }
2125
2126    RenderBlock* cb = this;
2127    const LogicalSelectionOffsetCaches* currentCache = &cache;
2128    while (cb != &rootBlock) {
2129        logicalLeft += cb->logicalLeft();
2130
2131        ASSERT(currentCache);
2132        auto info = currentCache->containingBlockInfo(*cb);
2133        cb = info.block();
2134        currentCache = info.cache();
2135    }
2136    return logicalLeft;
2137}
2138
2139LayoutUnit RenderBlock::logicalRightSelectionOffset(RenderBlock& rootBlock, LayoutUnit position, const LogicalSelectionOffsetCaches& cache)
2140{
2141    LayoutUnit logicalRight = logicalRightOffsetForLine(position, false);
2142    if (logicalRight == logicalRightOffsetForContent()) {
2143        if (&rootBlock != this) // The border can potentially be further extended by our containingBlock().
2144            return cache.containingBlockInfo(*this).logicalRightSelectionOffset(rootBlock, position + logicalTop());
2145        return logicalRight;
2146    }
2147
2148    RenderBlock* cb = this;
2149    const LogicalSelectionOffsetCaches* currentCache = &cache;
2150    while (cb != &rootBlock) {
2151        logicalRight += cb->logicalLeft();
2152
2153        ASSERT(currentCache);
2154        auto info = currentCache->containingBlockInfo(*cb);
2155        cb = info.block();
2156        currentCache = info.cache();
2157    }
2158    return logicalRight;
2159}
2160
2161RenderBlock* RenderBlock::blockBeforeWithinSelectionRoot(LayoutSize& offset) const
2162{
2163    if (isSelectionRoot())
2164        return 0;
2165
2166    const RenderElement* object = this;
2167    RenderObject* sibling;
2168    do {
2169        sibling = object->previousSibling();
2170        while (sibling && (!sibling->isRenderBlock() || toRenderBlock(sibling)->isSelectionRoot()))
2171            sibling = sibling->previousSibling();
2172
2173        offset -= LayoutSize(toRenderBlock(object)->logicalLeft(), toRenderBlock(object)->logicalTop());
2174        object = object->parent();
2175    } while (!sibling && object && object->isRenderBlock() && !toRenderBlock(object)->isSelectionRoot());
2176
2177    if (!sibling)
2178        return 0;
2179
2180    RenderBlock* beforeBlock = toRenderBlock(sibling);
2181
2182    offset += LayoutSize(beforeBlock->logicalLeft(), beforeBlock->logicalTop());
2183
2184    RenderObject* child = beforeBlock->lastChild();
2185    while (child && child->isRenderBlock()) {
2186        beforeBlock = toRenderBlock(child);
2187        offset += LayoutSize(beforeBlock->logicalLeft(), beforeBlock->logicalTop());
2188        child = beforeBlock->lastChild();
2189    }
2190    return beforeBlock;
2191}
2192
2193void RenderBlock::insertIntoTrackedRendererMaps(RenderBox& descendant, TrackedDescendantsMap*& descendantsMap, TrackedContainerMap*& containerMap)
2194{
2195    if (!descendantsMap) {
2196        descendantsMap = new TrackedDescendantsMap;
2197        containerMap = new TrackedContainerMap;
2198    }
2199
2200    TrackedRendererListHashSet* descendantSet = descendantsMap->get(this);
2201    if (!descendantSet) {
2202        descendantSet = new TrackedRendererListHashSet;
2203        descendantsMap->set(this, std::unique_ptr<TrackedRendererListHashSet>(descendantSet));
2204    }
2205    bool added = descendantSet->add(&descendant).isNewEntry;
2206    if (!added) {
2207        ASSERT(containerMap->get(&descendant));
2208        ASSERT(containerMap->get(&descendant)->contains(this));
2209        return;
2210    }
2211
2212    HashSet<RenderBlock*>* containerSet = containerMap->get(&descendant);
2213    if (!containerSet) {
2214        containerSet = new HashSet<RenderBlock*>;
2215        containerMap->set(&descendant, std::unique_ptr<HashSet<RenderBlock*>>(containerSet));
2216    }
2217    ASSERT(!containerSet->contains(this));
2218    containerSet->add(this);
2219}
2220
2221void RenderBlock::removeFromTrackedRendererMaps(RenderBox& descendant, TrackedDescendantsMap*& descendantsMap, TrackedContainerMap*& containerMap)
2222{
2223    if (!descendantsMap)
2224        return;
2225
2226    std::unique_ptr<HashSet<RenderBlock*>> containerSet = containerMap->take(&descendant);
2227    if (!containerSet)
2228        return;
2229
2230    for (auto it = containerSet->begin(), end = containerSet->end(); it != end; ++it) {
2231        RenderBlock* container = *it;
2232
2233        // FIXME: Disabling this assert temporarily until we fix the layout
2234        // bugs associated with positioned objects not properly cleared from
2235        // their ancestor chain before being moved. See webkit bug 93766.
2236        // ASSERT(descendant->isDescendantOf(container));
2237
2238        TrackedDescendantsMap::iterator descendantsMapIterator = descendantsMap->find(container);
2239        ASSERT(descendantsMapIterator != descendantsMap->end());
2240        if (descendantsMapIterator == descendantsMap->end())
2241            continue;
2242        TrackedRendererListHashSet* descendantSet = descendantsMapIterator->value.get();
2243        ASSERT(descendantSet->contains(&descendant));
2244        descendantSet->remove(&descendant);
2245        if (descendantSet->isEmpty())
2246            descendantsMap->remove(descendantsMapIterator);
2247    }
2248}
2249
2250TrackedRendererListHashSet* RenderBlock::positionedObjects() const
2251{
2252    if (gPositionedDescendantsMap)
2253        return gPositionedDescendantsMap->get(this);
2254    return 0;
2255}
2256
2257void RenderBlock::insertPositionedObject(RenderBox& o)
2258{
2259    ASSERT(!isAnonymousBlock());
2260
2261    if (o.isRenderFlowThread())
2262        return;
2263
2264    insertIntoTrackedRendererMaps(o, gPositionedDescendantsMap, gPositionedContainerMap);
2265}
2266
2267void RenderBlock::removePositionedObject(RenderBox& o)
2268{
2269    removeFromTrackedRendererMaps(o, gPositionedDescendantsMap, gPositionedContainerMap);
2270}
2271
2272void RenderBlock::removePositionedObjects(RenderBlock* o, ContainingBlockState containingBlockState)
2273{
2274    TrackedRendererListHashSet* positionedDescendants = positionedObjects();
2275    if (!positionedDescendants)
2276        return;
2277
2278    Vector<RenderBox*, 16> deadObjects;
2279
2280    for (auto it = positionedDescendants->begin(), end = positionedDescendants->end(); it != end; ++it) {
2281        RenderBox* r = *it;
2282        if (!o || r->isDescendantOf(o)) {
2283            if (containingBlockState == NewContainingBlock)
2284                r->setChildNeedsLayout(MarkOnlyThis);
2285
2286            // It is parent blocks job to add positioned child to positioned objects list of its containing block
2287            // Parent layout needs to be invalidated to ensure this happens.
2288            RenderElement* p = r->parent();
2289            while (p && !p->isRenderBlock())
2290                p = p->parent();
2291            if (p)
2292                p->setChildNeedsLayout();
2293
2294            deadObjects.append(r);
2295        }
2296    }
2297
2298    for (unsigned i = 0; i < deadObjects.size(); i++)
2299        removePositionedObject(*deadObjects.at(i));
2300}
2301
2302void RenderBlock::addPercentHeightDescendant(RenderBox& descendant)
2303{
2304    insertIntoTrackedRendererMaps(descendant, gPercentHeightDescendantsMap, gPercentHeightContainerMap);
2305}
2306
2307void RenderBlock::removePercentHeightDescendant(RenderBox& descendant)
2308{
2309    removeFromTrackedRendererMaps(descendant, gPercentHeightDescendantsMap, gPercentHeightContainerMap);
2310}
2311
2312TrackedRendererListHashSet* RenderBlock::percentHeightDescendants() const
2313{
2314    return gPercentHeightDescendantsMap ? gPercentHeightDescendantsMap->get(this) : 0;
2315}
2316
2317bool RenderBlock::hasPercentHeightContainerMap()
2318{
2319    return gPercentHeightContainerMap;
2320}
2321
2322bool RenderBlock::hasPercentHeightDescendant(RenderBox& descendant)
2323{
2324    // We don't null check gPercentHeightContainerMap since the caller
2325    // already ensures this and we need to call this function on every
2326    // descendant in clearPercentHeightDescendantsFrom().
2327    ASSERT(gPercentHeightContainerMap);
2328    return gPercentHeightContainerMap->contains(&descendant);
2329}
2330
2331void RenderBlock::removePercentHeightDescendantIfNeeded(RenderBox& descendant)
2332{
2333    // We query the map directly, rather than looking at style's
2334    // logicalHeight()/logicalMinHeight()/logicalMaxHeight() since those
2335    // can change with writing mode/directional changes.
2336    if (!hasPercentHeightContainerMap())
2337        return;
2338
2339    if (!hasPercentHeightDescendant(descendant))
2340        return;
2341
2342    removePercentHeightDescendant(descendant);
2343}
2344
2345void RenderBlock::clearPercentHeightDescendantsFrom(RenderBox& parent)
2346{
2347    ASSERT(gPercentHeightContainerMap);
2348    for (RenderObject* curr = parent.firstChild(); curr; curr = curr->nextInPreOrder(&parent)) {
2349        if (!curr->isBox())
2350            continue;
2351
2352        RenderBox& box = toRenderBox(*curr);
2353        if (!hasPercentHeightDescendant(box))
2354            continue;
2355
2356        removePercentHeightDescendant(box);
2357    }
2358}
2359
2360LayoutUnit RenderBlock::textIndentOffset() const
2361{
2362    LayoutUnit cw = 0;
2363    if (style().textIndent().isPercent())
2364        cw = containingBlock()->availableLogicalWidth();
2365    return minimumValueForLength(style().textIndent(), cw);
2366}
2367
2368LayoutUnit RenderBlock::logicalLeftOffsetForContent(RenderRegion* region) const
2369{
2370    LayoutUnit logicalLeftOffset = style().isHorizontalWritingMode() ? borderLeft() + paddingLeft() : borderTop() + paddingTop();
2371    if (!region)
2372        return logicalLeftOffset;
2373    LayoutRect boxRect = borderBoxRectInRegion(region);
2374    return logicalLeftOffset + (isHorizontalWritingMode() ? boxRect.x() : boxRect.y());
2375}
2376
2377LayoutUnit RenderBlock::logicalRightOffsetForContent(RenderRegion* region) const
2378{
2379    LayoutUnit logicalRightOffset = style().isHorizontalWritingMode() ? borderLeft() + paddingLeft() : borderTop() + paddingTop();
2380    logicalRightOffset += availableLogicalWidth();
2381    if (!region)
2382        return logicalRightOffset;
2383    LayoutRect boxRect = borderBoxRectInRegion(region);
2384    return logicalRightOffset - (logicalWidth() - (isHorizontalWritingMode() ? boxRect.maxX() : boxRect.maxY()));
2385}
2386
2387LayoutUnit RenderBlock::adjustLogicalLeftOffsetForLine(LayoutUnit offsetFromFloats, bool applyTextIndent) const
2388{
2389    LayoutUnit left = offsetFromFloats;
2390
2391    if (applyTextIndent && style().isLeftToRightDirection())
2392        left += textIndentOffset();
2393
2394    if (style().lineAlign() == LineAlignNone)
2395        return left;
2396
2397    // Push in our left offset so that it is aligned with the character grid.
2398    LayoutState* layoutState = view().layoutState();
2399    if (!layoutState)
2400        return left;
2401
2402    RenderBlock* lineGrid = layoutState->lineGrid();
2403    if (!lineGrid || lineGrid->style().writingMode() != style().writingMode())
2404        return left;
2405
2406    // FIXME: Should letter-spacing apply? This is complicated since it doesn't apply at the edge?
2407    float maxCharWidth = lineGrid->style().font().primaryFont()->maxCharWidth();
2408    if (!maxCharWidth)
2409        return left;
2410
2411    LayoutUnit lineGridOffset = lineGrid->isHorizontalWritingMode() ? layoutState->lineGridOffset().width(): layoutState->lineGridOffset().height();
2412    LayoutUnit layoutOffset = lineGrid->isHorizontalWritingMode() ? layoutState->layoutOffset().width() : layoutState->layoutOffset().height();
2413
2414    // Push in to the nearest character width (truncated so that we pixel snap left).
2415    // FIXME: Should be patched when subpixel layout lands, since this calculation doesn't have to pixel snap
2416    // any more (https://bugs.webkit.org/show_bug.cgi?id=79946).
2417    // FIXME: This is wrong for RTL (https://bugs.webkit.org/show_bug.cgi?id=79945).
2418    // FIXME: This doesn't work with columns or regions (https://bugs.webkit.org/show_bug.cgi?id=79942).
2419    // FIXME: This doesn't work when the inline position of the object isn't set ahead of time.
2420    // FIXME: Dynamic changes to the font or to the inline position need to result in a deep relayout.
2421    // (https://bugs.webkit.org/show_bug.cgi?id=79944)
2422    float remainder = fmodf(maxCharWidth - fmodf(left + layoutOffset - lineGridOffset, maxCharWidth), maxCharWidth);
2423    left += remainder;
2424    return left;
2425}
2426
2427LayoutUnit RenderBlock::adjustLogicalRightOffsetForLine(LayoutUnit offsetFromFloats, bool applyTextIndent) const
2428{
2429    LayoutUnit right = offsetFromFloats;
2430
2431    if (applyTextIndent && !style().isLeftToRightDirection())
2432        right -= textIndentOffset();
2433
2434    if (style().lineAlign() == LineAlignNone)
2435        return right;
2436
2437    // Push in our right offset so that it is aligned with the character grid.
2438    LayoutState* layoutState = view().layoutState();
2439    if (!layoutState)
2440        return right;
2441
2442    RenderBlock* lineGrid = layoutState->lineGrid();
2443    if (!lineGrid || lineGrid->style().writingMode() != style().writingMode())
2444        return right;
2445
2446    // FIXME: Should letter-spacing apply? This is complicated since it doesn't apply at the edge?
2447    float maxCharWidth = lineGrid->style().font().primaryFont()->maxCharWidth();
2448    if (!maxCharWidth)
2449        return right;
2450
2451    LayoutUnit lineGridOffset = lineGrid->isHorizontalWritingMode() ? layoutState->lineGridOffset().width(): layoutState->lineGridOffset().height();
2452    LayoutUnit layoutOffset = lineGrid->isHorizontalWritingMode() ? layoutState->layoutOffset().width() : layoutState->layoutOffset().height();
2453
2454    // Push in to the nearest character width (truncated so that we pixel snap right).
2455    // FIXME: Should be patched when subpixel layout lands, since this calculation doesn't have to pixel snap
2456    // any more (https://bugs.webkit.org/show_bug.cgi?id=79946).
2457    // FIXME: This is wrong for RTL (https://bugs.webkit.org/show_bug.cgi?id=79945).
2458    // FIXME: This doesn't work with columns or regions (https://bugs.webkit.org/show_bug.cgi?id=79942).
2459    // FIXME: This doesn't work when the inline position of the object isn't set ahead of time.
2460    // FIXME: Dynamic changes to the font or to the inline position need to result in a deep relayout.
2461    // (https://bugs.webkit.org/show_bug.cgi?id=79944)
2462    float remainder = fmodf(fmodf(right + layoutOffset - lineGridOffset, maxCharWidth), maxCharWidth);
2463    right -= ceilf(remainder);
2464    return right;
2465}
2466
2467bool RenderBlock::avoidsFloats() const
2468{
2469    // Floats can't intrude into our box if we have a non-auto column count or width.
2470    return RenderBox::avoidsFloats()
2471        || !style().hasAutoColumnCount()
2472        || !style().hasAutoColumnWidth()
2473        || style().hasFlowFrom();
2474}
2475
2476bool RenderBlock::isPointInOverflowControl(HitTestResult& result, const LayoutPoint& locationInContainer, const LayoutPoint& accumulatedOffset)
2477{
2478    if (!scrollsOverflow())
2479        return false;
2480
2481    return layer()->hitTestOverflowControls(result, roundedIntPoint(locationInContainer - toLayoutSize(accumulatedOffset)));
2482}
2483
2484Node* RenderBlock::nodeForHitTest() const
2485{
2486    // If we are in the margins of block elements that are part of a
2487    // continuation we're actually still inside the enclosing element
2488    // that was split. Use the appropriate inner node.
2489    if (isRenderView())
2490        return &document();
2491    return isAnonymousBlockContinuation() ? continuation()->element() : element();
2492}
2493
2494bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
2495{
2496    LayoutPoint adjustedLocation(accumulatedOffset + location());
2497    LayoutSize localOffset = toLayoutSize(adjustedLocation);
2498
2499    RenderFlowThread* flowThread = flowThreadContainingBlock();
2500    RenderNamedFlowFragment* namedFlowFragment = flowThread ? toRenderNamedFlowFragment(flowThread->currentRegion()) : nullptr;
2501    // If we are now searching inside a region, make sure this element
2502    // is being fragmented into this region.
2503    if (namedFlowFragment && !flowThread->objectShouldFragmentInFlowRegion(this, namedFlowFragment))
2504        return false;
2505
2506    if (!isRenderView()) {
2507        // Check if we need to do anything at all.
2508        LayoutRect overflowBox = visualOverflowRect();
2509        flipForWritingMode(overflowBox);
2510        overflowBox.moveBy(adjustedLocation);
2511        if (!locationInContainer.intersects(overflowBox))
2512            return false;
2513    }
2514
2515    if ((hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground) && isPointInOverflowControl(result, locationInContainer.point(), adjustedLocation)) {
2516        updateHitTestResult(result, locationInContainer.point() - localOffset);
2517        // FIXME: isPointInOverflowControl() doesn't handle rect-based tests yet.
2518        if (!result.addNodeToRectBasedTestResult(nodeForHitTest(), request, locationInContainer))
2519           return true;
2520    }
2521
2522    if (style().clipPath()) {
2523        switch (style().clipPath()->type()) {
2524        case ClipPathOperation::Shape: {
2525            ShapeClipPathOperation* clipPath = toShapeClipPathOperation(style().clipPath());
2526
2527            LayoutRect referenceBoxRect;
2528            switch (clipPath->referenceBox()) {
2529            case CSSBoxType::MarginBox:
2530                referenceBoxRect = marginBoxRect();
2531                break;
2532            case CSSBoxType::BorderBox:
2533                referenceBoxRect = borderBoxRect();
2534                break;
2535            case CSSBoxType::PaddingBox:
2536                referenceBoxRect = paddingBoxRect();
2537                break;
2538            case CSSBoxType::ContentBox:
2539                referenceBoxRect = contentBoxRect();
2540                break;
2541            case CSSBoxType::BoxMissing:
2542            case CSSBoxType::Fill:
2543            case CSSBoxType::Stroke:
2544            case CSSBoxType::ViewBox:
2545                referenceBoxRect = borderBoxRect();
2546            }
2547            if (!clipPath->pathForReferenceRect(referenceBoxRect).contains(locationInContainer.point() - localOffset, clipPath->windRule()))
2548                return false;
2549            break;
2550        }
2551        // FIXME: handle Reference/Box
2552        case ClipPathOperation::Reference:
2553        case ClipPathOperation::Box:
2554            break;
2555        }
2556    }
2557
2558    // If we have clipping, then we can't have any spillout.
2559    bool useOverflowClip = hasOverflowClip() && !hasSelfPaintingLayer();
2560    bool useClip = (hasControlClip() || useOverflowClip);
2561    bool checkChildren = !useClip || (hasControlClip() ? locationInContainer.intersects(controlClipRect(adjustedLocation)) : locationInContainer.intersects(overflowClipRect(adjustedLocation, namedFlowFragment, IncludeOverlayScrollbarSize)));
2562    if (checkChildren) {
2563        // Hit test descendants first.
2564        LayoutSize scrolledOffset(localOffset - scrolledContentOffset());
2565
2566        if (hitTestContents(request, result, locationInContainer, toLayoutPoint(scrolledOffset), hitTestAction)) {
2567            updateHitTestResult(result, flipForWritingMode(locationInContainer.point() - localOffset));
2568            return true;
2569        }
2570        if (hitTestAction == HitTestFloat && hitTestFloats(request, result, locationInContainer, toLayoutPoint(scrolledOffset)))
2571            return true;
2572    }
2573
2574    // Check if the point is outside radii.
2575    if (!isRenderView() && style().hasBorderRadius()) {
2576        LayoutRect borderRect = borderBoxRect();
2577        borderRect.moveBy(adjustedLocation);
2578        RoundedRect border = style().getRoundedBorderFor(borderRect);
2579        if (!locationInContainer.intersects(border))
2580            return false;
2581    }
2582
2583    // Now hit test our background
2584    if (hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground) {
2585        LayoutRect boundsRect(adjustedLocation, size());
2586        if (visibleToHitTesting() && locationInContainer.intersects(boundsRect)) {
2587            updateHitTestResult(result, flipForWritingMode(locationInContainer.point() - localOffset));
2588            if (!result.addNodeToRectBasedTestResult(nodeForHitTest(), request, locationInContainer, boundsRect))
2589                return true;
2590        }
2591    }
2592
2593    return false;
2594}
2595
2596bool RenderBlock::hitTestContents(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
2597{
2598    if (childrenInline() && !isTable())
2599        return hitTestInlineChildren(request, result, locationInContainer, accumulatedOffset, hitTestAction);
2600
2601    // Hit test our children.
2602    HitTestAction childHitTest = hitTestAction;
2603    if (hitTestAction == HitTestChildBlockBackgrounds)
2604        childHitTest = HitTestChildBlockBackground;
2605    for (auto child = lastChildBox(); child; child = child->previousSiblingBox()) {
2606        LayoutPoint childPoint = flipForWritingModeForChild(child, accumulatedOffset);
2607        if (!child->hasSelfPaintingLayer() && !child->isFloating() && child->nodeAtPoint(request, result, locationInContainer, childPoint, childHitTest))
2608            return true;
2609    }
2610
2611    return false;
2612}
2613
2614static inline bool isEditingBoundary(RenderElement* ancestor, RenderObject& child)
2615{
2616    ASSERT(!ancestor || ancestor->nonPseudoElement());
2617    ASSERT(child.nonPseudoNode());
2618    return !ancestor || !ancestor->parent() || (ancestor->hasLayer() && ancestor->parent()->isRenderView())
2619        || ancestor->nonPseudoElement()->hasEditableStyle() == child.nonPseudoNode()->hasEditableStyle();
2620}
2621
2622// FIXME: This function should go on RenderObject as an instance method. Then
2623// all cases in which positionForPoint recurs could call this instead to
2624// prevent crossing editable boundaries. This would require many tests.
2625VisiblePosition positionForPointRespectingEditingBoundaries(RenderBlock& parent, RenderBox& child, const LayoutPoint& pointInParentCoordinates)
2626{
2627    LayoutPoint childLocation = child.location();
2628    if (child.isInFlowPositioned())
2629        childLocation += child.offsetForInFlowPosition();
2630
2631    // FIXME: This is wrong if the child's writing-mode is different from the parent's.
2632    LayoutPoint pointInChildCoordinates(toLayoutPoint(pointInParentCoordinates - childLocation));
2633
2634    // If this is an anonymous renderer, we just recur normally
2635    Element* childElement= child.nonPseudoElement();
2636    if (!childElement)
2637        return child.positionForPoint(pointInChildCoordinates, nullptr);
2638
2639    // Otherwise, first make sure that the editability of the parent and child agree.
2640    // If they don't agree, then we return a visible position just before or after the child
2641    RenderElement* ancestor = &parent;
2642    while (ancestor && !ancestor->nonPseudoElement())
2643        ancestor = ancestor->parent();
2644
2645    // If we can't find an ancestor to check editability on, or editability is unchanged, we recur like normal
2646    if (isEditingBoundary(ancestor, child))
2647        return child.positionForPoint(pointInChildCoordinates, nullptr);
2648
2649#if PLATFORM(IOS)
2650    // On iOS we want to constrain VisiblePositions to the editable region closest to the input position, so
2651    // we will allow descent from non-editable to editable content.
2652    // FIXME: This constraining must be done at a higher level once we implement contentEditable. For now, if something
2653    // is editable, the whole document will be.
2654    if (childElement->isContentEditable() && !ancestor->element()->isContentEditable())
2655        return child.positionForPoint(pointInChildCoordinates, nullptr);
2656#endif
2657
2658    // Otherwise return before or after the child, depending on if the click was to the logical left or logical right of the child
2659    LayoutUnit childMiddle = parent.logicalWidthForChild(child) / 2;
2660    LayoutUnit logicalLeft = parent.isHorizontalWritingMode() ? pointInChildCoordinates.x() : pointInChildCoordinates.y();
2661    if (logicalLeft < childMiddle)
2662        return ancestor->createVisiblePosition(childElement->nodeIndex(), DOWNSTREAM);
2663    return ancestor->createVisiblePosition(childElement->nodeIndex() + 1, UPSTREAM);
2664}
2665
2666VisiblePosition RenderBlock::positionForPointWithInlineChildren(const LayoutPoint&, const RenderRegion*)
2667{
2668    ASSERT_NOT_REACHED();
2669    return VisiblePosition();
2670}
2671
2672static inline bool isChildHitTestCandidate(const RenderBox& box)
2673{
2674    return box.height() && box.style().visibility() == VISIBLE && !box.isFloatingOrOutOfFlowPositioned() && !box.isInFlowRenderFlowThread();
2675}
2676
2677// Valid candidates in a FlowThread must be rendered by the region.
2678static inline bool isChildHitTestCandidate(const RenderBox& box, const RenderRegion* region, const LayoutPoint& point)
2679{
2680    if (!isChildHitTestCandidate(box))
2681        return false;
2682    if (!region)
2683        return true;
2684    const RenderBlock& block = box.isRenderBlock() ? toRenderBlock(box) : *box.containingBlock();
2685    return block.regionAtBlockOffset(point.y()) == region;
2686}
2687
2688VisiblePosition RenderBlock::positionForPoint(const LayoutPoint& point, const RenderRegion* region)
2689{
2690    if (isTable())
2691        return RenderBox::positionForPoint(point, region);
2692
2693    if (isReplaced()) {
2694        // FIXME: This seems wrong when the object's writing-mode doesn't match the line's writing-mode.
2695        LayoutUnit pointLogicalLeft = isHorizontalWritingMode() ? point.x() : point.y();
2696        LayoutUnit pointLogicalTop = isHorizontalWritingMode() ? point.y() : point.x();
2697
2698        if (pointLogicalTop < 0 || (pointLogicalTop < logicalHeight() && pointLogicalLeft < 0))
2699            return createVisiblePosition(caretMinOffset(), DOWNSTREAM);
2700        if (pointLogicalTop >= logicalHeight() || (pointLogicalTop >= 0 && pointLogicalLeft >= logicalWidth()))
2701            return createVisiblePosition(caretMaxOffset(), DOWNSTREAM);
2702    }
2703
2704    LayoutPoint pointInContents = point;
2705    offsetForContents(pointInContents);
2706    LayoutPoint pointInLogicalContents(pointInContents);
2707    if (!isHorizontalWritingMode())
2708        pointInLogicalContents = pointInLogicalContents.transposedPoint();
2709
2710    if (childrenInline())
2711        return positionForPointWithInlineChildren(pointInLogicalContents, region);
2712
2713    RenderBox* lastCandidateBox = lastChildBox();
2714
2715    if (!region)
2716        region = regionAtBlockOffset(pointInLogicalContents.y());
2717
2718    while (lastCandidateBox && !isChildHitTestCandidate(*lastCandidateBox, region, pointInLogicalContents))
2719        lastCandidateBox = lastCandidateBox->previousSiblingBox();
2720
2721    bool blocksAreFlipped = style().isFlippedBlocksWritingMode();
2722    if (lastCandidateBox) {
2723        if (pointInLogicalContents.y() > logicalTopForChild(*lastCandidateBox)
2724            || (!blocksAreFlipped && pointInLogicalContents.y() == logicalTopForChild(*lastCandidateBox)))
2725            return positionForPointRespectingEditingBoundaries(*this, *lastCandidateBox, pointInContents);
2726
2727        for (auto childBox = firstChildBox(); childBox; childBox = childBox->nextSiblingBox()) {
2728            if (!isChildHitTestCandidate(*childBox, region, pointInLogicalContents))
2729                continue;
2730            LayoutUnit childLogicalBottom = logicalTopForChild(*childBox) + logicalHeightForChild(*childBox);
2731            // We hit child if our click is above the bottom of its padding box (like IE6/7 and FF3).
2732            if (isChildHitTestCandidate(*childBox, region, pointInLogicalContents) && (pointInLogicalContents.y() < childLogicalBottom
2733                || (blocksAreFlipped && pointInLogicalContents.y() == childLogicalBottom)))
2734                return positionForPointRespectingEditingBoundaries(*this, *childBox, pointInContents);
2735        }
2736    }
2737
2738    // We only get here if there are no hit test candidate children below the click.
2739    return RenderBox::positionForPoint(point, region);
2740}
2741
2742void RenderBlock::offsetForContents(LayoutPoint& offset) const
2743{
2744    offset = flipForWritingMode(offset);
2745    offset += scrolledContentOffset();
2746    offset = flipForWritingMode(offset);
2747}
2748
2749void RenderBlock::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
2750{
2751    ASSERT(!childrenInline());
2752
2753    computeBlockPreferredLogicalWidths(minLogicalWidth, maxLogicalWidth);
2754
2755    maxLogicalWidth = std::max(minLogicalWidth, maxLogicalWidth);
2756
2757    int scrollbarWidth = instrinsicScrollbarLogicalWidth();
2758    maxLogicalWidth += scrollbarWidth;
2759    minLogicalWidth += scrollbarWidth;
2760}
2761
2762void RenderBlock::computePreferredLogicalWidths()
2763{
2764    ASSERT(preferredLogicalWidthsDirty());
2765
2766    updateFirstLetter();
2767
2768    m_minPreferredLogicalWidth = 0;
2769    m_maxPreferredLogicalWidth = 0;
2770
2771    const RenderStyle& styleToUse = style();
2772    if (!isTableCell() && styleToUse.logicalWidth().isFixed() && styleToUse.logicalWidth().value() >= 0
2773        && !(isDeprecatedFlexItem() && !styleToUse.logicalWidth().intValue()))
2774        m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalWidth().value());
2775    else
2776        computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
2777
2778    if (styleToUse.logicalMinWidth().isFixed() && styleToUse.logicalMinWidth().value() > 0) {
2779        m_maxPreferredLogicalWidth = std::max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMinWidth().value()));
2780        m_minPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMinWidth().value()));
2781    }
2782
2783    if (styleToUse.logicalMaxWidth().isFixed()) {
2784        m_maxPreferredLogicalWidth = std::min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMaxWidth().value()));
2785        m_minPreferredLogicalWidth = std::min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMaxWidth().value()));
2786    }
2787
2788    // Table layout uses integers, ceil the preferred widths to ensure that they can contain the contents.
2789    if (isTableCell()) {
2790        m_minPreferredLogicalWidth = m_minPreferredLogicalWidth.ceil();
2791        m_maxPreferredLogicalWidth = m_maxPreferredLogicalWidth.ceil();
2792    }
2793
2794    LayoutUnit borderAndPadding = borderAndPaddingLogicalWidth();
2795    m_minPreferredLogicalWidth += borderAndPadding;
2796    m_maxPreferredLogicalWidth += borderAndPadding;
2797
2798    setPreferredLogicalWidthsDirty(false);
2799}
2800
2801struct InlineMinMaxIterator {
2802/* InlineMinMaxIterator is a class that will iterate over all render objects that contribute to
2803   inline min/max width calculations.  Note the following about the way it walks:
2804   (1) Positioned content is skipped (since it does not contribute to min/max width of a block)
2805   (2) We do not drill into the children of floats or replaced elements, since you can't break
2806       in the middle of such an element.
2807   (3) Inline flows (e.g., <a>, <span>, <i>) are walked twice, since each side can have
2808       distinct borders/margin/padding that contribute to the min/max width.
2809*/
2810    RenderObject* parent;
2811    RenderObject* current;
2812    bool endOfInline;
2813
2814    InlineMinMaxIterator(RenderObject* p, bool end = false)
2815        :parent(p), current(p), endOfInline(end) {}
2816
2817    RenderObject* next();
2818};
2819
2820RenderObject* InlineMinMaxIterator::next()
2821{
2822    RenderObject* result = 0;
2823    bool oldEndOfInline = endOfInline;
2824    endOfInline = false;
2825    while (current || current == parent) {
2826        if (!oldEndOfInline &&
2827            (current == parent ||
2828             (!current->isFloating() && !current->isReplaced() && !current->isOutOfFlowPositioned())))
2829            result = current->firstChildSlow();
2830        if (!result) {
2831            // We hit the end of our inline. (It was empty, e.g., <span></span>.)
2832            if (!oldEndOfInline && current->isRenderInline()) {
2833                result = current;
2834                endOfInline = true;
2835                break;
2836            }
2837
2838            while (current && current != parent) {
2839                result = current->nextSibling();
2840                if (result) break;
2841                current = current->parent();
2842                if (current && current != parent && current->isRenderInline()) {
2843                    result = current;
2844                    endOfInline = true;
2845                    break;
2846                }
2847            }
2848        }
2849
2850        if (!result)
2851            break;
2852
2853        if (!result->isOutOfFlowPositioned() && (result->isTextOrLineBreak() || result->isFloating() || result->isReplaced() || result->isRenderInline()))
2854             break;
2855
2856        current = result;
2857        result = 0;
2858    }
2859
2860    // Update our position.
2861    current = result;
2862    return current;
2863}
2864
2865static LayoutUnit getBPMWidth(LayoutUnit childValue, Length cssUnit)
2866{
2867    if (cssUnit.type() != Auto)
2868        return (cssUnit.isFixed() ? LayoutUnit(cssUnit.value()) : childValue);
2869    return 0;
2870}
2871
2872static LayoutUnit getBorderPaddingMargin(const RenderBoxModelObject* child, bool endOfInline)
2873{
2874    const RenderStyle& childStyle = child->style();
2875    if (endOfInline)
2876        return getBPMWidth(child->marginEnd(), childStyle.marginEnd()) +
2877               getBPMWidth(child->paddingEnd(), childStyle.paddingEnd()) +
2878               child->borderEnd();
2879    return getBPMWidth(child->marginStart(), childStyle.marginStart()) +
2880               getBPMWidth(child->paddingStart(), childStyle.paddingStart()) +
2881               child->borderStart();
2882}
2883
2884static inline void stripTrailingSpace(float& inlineMax, float& inlineMin,
2885                                      RenderObject* trailingSpaceChild)
2886{
2887    if (trailingSpaceChild && trailingSpaceChild->isText()) {
2888        // Collapse away the trailing space at the end of a block.
2889        RenderText* t = toRenderText(trailingSpaceChild);
2890        const UChar space = ' ';
2891        const Font& font = t->style().font(); // FIXME: This ignores first-line.
2892        float spaceWidth = font.width(RenderBlock::constructTextRun(t, font, &space, 1, t->style()));
2893        inlineMax -= spaceWidth + font.wordSpacing();
2894        if (inlineMin > inlineMax)
2895            inlineMin = inlineMax;
2896    }
2897}
2898
2899static inline void updatePreferredWidth(LayoutUnit& preferredWidth, float& result)
2900{
2901    LayoutUnit snappedResult = ceiledLayoutUnit(result);
2902    preferredWidth = std::max(snappedResult, preferredWidth);
2903}
2904
2905// With sub-pixel enabled: When converting between floating point and LayoutUnits
2906// we risk losing precision with each conversion. When this occurs while
2907// accumulating our preferred widths, we can wind up with a line width that's
2908// larger than our maxPreferredWidth due to pure float accumulation.
2909//
2910// With sub-pixel disabled: values from Lengths or the render tree aren't subject
2911// to the same loss of precision, as they're always truncated and stored as
2912// integers. We mirror that behavior here to prevent over-allocating our preferred
2913// width.
2914static inline LayoutUnit adjustFloatForSubPixelLayout(float value)
2915{
2916#if ENABLE(SUBPIXEL_LAYOUT)
2917    return ceiledLayoutUnit(value);
2918#else
2919    return static_cast<int>(value);
2920#endif
2921}
2922
2923
2924void RenderBlock::computeInlinePreferredLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth)
2925{
2926    float inlineMax = 0;
2927    float inlineMin = 0;
2928
2929    const RenderStyle& styleToUse = style();
2930    RenderBlock* containingBlock = this->containingBlock();
2931    LayoutUnit cw = containingBlock ? containingBlock->contentLogicalWidth() : LayoutUnit();
2932
2933    // If we are at the start of a line, we want to ignore all white-space.
2934    // Also strip spaces if we previously had text that ended in a trailing space.
2935    bool stripFrontSpaces = true;
2936    RenderObject* trailingSpaceChild = 0;
2937
2938    // Firefox and Opera will allow a table cell to grow to fit an image inside it under
2939    // very specific cirucumstances (in order to match common WinIE renderings).
2940    // Not supporting the quirk has caused us to mis-render some real sites. (See Bugzilla 10517.)
2941    bool allowImagesToBreak = !document().inQuirksMode() || !isTableCell() || !styleToUse.logicalWidth().isIntrinsicOrAuto();
2942
2943    bool autoWrap, oldAutoWrap;
2944    autoWrap = oldAutoWrap = styleToUse.autoWrap();
2945
2946    InlineMinMaxIterator childIterator(this);
2947
2948    // Only gets added to the max preffered width once.
2949    bool addedTextIndent = false;
2950    // Signals the text indent was more negative than the min preferred width
2951    bool hasRemainingNegativeTextIndent = false;
2952
2953    LayoutUnit textIndent = minimumValueForLength(styleToUse.textIndent(), cw);
2954    RenderObject* prevFloat = 0;
2955    bool isPrevChildInlineFlow = false;
2956    bool shouldBreakLineAfterText = false;
2957    while (RenderObject* child = childIterator.next()) {
2958        autoWrap = child->isReplaced() ? child->parent()->style().autoWrap() :
2959            child->style().autoWrap();
2960
2961        if (!child->isBR()) {
2962            // Step One: determine whether or not we need to go ahead and
2963            // terminate our current line.  Each discrete chunk can become
2964            // the new min-width, if it is the widest chunk seen so far, and
2965            // it can also become the max-width.
2966
2967            // Children fall into three categories:
2968            // (1) An inline flow object.  These objects always have a min/max of 0,
2969            // and are included in the iteration solely so that their margins can
2970            // be added in.
2971            //
2972            // (2) An inline non-text non-flow object, e.g., an inline replaced element.
2973            // These objects can always be on a line by themselves, so in this situation
2974            // we need to go ahead and break the current line, and then add in our own
2975            // margins and min/max width on its own line, and then terminate the line.
2976            //
2977            // (3) A text object.  Text runs can have breakable characters at the start,
2978            // the middle or the end.  They may also lose whitespace off the front if
2979            // we're already ignoring whitespace.  In order to compute accurate min-width
2980            // information, we need three pieces of information.
2981            // (a) the min-width of the first non-breakable run.  Should be 0 if the text string
2982            // starts with whitespace.
2983            // (b) the min-width of the last non-breakable run. Should be 0 if the text string
2984            // ends with whitespace.
2985            // (c) the min/max width of the string (trimmed for whitespace).
2986            //
2987            // If the text string starts with whitespace, then we need to go ahead and
2988            // terminate our current line (unless we're already in a whitespace stripping
2989            // mode.
2990            //
2991            // If the text string has a breakable character in the middle, but didn't start
2992            // with whitespace, then we add the width of the first non-breakable run and
2993            // then end the current line.  We then need to use the intermediate min/max width
2994            // values (if any of them are larger than our current min/max).  We then look at
2995            // the width of the last non-breakable run and use that to start a new line
2996            // (unless we end in whitespace).
2997            const RenderStyle& childStyle = child->style();
2998            float childMin = 0;
2999            float childMax = 0;
3000
3001            if (!child->isText()) {
3002                if (child->isLineBreakOpportunity()) {
3003                    updatePreferredWidth(minLogicalWidth, inlineMin);
3004                    inlineMin = 0;
3005                    continue;
3006                }
3007                // Case (1) and (2).  Inline replaced and inline flow elements.
3008                if (child->isRenderInline()) {
3009                    // Add in padding/border/margin from the appropriate side of
3010                    // the element.
3011                    float bpm = getBorderPaddingMargin(toRenderInline(child), childIterator.endOfInline);
3012                    childMin += bpm;
3013                    childMax += bpm;
3014
3015                    inlineMin += childMin;
3016                    inlineMax += childMax;
3017
3018                    child->setPreferredLogicalWidthsDirty(false);
3019                } else {
3020                    // Inline replaced elts add in their margins to their min/max values.
3021                    LayoutUnit margins = 0;
3022                    Length startMargin = childStyle.marginStart();
3023                    Length endMargin = childStyle.marginEnd();
3024                    if (startMargin.isFixed())
3025                        margins += adjustFloatForSubPixelLayout(startMargin.value());
3026                    if (endMargin.isFixed())
3027                        margins += adjustFloatForSubPixelLayout(endMargin.value());
3028                    childMin += margins.ceilToFloat();
3029                    childMax += margins.ceilToFloat();
3030                }
3031            }
3032
3033            if (!child->isRenderInline() && !child->isText()) {
3034                // Case (2). Inline replaced elements and floats.
3035                // Go ahead and terminate the current line as far as
3036                // minwidth is concerned.
3037                childMin += child->minPreferredLogicalWidth().ceilToFloat();
3038                childMax += child->maxPreferredLogicalWidth().ceilToFloat();
3039
3040                bool clearPreviousFloat;
3041                if (child->isFloating()) {
3042                    clearPreviousFloat = (prevFloat
3043                        && ((prevFloat->style().floating() == LeftFloat && (childStyle.clear() & CLEFT))
3044                            || (prevFloat->style().floating() == RightFloat && (childStyle.clear() & CRIGHT))));
3045                    prevFloat = child;
3046                } else
3047                    clearPreviousFloat = false;
3048
3049                bool canBreakReplacedElement = !child->isImage() || allowImagesToBreak;
3050                if ((canBreakReplacedElement && (autoWrap || oldAutoWrap) && (!isPrevChildInlineFlow || shouldBreakLineAfterText)) || clearPreviousFloat) {
3051                    updatePreferredWidth(minLogicalWidth, inlineMin);
3052                    inlineMin = 0;
3053                }
3054
3055                // If we're supposed to clear the previous float, then terminate maxwidth as well.
3056                if (clearPreviousFloat) {
3057                    updatePreferredWidth(maxLogicalWidth, inlineMax);
3058                    inlineMax = 0;
3059                }
3060
3061                // Add in text-indent.  This is added in only once.
3062                if (!addedTextIndent && !child->isFloating()) {
3063                    LayoutUnit ceiledIndent = textIndent.ceilToFloat();
3064                    childMin += ceiledIndent;
3065                    childMax += ceiledIndent;
3066
3067                    if (childMin < 0)
3068                        textIndent = adjustFloatForSubPixelLayout(childMin);
3069                    else
3070                        addedTextIndent = true;
3071                }
3072
3073                // Add our width to the max.
3074                inlineMax += std::max<float>(0, childMax);
3075
3076                if (!autoWrap || !canBreakReplacedElement || (isPrevChildInlineFlow && !shouldBreakLineAfterText)) {
3077                    if (child->isFloating())
3078                        updatePreferredWidth(minLogicalWidth, childMin);
3079                    else
3080                        inlineMin += childMin;
3081                } else {
3082                    // Now check our line.
3083                    updatePreferredWidth(minLogicalWidth, childMin);
3084
3085                    // Now start a new line.
3086                    inlineMin = 0;
3087                }
3088
3089                if (autoWrap && canBreakReplacedElement && isPrevChildInlineFlow) {
3090                    updatePreferredWidth(minLogicalWidth, inlineMin);
3091                    inlineMin = 0;
3092                }
3093
3094                // We are no longer stripping whitespace at the start of
3095                // a line.
3096                if (!child->isFloating()) {
3097                    stripFrontSpaces = false;
3098                    trailingSpaceChild = 0;
3099                }
3100            } else if (child->isText()) {
3101                // Case (3). Text.
3102                RenderText* t = toRenderText(child);
3103
3104                if (t->style().hasTextCombine() && t->isCombineText())
3105                    toRenderCombineText(*t).combineText();
3106
3107                // Determine if we have a breakable character.  Pass in
3108                // whether or not we should ignore any spaces at the front
3109                // of the string.  If those are going to be stripped out,
3110                // then they shouldn't be considered in the breakable char
3111                // check.
3112                bool hasBreakableChar, hasBreak;
3113                float beginMin, endMin;
3114                bool beginWS, endWS;
3115                float beginMax, endMax;
3116                t->trimmedPrefWidths(inlineMax, beginMin, beginWS, endMin, endWS,
3117                                     hasBreakableChar, hasBreak, beginMax, endMax,
3118                                     childMin, childMax, stripFrontSpaces);
3119
3120                // This text object will not be rendered, but it may still provide a breaking opportunity.
3121                if (!hasBreak && childMax == 0) {
3122                    if (autoWrap && (beginWS || endWS)) {
3123                        updatePreferredWidth(minLogicalWidth, inlineMin);
3124                        inlineMin = 0;
3125                    }
3126                    continue;
3127                }
3128
3129                if (stripFrontSpaces)
3130                    trailingSpaceChild = child;
3131                else
3132                    trailingSpaceChild = 0;
3133
3134                // Add in text-indent.  This is added in only once.
3135                float ti = 0;
3136                if (!addedTextIndent || hasRemainingNegativeTextIndent) {
3137                    ti = textIndent.ceilToFloat();
3138                    childMin += ti;
3139                    beginMin += ti;
3140
3141                    // It the text indent negative and larger than the child minimum, we re-use the remainder
3142                    // in future minimum calculations, but using the negative value again on the maximum
3143                    // will lead to under-counting the max pref width.
3144                    if (!addedTextIndent) {
3145                        childMax += ti;
3146                        beginMax += ti;
3147                        addedTextIndent = true;
3148                    }
3149
3150                    if (childMin < 0) {
3151                        textIndent = childMin;
3152                        hasRemainingNegativeTextIndent = true;
3153                    }
3154                }
3155
3156                // If we have no breakable characters at all,
3157                // then this is the easy case. We add ourselves to the current
3158                // min and max and continue.
3159                if (!hasBreakableChar) {
3160                    inlineMin += childMin;
3161                } else {
3162                    // We have a breakable character.  Now we need to know if
3163                    // we start and end with whitespace.
3164                    if (beginWS)
3165                        // Go ahead and end the current line.
3166                        updatePreferredWidth(minLogicalWidth, inlineMin);
3167                    else {
3168                        inlineMin += beginMin;
3169                        updatePreferredWidth(minLogicalWidth, inlineMin);
3170                        childMin -= ti;
3171                    }
3172
3173                    inlineMin = childMin;
3174
3175                    if (endWS) {
3176                        // We end in whitespace, which means we can go ahead
3177                        // and end our current line.
3178                        updatePreferredWidth(minLogicalWidth, inlineMin);
3179                        inlineMin = 0;
3180                        shouldBreakLineAfterText = false;
3181                    } else {
3182                        updatePreferredWidth(minLogicalWidth, inlineMin);
3183                        inlineMin = endMin;
3184                        shouldBreakLineAfterText = true;
3185                    }
3186                }
3187
3188                if (hasBreak) {
3189                    inlineMax += beginMax;
3190                    updatePreferredWidth(maxLogicalWidth, inlineMax);
3191                    updatePreferredWidth(maxLogicalWidth, childMax);
3192                    inlineMax = endMax;
3193                    addedTextIndent = true;
3194                } else
3195                    inlineMax += std::max<float>(0, childMax);
3196            }
3197
3198            // Ignore spaces after a list marker.
3199            if (child->isListMarker())
3200                stripFrontSpaces = true;
3201        } else {
3202            updatePreferredWidth(minLogicalWidth, inlineMin);
3203            updatePreferredWidth(maxLogicalWidth, inlineMax);
3204            inlineMin = inlineMax = 0;
3205            stripFrontSpaces = true;
3206            trailingSpaceChild = 0;
3207            addedTextIndent = true;
3208        }
3209
3210        if (!child->isText() && child->isRenderInline())
3211            isPrevChildInlineFlow = true;
3212        else
3213            isPrevChildInlineFlow = false;
3214
3215        oldAutoWrap = autoWrap;
3216    }
3217
3218    if (styleToUse.collapseWhiteSpace())
3219        stripTrailingSpace(inlineMax, inlineMin, trailingSpaceChild);
3220
3221    updatePreferredWidth(minLogicalWidth, inlineMin);
3222    updatePreferredWidth(maxLogicalWidth, inlineMax);
3223}
3224
3225void RenderBlock::computeBlockPreferredLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
3226{
3227    const RenderStyle& styleToUse = style();
3228    bool nowrap = styleToUse.whiteSpace() == NOWRAP;
3229
3230    RenderObject* child = firstChild();
3231    RenderBlock* containingBlock = this->containingBlock();
3232    LayoutUnit floatLeftWidth = 0, floatRightWidth = 0;
3233    while (child) {
3234        // Positioned children don't affect the min/max width
3235        if (child->isOutOfFlowPositioned()) {
3236            child = child->nextSibling();
3237            continue;
3238        }
3239
3240        const RenderStyle& childStyle = child->style();
3241        if (child->isFloating() || (child->isBox() && toRenderBox(child)->avoidsFloats())) {
3242            LayoutUnit floatTotalWidth = floatLeftWidth + floatRightWidth;
3243            if (childStyle.clear() & CLEFT) {
3244                maxLogicalWidth = std::max(floatTotalWidth, maxLogicalWidth);
3245                floatLeftWidth = 0;
3246            }
3247            if (childStyle.clear() & CRIGHT) {
3248                maxLogicalWidth = std::max(floatTotalWidth, maxLogicalWidth);
3249                floatRightWidth = 0;
3250            }
3251        }
3252
3253        // A margin basically has three types: fixed, percentage, and auto (variable).
3254        // Auto and percentage margins simply become 0 when computing min/max width.
3255        // Fixed margins can be added in as is.
3256        Length startMarginLength = childStyle.marginStartUsing(&styleToUse);
3257        Length endMarginLength = childStyle.marginEndUsing(&styleToUse);
3258        LayoutUnit margin = 0;
3259        LayoutUnit marginStart = 0;
3260        LayoutUnit marginEnd = 0;
3261        if (startMarginLength.isFixed())
3262            marginStart += startMarginLength.value();
3263        if (endMarginLength.isFixed())
3264            marginEnd += endMarginLength.value();
3265        margin = marginStart + marginEnd;
3266
3267        LayoutUnit childMinPreferredLogicalWidth, childMaxPreferredLogicalWidth;
3268        if (child->isBox() && child->isHorizontalWritingMode() != isHorizontalWritingMode()) {
3269            RenderBox* childBox = toRenderBox(child);
3270            LogicalExtentComputedValues computedValues;
3271            childBox->computeLogicalHeight(childBox->borderAndPaddingLogicalHeight(), 0, computedValues);
3272            childMinPreferredLogicalWidth = childMaxPreferredLogicalWidth = computedValues.m_extent;
3273        } else {
3274            childMinPreferredLogicalWidth = child->minPreferredLogicalWidth();
3275            childMaxPreferredLogicalWidth = child->maxPreferredLogicalWidth();
3276        }
3277
3278        LayoutUnit w = childMinPreferredLogicalWidth + margin;
3279        minLogicalWidth = std::max(w, minLogicalWidth);
3280
3281        // IE ignores tables for calculation of nowrap. Makes some sense.
3282        if (nowrap && !child->isTable())
3283            maxLogicalWidth = std::max(w, maxLogicalWidth);
3284
3285        w = childMaxPreferredLogicalWidth + margin;
3286
3287        if (!child->isFloating()) {
3288            if (child->isBox() && toRenderBox(child)->avoidsFloats()) {
3289                // Determine a left and right max value based off whether or not the floats can fit in the
3290                // margins of the object.  For negative margins, we will attempt to overlap the float if the negative margin
3291                // is smaller than the float width.
3292                bool ltr = containingBlock ? containingBlock->style().isLeftToRightDirection() : styleToUse.isLeftToRightDirection();
3293                LayoutUnit marginLogicalLeft = ltr ? marginStart : marginEnd;
3294                LayoutUnit marginLogicalRight = ltr ? marginEnd : marginStart;
3295                LayoutUnit maxLeft = marginLogicalLeft > 0 ? std::max(floatLeftWidth, marginLogicalLeft) : floatLeftWidth + marginLogicalLeft;
3296                LayoutUnit maxRight = marginLogicalRight > 0 ? std::max(floatRightWidth, marginLogicalRight) : floatRightWidth + marginLogicalRight;
3297                w = childMaxPreferredLogicalWidth + maxLeft + maxRight;
3298                w = std::max(w, floatLeftWidth + floatRightWidth);
3299            }
3300            else
3301                maxLogicalWidth = std::max(floatLeftWidth + floatRightWidth, maxLogicalWidth);
3302            floatLeftWidth = floatRightWidth = 0;
3303        }
3304
3305        if (child->isFloating()) {
3306            if (childStyle.floating() == LeftFloat)
3307                floatLeftWidth += w;
3308            else
3309                floatRightWidth += w;
3310        } else
3311            maxLogicalWidth = std::max(w, maxLogicalWidth);
3312
3313        child = child->nextSibling();
3314    }
3315
3316    // Always make sure these values are non-negative.
3317    minLogicalWidth = std::max<LayoutUnit>(0, minLogicalWidth);
3318    maxLogicalWidth = std::max<LayoutUnit>(0, maxLogicalWidth);
3319
3320    maxLogicalWidth = std::max(floatLeftWidth + floatRightWidth, maxLogicalWidth);
3321}
3322
3323bool RenderBlock::hasLineIfEmpty() const
3324{
3325    if (!element())
3326        return false;
3327
3328    if (element()->isRootEditableElement())
3329        return true;
3330
3331    return false;
3332}
3333
3334LayoutUnit RenderBlock::lineHeight(bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
3335{
3336    // Inline blocks are replaced elements. Otherwise, just pass off to
3337    // the base class.  If we're being queried as though we're the root line
3338    // box, then the fact that we're an inline-block is irrelevant, and we behave
3339    // just like a block.
3340    if (isReplaced() && linePositionMode == PositionOnContainingLine)
3341        return RenderBox::lineHeight(firstLine, direction, linePositionMode);
3342
3343    if (firstLine && document().styleSheetCollection().usesFirstLineRules()) {
3344        RenderStyle& s = firstLine ? firstLineStyle() : style();
3345        if (&s != &style())
3346            return s.computedLineHeight();
3347    }
3348
3349    if (m_lineHeight == -1)
3350        m_lineHeight = style().computedLineHeight();
3351
3352    return m_lineHeight;
3353}
3354
3355int RenderBlock::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
3356{
3357    // Inline blocks are replaced elements. Otherwise, just pass off to
3358    // the base class.  If we're being queried as though we're the root line
3359    // box, then the fact that we're an inline-block is irrelevant, and we behave
3360    // just like a block.
3361    if (isReplaced() && linePositionMode == PositionOnContainingLine) {
3362        // For "leaf" theme objects, let the theme decide what the baseline position is.
3363        // FIXME: Might be better to have a custom CSS property instead, so that if the theme
3364        // is turned off, checkboxes/radios will still have decent baselines.
3365        // FIXME: Need to patch form controls to deal with vertical lines.
3366        if (style().hasAppearance() && !theme().isControlContainer(style().appearance()))
3367            return theme().baselinePosition(*this);
3368
3369        // CSS2.1 states that the baseline of an inline block is the baseline of the last line box in
3370        // the normal flow.  We make an exception for marquees, since their baselines are meaningless
3371        // (the content inside them moves).  This matches WinIE as well, which just bottom-aligns them.
3372        // We also give up on finding a baseline if we have a vertical scrollbar, or if we are scrolled
3373        // vertically (e.g., an overflow:hidden block that has had scrollTop moved) or if the baseline is outside
3374        // of our content box.
3375        bool ignoreBaseline = (layer() && (layer()->marquee() || (direction == HorizontalLine ? (layer()->verticalScrollbar() || layer()->scrollYOffset() != 0)
3376            : (layer()->horizontalScrollbar() || layer()->scrollXOffset() != 0)))) || (isWritingModeRoot() && !isRubyRun());
3377
3378        int baselinePos = ignoreBaseline ? -1 : inlineBlockBaseline(direction);
3379
3380        LayoutUnit bottomOfContent = direction == HorizontalLine ? borderTop() + paddingTop() + contentHeight() : borderRight() + paddingRight() + contentWidth();
3381        if (baselinePos != -1 && baselinePos <= bottomOfContent)
3382            return direction == HorizontalLine ? marginTop() + baselinePos : marginRight() + baselinePos;
3383
3384        return RenderBox::baselinePosition(baselineType, firstLine, direction, linePositionMode);
3385    }
3386
3387    const RenderStyle& style = firstLine ? firstLineStyle() : this->style();
3388    const FontMetrics& fontMetrics = style.fontMetrics();
3389    return fontMetrics.ascent(baselineType) + (lineHeight(firstLine, direction, linePositionMode) - fontMetrics.height()) / 2;
3390}
3391
3392LayoutUnit RenderBlock::minLineHeightForReplacedRenderer(bool isFirstLine, LayoutUnit replacedHeight) const
3393{
3394    if (!document().inNoQuirksMode() && replacedHeight)
3395        return replacedHeight;
3396
3397    const RenderStyle& style = isFirstLine ? firstLineStyle() : this->style();
3398    if (!(style.lineBoxContain() & LineBoxContainBlock))
3399        return 0;
3400
3401    return std::max<LayoutUnit>(replacedHeight, lineHeight(isFirstLine, isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes));
3402}
3403
3404int RenderBlock::firstLineBaseline() const
3405{
3406    if (isWritingModeRoot() && !isRubyRun())
3407        return -1;
3408
3409    for (RenderBox* curr = firstChildBox(); curr; curr = curr->nextSiblingBox()) {
3410        if (!curr->isFloatingOrOutOfFlowPositioned()) {
3411            int result = curr->firstLineBaseline();
3412            if (result != -1)
3413                return curr->logicalTop() + result; // Translate to our coordinate space.
3414        }
3415    }
3416
3417    return -1;
3418}
3419
3420int RenderBlock::inlineBlockBaseline(LineDirectionMode lineDirection) const
3421{
3422    if (isWritingModeRoot() && !isRubyRun())
3423        return -1;
3424
3425    bool haveNormalFlowChild = false;
3426    for (auto box = lastChildBox(); box; box = box->previousSiblingBox()) {
3427        if (box->isFloatingOrOutOfFlowPositioned())
3428            continue;
3429        haveNormalFlowChild = true;
3430        int result = box->inlineBlockBaseline(lineDirection);
3431        if (result != -1)
3432            return box->logicalTop() + result; // Translate to our coordinate space.
3433    }
3434
3435    if (!haveNormalFlowChild && hasLineIfEmpty()) {
3436        auto& fontMetrics = firstLineStyle().fontMetrics();
3437        return fontMetrics.ascent()
3438             + (lineHeight(true, lineDirection, PositionOfInteriorLineBoxes) - fontMetrics.height()) / 2
3439             + (lineDirection == HorizontalLine ? borderTop() + paddingTop() : borderRight() + paddingRight());
3440    }
3441
3442    return -1;
3443}
3444
3445RenderBlock* RenderBlock::firstLineBlock() const
3446{
3447    RenderBlock* firstLineBlock = const_cast<RenderBlock*>(this);
3448    bool hasPseudo = false;
3449    while (true) {
3450        hasPseudo = firstLineBlock->style().hasPseudoStyle(FIRST_LINE);
3451        if (hasPseudo)
3452            break;
3453        RenderElement* parentBlock = firstLineBlock->parent();
3454        // We include isRenderButton in this check because buttons are
3455        // implemented using flex box but should still support first-line. The
3456        // flex box spec requires that flex box does not support first-line,
3457        // though.
3458        // FIXME: Remove when buttons are implemented with align-items instead
3459        // of flexbox.
3460        if (firstLineBlock->isReplaced() || firstLineBlock->isFloating()
3461            || !parentBlock || parentBlock->firstChild() != firstLineBlock || (!parentBlock->isRenderBlockFlow() && !parentBlock->isRenderButton()))
3462            break;
3463        firstLineBlock = toRenderBlock(parentBlock);
3464    }
3465
3466    if (!hasPseudo)
3467        return 0;
3468
3469    return firstLineBlock;
3470}
3471
3472static RenderStyle* styleForFirstLetter(RenderObject* firstLetterBlock, RenderObject* firstLetterContainer)
3473{
3474    RenderStyle* pseudoStyle = firstLetterBlock->getCachedPseudoStyle(FIRST_LETTER, &firstLetterContainer->firstLineStyle());
3475    // Force inline display (except for floating first-letters).
3476    pseudoStyle->setDisplay(pseudoStyle->isFloating() ? BLOCK : INLINE);
3477    // CSS2 says first-letter can't be positioned.
3478    pseudoStyle->setPosition(StaticPosition);
3479    return pseudoStyle;
3480}
3481
3482// CSS 2.1 http://www.w3.org/TR/CSS21/selector.html#first-letter
3483// "Punctuation (i.e, characters defined in Unicode [UNICODE] in the "open" (Ps), "close" (Pe),
3484// "initial" (Pi). "final" (Pf) and "other" (Po) punctuation classes), that precedes or follows the first letter should be included"
3485static inline bool isPunctuationForFirstLetter(UChar c)
3486{
3487    return U_GET_GC_MASK(c) & (U_GC_PS_MASK | U_GC_PE_MASK | U_GC_PI_MASK | U_GC_PF_MASK | U_GC_PO_MASK);
3488}
3489
3490static inline bool shouldSkipForFirstLetter(UChar c)
3491{
3492    return isSpaceOrNewline(c) || c == noBreakSpace || isPunctuationForFirstLetter(c);
3493}
3494
3495static inline RenderBlock* findFirstLetterBlock(RenderBlock* start)
3496{
3497    RenderBlock* firstLetterBlock = start;
3498    while (true) {
3499        // We include isRenderButton in these two checks because buttons are
3500        // implemented using flex box but should still support first-letter.
3501        // The flex box spec requires that flex box does not support
3502        // first-letter, though.
3503        // FIXME: Remove when buttons are implemented with align-items instead
3504        // of flexbox.
3505        bool canHaveFirstLetterRenderer = firstLetterBlock->style().hasPseudoStyle(FIRST_LETTER)
3506            && firstLetterBlock->canHaveGeneratedChildren()
3507            && (!firstLetterBlock->isFlexibleBox() || firstLetterBlock->isRenderButton());
3508        if (canHaveFirstLetterRenderer)
3509            return firstLetterBlock;
3510
3511        RenderElement* parentBlock = firstLetterBlock->parent();
3512        if (firstLetterBlock->isReplaced() || !parentBlock || parentBlock->firstChild() != firstLetterBlock
3513            || (!parentBlock->isRenderBlockFlow() && !parentBlock->isRenderButton()))
3514            return 0;
3515        firstLetterBlock = toRenderBlock(parentBlock);
3516    }
3517
3518    return 0;
3519}
3520
3521void RenderBlock::updateFirstLetterStyle(RenderObject* firstLetterBlock, RenderObject* currentChild)
3522{
3523    RenderElement* firstLetter = currentChild->parent();
3524    RenderElement* firstLetterContainer = firstLetter->parent();
3525    RenderStyle* pseudoStyle = styleForFirstLetter(firstLetterBlock, firstLetterContainer);
3526    ASSERT(firstLetter->isFloating() || firstLetter->isInline());
3527
3528    if (Style::determineChange(&firstLetter->style(), pseudoStyle) == Style::Detach) {
3529        // The first-letter renderer needs to be replaced. Create a new renderer of the right type.
3530        RenderBoxModelObject* newFirstLetter;
3531        if (pseudoStyle->display() == INLINE)
3532            newFirstLetter = new RenderInline(document(), *pseudoStyle);
3533        else
3534            newFirstLetter = new RenderBlockFlow(document(), *pseudoStyle);
3535        newFirstLetter->initializeStyle();
3536
3537        // Move the first letter into the new renderer.
3538        LayoutStateDisabler layoutStateDisabler(&view());
3539        while (RenderObject* child = firstLetter->firstChild()) {
3540            if (child->isText())
3541                toRenderText(child)->removeAndDestroyTextBoxes();
3542            firstLetter->removeChild(*child);
3543            newFirstLetter->addChild(child, 0);
3544        }
3545
3546        RenderObject* nextSibling = firstLetter->nextSibling();
3547        if (RenderTextFragment* remainingText = toRenderBoxModelObject(firstLetter)->firstLetterRemainingText()) {
3548            ASSERT(remainingText->isAnonymous() || remainingText->textNode()->renderer() == remainingText);
3549            // Replace the old renderer with the new one.
3550            remainingText->setFirstLetter(*newFirstLetter);
3551            newFirstLetter->setFirstLetterRemainingText(remainingText);
3552        }
3553        // To prevent removal of single anonymous block in RenderBlock::removeChild and causing
3554        // |nextSibling| to go stale, we remove the old first letter using removeChildNode first.
3555        firstLetterContainer->removeChildInternal(*firstLetter, NotifyChildren);
3556        firstLetter->destroy();
3557        firstLetter = newFirstLetter;
3558        firstLetterContainer->addChild(firstLetter, nextSibling);
3559    } else
3560        firstLetter->setStyle(*pseudoStyle);
3561}
3562
3563void RenderBlock::createFirstLetterRenderer(RenderObject* firstLetterBlock, RenderText* currentTextChild)
3564{
3565    RenderElement* firstLetterContainer = currentTextChild->parent();
3566    RenderStyle* pseudoStyle = styleForFirstLetter(firstLetterBlock, firstLetterContainer);
3567    RenderBoxModelObject* firstLetter = 0;
3568    if (pseudoStyle->display() == INLINE)
3569        firstLetter = new RenderInline(document(), *pseudoStyle);
3570    else
3571        firstLetter = new RenderBlockFlow(document(), *pseudoStyle);
3572    firstLetter->initializeStyle();
3573    firstLetterContainer->addChild(firstLetter, currentTextChild);
3574
3575    // The original string is going to be either a generated content string or a DOM node's
3576    // string.  We want the original string before it got transformed in case first-letter has
3577    // no text-transform or a different text-transform applied to it.
3578    String oldText = currentTextChild->originalText();
3579    ASSERT(!oldText.isNull());
3580
3581    if (!oldText.isEmpty()) {
3582        unsigned length = 0;
3583
3584        // Account for leading spaces and punctuation.
3585        while (length < oldText.length() && shouldSkipForFirstLetter(oldText[length]))
3586            length++;
3587
3588        // Account for first letter.
3589        length++;
3590
3591        // Keep looking for whitespace and allowed punctuation, but avoid
3592        // accumulating just whitespace into the :first-letter.
3593        for (unsigned scanLength = length; scanLength < oldText.length(); ++scanLength) {
3594            UChar c = oldText[scanLength];
3595
3596            if (!shouldSkipForFirstLetter(c))
3597                break;
3598
3599            if (isPunctuationForFirstLetter(c))
3600                length = scanLength + 1;
3601         }
3602
3603        // Construct a text fragment for the text after the first letter.
3604        // This text fragment might be empty.
3605        RenderTextFragment* remainingText;
3606        if (currentTextChild->textNode())
3607            remainingText = new RenderTextFragment(*currentTextChild->textNode(), oldText, length, oldText.length() - length);
3608        else
3609            remainingText = new RenderTextFragment(document(), oldText, length, oldText.length() - length);
3610
3611        if (remainingText->textNode())
3612            remainingText->textNode()->setRenderer(remainingText);
3613
3614        firstLetterContainer->addChild(remainingText, currentTextChild);
3615        firstLetterContainer->removeChild(*currentTextChild);
3616        remainingText->setFirstLetter(*firstLetter);
3617        firstLetter->setFirstLetterRemainingText(remainingText);
3618
3619        // construct text fragment for the first letter
3620        RenderTextFragment* letter;
3621        if (remainingText->textNode())
3622            letter = new RenderTextFragment(*remainingText->textNode(), oldText, 0, length);
3623        else
3624            letter = new RenderTextFragment(document(), oldText, 0, length);
3625
3626        firstLetter->addChild(letter);
3627
3628        currentTextChild->destroy();
3629    }
3630}
3631
3632void RenderBlock::getFirstLetter(RenderObject*& firstLetter, RenderElement*& firstLetterContainer, RenderObject* skipObject)
3633{
3634    firstLetter = nullptr;
3635    firstLetterContainer = nullptr;
3636
3637    if (!document().styleSheetCollection().usesFirstLetterRules())
3638        return;
3639
3640    // Don't recur
3641    if (style().styleType() == FIRST_LETTER)
3642        return;
3643
3644    // FIXME: We need to destroy the first-letter object if it is no longer the first child. Need to find
3645    // an efficient way to check for that situation though before implementing anything.
3646    firstLetterContainer = findFirstLetterBlock(this);
3647    if (!firstLetterContainer)
3648        return;
3649
3650    // Drill into inlines looking for our first text descendant.
3651    firstLetter = firstLetterContainer->firstChild();
3652    while (firstLetter) {
3653        if (firstLetter->isText()) {
3654            if (firstLetter == skipObject) {
3655                firstLetter = firstLetter->nextSibling();
3656                continue;
3657            }
3658
3659            break;
3660        }
3661
3662        RenderElement& current = toRenderElement(*firstLetter);
3663        if (current.isListMarker())
3664            firstLetter = current.nextSibling();
3665        else if (current.isFloatingOrOutOfFlowPositioned()) {
3666            if (current.style().styleType() == FIRST_LETTER) {
3667                firstLetter = current.firstChild();
3668                break;
3669            }
3670            firstLetter = current.nextSibling();
3671        } else if (current.isReplaced() || current.isRenderButton() || current.isMenuList())
3672            break;
3673        else if (current.style().hasPseudoStyle(FIRST_LETTER) && current.canHaveGeneratedChildren())  {
3674            // We found a lower-level node with first-letter, which supersedes the higher-level style
3675            firstLetterContainer = &current;
3676            firstLetter = current.firstChild();
3677        } else
3678            firstLetter = current.firstChild();
3679    }
3680
3681    if (!firstLetter)
3682        firstLetterContainer = nullptr;
3683}
3684
3685void RenderBlock::updateFirstLetter()
3686{
3687    RenderObject* firstLetterObj;
3688    RenderElement* firstLetterContainer;
3689    getFirstLetter(firstLetterObj, firstLetterContainer);
3690
3691    if (!firstLetterObj)
3692        return;
3693
3694    // If the child already has style, then it has already been created, so we just want
3695    // to update it.
3696    if (firstLetterObj->parent()->style().styleType() == FIRST_LETTER) {
3697        updateFirstLetterStyle(firstLetterContainer, firstLetterObj);
3698        return;
3699    }
3700
3701    if (!firstLetterObj->isText())
3702        return;
3703
3704    // Our layout state is not valid for the repaints we are going to trigger by
3705    // adding and removing children of firstLetterContainer.
3706    LayoutStateDisabler layoutStateDisabler(&view());
3707
3708    createFirstLetterRenderer(firstLetterContainer, toRenderText(firstLetterObj));
3709}
3710
3711LayoutUnit RenderBlock::paginationStrut() const
3712{
3713    RenderBlockRareData* rareData = getRareData(this);
3714    return rareData ? rareData->m_paginationStrut : LayoutUnit();
3715}
3716
3717LayoutUnit RenderBlock::pageLogicalOffset() const
3718{
3719    RenderBlockRareData* rareData = getRareData(this);
3720    return rareData ? rareData->m_pageLogicalOffset : LayoutUnit();
3721}
3722
3723void RenderBlock::setPaginationStrut(LayoutUnit strut)
3724{
3725    RenderBlockRareData* rareData = getRareData(this);
3726    if (!rareData) {
3727        if (!strut)
3728            return;
3729        rareData = &ensureRareData(this);
3730    }
3731    rareData->m_paginationStrut = strut;
3732}
3733
3734void RenderBlock::setPageLogicalOffset(LayoutUnit logicalOffset)
3735{
3736    RenderBlockRareData* rareData = getRareData(this);
3737    if (!rareData) {
3738        if (!logicalOffset)
3739            return;
3740        rareData = &ensureRareData(this);
3741    }
3742    rareData->m_pageLogicalOffset = logicalOffset;
3743}
3744
3745void RenderBlock::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
3746{
3747    // For blocks inside inlines, we go ahead and include margins so that we run right up to the
3748    // inline boxes above and below us (thus getting merged with them to form a single irregular
3749    // shape).
3750    if (isAnonymousBlockContinuation()) {
3751        // FIXME: This is wrong for block-flows that are horizontal.
3752        // https://bugs.webkit.org/show_bug.cgi?id=46781
3753        rects.append(pixelSnappedIntRect(accumulatedOffset.x(), accumulatedOffset.y() - collapsedMarginBefore(),
3754                                width(), height() + collapsedMarginBefore() + collapsedMarginAfter()));
3755        continuation()->absoluteRects(rects, accumulatedOffset - toLayoutSize(location() +
3756                inlineElementContinuation()->containingBlock()->location()));
3757    } else
3758        rects.append(pixelSnappedIntRect(accumulatedOffset, size()));
3759}
3760
3761void RenderBlock::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
3762{
3763    // For blocks inside inlines, we go ahead and include margins so that we run right up to the
3764    // inline boxes above and below us (thus getting merged with them to form a single irregular
3765    // shape).
3766    FloatRect localRect = isAnonymousBlockContinuation()
3767        ? FloatRect(0, -collapsedMarginBefore(), width(), height() + collapsedMarginBefore() + collapsedMarginAfter())
3768        : FloatRect(0, 0, width(), height());
3769
3770    // FIXME: This is wrong for block-flows that are horizontal.
3771    // https://bugs.webkit.org/show_bug.cgi?id=46781
3772    RenderFlowThread* flowThread = flowThreadContainingBlock();
3773    if (!flowThread || !flowThread->absoluteQuadsForBox(quads, wasFixed, this, localRect.y(), localRect.maxY()))
3774        quads.append(localToAbsoluteQuad(localRect, 0 /* mode */, wasFixed));
3775
3776    if (isAnonymousBlockContinuation())
3777        continuation()->absoluteQuads(quads, wasFixed);
3778}
3779
3780LayoutRect RenderBlock::rectWithOutlineForRepaint(const RenderLayerModelObject* repaintContainer, LayoutUnit outlineWidth) const
3781{
3782    LayoutRect r(RenderBox::rectWithOutlineForRepaint(repaintContainer, outlineWidth));
3783    if (isAnonymousBlockContinuation())
3784        r.inflateY(collapsedMarginBefore()); // FIXME: This is wrong for block-flows that are horizontal.
3785    return r;
3786}
3787
3788RenderElement* RenderBlock::hoverAncestor() const
3789{
3790    return isAnonymousBlockContinuation() ? continuation() : RenderBox::hoverAncestor();
3791}
3792
3793void RenderBlock::updateDragState(bool dragOn)
3794{
3795    RenderBox::updateDragState(dragOn);
3796    if (RenderBoxModelObject* continuation = this->continuation())
3797        continuation->updateDragState(dragOn);
3798}
3799
3800const RenderStyle& RenderBlock::outlineStyleForRepaint() const
3801{
3802    return isAnonymousBlockContinuation() ? continuation()->style() : style();
3803}
3804
3805void RenderBlock::childBecameNonInline(RenderObject*)
3806{
3807    makeChildrenNonInline();
3808    if (isAnonymousBlock() && parent() && parent()->isRenderBlock())
3809        toRenderBlock(parent())->removeLeftoverAnonymousBlock(this);
3810    // |this| may be dead here
3811}
3812
3813void RenderBlock::updateHitTestResult(HitTestResult& result, const LayoutPoint& point)
3814{
3815    if (result.innerNode())
3816        return;
3817
3818    if (Node* n = nodeForHitTest()) {
3819        result.setInnerNode(n);
3820        if (!result.innerNonSharedNode())
3821            result.setInnerNonSharedNode(n);
3822        result.setLocalPoint(point);
3823    }
3824}
3825
3826LayoutRect RenderBlock::localCaretRect(InlineBox* inlineBox, int caretOffset, LayoutUnit* extraWidthToEndOfLine)
3827{
3828    // Do the normal calculation in most cases.
3829    if (firstChild())
3830        return RenderBox::localCaretRect(inlineBox, caretOffset, extraWidthToEndOfLine);
3831
3832    LayoutRect caretRect = localCaretRectForEmptyElement(width(), textIndentOffset());
3833
3834    // FIXME: Does this need to adjust for vertical orientation?
3835    if (extraWidthToEndOfLine)
3836        *extraWidthToEndOfLine = width() - caretRect.maxX();
3837
3838    return caretRect;
3839}
3840
3841void RenderBlock::addFocusRingRectsForInlineChildren(Vector<IntRect>&, const LayoutPoint&, const RenderLayerModelObject*)
3842{
3843    ASSERT_NOT_REACHED();
3844}
3845
3846void RenderBlock::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer)
3847{
3848    // For blocks inside inlines, we go ahead and include margins so that we run right up to the
3849    // inline boxes above and below us (thus getting merged with them to form a single irregular
3850    // shape).
3851    if (inlineElementContinuation()) {
3852        // FIXME: This check really isn't accurate.
3853        bool nextInlineHasLineBox = inlineElementContinuation()->firstLineBox();
3854        // FIXME: This is wrong. The principal renderer may not be the continuation preceding this block.
3855        // FIXME: This is wrong for block-flows that are horizontal.
3856        // https://bugs.webkit.org/show_bug.cgi?id=46781
3857        bool prevInlineHasLineBox = toRenderInline(inlineElementContinuation()->element()->renderer())->firstLineBox();
3858        float topMargin = prevInlineHasLineBox ? collapsedMarginBefore() : LayoutUnit();
3859        float bottomMargin = nextInlineHasLineBox ? collapsedMarginAfter() : LayoutUnit();
3860        LayoutRect rect(additionalOffset.x(), additionalOffset.y() - topMargin, width(), height() + topMargin + bottomMargin);
3861        if (!rect.isEmpty())
3862            rects.append(pixelSnappedIntRect(rect));
3863    } else if (width() && height())
3864        rects.append(pixelSnappedIntRect(additionalOffset, size()));
3865
3866    if (!hasOverflowClip() && !hasControlClip()) {
3867        if (childrenInline())
3868            addFocusRingRectsForInlineChildren(rects, additionalOffset, paintContainer);
3869
3870        for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
3871            if (!curr->isText() && !curr->isListMarker() && curr->isBox()) {
3872                RenderBox* box = toRenderBox(curr);
3873                FloatPoint pos;
3874                // FIXME: This doesn't work correctly with transforms.
3875                if (box->layer())
3876                    pos = curr->localToContainerPoint(FloatPoint(), paintContainer);
3877                else
3878                    pos = FloatPoint(additionalOffset.x() + box->x(), additionalOffset.y() + box->y());
3879                box->addFocusRingRects(rects, flooredLayoutPoint(pos), paintContainer);
3880            }
3881        }
3882    }
3883
3884    if (inlineElementContinuation())
3885        inlineElementContinuation()->addFocusRingRects(rects, flooredLayoutPoint(LayoutPoint(additionalOffset + inlineElementContinuation()->containingBlock()->location() - location())), paintContainer);
3886}
3887
3888RenderBox* RenderBlock::createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const
3889{
3890    return createAnonymousWithParentRendererAndDisplay(parent, style().display());
3891}
3892
3893LayoutUnit RenderBlock::offsetFromLogicalTopOfFirstPage() const
3894{
3895    LayoutState* layoutState = view().layoutState();
3896    if (layoutState && !layoutState->isPaginated())
3897        return 0;
3898
3899    RenderFlowThread* flowThread = flowThreadContainingBlock();
3900    if (flowThread)
3901        return flowThread->offsetFromLogicalTopOfFirstRegion(this);
3902
3903    if (layoutState) {
3904        ASSERT(layoutState->m_renderer == this);
3905
3906        LayoutSize offsetDelta = layoutState->m_layoutOffset - layoutState->m_pageOffset;
3907        return isHorizontalWritingMode() ? offsetDelta.height() : offsetDelta.width();
3908    }
3909
3910    ASSERT_NOT_REACHED();
3911    return 0;
3912}
3913
3914RenderRegion* RenderBlock::regionAtBlockOffset(LayoutUnit blockOffset) const
3915{
3916    RenderFlowThread* flowThread = flowThreadContainingBlock();
3917    if (!flowThread || !flowThread->hasValidRegionInfo())
3918        return 0;
3919
3920    return flowThread->regionAtBlockOffset(this, offsetFromLogicalTopOfFirstPage() + blockOffset, true);
3921}
3922
3923static bool canComputeRegionRangeForBox(const RenderBlock* parentBlock, const RenderBox& childBox, const RenderFlowThread* flowThreadContainingBlock)
3924{
3925    ASSERT(parentBlock);
3926    ASSERT(!childBox.isRenderFlowThread());
3927
3928    if (!flowThreadContainingBlock)
3929        return false;
3930
3931    if (!flowThreadContainingBlock->hasRegions())
3932        return false;
3933
3934    if (!childBox.canHaveOutsideRegionRange())
3935        return false;
3936
3937    return flowThreadContainingBlock->hasCachedRegionRangeForBox(parentBlock);
3938}
3939
3940bool RenderBlock::childBoxIsUnsplittableForFragmentation(const RenderBox& child) const
3941{
3942    RenderFlowThread* flowThread = flowThreadContainingBlock();
3943    bool checkColumnBreaks = flowThread && flowThread->shouldCheckColumnBreaks();
3944    bool checkPageBreaks = !checkColumnBreaks && view().layoutState()->m_pageLogicalHeight;
3945    bool checkRegionBreaks = flowThread && flowThread->isRenderNamedFlowThread();
3946    return child.isUnsplittableForPagination() || (checkColumnBreaks && child.style().columnBreakInside() == PBAVOID)
3947        || (checkPageBreaks && child.style().pageBreakInside() == PBAVOID)
3948        || (checkRegionBreaks && child.style().regionBreakInside() == PBAVOID);
3949}
3950
3951void RenderBlock::computeRegionRangeForBoxChild(const RenderBox& box) const
3952{
3953    RenderFlowThread* flowThread = flowThreadContainingBlock();
3954    ASSERT(canComputeRegionRangeForBox(this, box, flowThread));
3955
3956    RenderRegion* startRegion;
3957    RenderRegion* endRegion;
3958    LayoutUnit offsetFromLogicalTopOfFirstRegion = box.offsetFromLogicalTopOfFirstPage();
3959    if (childBoxIsUnsplittableForFragmentation(box))
3960        startRegion = endRegion = flowThread->regionAtBlockOffset(this, offsetFromLogicalTopOfFirstRegion, true);
3961    else {
3962        startRegion = flowThread->regionAtBlockOffset(this, offsetFromLogicalTopOfFirstRegion, true);
3963        endRegion = flowThread->regionAtBlockOffset(this, offsetFromLogicalTopOfFirstRegion + logicalHeightForChild(box), true);
3964    }
3965
3966    flowThread->setRegionRangeForBox(&box, startRegion, endRegion);
3967}
3968
3969void RenderBlock::estimateRegionRangeForBoxChild(const RenderBox& box) const
3970{
3971    RenderFlowThread* flowThread = flowThreadContainingBlock();
3972    if (!canComputeRegionRangeForBox(this, box, flowThread))
3973        return;
3974
3975    if (childBoxIsUnsplittableForFragmentation(box)) {
3976        computeRegionRangeForBoxChild(box);
3977        return;
3978    }
3979
3980    LogicalExtentComputedValues estimatedValues;
3981    box.computeLogicalHeight(RenderFlowThread::maxLogicalHeight(), logicalTopForChild(box), estimatedValues);
3982
3983    LayoutUnit offsetFromLogicalTopOfFirstRegion = box.offsetFromLogicalTopOfFirstPage();
3984    RenderRegion* startRegion = flowThread->regionAtBlockOffset(this, offsetFromLogicalTopOfFirstRegion, true);
3985    RenderRegion* endRegion = flowThread->regionAtBlockOffset(this, offsetFromLogicalTopOfFirstRegion + estimatedValues.m_extent, true);
3986
3987    flowThread->setRegionRangeForBox(&box, startRegion, endRegion);
3988}
3989
3990bool RenderBlock::updateRegionRangeForBoxChild(const RenderBox& box) const
3991{
3992    RenderFlowThread* flowThread = flowThreadContainingBlock();
3993    if (!canComputeRegionRangeForBox(this, box, flowThread))
3994        return false;
3995
3996    RenderRegion* startRegion = nullptr;
3997    RenderRegion* endRegion = nullptr;
3998    flowThread->getRegionRangeForBox(&box, startRegion, endRegion);
3999
4000    computeRegionRangeForBoxChild(box);
4001
4002    RenderRegion* newStartRegion = nullptr;
4003    RenderRegion* newEndRegion = nullptr;
4004    flowThread->getRegionRangeForBox(&box, newStartRegion, newEndRegion);
4005
4006
4007    // Changing the start region means we shift everything and a relayout is needed.
4008    if (newStartRegion != startRegion)
4009        return true;
4010
4011    // The region range of the box has changed. Some boxes (e.g floats) may have been positioned assuming
4012    // a different range.
4013    if (box.needsLayoutAfterRegionRangeChange() && newEndRegion != endRegion)
4014        return true;
4015
4016    return false;
4017}
4018
4019LayoutUnit RenderBlock::collapsedMarginBeforeForChild(const RenderBox& child) const
4020{
4021    // If the child has the same directionality as we do, then we can just return its
4022    // collapsed margin.
4023    if (!child.isWritingModeRoot())
4024        return child.collapsedMarginBefore();
4025
4026    // The child has a different directionality.  If the child is parallel, then it's just
4027    // flipped relative to us.  We can use the collapsed margin for the opposite edge.
4028    if (child.isHorizontalWritingMode() == isHorizontalWritingMode())
4029        return child.collapsedMarginAfter();
4030
4031    // The child is perpendicular to us, which means its margins don't collapse but are on the
4032    // "logical left/right" sides of the child box.  We can just return the raw margin in this case.
4033    return marginBeforeForChild(child);
4034}
4035
4036LayoutUnit RenderBlock::collapsedMarginAfterForChild(const RenderBox& child) const
4037{
4038    // If the child has the same directionality as we do, then we can just return its
4039    // collapsed margin.
4040    if (!child.isWritingModeRoot())
4041        return child.collapsedMarginAfter();
4042
4043    // The child has a different directionality.  If the child is parallel, then it's just
4044    // flipped relative to us.  We can use the collapsed margin for the opposite edge.
4045    if (child.isHorizontalWritingMode() == isHorizontalWritingMode())
4046        return child.collapsedMarginBefore();
4047
4048    // The child is perpendicular to us, which means its margins don't collapse but are on the
4049    // "logical left/right" side of the child box.  We can just return the raw margin in this case.
4050    return marginAfterForChild(child);
4051}
4052
4053bool RenderBlock::hasMarginBeforeQuirk(const RenderBox& child) const
4054{
4055    // If the child has the same directionality as we do, then we can just return its
4056    // margin quirk.
4057    if (!child.isWritingModeRoot())
4058        return child.isRenderBlock() ? toRenderBlock(child).hasMarginBeforeQuirk() : child.style().hasMarginBeforeQuirk();
4059
4060    // The child has a different directionality. If the child is parallel, then it's just
4061    // flipped relative to us. We can use the opposite edge.
4062    if (child.isHorizontalWritingMode() == isHorizontalWritingMode())
4063        return child.isRenderBlock() ? toRenderBlock(child).hasMarginAfterQuirk() : child.style().hasMarginAfterQuirk();
4064
4065    // The child is perpendicular to us and box sides are never quirky in html.css, and we don't really care about
4066    // whether or not authors specified quirky ems, since they're an implementation detail.
4067    return false;
4068}
4069
4070bool RenderBlock::hasMarginAfterQuirk(const RenderBox& child) const
4071{
4072    // If the child has the same directionality as we do, then we can just return its
4073    // margin quirk.
4074    if (!child.isWritingModeRoot())
4075        return child.isRenderBlock() ? toRenderBlock(child).hasMarginAfterQuirk() : child.style().hasMarginAfterQuirk();
4076
4077    // The child has a different directionality. If the child is parallel, then it's just
4078    // flipped relative to us. We can use the opposite edge.
4079    if (child.isHorizontalWritingMode() == isHorizontalWritingMode())
4080        return child.isRenderBlock() ? toRenderBlock(child).hasMarginBeforeQuirk() : child.style().hasMarginBeforeQuirk();
4081
4082    // The child is perpendicular to us and box sides are never quirky in html.css, and we don't really care about
4083    // whether or not authors specified quirky ems, since they're an implementation detail.
4084    return false;
4085}
4086
4087const char* RenderBlock::renderName() const
4088{
4089    if (isBody())
4090        return "RenderBody"; // FIXME: Temporary hack until we know that the regression tests pass.
4091
4092    if (isFloating())
4093        return "RenderBlock (floating)";
4094    if (isOutOfFlowPositioned())
4095        return "RenderBlock (positioned)";
4096    if (isAnonymousBlock())
4097        return "RenderBlock (anonymous)";
4098    // FIXME: Temporary hack while the new generated content system is being implemented.
4099    if (isPseudoElement())
4100        return "RenderBlock (generated)";
4101    if (isAnonymous())
4102        return "RenderBlock (generated)";
4103    if (isRelPositioned())
4104        return "RenderBlock (relative positioned)";
4105    if (isStickyPositioned())
4106        return "RenderBlock (sticky positioned)";
4107    return "RenderBlock";
4108}
4109
4110template <typename CharacterType>
4111static inline TextRun constructTextRunInternal(RenderObject* context, const Font& font, const CharacterType* characters, int length, const RenderStyle& style, TextRun::ExpansionBehavior expansion)
4112{
4113    TextDirection textDirection = LTR;
4114    bool directionalOverride = style.rtlOrdering() == VisualOrder;
4115
4116    TextRun run(characters, length, 0, 0, expansion, textDirection, directionalOverride);
4117    if (font.primaryFont()->isSVGFont()) {
4118        ASSERT(context); // FIXME: Thread a RenderObject& to this point so we don't have to dereference anything.
4119        run.setRenderingContext(SVGTextRunRenderingContext::create(*context));
4120    }
4121
4122    return run;
4123}
4124
4125template <typename CharacterType>
4126static inline TextRun constructTextRunInternal(RenderObject* context, const Font& font, const CharacterType* characters, int length, const RenderStyle& style, TextRun::ExpansionBehavior expansion, TextRunFlags flags)
4127{
4128    TextDirection textDirection = LTR;
4129    bool directionalOverride = style.rtlOrdering() == VisualOrder;
4130    if (flags != DefaultTextRunFlags) {
4131        if (flags & RespectDirection)
4132            textDirection = style.direction();
4133        if (flags & RespectDirectionOverride)
4134            directionalOverride |= isOverride(style.unicodeBidi());
4135    }
4136    TextRun run(characters, length, 0, 0, expansion, textDirection, directionalOverride);
4137    if (font.primaryFont()->isSVGFont()) {
4138        ASSERT(context); // FIXME: Thread a RenderObject& to this point so we don't have to dereference anything.
4139        run.setRenderingContext(SVGTextRunRenderingContext::create(*context));
4140    }
4141
4142    return run;
4143}
4144
4145TextRun RenderBlock::constructTextRun(RenderObject* context, const Font& font, const LChar* characters, int length, const RenderStyle& style, TextRun::ExpansionBehavior expansion)
4146{
4147    return constructTextRunInternal(context, font, characters, length, style, expansion);
4148}
4149
4150TextRun RenderBlock::constructTextRun(RenderObject* context, const Font& font, const UChar* characters, int length, const RenderStyle& style, TextRun::ExpansionBehavior expansion)
4151{
4152    return constructTextRunInternal(context, font, characters, length, style, expansion);
4153}
4154
4155TextRun RenderBlock::constructTextRun(RenderObject* context, const Font& font, const RenderText* text, const RenderStyle& style, TextRun::ExpansionBehavior expansion)
4156{
4157    if (text->is8Bit())
4158        return constructTextRunInternal(context, font, text->characters8(), text->textLength(), style, expansion);
4159    return constructTextRunInternal(context, font, text->characters16(), text->textLength(), style, expansion);
4160}
4161
4162TextRun RenderBlock::constructTextRun(RenderObject* context, const Font& font, const RenderText* text, unsigned offset, unsigned length, const RenderStyle& style, TextRun::ExpansionBehavior expansion)
4163{
4164    ASSERT(offset + length <= text->textLength());
4165    if (text->is8Bit())
4166        return constructTextRunInternal(context, font, text->characters8() + offset, length, style, expansion);
4167    return constructTextRunInternal(context, font, text->characters16() + offset, length, style, expansion);
4168}
4169
4170TextRun RenderBlock::constructTextRun(RenderObject* context, const Font& font, const String& string, const RenderStyle& style, TextRun::ExpansionBehavior expansion, TextRunFlags flags)
4171{
4172    unsigned length = string.length();
4173
4174    if (!length || string.is8Bit())
4175        return constructTextRunInternal(context, font, string.characters8(), length, style, expansion, flags);
4176    return constructTextRunInternal(context, font, string.characters16(), length, style, expansion, flags);
4177}
4178
4179RenderBlock* RenderBlock::createAnonymousWithParentRendererAndDisplay(const RenderObject* parent, EDisplay display)
4180{
4181    // FIXME: Do we need to convert all our inline displays to block-type in the anonymous logic ?
4182    RenderBlock* newBox;
4183    if (display == FLEX || display == INLINE_FLEX)
4184        newBox = new RenderFlexibleBox(parent->document(), RenderStyle::createAnonymousStyleWithDisplay(&parent->style(), FLEX));
4185    else
4186        newBox = new RenderBlockFlow(parent->document(), RenderStyle::createAnonymousStyleWithDisplay(&parent->style(), BLOCK));
4187
4188    newBox->initializeStyle();
4189    return newBox;
4190}
4191
4192#ifndef NDEBUG
4193void RenderBlock::checkPositionedObjectsNeedLayout()
4194{
4195    if (!gPositionedDescendantsMap)
4196        return;
4197
4198    TrackedRendererListHashSet* positionedDescendantSet = positionedObjects();
4199    if (!positionedDescendantSet)
4200        return;
4201
4202    for (auto it = positionedDescendantSet->begin(), end = positionedDescendantSet->end(); it != end; ++it) {
4203        RenderBox* currBox = *it;
4204        ASSERT(!currBox->needsLayout());
4205    }
4206}
4207
4208void RenderBlock::showLineTreeAndMark(const InlineBox*, const char*, const InlineBox*, const char*, const RenderObject*) const
4209{
4210    showRenderObject();
4211}
4212
4213#endif
4214
4215} // namespace WebCore
4216