1/*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4 *           (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
5 *           (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com)
6 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights reserved.
7 * Copyright (C) 2010, 2012 Google Inc. All rights reserved.
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * Library General Public License for more details.
18 *
19 * You should have received a copy of the GNU Library General Public License
20 * along with this library; see the file COPYING.LIB.  If not, write to
21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
23 */
24
25#include "config.h"
26#include "RenderElement.h"
27
28#include "AXObjectCache.h"
29#include "ContentData.h"
30#include "ControlStates.h"
31#include "CursorList.h"
32#include "EventHandler.h"
33#include "Frame.h"
34#include "FrameSelection.h"
35#include "HTMLElement.h"
36#include "HTMLNames.h"
37#include "FlowThreadController.h"
38#include "RenderCounter.h"
39#include "RenderDeprecatedFlexibleBox.h"
40#include "RenderFlexibleBox.h"
41#include "RenderImage.h"
42#include "RenderImageResourceStyleImage.h"
43#include "RenderIterator.h"
44#include "RenderLayer.h"
45#include "RenderLayerCompositor.h"
46#include "RenderLineBreak.h"
47#include "RenderListItem.h"
48#include "RenderNamedFlowThread.h"
49#include "RenderRegion.h"
50#include "RenderRuby.h"
51#include "RenderRubyText.h"
52#include "RenderTableCaption.h"
53#include "RenderTableCell.h"
54#include "RenderTableCol.h"
55#include "RenderTableRow.h"
56#include "RenderText.h"
57#include "RenderTheme.h"
58#include "RenderView.h"
59#include "SVGRenderSupport.h"
60#include "Settings.h"
61#include "StyleResolver.h"
62#include <wtf/MathExtras.h>
63#include <wtf/StackStats.h>
64
65#if ENABLE(CSS_GRID_LAYOUT)
66#include "RenderGrid.h"
67#endif
68
69namespace WebCore {
70
71bool RenderElement::s_affectsParentBlock = false;
72bool RenderElement::s_noLongerAffectsParentBlock = false;
73
74static HashMap<const RenderObject*, ControlStates*>& controlStatesRendererMap()
75{
76    static NeverDestroyed<HashMap<const RenderObject*, ControlStates*>> map;
77    return map;
78}
79
80inline RenderElement::RenderElement(ContainerNode& elementOrDocument, PassRef<RenderStyle> style, unsigned baseTypeFlags)
81    : RenderObject(elementOrDocument)
82    , m_baseTypeFlags(baseTypeFlags)
83    , m_ancestorLineBoxDirty(false)
84    , m_hasInitializedStyle(false)
85    , m_renderInlineAlwaysCreatesLineBoxes(false)
86    , m_renderBoxNeedsLazyRepaint(false)
87    , m_hasPausedImageAnimations(false)
88    , m_firstChild(nullptr)
89    , m_lastChild(nullptr)
90    , m_style(WTF::move(style))
91{
92}
93
94RenderElement::RenderElement(Element& element, PassRef<RenderStyle> style, unsigned baseTypeFlags)
95    : RenderElement(static_cast<ContainerNode&>(element), WTF::move(style), baseTypeFlags)
96{
97}
98
99RenderElement::RenderElement(Document& document, PassRef<RenderStyle> style, unsigned baseTypeFlags)
100    : RenderElement(static_cast<ContainerNode&>(document), WTF::move(style), baseTypeFlags)
101{
102}
103
104RenderElement::~RenderElement()
105{
106    if (hasInitializedStyle()) {
107        for (const FillLayer* bgLayer = m_style->backgroundLayers(); bgLayer; bgLayer = bgLayer->next()) {
108            if (StyleImage* backgroundImage = bgLayer->image())
109                backgroundImage->removeClient(this);
110        }
111
112        for (const FillLayer* maskLayer = m_style->maskLayers(); maskLayer; maskLayer = maskLayer->next()) {
113            if (StyleImage* maskImage = maskLayer->image())
114                maskImage->removeClient(this);
115        }
116
117        if (StyleImage* borderImage = m_style->borderImage().image())
118            borderImage->removeClient(this);
119
120        if (StyleImage* maskBoxImage = m_style->maskBoxImage().image())
121            maskBoxImage->removeClient(this);
122
123#if ENABLE(CSS_SHAPES)
124        if (auto shapeValue = m_style->shapeOutside()) {
125            if (auto shapeImage = shapeValue->image())
126                shapeImage->removeClient(this);
127        }
128#endif
129    }
130    if (m_hasPausedImageAnimations)
131        view().removeRendererWithPausedImageAnimations(*this);
132}
133
134RenderPtr<RenderElement> RenderElement::createFor(Element& element, PassRef<RenderStyle> style)
135{
136    // Minimal support for content properties replacing an entire element.
137    // Works only if we have exactly one piece of content and it's a URL.
138    // Otherwise acts as if we didn't support this feature.
139    const ContentData* contentData = style.get().contentData();
140    if (contentData && !contentData->next() && contentData->isImage() && !element.isPseudoElement()) {
141        auto& styleImage = toImageContentData(contentData)->image();
142        auto image = createRenderer<RenderImage>(element, WTF::move(style), const_cast<StyleImage*>(&styleImage));
143        image->setIsGeneratedContent();
144        return WTF::move(image);
145    }
146
147    if (element.hasTagName(HTMLNames::rubyTag)) {
148        if (style.get().display() == INLINE)
149            return createRenderer<RenderRubyAsInline>(element, WTF::move(style));
150        if (style.get().display() == BLOCK)
151            return createRenderer<RenderRubyAsBlock>(element, WTF::move(style));
152    }
153    // treat <rt> as ruby text ONLY if it still has its default treatment of block
154    if (element.hasTagName(HTMLNames::rtTag) && style.get().display() == BLOCK)
155        return createRenderer<RenderRubyText>(element, WTF::move(style));
156    switch (style.get().display()) {
157    case NONE:
158        style.dropRef();
159        return nullptr;
160    case INLINE:
161        return createRenderer<RenderInline>(element, WTF::move(style));
162    case BLOCK:
163    case INLINE_BLOCK:
164    case COMPACT:
165        return createRenderer<RenderBlockFlow>(element, WTF::move(style));
166    case LIST_ITEM:
167        return createRenderer<RenderListItem>(element, WTF::move(style));
168    case TABLE:
169    case INLINE_TABLE:
170        return createRenderer<RenderTable>(element, WTF::move(style));
171    case TABLE_ROW_GROUP:
172    case TABLE_HEADER_GROUP:
173    case TABLE_FOOTER_GROUP:
174        return createRenderer<RenderTableSection>(element, WTF::move(style));
175    case TABLE_ROW:
176        return createRenderer<RenderTableRow>(element, WTF::move(style));
177    case TABLE_COLUMN_GROUP:
178    case TABLE_COLUMN:
179        return createRenderer<RenderTableCol>(element, WTF::move(style));
180    case TABLE_CELL:
181        return createRenderer<RenderTableCell>(element, WTF::move(style));
182    case TABLE_CAPTION:
183        return createRenderer<RenderTableCaption>(element, WTF::move(style));
184    case BOX:
185    case INLINE_BOX:
186        return createRenderer<RenderDeprecatedFlexibleBox>(element, WTF::move(style));
187    case FLEX:
188    case INLINE_FLEX:
189        return createRenderer<RenderFlexibleBox>(element, WTF::move(style));
190#if ENABLE(CSS_GRID_LAYOUT)
191    case GRID:
192    case INLINE_GRID:
193        return createRenderer<RenderGrid>(element, WTF::move(style));
194#endif
195    }
196    ASSERT_NOT_REACHED();
197    return nullptr;
198}
199
200enum StyleCacheState {
201    Cached,
202    Uncached
203};
204
205static PassRefPtr<RenderStyle> firstLineStyleForCachedUncachedType(StyleCacheState type, const RenderElement& renderer, RenderStyle* style)
206{
207    RenderElement& rendererForFirstLineStyle = renderer.isBeforeOrAfterContent() ? *renderer.parent() : const_cast<RenderElement&>(renderer);
208
209    if (rendererForFirstLineStyle.isRenderBlockFlow() || rendererForFirstLineStyle.isRenderButton()) {
210        if (RenderBlock* firstLineBlock = rendererForFirstLineStyle.firstLineBlock()) {
211            if (type == Cached)
212                return firstLineBlock->getCachedPseudoStyle(FIRST_LINE, style);
213            return firstLineBlock->getUncachedPseudoStyle(PseudoStyleRequest(FIRST_LINE), style, firstLineBlock == &renderer ? style : nullptr);
214        }
215    } else if (!rendererForFirstLineStyle.isAnonymous() && rendererForFirstLineStyle.isRenderInline()) {
216        RenderStyle& parentStyle = rendererForFirstLineStyle.parent()->firstLineStyle();
217        if (&parentStyle != &rendererForFirstLineStyle.parent()->style()) {
218            if (type == Cached) {
219                // A first-line style is in effect. Cache a first-line style for ourselves.
220                rendererForFirstLineStyle.style().setHasPseudoStyle(FIRST_LINE_INHERITED);
221                return rendererForFirstLineStyle.getCachedPseudoStyle(FIRST_LINE_INHERITED, &parentStyle);
222            }
223            return rendererForFirstLineStyle.getUncachedPseudoStyle(PseudoStyleRequest(FIRST_LINE_INHERITED), &parentStyle, style);
224        }
225    }
226    return nullptr;
227}
228
229PassRefPtr<RenderStyle> RenderElement::uncachedFirstLineStyle(RenderStyle* style) const
230{
231    if (!document().styleSheetCollection().usesFirstLineRules())
232        return nullptr;
233
234    return firstLineStyleForCachedUncachedType(Uncached, *this, style);
235}
236
237RenderStyle* RenderElement::cachedFirstLineStyle() const
238{
239    ASSERT(document().styleSheetCollection().usesFirstLineRules());
240
241    RenderStyle& style = this->style();
242    if (RefPtr<RenderStyle> firstLineStyle = firstLineStyleForCachedUncachedType(Cached, *this, &style))
243        return firstLineStyle.get();
244
245    return &style;
246}
247
248StyleDifference RenderElement::adjustStyleDifference(StyleDifference diff, unsigned contextSensitiveProperties) const
249{
250    // If transform changed, and we are not composited, need to do a layout.
251    if (contextSensitiveProperties & ContextSensitivePropertyTransform) {
252        // Text nodes share style with their parents but transforms don't apply to them,
253        // hence the !isText() check.
254        // FIXME: when transforms are taken into account for overflow, we will need to do a layout.
255        if (!hasLayer() || !toRenderLayerModelObject(this)->layer()->isComposited()) {
256            // We need to set at least SimplifiedLayout, but if PositionedMovementOnly is already set
257            // then we actually need SimplifiedLayoutAndPositionedMovement.
258            if (!hasLayer())
259                diff = StyleDifferenceLayout; // FIXME: Do this for now since SimplifiedLayout cannot handle updating floating objects lists.
260            else if (diff < StyleDifferenceLayoutPositionedMovementOnly)
261                diff = StyleDifferenceSimplifiedLayout;
262            else if (diff < StyleDifferenceSimplifiedLayout)
263                diff = StyleDifferenceSimplifiedLayoutAndPositionedMovement;
264        } else if (diff < StyleDifferenceRecompositeLayer)
265            diff = StyleDifferenceRecompositeLayer;
266    }
267
268    // If opacity changed, and we are not composited, need to repaint (also
269    // ignoring text nodes)
270    if (contextSensitiveProperties & ContextSensitivePropertyOpacity) {
271        if (!hasLayer() || !toRenderLayerModelObject(this)->layer()->isComposited())
272            diff = StyleDifferenceRepaintLayer;
273        else if (diff < StyleDifferenceRecompositeLayer)
274            diff = StyleDifferenceRecompositeLayer;
275    }
276
277#if ENABLE(CSS_FILTERS)
278    if ((contextSensitiveProperties & ContextSensitivePropertyFilter) && hasLayer()) {
279        RenderLayer* layer = toRenderLayerModelObject(this)->layer();
280        if (!layer->isComposited() || layer->paintsWithFilters())
281            diff = StyleDifferenceRepaintLayer;
282        else if (diff < StyleDifferenceRecompositeLayer)
283            diff = StyleDifferenceRecompositeLayer;
284    }
285#endif
286
287    // The answer to requiresLayer() for plugins, iframes, and canvas can change without the actual
288    // style changing, since it depends on whether we decide to composite these elements. When the
289    // layer status of one of these elements changes, we need to force a layout.
290    if (diff == StyleDifferenceEqual && isRenderLayerModelObject()) {
291        if (hasLayer() != toRenderLayerModelObject(this)->requiresLayer())
292            diff = StyleDifferenceLayout;
293    }
294
295    // If we have no layer(), just treat a RepaintLayer hint as a normal Repaint.
296    if (diff == StyleDifferenceRepaintLayer && !hasLayer())
297        diff = StyleDifferenceRepaint;
298
299    return diff;
300}
301
302inline bool RenderElement::hasImmediateNonWhitespaceTextChildOrBorderOrOutline() const
303{
304    for (auto& child : childrenOfType<RenderObject>(*this)) {
305        if (child.isText() && !toRenderText(child).isAllCollapsibleWhitespace())
306            return true;
307        if (child.style().hasOutline() || child.style().hasBorder())
308            return true;
309    }
310    return false;
311}
312
313inline bool RenderElement::shouldRepaintForStyleDifference(StyleDifference diff) const
314{
315    return diff == StyleDifferenceRepaint || (diff == StyleDifferenceRepaintIfTextOrBorderOrOutline && hasImmediateNonWhitespaceTextChildOrBorderOrOutline());
316}
317
318void RenderElement::updateFillImages(const FillLayer* oldLayers, const FillLayer* newLayers)
319{
320    // Optimize the common case
321    if (oldLayers && !oldLayers->next() && newLayers && !newLayers->next() && (oldLayers->image() == newLayers->image()))
322        return;
323
324    // Go through the new layers and addClients first, to avoid removing all clients of an image.
325    for (const FillLayer* currNew = newLayers; currNew; currNew = currNew->next()) {
326        if (currNew->image())
327            currNew->image()->addClient(this);
328    }
329
330    for (const FillLayer* currOld = oldLayers; currOld; currOld = currOld->next()) {
331        if (currOld->image())
332            currOld->image()->removeClient(this);
333    }
334}
335
336void RenderElement::updateImage(StyleImage* oldImage, StyleImage* newImage)
337{
338    if (oldImage == newImage)
339        return;
340    if (oldImage)
341        oldImage->removeClient(this);
342    if (newImage)
343        newImage->addClient(this);
344}
345
346#if ENABLE(CSS_SHAPES)
347void RenderElement::updateShapeImage(const ShapeValue* oldShapeValue, const ShapeValue* newShapeValue)
348{
349    if (oldShapeValue || newShapeValue)
350        updateImage(oldShapeValue ? oldShapeValue->image() : nullptr, newShapeValue ? newShapeValue->image() : nullptr);
351}
352#endif
353
354void RenderElement::initializeStyle()
355{
356    styleWillChange(StyleDifferenceEqual, style());
357
358    m_hasInitializedStyle = true;
359
360    updateFillImages(nullptr, m_style->backgroundLayers());
361    updateFillImages(nullptr, m_style->maskLayers());
362
363    updateImage(nullptr, m_style->borderImage().image());
364    updateImage(nullptr, m_style->maskBoxImage().image());
365
366#if ENABLE(CSS_SHAPES)
367    updateShapeImage(nullptr, m_style->shapeOutside());
368#endif
369
370    // We need to ensure that view->maximalOutlineSize() is valid for any repaints that happen
371    // during styleDidChange (it's used by clippedOverflowRectForRepaint()).
372    if (m_style->outlineWidth() > 0 && m_style->outlineSize() > maximalOutlineSize(PaintPhaseOutline))
373        view().setMaximalOutlineSize(std::max(theme().platformFocusRingMaxWidth(), static_cast<int>(m_style->outlineSize())));
374
375    styleDidChange(StyleDifferenceEqual, nullptr);
376
377    // We shouldn't have any text children that would need styleDidChange at this point.
378    ASSERT(!childrenOfType<RenderText>(*this).first());
379
380    // It would be nice to assert that !parent() here, but some RenderLayer subrenderers
381    // have their parent set before getting a call to initializeStyle() :|
382}
383
384void RenderElement::setStyle(PassRef<RenderStyle> style)
385{
386    // FIXME: Should change RenderView so it can use initializeStyle too.
387    // If we do that, we can assert m_hasInitializedStyle unconditionally,
388    // and remove the check of m_hasInitializedStyle below too.
389    ASSERT(m_hasInitializedStyle || isRenderView());
390
391    if (&m_style.get() == &style.get()) {
392        // FIXME: Can we change things so we never hit this code path?
393        // We need to run through adjustStyleDifference() for iframes, plugins, and canvas so
394        // style sharing is disabled for them. That should ensure that we never hit this code path.
395        ASSERT(!isRenderIFrame());
396        ASSERT(!isEmbeddedObject());
397        ASSERT(!isCanvas());
398        style.dropRef();
399        return;
400    }
401
402    StyleDifference diff = StyleDifferenceEqual;
403    unsigned contextSensitiveProperties = ContextSensitivePropertyNone;
404    if (m_hasInitializedStyle)
405        diff = m_style->diff(&style.get(), contextSensitiveProperties);
406
407    diff = adjustStyleDifference(diff, contextSensitiveProperties);
408
409    styleWillChange(diff, style.get());
410
411    Ref<RenderStyle> oldStyle(m_style.replace(WTF::move(style)));
412
413    updateFillImages(oldStyle.get().backgroundLayers(), m_style->backgroundLayers());
414    updateFillImages(oldStyle.get().maskLayers(), m_style->maskLayers());
415
416    updateImage(oldStyle.get().borderImage().image(), m_style->borderImage().image());
417    updateImage(oldStyle.get().maskBoxImage().image(), m_style->maskBoxImage().image());
418
419#if ENABLE(CSS_SHAPES)
420    updateShapeImage(oldStyle.get().shapeOutside(), m_style->shapeOutside());
421#endif
422
423    // We need to ensure that view->maximalOutlineSize() is valid for any repaints that happen
424    // during styleDidChange (it's used by clippedOverflowRectForRepaint()).
425    if (m_style->outlineWidth() > 0 && m_style->outlineSize() > maximalOutlineSize(PaintPhaseOutline))
426        view().setMaximalOutlineSize(std::max(theme().platformFocusRingMaxWidth(), static_cast<int>(m_style->outlineSize())));
427
428    bool doesNotNeedLayout = !parent();
429
430    styleDidChange(diff, &oldStyle.get());
431
432    // Text renderers use their parent style. Notify them about the change.
433    for (auto& child : childrenOfType<RenderText>(*this))
434        child.styleDidChange(diff, &oldStyle.get());
435
436    // FIXME: |this| might be destroyed here. This can currently happen for a RenderTextFragment when
437    // its first-letter block gets an update in RenderTextFragment::styleDidChange. For RenderTextFragment(s),
438    // we will safely bail out with the doesNotNeedLayout flag. We might want to broaden this condition
439    // in the future as we move renderer changes out of layout and into style changes.
440    if (doesNotNeedLayout)
441        return;
442
443    // Now that the layer (if any) has been updated, we need to adjust the diff again,
444    // check whether we should layout now, and decide if we need to repaint.
445    StyleDifference updatedDiff = adjustStyleDifference(diff, contextSensitiveProperties);
446
447    if (diff <= StyleDifferenceLayoutPositionedMovementOnly) {
448        if (updatedDiff == StyleDifferenceLayout)
449            setNeedsLayoutAndPrefWidthsRecalc();
450        else if (updatedDiff == StyleDifferenceLayoutPositionedMovementOnly)
451            setNeedsPositionedMovementLayout(&oldStyle.get());
452        else if (updatedDiff == StyleDifferenceSimplifiedLayoutAndPositionedMovement) {
453            setNeedsPositionedMovementLayout(&oldStyle.get());
454            setNeedsSimplifiedNormalFlowLayout();
455        } else if (updatedDiff == StyleDifferenceSimplifiedLayout)
456            setNeedsSimplifiedNormalFlowLayout();
457    }
458
459    if (updatedDiff == StyleDifferenceRepaintLayer || shouldRepaintForStyleDifference(updatedDiff)) {
460        // Do a repaint with the new style now, e.g., for example if we go from
461        // not having an outline to having an outline.
462        repaint();
463    }
464}
465
466void RenderElement::addChild(RenderObject* newChild, RenderObject* beforeChild)
467{
468    bool needsTable = false;
469
470    if (newChild->isRenderTableCol()) {
471        RenderTableCol* newTableColumn = toRenderTableCol(newChild);
472        bool isColumnInColumnGroup = newTableColumn->isTableColumn() && isRenderTableCol();
473        needsTable = !isTable() && !isColumnInColumnGroup;
474    } else if (newChild->isTableCaption())
475        needsTable = !isTable();
476    else if (newChild->isTableSection())
477        needsTable = !isTable();
478    else if (newChild->isTableRow())
479        needsTable = !isTableSection();
480    else if (newChild->isTableCell())
481        needsTable = !isTableRow();
482
483    if (needsTable) {
484        RenderTable* table;
485        RenderObject* afterChild = beforeChild ? beforeChild->previousSibling() : m_lastChild;
486        if (afterChild && afterChild->isAnonymous() && afterChild->isTable() && !afterChild->isBeforeContent())
487            table = toRenderTable(afterChild);
488        else {
489            table = RenderTable::createAnonymousWithParentRenderer(this);
490            addChild(table, beforeChild);
491        }
492        table->addChild(newChild);
493    } else
494        insertChildInternal(newChild, beforeChild, NotifyChildren);
495
496    if (newChild->isText())
497        toRenderText(newChild)->styleDidChange(StyleDifferenceEqual, nullptr);
498
499    // SVG creates renderers for <g display="none">, as SVG requires children of hidden
500    // <g>s to have renderers - at least that's how our implementation works. Consider:
501    // <g display="none"><foreignObject><body style="position: relative">FOO...
502    // - requiresLayer() would return true for the <body>, creating a new RenderLayer
503    // - when the document is painted, both layers are painted. The <body> layer doesn't
504    //   know that it's inside a "hidden SVG subtree", and thus paints, even if it shouldn't.
505    // To avoid the problem alltogether, detect early if we're inside a hidden SVG subtree
506    // and stop creating layers at all for these cases - they're not used anyways.
507    if (newChild->hasLayer() && !layerCreationAllowedForSubtree())
508        toRenderLayerModelObject(newChild)->layer()->removeOnlyThisLayer();
509
510    SVGRenderSupport::childAdded(*this, *newChild);
511}
512
513RenderObject* RenderElement::removeChild(RenderObject& oldChild)
514{
515    return removeChildInternal(oldChild, NotifyChildren);
516}
517
518void RenderElement::destroyLeftoverChildren()
519{
520    while (m_firstChild) {
521        if (m_firstChild->isListMarker() || (m_firstChild->style().styleType() == FIRST_LETTER && !m_firstChild->isText())) {
522            m_firstChild->removeFromParent(); // List markers are owned by their enclosing list and so don't get destroyed by this container. Similarly, first letters are destroyed by their remaining text fragment.
523        } else {
524            // Destroy any anonymous children remaining in the render tree, as well as implicit (shadow) DOM elements like those used in the engine-based text fields.
525            if (m_firstChild->node())
526                m_firstChild->node()->setRenderer(nullptr);
527            m_firstChild->destroy();
528        }
529    }
530}
531
532void RenderElement::insertChildInternal(RenderObject* newChild, RenderObject* beforeChild, NotifyChildrenType notifyChildren)
533{
534    ASSERT(canHaveChildren() || canHaveGeneratedChildren());
535    ASSERT(!newChild->parent());
536    ASSERT(!isRenderBlockFlow() || (!newChild->isTableSection() && !newChild->isTableRow() && !newChild->isTableCell()));
537
538    while (beforeChild && beforeChild->parent() && beforeChild->parent() != this)
539        beforeChild = beforeChild->parent();
540
541    // This should never happen, but if it does prevent render tree corruption
542    // where child->parent() ends up being owner but child->nextSibling()->parent()
543    // is not owner.
544    if (beforeChild && beforeChild->parent() != this) {
545        ASSERT_NOT_REACHED();
546        return;
547    }
548
549    newChild->setParent(this);
550
551    if (m_firstChild == beforeChild)
552        m_firstChild = newChild;
553
554    if (beforeChild) {
555        RenderObject* previousSibling = beforeChild->previousSibling();
556        if (previousSibling)
557            previousSibling->setNextSibling(newChild);
558        newChild->setPreviousSibling(previousSibling);
559        newChild->setNextSibling(beforeChild);
560        beforeChild->setPreviousSibling(newChild);
561    } else {
562        if (lastChild())
563            lastChild()->setNextSibling(newChild);
564        newChild->setPreviousSibling(lastChild());
565        m_lastChild = newChild;
566    }
567
568    if (!documentBeingDestroyed()) {
569        if (notifyChildren == NotifyChildren)
570            newChild->insertedIntoTree();
571        RenderCounter::rendererSubtreeAttached(newChild);
572    }
573
574    newChild->setNeedsLayoutAndPrefWidthsRecalc();
575    setPreferredLogicalWidthsDirty(true);
576    if (!normalChildNeedsLayout())
577        setChildNeedsLayout(); // We may supply the static position for an absolute positioned child.
578
579    if (AXObjectCache* cache = document().axObjectCache())
580        cache->childrenChanged(this, newChild);
581}
582
583RenderObject* RenderElement::removeChildInternal(RenderObject& oldChild, NotifyChildrenType notifyChildren)
584{
585    ASSERT(canHaveChildren() || canHaveGeneratedChildren());
586    ASSERT(oldChild.parent() == this);
587
588    if (oldChild.isFloatingOrOutOfFlowPositioned())
589        toRenderBox(oldChild).removeFloatingOrPositionedChildFromBlockLists();
590
591    // So that we'll get the appropriate dirty bit set (either that a normal flow child got yanked or
592    // that a positioned child got yanked). We also repaint, so that the area exposed when the child
593    // disappears gets repainted properly.
594    if (!documentBeingDestroyed() && notifyChildren == NotifyChildren && oldChild.everHadLayout()) {
595        oldChild.setNeedsLayoutAndPrefWidthsRecalc();
596        // We only repaint |oldChild| if we have a RenderLayer as its visual overflow may not be tracked by its parent.
597        if (oldChild.isBody())
598            view().repaintRootContents();
599        else
600            oldChild.repaint();
601    }
602
603    // If we have a line box wrapper, delete it.
604    if (oldChild.isBox())
605        toRenderBox(oldChild).deleteLineBoxWrapper();
606    else if (oldChild.isLineBreak())
607        toRenderLineBreak(oldChild).deleteInlineBoxWrapper();
608
609    // If oldChild is the start or end of the selection, then clear the selection to
610    // avoid problems of invalid pointers.
611    if (!documentBeingDestroyed() && oldChild.isSelectionBorder())
612        frame().selection().setNeedsSelectionUpdate();
613
614    if (!documentBeingDestroyed() && notifyChildren == NotifyChildren)
615        oldChild.willBeRemovedFromTree();
616
617    // WARNING: There should be no code running between willBeRemovedFromTree and the actual removal below.
618    // This is needed to avoid race conditions where willBeRemovedFromTree would dirty the tree's structure
619    // and the code running here would force an untimely rebuilding, leaving |oldChild| dangling.
620
621    RenderObject* nextSibling = oldChild.nextSibling();
622
623    if (oldChild.previousSibling())
624        oldChild.previousSibling()->setNextSibling(nextSibling);
625    if (nextSibling)
626        nextSibling->setPreviousSibling(oldChild.previousSibling());
627
628    if (m_firstChild == &oldChild)
629        m_firstChild = nextSibling;
630    if (m_lastChild == &oldChild)
631        m_lastChild = oldChild.previousSibling();
632
633    oldChild.setPreviousSibling(nullptr);
634    oldChild.setNextSibling(nullptr);
635    oldChild.setParent(nullptr);
636
637    // rendererRemovedFromTree walks the whole subtree. We can improve performance
638    // by skipping this step when destroying the entire tree.
639    if (!documentBeingDestroyed())
640        RenderCounter::rendererRemovedFromTree(oldChild);
641
642    if (AXObjectCache* cache = document().existingAXObjectCache())
643        cache->childrenChanged(this);
644
645    return nextSibling;
646}
647
648static void addLayers(RenderElement& renderer, RenderLayer* parentLayer, RenderElement*& newObject, RenderLayer*& beforeChild)
649{
650    if (renderer.hasLayer()) {
651        if (!beforeChild && newObject) {
652            // We need to figure out the layer that follows newObject. We only do
653            // this the first time we find a child layer, and then we update the
654            // pointer values for newObject and beforeChild used by everyone else.
655            beforeChild = newObject->parent()->findNextLayer(parentLayer, newObject);
656            newObject = nullptr;
657        }
658        parentLayer->addChild(toRenderLayerModelObject(renderer).layer(), beforeChild);
659        return;
660    }
661
662    for (auto& child : childrenOfType<RenderElement>(renderer))
663        addLayers(child, parentLayer, newObject, beforeChild);
664}
665
666void RenderElement::addLayers(RenderLayer* parentLayer)
667{
668    if (!parentLayer)
669        return;
670
671    RenderElement* renderer = this;
672    RenderLayer* beforeChild = nullptr;
673    WebCore::addLayers(*this, parentLayer, renderer, beforeChild);
674}
675
676void RenderElement::removeLayers(RenderLayer* parentLayer)
677{
678    if (!parentLayer)
679        return;
680
681    if (hasLayer()) {
682        parentLayer->removeChild(toRenderLayerModelObject(this)->layer());
683        return;
684    }
685
686    for (auto& child : childrenOfType<RenderElement>(*this))
687        child.removeLayers(parentLayer);
688}
689
690void RenderElement::moveLayers(RenderLayer* oldParent, RenderLayer* newParent)
691{
692    if (!newParent)
693        return;
694
695    if (hasLayer()) {
696        RenderLayer* layer = toRenderLayerModelObject(this)->layer();
697        ASSERT(oldParent == layer->parent());
698        if (oldParent)
699            oldParent->removeChild(layer);
700        newParent->addChild(layer);
701        return;
702    }
703
704    for (auto& child : childrenOfType<RenderElement>(*this))
705        child.moveLayers(oldParent, newParent);
706}
707
708RenderLayer* RenderElement::findNextLayer(RenderLayer* parentLayer, RenderObject* startPoint, bool checkParent)
709{
710    // Error check the parent layer passed in. If it's null, we can't find anything.
711    if (!parentLayer)
712        return nullptr;
713
714    // Step 1: If our layer is a child of the desired parent, then return our layer.
715    RenderLayer* ourLayer = hasLayer() ? toRenderLayerModelObject(this)->layer() : nullptr;
716    if (ourLayer && ourLayer->parent() == parentLayer)
717        return ourLayer;
718
719    // Step 2: If we don't have a layer, or our layer is the desired parent, then descend
720    // into our siblings trying to find the next layer whose parent is the desired parent.
721    if (!ourLayer || ourLayer == parentLayer) {
722        for (RenderObject* child = startPoint ? startPoint->nextSibling() : firstChild(); child; child = child->nextSibling()) {
723            if (!child->isRenderElement())
724                continue;
725            RenderLayer* nextLayer = toRenderElement(child)->findNextLayer(parentLayer, nullptr, false);
726            if (nextLayer)
727                return nextLayer;
728        }
729    }
730
731    // Step 3: If our layer is the desired parent layer, then we're finished. We didn't
732    // find anything.
733    if (parentLayer == ourLayer)
734        return nullptr;
735
736    // Step 4: If |checkParent| is set, climb up to our parent and check its siblings that
737    // follow us to see if we can locate a layer.
738    if (checkParent && parent())
739        return parent()->findNextLayer(parentLayer, this, true);
740
741    return nullptr;
742}
743
744bool RenderElement::layerCreationAllowedForSubtree() const
745{
746    RenderElement* parentRenderer = parent();
747    while (parentRenderer) {
748        if (parentRenderer->isSVGHiddenContainer())
749            return false;
750        parentRenderer = parentRenderer->parent();
751    }
752
753    return true;
754}
755
756void RenderElement::propagateStyleToAnonymousChildren(StylePropagationType propagationType)
757{
758    // FIXME: We could save this call when the change only affected non-inherited properties.
759    for (auto& elementChild : childrenOfType<RenderElement>(*this)) {
760        if (!elementChild.isAnonymous() || elementChild.style().styleType() != NOPSEUDO)
761            continue;
762
763        if (propagationType == PropagateToBlockChildrenOnly && !elementChild.isRenderBlock())
764            continue;
765
766#if ENABLE(FULLSCREEN_API)
767        if (elementChild.isRenderFullScreen() || elementChild.isRenderFullScreenPlaceholder())
768            continue;
769#endif
770
771        // RenderFlowThreads are updated through the RenderView::styleDidChange function.
772        if (elementChild.isRenderFlowThread())
773            continue;
774
775        auto newStyle = RenderStyle::createAnonymousStyleWithDisplay(&style(), elementChild.style().display());
776        if (style().specifiesColumns()) {
777            if (elementChild.style().specifiesColumns())
778                newStyle.get().inheritColumnPropertiesFrom(&style());
779            if (elementChild.style().columnSpan())
780                newStyle.get().setColumnSpan(ColumnSpanAll);
781        }
782
783        // Preserve the position style of anonymous block continuations as they can have relative or sticky position when
784        // they contain block descendants of relative or sticky positioned inlines.
785        if (elementChild.isInFlowPositioned() && toRenderBlock(elementChild).isAnonymousBlockContinuation())
786            newStyle.get().setPosition(elementChild.style().position());
787
788        elementChild.setStyle(WTF::move(newStyle));
789    }
790}
791
792static inline bool rendererHasBackground(const RenderElement* renderer)
793{
794    return renderer && renderer->hasBackground();
795}
796
797void RenderElement::styleWillChange(StyleDifference diff, const RenderStyle& newStyle)
798{
799    RenderStyle* oldStyle = hasInitializedStyle() ? &style() : nullptr;
800    if (oldStyle) {
801        // If our z-index changes value or our visibility changes,
802        // we need to dirty our stacking context's z-order list.
803        bool visibilityChanged = m_style->visibility() != newStyle.visibility()
804            || m_style->zIndex() != newStyle.zIndex()
805            || m_style->hasAutoZIndex() != newStyle.hasAutoZIndex();
806#if ENABLE(DASHBOARD_SUPPORT)
807        if (visibilityChanged)
808            document().setAnnotatedRegionsDirty(true);
809#endif
810#if PLATFORM(IOS) && ENABLE(TOUCH_EVENTS)
811        if (visibilityChanged)
812            document().dirtyTouchEventRects();
813#endif
814        if (visibilityChanged) {
815            if (AXObjectCache* cache = document().existingAXObjectCache())
816                cache->childrenChanged(parent(), this);
817        }
818
819        // Keep layer hierarchy visibility bits up to date if visibility changes.
820        if (m_style->visibility() != newStyle.visibility()) {
821            if (RenderLayer* layer = enclosingLayer()) {
822                if (newStyle.visibility() == VISIBLE)
823                    layer->setHasVisibleContent();
824                else if (layer->hasVisibleContent() && (this == &layer->renderer() || layer->renderer().style().visibility() != VISIBLE)) {
825                    layer->dirtyVisibleContentStatus();
826                    if (diff > StyleDifferenceRepaintLayer)
827                        repaint();
828                }
829            }
830        }
831
832        if (m_parent && (newStyle.outlineSize() < m_style->outlineSize() || shouldRepaintForStyleDifference(diff)))
833            repaint();
834        if (isFloating() && (m_style->floating() != newStyle.floating()))
835            // For changes in float styles, we need to conceivably remove ourselves
836            // from the floating objects list.
837            toRenderBox(this)->removeFloatingOrPositionedChildFromBlockLists();
838        else if (isOutOfFlowPositioned() && (m_style->position() != newStyle.position()))
839            // For changes in positioning styles, we need to conceivably remove ourselves
840            // from the positioned objects list.
841            toRenderBox(this)->removeFloatingOrPositionedChildFromBlockLists();
842
843        s_affectsParentBlock = isFloatingOrOutOfFlowPositioned()
844            && (!newStyle.isFloating() && !newStyle.hasOutOfFlowPosition())
845            && parent() && (parent()->isRenderBlockFlow() || parent()->isRenderInline());
846
847        s_noLongerAffectsParentBlock = ((!isFloating() && newStyle.isFloating()) || (!isOutOfFlowPositioned() && newStyle.hasOutOfFlowPosition()))
848            && parent() && parent()->isRenderBlock();
849
850        // reset style flags
851        if (diff == StyleDifferenceLayout || diff == StyleDifferenceLayoutPositionedMovementOnly) {
852            setFloating(false);
853            clearPositionedState();
854        }
855        setHorizontalWritingMode(true);
856        setHasBoxDecorations(false);
857        setHasOverflowClip(false);
858        setHasTransform(false);
859        setHasReflection(false);
860    } else {
861        s_affectsParentBlock = false;
862        s_noLongerAffectsParentBlock = false;
863    }
864
865    bool newStyleUsesFixedBackgrounds = newStyle.hasFixedBackgroundImage();
866    bool oldStyleUsesFixedBackgrounds = m_style->hasFixedBackgroundImage();
867    if (newStyleUsesFixedBackgrounds || oldStyleUsesFixedBackgrounds) {
868        bool repaintFixedBackgroundsOnScroll = !frame().settings().fixedBackgroundsPaintRelativeToDocument();
869
870        bool newStyleSlowScroll = repaintFixedBackgroundsOnScroll && newStyleUsesFixedBackgrounds;
871        bool oldStyleSlowScroll = oldStyle && repaintFixedBackgroundsOnScroll && oldStyleUsesFixedBackgrounds;
872        bool drawsRootBackground = isRoot() || (isBody() && !rendererHasBackground(document().documentElement()->renderer()));
873        if (drawsRootBackground && repaintFixedBackgroundsOnScroll) {
874            if (view().compositor().supportsFixedRootBackgroundCompositing()) {
875                if (newStyleSlowScroll && newStyle.hasEntirelyFixedBackground())
876                    newStyleSlowScroll = false;
877
878                if (oldStyleSlowScroll && m_style->hasEntirelyFixedBackground())
879                    oldStyleSlowScroll = false;
880            }
881        }
882
883        if (oldStyleSlowScroll != newStyleSlowScroll) {
884            if (oldStyleSlowScroll)
885                view().frameView().removeSlowRepaintObject(this);
886
887            if (newStyleSlowScroll)
888                view().frameView().addSlowRepaintObject(this);
889        }
890    }
891
892    if (isRoot() || isBody())
893        view().frameView().updateExtendBackgroundIfNecessary();
894}
895
896#if !PLATFORM(IOS)
897static bool areNonIdenticalCursorListsEqual(const RenderStyle* a, const RenderStyle* b)
898{
899    ASSERT(a->cursors() != b->cursors());
900    return a->cursors() && b->cursors() && *a->cursors() == *b->cursors();
901}
902
903static inline bool areCursorsEqual(const RenderStyle* a, const RenderStyle* b)
904{
905    return a->cursor() == b->cursor() && (a->cursors() == b->cursors() || areNonIdenticalCursorListsEqual(a, b));
906}
907#endif
908
909void RenderElement::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
910{
911    if (s_affectsParentBlock)
912        handleDynamicFloatPositionChange();
913
914    if (s_noLongerAffectsParentBlock)
915        removeAnonymousWrappersForInlinesIfNecessary();
916
917    SVGRenderSupport::styleChanged(*this, oldStyle);
918
919    if (!m_parent)
920        return;
921
922    if (diff == StyleDifferenceLayout || diff == StyleDifferenceSimplifiedLayout) {
923        RenderCounter::rendererStyleChanged(this, oldStyle, &m_style.get());
924
925        // If the object already needs layout, then setNeedsLayout won't do
926        // any work. But if the containing block has changed, then we may need
927        // to mark the new containing blocks for layout. The change that can
928        // directly affect the containing block of this object is a change to
929        // the position style.
930        if (needsLayout() && oldStyle->position() != m_style->position())
931            markContainingBlocksForLayout();
932
933        if (diff == StyleDifferenceLayout)
934            setNeedsLayoutAndPrefWidthsRecalc();
935        else
936            setNeedsSimplifiedNormalFlowLayout();
937    } else if (diff == StyleDifferenceSimplifiedLayoutAndPositionedMovement) {
938        setNeedsPositionedMovementLayout(oldStyle);
939        setNeedsSimplifiedNormalFlowLayout();
940    } else if (diff == StyleDifferenceLayoutPositionedMovementOnly)
941        setNeedsPositionedMovementLayout(oldStyle);
942
943    // Don't check for repaint here; we need to wait until the layer has been
944    // updated by subclasses before we know if we have to repaint (in setStyle()).
945
946#if !PLATFORM(IOS)
947    if (oldStyle && !areCursorsEqual(oldStyle, &style()))
948        frame().eventHandler().scheduleCursorUpdate();
949#endif
950}
951
952void RenderElement::insertedIntoTree()
953{
954    if (auto* containerFlowThread = parent()->renderNamedFlowThreadWrapper())
955        containerFlowThread->addFlowChild(*this);
956
957    // Keep our layer hierarchy updated. Optimize for the common case where we don't have any children
958    // and don't have a layer attached to ourselves.
959    RenderLayer* layer = nullptr;
960    if (firstChild() || hasLayer()) {
961        layer = parent()->enclosingLayer();
962        addLayers(layer);
963    }
964
965    // If |this| is visible but this object was not, tell the layer it has some visible content
966    // that needs to be drawn and layer visibility optimization can't be used
967    if (parent()->style().visibility() != VISIBLE && style().visibility() == VISIBLE && !hasLayer()) {
968        if (!layer)
969            layer = parent()->enclosingLayer();
970        if (layer)
971            layer->setHasVisibleContent();
972    }
973
974    RenderObject::insertedIntoTree();
975}
976
977void RenderElement::willBeRemovedFromTree()
978{
979    // If we remove a visible child from an invisible parent, we don't know the layer visibility any more.
980    RenderLayer* layer = nullptr;
981    if (parent()->style().visibility() != VISIBLE && style().visibility() == VISIBLE && !hasLayer()) {
982        if ((layer = parent()->enclosingLayer()))
983            layer->dirtyVisibleContentStatus();
984    }
985    // Keep our layer hierarchy updated.
986    if (firstChild() || hasLayer()) {
987        if (!layer)
988            layer = parent()->enclosingLayer();
989        removeLayers(layer);
990    }
991
992    if (m_style->hasFixedBackgroundImage() && !frame().settings().fixedBackgroundsPaintRelativeToDocument())
993        view().frameView().removeSlowRepaintObject(this);
994
995    if (isOutOfFlowPositioned() && parent()->childrenInline())
996        parent()->dirtyLinesFromChangedChild(this);
997
998    if (auto* containerFlowThread = parent()->renderNamedFlowThreadWrapper())
999        containerFlowThread->removeFlowChild(*this);
1000
1001    RenderObject::willBeRemovedFromTree();
1002}
1003
1004void RenderElement::willBeDestroyed()
1005{
1006    animation().cancelAnimations(this);
1007
1008    destroyLeftoverChildren();
1009
1010    RenderObject::willBeDestroyed();
1011
1012#if !ASSERT_DISABLED
1013    if (!documentBeingDestroyed() && view().hasRenderNamedFlowThreads()) {
1014        // After remove, the object and the associated information should not be in any flow thread.
1015        for (auto& flowThread : *view().flowThreadController().renderNamedFlowThreadList()) {
1016            ASSERT(!flowThread->hasChild(*this));
1017            ASSERT(!flowThread->hasChildInfo(this));
1018        }
1019    }
1020#endif
1021}
1022
1023void RenderElement::setNeedsPositionedMovementLayout(const RenderStyle* oldStyle)
1024{
1025    ASSERT(!isSetNeedsLayoutForbidden());
1026    if (needsPositionedMovementLayout())
1027        return;
1028    setNeedsPositionedMovementLayoutBit(true);
1029    markContainingBlocksForLayout();
1030    if (hasLayer()) {
1031        if (oldStyle && style().diffRequiresLayerRepaint(*oldStyle, toRenderLayerModelObject(this)->layer()->isComposited()))
1032            setLayerNeedsFullRepaint();
1033        else
1034            setLayerNeedsFullRepaintForPositionedMovementLayout();
1035    }
1036}
1037
1038void RenderElement::clearChildNeedsLayout()
1039{
1040    setNormalChildNeedsLayoutBit(false);
1041    setPosChildNeedsLayoutBit(false);
1042    setNeedsSimplifiedNormalFlowLayoutBit(false);
1043    setNormalChildNeedsLayoutBit(false);
1044    setNeedsPositionedMovementLayoutBit(false);
1045}
1046
1047void RenderElement::setNeedsSimplifiedNormalFlowLayout()
1048{
1049    ASSERT(!isSetNeedsLayoutForbidden());
1050    if (needsSimplifiedNormalFlowLayout())
1051        return;
1052    setNeedsSimplifiedNormalFlowLayoutBit(true);
1053    markContainingBlocksForLayout();
1054    if (hasLayer())
1055        setLayerNeedsFullRepaint();
1056}
1057
1058RenderElement& RenderElement::rendererForRootBackground()
1059{
1060    ASSERT(isRoot());
1061    if (!hasBackground() && element() && element()->hasTagName(HTMLNames::htmlTag)) {
1062        // Locate the <body> element using the DOM. This is easier than trying
1063        // to crawl around a render tree with potential :before/:after content and
1064        // anonymous blocks created by inline <body> tags etc. We can locate the <body>
1065        // render object very easily via the DOM.
1066        if (auto body = document().body()) {
1067            if (body->hasTagName(HTMLNames::bodyTag)) {
1068                if (auto renderer = body->renderer())
1069                    return *renderer;
1070            }
1071        }
1072    }
1073    return *this;
1074}
1075
1076RenderElement* RenderElement::hoverAncestor() const
1077{
1078    // When searching for the hover ancestor and encountering a named flow thread,
1079    // the search will continue with the DOM ancestor of the top-most element
1080    // in the named flow thread.
1081    // See https://bugs.webkit.org/show_bug.cgi?id=111749
1082    RenderElement* hoverAncestor = parent();
1083
1084    // Skip anonymous blocks directly flowed into flow threads as it would
1085    // prevent us from continuing the search on the DOM tree when reaching the named flow thread.
1086    if (hoverAncestor && hoverAncestor->isAnonymousBlock() && hoverAncestor->parent() && hoverAncestor->parent()->isRenderNamedFlowThread())
1087        hoverAncestor = hoverAncestor->parent();
1088
1089    if (hoverAncestor && hoverAncestor->isRenderNamedFlowThread()) {
1090        hoverAncestor = nullptr;
1091        if (Element* element = this->element()) {
1092            if (auto parent = element->parentNode())
1093                hoverAncestor = parent->renderer();
1094        }
1095    }
1096
1097    return hoverAncestor;
1098}
1099
1100void RenderElement::layout()
1101{
1102    StackStats::LayoutCheckPoint layoutCheckPoint;
1103    ASSERT(needsLayout());
1104    RenderObject* child = firstChild();
1105    while (child) {
1106        if (child->needsLayout())
1107            toRenderElement(child)->layout();
1108        ASSERT(!child->needsLayout());
1109        child = child->nextSibling();
1110    }
1111    clearNeedsLayout();
1112}
1113
1114static bool mustRepaintFillLayers(const RenderElement& renderer, const FillLayer* layer)
1115{
1116    // Nobody will use multiple layers without wanting fancy positioning.
1117    if (layer->next())
1118        return true;
1119
1120    // Make sure we have a valid image.
1121    StyleImage* image = layer->image();
1122    if (!image || !image->canRender(&renderer, renderer.style().effectiveZoom()))
1123        return false;
1124
1125    if (!layer->xPosition().isZero() || !layer->yPosition().isZero())
1126        return true;
1127
1128    EFillSizeType sizeType = layer->sizeType();
1129
1130    if (sizeType == Contain || sizeType == Cover)
1131        return true;
1132
1133    if (sizeType == SizeLength) {
1134        LengthSize size = layer->sizeLength();
1135        if (size.width().isPercent() || size.height().isPercent())
1136            return true;
1137        // If the image has neither an intrinsic width nor an intrinsic height, its size is determined as for 'contain'.
1138        if ((size.width().isAuto() || size.height().isAuto()) && image->isGeneratedImage())
1139            return true;
1140    } else if (image->usesImageContainerSize())
1141        return true;
1142
1143    return false;
1144}
1145
1146static bool mustRepaintBackgroundOrBorder(const RenderElement& renderer)
1147{
1148    if (renderer.hasMask() && mustRepaintFillLayers(renderer, renderer.style().maskLayers()))
1149        return true;
1150
1151    // If we don't have a background/border/mask, then nothing to do.
1152    if (!renderer.hasBoxDecorations())
1153        return false;
1154
1155    if (mustRepaintFillLayers(renderer, renderer.style().backgroundLayers()))
1156        return true;
1157
1158    // Our fill layers are ok. Let's check border.
1159    if (renderer.style().hasBorder() && renderer.borderImageIsLoadedAndCanBeRendered())
1160        return true;
1161
1162    return false;
1163}
1164
1165bool RenderElement::repaintAfterLayoutIfNeeded(const RenderLayerModelObject* repaintContainer, const LayoutRect& oldBounds, const LayoutRect& oldOutlineBox, const LayoutRect* newBoundsPtr, const LayoutRect* newOutlineBoxRectPtr)
1166{
1167    if (view().printing())
1168        return false; // Don't repaint if we're printing.
1169
1170    // This ASSERT fails due to animations. See https://bugs.webkit.org/show_bug.cgi?id=37048
1171    // ASSERT(!newBoundsPtr || *newBoundsPtr == clippedOverflowRectForRepaint(repaintContainer));
1172    LayoutRect newBounds = newBoundsPtr ? *newBoundsPtr : clippedOverflowRectForRepaint(repaintContainer);
1173    LayoutRect newOutlineBox;
1174
1175    bool fullRepaint = selfNeedsLayout();
1176    // Presumably a background or a border exists if border-fit:lines was specified.
1177    if (!fullRepaint && style().borderFit() == BorderFitLines)
1178        fullRepaint = true;
1179    if (!fullRepaint) {
1180        // This ASSERT fails due to animations. See https://bugs.webkit.org/show_bug.cgi?id=37048
1181        // ASSERT(!newOutlineBoxRectPtr || *newOutlineBoxRectPtr == outlineBoundsForRepaint(repaintContainer));
1182        newOutlineBox = newOutlineBoxRectPtr ? *newOutlineBoxRectPtr : outlineBoundsForRepaint(repaintContainer);
1183        if (newOutlineBox.location() != oldOutlineBox.location() || (mustRepaintBackgroundOrBorder(*this) && (newBounds != oldBounds || newOutlineBox != oldOutlineBox)))
1184            fullRepaint = true;
1185    }
1186
1187    if (!repaintContainer)
1188        repaintContainer = &view();
1189
1190    if (fullRepaint) {
1191        repaintUsingContainer(repaintContainer, oldBounds);
1192        if (newBounds != oldBounds)
1193            repaintUsingContainer(repaintContainer, newBounds);
1194        return true;
1195    }
1196
1197    if (newBounds == oldBounds && newOutlineBox == oldOutlineBox)
1198        return false;
1199
1200    LayoutUnit deltaLeft = newBounds.x() - oldBounds.x();
1201    if (deltaLeft > 0)
1202        repaintUsingContainer(repaintContainer, LayoutRect(oldBounds.x(), oldBounds.y(), deltaLeft, oldBounds.height()));
1203    else if (deltaLeft < 0)
1204        repaintUsingContainer(repaintContainer, LayoutRect(newBounds.x(), newBounds.y(), -deltaLeft, newBounds.height()));
1205
1206    LayoutUnit deltaRight = newBounds.maxX() - oldBounds.maxX();
1207    if (deltaRight > 0)
1208        repaintUsingContainer(repaintContainer, LayoutRect(oldBounds.maxX(), newBounds.y(), deltaRight, newBounds.height()));
1209    else if (deltaRight < 0)
1210        repaintUsingContainer(repaintContainer, LayoutRect(newBounds.maxX(), oldBounds.y(), -deltaRight, oldBounds.height()));
1211
1212    LayoutUnit deltaTop = newBounds.y() - oldBounds.y();
1213    if (deltaTop > 0)
1214        repaintUsingContainer(repaintContainer, LayoutRect(oldBounds.x(), oldBounds.y(), oldBounds.width(), deltaTop));
1215    else if (deltaTop < 0)
1216        repaintUsingContainer(repaintContainer, LayoutRect(newBounds.x(), newBounds.y(), newBounds.width(), -deltaTop));
1217
1218    LayoutUnit deltaBottom = newBounds.maxY() - oldBounds.maxY();
1219    if (deltaBottom > 0)
1220        repaintUsingContainer(repaintContainer, LayoutRect(newBounds.x(), oldBounds.maxY(), newBounds.width(), deltaBottom));
1221    else if (deltaBottom < 0)
1222        repaintUsingContainer(repaintContainer, LayoutRect(oldBounds.x(), newBounds.maxY(), oldBounds.width(), -deltaBottom));
1223
1224    if (newOutlineBox == oldOutlineBox)
1225        return false;
1226
1227    // We didn't move, but we did change size. Invalidate the delta, which will consist of possibly
1228    // two rectangles (but typically only one).
1229    const RenderStyle& outlineStyle = outlineStyleForRepaint();
1230    LayoutUnit outlineWidth = outlineStyle.outlineSize();
1231    LayoutBoxExtent insetShadowExtent = style().getBoxShadowInsetExtent();
1232    LayoutUnit width = absoluteValue(newOutlineBox.width() - oldOutlineBox.width());
1233    if (width) {
1234        LayoutUnit shadowLeft;
1235        LayoutUnit shadowRight;
1236        style().getBoxShadowHorizontalExtent(shadowLeft, shadowRight);
1237        LayoutUnit borderRight = isBox() ? toRenderBox(this)->borderRight() : LayoutUnit::fromPixel(0);
1238        LayoutUnit boxWidth = isBox() ? toRenderBox(this)->width() : LayoutUnit();
1239        LayoutUnit minInsetRightShadowExtent = std::min<LayoutUnit>(-insetShadowExtent.right(), std::min<LayoutUnit>(newBounds.width(), oldBounds.width()));
1240        LayoutUnit borderWidth = std::max<LayoutUnit>(borderRight, std::max<LayoutUnit>(valueForLength(style().borderTopRightRadius().width(), boxWidth), valueForLength(style().borderBottomRightRadius().width(), boxWidth)));
1241        LayoutUnit decorationsWidth = std::max<LayoutUnit>(-outlineStyle.outlineOffset(), borderWidth + minInsetRightShadowExtent) + std::max<LayoutUnit>(outlineWidth, shadowRight);
1242        LayoutRect rightRect(newOutlineBox.x() + std::min(newOutlineBox.width(), oldOutlineBox.width()) - decorationsWidth,
1243            newOutlineBox.y(),
1244            width + decorationsWidth,
1245            std::max(newOutlineBox.height(), oldOutlineBox.height()));
1246        LayoutUnit right = std::min<LayoutUnit>(newBounds.maxX(), oldBounds.maxX());
1247        if (rightRect.x() < right) {
1248            rightRect.setWidth(std::min(rightRect.width(), right - rightRect.x()));
1249            repaintUsingContainer(repaintContainer, rightRect);
1250        }
1251    }
1252    LayoutUnit height = absoluteValue(newOutlineBox.height() - oldOutlineBox.height());
1253    if (height) {
1254        LayoutUnit shadowTop;
1255        LayoutUnit shadowBottom;
1256        style().getBoxShadowVerticalExtent(shadowTop, shadowBottom);
1257        LayoutUnit borderBottom = isBox() ? toRenderBox(this)->borderBottom() : LayoutUnit::fromPixel(0);
1258        LayoutUnit boxHeight = isBox() ? toRenderBox(this)->height() : LayoutUnit();
1259        LayoutUnit minInsetBottomShadowExtent = std::min<LayoutUnit>(-insetShadowExtent.bottom(), std::min<LayoutUnit>(newBounds.height(), oldBounds.height()));
1260        LayoutUnit borderHeight = std::max<LayoutUnit>(borderBottom, std::max<LayoutUnit>(valueForLength(style().borderBottomLeftRadius().height(), boxHeight),
1261            valueForLength(style().borderBottomRightRadius().height(), boxHeight)));
1262        LayoutUnit decorationsHeight = std::max<LayoutUnit>(-outlineStyle.outlineOffset(), borderHeight + minInsetBottomShadowExtent) + std::max<LayoutUnit>(outlineWidth, shadowBottom);
1263        LayoutRect bottomRect(newOutlineBox.x(),
1264            std::min(newOutlineBox.maxY(), oldOutlineBox.maxY()) - decorationsHeight,
1265            std::max(newOutlineBox.width(), oldOutlineBox.width()),
1266            height + decorationsHeight);
1267        LayoutUnit bottom = std::min(newBounds.maxY(), oldBounds.maxY());
1268        if (bottomRect.y() < bottom) {
1269            bottomRect.setHeight(std::min(bottomRect.height(), bottom - bottomRect.y()));
1270            repaintUsingContainer(repaintContainer, bottomRect);
1271        }
1272    }
1273    return false;
1274}
1275
1276bool RenderElement::borderImageIsLoadedAndCanBeRendered() const
1277{
1278    ASSERT(style().hasBorder());
1279
1280    StyleImage* borderImage = style().borderImage().image();
1281    return borderImage && borderImage->canRender(this, style().effectiveZoom()) && borderImage->isLoaded();
1282}
1283
1284static bool shouldRepaintForImageAnimation(const RenderElement& renderer, const IntRect& visibleRect)
1285{
1286    const Document& document = renderer.document();
1287    if (document.inPageCache())
1288        return false;
1289    auto& frameView = renderer.view().frameView();
1290    if (frameView.isOffscreen())
1291        return false;
1292#if PLATFORM(IOS)
1293    if (document.frame()->timersPaused())
1294        return false;
1295#endif
1296    if (document.activeDOMObjectsAreSuspended())
1297        return false;
1298    if (renderer.style().visibility() != VISIBLE)
1299        return false;
1300    if (!visibleRect.intersects(renderer.absoluteBoundingBoxRect()))
1301        return false;
1302
1303    return true;
1304}
1305
1306void RenderElement::newImageAnimationFrameAvailable(CachedImage& image)
1307{
1308    auto& frameView = view().frameView();
1309    auto visibleRect = frameView.windowToContents(frameView.windowClipRect());
1310    if (!shouldRepaintForImageAnimation(*this, visibleRect)) {
1311        view().addRendererWithPausedImageAnimations(*this);
1312        return;
1313    }
1314    imageChanged(&image);
1315}
1316
1317bool RenderElement::repaintForPausedImageAnimationsIfNeeded(const IntRect& visibleRect)
1318{
1319    ASSERT(m_hasPausedImageAnimations);
1320    if (!shouldRepaintForImageAnimation(*this, visibleRect))
1321        return false;
1322    repaint();
1323    return true;
1324}
1325
1326RenderNamedFlowThread* RenderElement::renderNamedFlowThreadWrapper()
1327{
1328    auto renderer = this;
1329    while (renderer && renderer->isAnonymousBlock() && !renderer->isRenderNamedFlowThread())
1330        renderer = renderer->parent();
1331    return renderer && renderer->isRenderNamedFlowThread() ? toRenderNamedFlowThread(renderer) : nullptr;
1332}
1333
1334bool RenderElement::hasControlStatesForRenderer(const RenderObject* o)
1335{
1336    return controlStatesRendererMap().contains(o);
1337}
1338
1339ControlStates* RenderElement::controlStatesForRenderer(const RenderObject* o)
1340{
1341    return controlStatesRendererMap().get(o);
1342}
1343
1344void RenderElement::removeControlStatesForRenderer(const RenderObject* o)
1345{
1346    ControlStates* states = controlStatesRendererMap().get(o);
1347    if (states) {
1348        controlStatesRendererMap().remove(o);
1349        delete states;
1350    }
1351}
1352
1353void RenderElement::addControlStatesForRenderer(const RenderObject* o, ControlStates* states)
1354{
1355    controlStatesRendererMap().add(o, states);
1356}
1357
1358}
1359