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, 2015 Apple Inc. All rights reserved.
7 * Copyright (C) 2010, 2012 Google Inc. All rights reserved.
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.
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.
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.
26 #include "RenderElement.h"
28 #include "AXObjectCache.h"
29 #include "ContentData.h"
30 #include "CursorList.h"
31 #include "ElementChildIterator.h"
32 #include "EventHandler.h"
33 #include "FocusController.h"
35 #include "FrameSelection.h"
36 #include "HTMLAnchorElement.h"
37 #include "HTMLBodyElement.h"
38 #include "HTMLHtmlElement.h"
39 #include "HTMLImageElement.h"
40 #include "HTMLNames.h"
43 #include "PathUtilities.h"
44 #include "RenderBlock.h"
45 #include "RenderChildIterator.h"
46 #include "RenderCounter.h"
47 #include "RenderDeprecatedFlexibleBox.h"
48 #include "RenderDescendantIterator.h"
49 #include "RenderFlexibleBox.h"
50 #include "RenderFragmentedFlow.h"
51 #include "RenderImage.h"
52 #include "RenderImageResourceStyleImage.h"
53 #include "RenderInline.h"
54 #include "RenderIterator.h"
55 #include "RenderLayer.h"
56 #include "RenderLayerCompositor.h"
57 #include "RenderLineBreak.h"
58 #include "RenderListItem.h"
60 #include "RenderListMarker.h"
62 #include "RenderFragmentContainer.h"
63 #include "RenderTableCaption.h"
64 #include "RenderTableCell.h"
65 #include "RenderTableCol.h"
66 #include "RenderTableRow.h"
67 #include "RenderText.h"
68 #include "RenderTheme.h"
69 #include "RenderTreeBuilder.h"
70 #include "RenderView.h"
72 #include "SVGRenderSupport.h"
74 #include "ShadowRoot.h"
75 #include "StylePendingResources.h"
76 #include "StyleResolver.h"
77 #include "TextAutoSizing.h"
78 #include <wtf/IsoMallocInlines.h>
79 #include <wtf/MathExtras.h>
80 #include <wtf/StackStats.h>
82 #include "RenderGrid.h"
86 WTF_MAKE_ISO_ALLOCATED_IMPL(RenderElement);
88 struct SameSizeAsRenderElement : public RenderObject {
89 unsigned bitfields : 25;
95 static_assert(sizeof(RenderElement) == sizeof(SameSizeAsRenderElement), "RenderElement should stay small");
97 bool RenderElement::s_affectsParentBlock = false;
98 bool RenderElement::s_noLongerAffectsParentBlock = false;
100 inline RenderElement::RenderElement(ContainerNode& elementOrDocument, RenderStyle&& style, BaseTypeFlags baseTypeFlags)
101 : RenderObject(elementOrDocument)
102 , m_baseTypeFlags(baseTypeFlags)
103 , m_ancestorLineBoxDirty(false)
104 , m_hasInitializedStyle(false)
105 , m_renderInlineAlwaysCreatesLineBoxes(false)
106 , m_renderBoxNeedsLazyRepaint(false)
107 , m_hasPausedImageAnimations(false)
108 , m_hasCounterNodeMap(false)
109 , m_hasContinuationChainNode(false)
110 , m_isContinuation(false)
111 , m_isFirstLetter(false)
112 , m_hasValidCachedFirstLineStyle(false)
113 , m_renderBlockHasMarginBeforeQuirk(false)
114 , m_renderBlockHasMarginAfterQuirk(false)
115 , m_renderBlockShouldForceRelayoutChildren(false)
116 , m_renderBlockFlowHasMarkupTruncation(false)
117 , m_renderBlockFlowLineLayoutPath(RenderBlockFlow::UndeterminedPath)
118 , m_isRegisteredForVisibleInViewportCallback(false)
119 , m_visibleInViewportState(static_cast<unsigned>(VisibleInViewportState::Unknown))
120 , m_firstChild(nullptr)
121 , m_lastChild(nullptr)
122 , m_style(WTFMove(style))
126 RenderElement::RenderElement(Element& element, RenderStyle&& style, BaseTypeFlags baseTypeFlags)
127 : RenderElement(static_cast<ContainerNode&>(element), WTFMove(style), baseTypeFlags)
131 RenderElement::RenderElement(Document& document, RenderStyle&& style, BaseTypeFlags baseTypeFlags)
132 : RenderElement(static_cast<ContainerNode&>(document), WTFMove(style), baseTypeFlags)
136 RenderElement::~RenderElement()
138 // Do not add any code here. Add it to willBeDestroyed() instead.
139 ASSERT(!m_firstChild);
142 RenderPtr<RenderElement> RenderElement::createFor(Element& element, RenderStyle&& style, RendererCreationType creationType)
144 // Minimal support for content properties replacing an entire element.
145 // Works only if we have exactly one piece of content and it's a URL.
146 // Otherwise acts as if we didn't support this feature.
147 const ContentData* contentData = style.contentData();
148 if (creationType == CreateAllRenderers && contentData && !contentData->next() && is<ImageContentData>(*contentData) && !element.isPseudoElement()) {
149 Style::loadPendingResources(style, element.document(), &element);
150 auto& styleImage = downcast<ImageContentData>(*contentData).image();
151 auto image = createRenderer<RenderImage>(element, WTFMove(style), const_cast<StyleImage*>(&styleImage));
152 image->setIsGeneratedContent();
153 return WTFMove(image);
156 switch (style.display()) {
161 if (creationType == CreateAllRenderers)
162 return createRenderer<RenderInline>(element, WTFMove(style));
163 FALLTHROUGH; // Fieldsets should make a block flow if display:inline is set.
167 return createRenderer<RenderBlockFlow>(element, WTFMove(style));
169 return createRenderer<RenderListItem>(element, WTFMove(style));
173 case WEBKIT_INLINE_FLEX:
174 return createRenderer<RenderFlexibleBox>(element, WTFMove(style));
177 return createRenderer<RenderGrid>(element, WTFMove(style));
180 return createRenderer<RenderDeprecatedFlexibleBox>(element, WTFMove(style));
182 if (creationType == OnlyCreateBlockAndFlexboxRenderers)
183 return createRenderer<RenderBlockFlow>(element, WTFMove(style));
184 switch (style.display()) {
187 return createRenderer<RenderTable>(element, WTFMove(style));
189 return createRenderer<RenderTableCell>(element, WTFMove(style));
191 return createRenderer<RenderTableCaption>(element, WTFMove(style));
192 case TABLE_ROW_GROUP:
193 case TABLE_HEADER_GROUP:
194 case TABLE_FOOTER_GROUP:
195 return createRenderer<RenderTableSection>(element, WTFMove(style));
197 return createRenderer<RenderTableRow>(element, WTFMove(style));
198 case TABLE_COLUMN_GROUP:
200 return createRenderer<RenderTableCol>(element, WTFMove(style));
207 ASSERT_NOT_REACHED();
211 std::unique_ptr<RenderStyle> RenderElement::computeFirstLineStyle() const
213 ASSERT(view().usesFirstLineRules());
215 RenderElement& rendererForFirstLineStyle = isBeforeOrAfterContent() ? *parent() : const_cast<RenderElement&>(*this);
217 if (rendererForFirstLineStyle.isRenderBlockFlow() || rendererForFirstLineStyle.isRenderButton()) {
218 RenderBlock* firstLineBlock = rendererForFirstLineStyle.firstLineBlock();
221 auto* firstLineStyle = firstLineBlock->getCachedPseudoStyle(FIRST_LINE, &style());
224 return RenderStyle::clonePtr(*firstLineStyle);
227 if (!rendererForFirstLineStyle.isRenderInline())
230 auto& parentStyle = rendererForFirstLineStyle.parent()->firstLineStyle();
231 if (&parentStyle == &rendererForFirstLineStyle.parent()->style())
234 if (rendererForFirstLineStyle.isAnonymous()) {
235 auto* textRendererWithDisplayContentsParent = RenderText::findByDisplayContentsInlineWrapperCandidate(rendererForFirstLineStyle);
236 if (!textRendererWithDisplayContentsParent)
238 auto* composedTreeParentElement = textRendererWithDisplayContentsParent->textNode()->parentElementInComposedTree();
239 if (!composedTreeParentElement)
242 auto style = composedTreeParentElement->styleResolver().styleForElement(*composedTreeParentElement, &parentStyle).renderStyle;
243 ASSERT(style->display() == CONTENTS);
245 // We act as if there was an unstyled <span> around the text node. Only styling happens via inheritance.
246 auto firstLineStyle = RenderStyle::createPtr();
247 firstLineStyle->inheritFrom(*style);
248 return firstLineStyle;
251 return rendererForFirstLineStyle.element()->styleResolver().styleForElement(*element(), &parentStyle).renderStyle;
254 const RenderStyle& RenderElement::firstLineStyle() const
256 if (!view().usesFirstLineRules())
259 if (!m_hasValidCachedFirstLineStyle) {
260 auto firstLineStyle = computeFirstLineStyle();
261 if (firstLineStyle || hasRareData())
262 const_cast<RenderElement&>(*this).ensureRareData().cachedFirstLineStyle = WTFMove(firstLineStyle);
263 m_hasValidCachedFirstLineStyle = true;
266 return (hasRareData() && rareData().cachedFirstLineStyle) ? *rareData().cachedFirstLineStyle : style();
269 StyleDifference RenderElement::adjustStyleDifference(StyleDifference diff, unsigned contextSensitiveProperties) const
271 // If transform changed, and we are not composited, need to do a layout.
272 if (contextSensitiveProperties & ContextSensitivePropertyTransform) {
273 // FIXME: when transforms are taken into account for overflow, we will need to do a layout.
274 if (!hasLayer() || !downcast<RenderLayerModelObject>(*this).layer()->isComposited()) {
276 diff = std::max(diff, StyleDifferenceLayout);
278 // We need to set at least SimplifiedLayout, but if PositionedMovementOnly is already set
279 // then we actually need SimplifiedLayoutAndPositionedMovement.
280 diff = std::max(diff, (diff == StyleDifferenceLayoutPositionedMovementOnly) ? StyleDifferenceSimplifiedLayoutAndPositionedMovement : StyleDifferenceSimplifiedLayout);
284 diff = std::max(diff, StyleDifferenceRecompositeLayer);
287 if (contextSensitiveProperties & ContextSensitivePropertyOpacity) {
288 if (!hasLayer() || !downcast<RenderLayerModelObject>(*this).layer()->isComposited())
289 diff = std::max(diff, StyleDifferenceRepaintLayer);
291 diff = std::max(diff, StyleDifferenceRecompositeLayer);
294 if (contextSensitiveProperties & ContextSensitivePropertyClipPath) {
296 && downcast<RenderLayerModelObject>(*this).layer()->isComposited()
298 && RenderLayerCompositor::canCompositeClipPath(*downcast<RenderLayerModelObject>(*this).layer()))
299 diff = std::max(diff, StyleDifferenceRecompositeLayer);
301 diff = std::max(diff, StyleDifferenceRepaint);
304 if (contextSensitiveProperties & ContextSensitivePropertyWillChange) {
305 if (style().willChange() && style().willChange()->canTriggerCompositing())
306 diff = std::max(diff, StyleDifferenceRecompositeLayer);
309 if ((contextSensitiveProperties & ContextSensitivePropertyFilter) && hasLayer()) {
310 auto& layer = *downcast<RenderLayerModelObject>(*this).layer();
311 if (!layer.isComposited() || layer.paintsWithFilters())
312 diff = std::max(diff, StyleDifferenceRepaintLayer);
314 diff = std::max(diff, StyleDifferenceRecompositeLayer);
317 // The answer to requiresLayer() for plugins, iframes, and canvas can change without the actual
318 // style changing, since it depends on whether we decide to composite these elements. When the
319 // layer status of one of these elements changes, we need to force a layout.
320 if (diff < StyleDifferenceLayout && isRenderLayerModelObject()) {
321 if (hasLayer() != downcast<RenderLayerModelObject>(*this).requiresLayer())
322 diff = StyleDifferenceLayout;
325 // If we have no layer(), just treat a RepaintLayer hint as a normal Repaint.
326 if (diff == StyleDifferenceRepaintLayer && !hasLayer())
327 diff = StyleDifferenceRepaint;
332 inline bool RenderElement::hasImmediateNonWhitespaceTextChildOrBorderOrOutline() const
334 for (auto& child : childrenOfType<RenderObject>(*this)) {
335 if (is<RenderText>(child) && !downcast<RenderText>(child).isAllCollapsibleWhitespace())
337 if (child.style().hasOutline() || child.style().hasBorder())
343 inline bool RenderElement::shouldRepaintForStyleDifference(StyleDifference diff) const
345 return diff == StyleDifferenceRepaint || (diff == StyleDifferenceRepaintIfTextOrBorderOrOutline && hasImmediateNonWhitespaceTextChildOrBorderOrOutline());
348 void RenderElement::updateFillImages(const FillLayer* oldLayers, const FillLayer& newLayers)
350 // Optimize the common case.
351 if (FillLayer::imagesIdentical(oldLayers, &newLayers))
354 // Add before removing, to avoid removing all clients of an image that is in both sets.
355 for (auto* layer = &newLayers; layer; layer = layer->next()) {
357 layer->image()->addClient(this);
359 for (auto* layer = oldLayers; layer; layer = layer->next()) {
361 layer->image()->removeClient(this);
365 void RenderElement::updateImage(StyleImage* oldImage, StyleImage* newImage)
367 if (oldImage == newImage)
370 oldImage->removeClient(this);
372 newImage->addClient(this);
375 void RenderElement::updateShapeImage(const ShapeValue* oldShapeValue, const ShapeValue* newShapeValue)
377 if (oldShapeValue || newShapeValue)
378 updateImage(oldShapeValue ? oldShapeValue->image() : nullptr, newShapeValue ? newShapeValue->image() : nullptr);
381 void RenderElement::initializeStyle()
383 Style::loadPendingResources(m_style, document(), element());
385 styleWillChange(StyleDifferenceNewStyle, style());
386 m_hasInitializedStyle = true;
387 styleDidChange(StyleDifferenceNewStyle, nullptr);
389 // We shouldn't have any text children that would need styleDidChange at this point.
390 ASSERT(!childrenOfType<RenderText>(*this).first());
392 // It would be nice to assert that !parent() here, but some RenderLayer subrenderers
393 // have their parent set before getting a call to initializeStyle() :|
396 void RenderElement::setStyle(RenderStyle&& style, StyleDifference minimalStyleDifference)
398 // FIXME: Should change RenderView so it can use initializeStyle too.
399 // If we do that, we can assert m_hasInitializedStyle unconditionally,
400 // and remove the check of m_hasInitializedStyle below too.
401 ASSERT(m_hasInitializedStyle || isRenderView());
403 StyleDifference diff = StyleDifferenceEqual;
404 unsigned contextSensitiveProperties = ContextSensitivePropertyNone;
405 if (m_hasInitializedStyle)
406 diff = m_style.diff(style, contextSensitiveProperties);
408 diff = std::max(diff, minimalStyleDifference);
410 diff = adjustStyleDifference(diff, contextSensitiveProperties);
412 Style::loadPendingResources(style, document(), element());
414 styleWillChange(diff, style);
415 auto oldStyle = m_style.replace(WTFMove(style));
416 bool detachedFromParent = !parent();
418 // Make sure we invalidate the containing block cache for flows when the contianing block context changes
419 // so that styleDidChange can safely use RenderBlock::locateEnclosingFragmentedFlow()
420 if (oldStyle.position() != m_style.position())
421 adjustFragmentedFlowStateOnContainingBlockChangeIfNeeded();
423 styleDidChange(diff, &oldStyle);
425 // Text renderers use their parent style. Notify them about the change.
426 for (auto& child : childrenOfType<RenderText>(*this))
427 child.styleDidChange(diff, &oldStyle);
429 // FIXME: |this| might be destroyed here. This can currently happen for a RenderTextFragment when
430 // its first-letter block gets an update in RenderTextFragment::styleDidChange. For RenderTextFragment(s),
431 // we will safely bail out with the detachedFromParent flag. We might want to broaden this condition
432 // in the future as we move renderer changes out of layout and into style changes.
433 if (detachedFromParent)
436 // Now that the layer (if any) has been updated, we need to adjust the diff again,
437 // check whether we should layout now, and decide if we need to repaint.
438 StyleDifference updatedDiff = adjustStyleDifference(diff, contextSensitiveProperties);
440 if (diff <= StyleDifferenceLayoutPositionedMovementOnly) {
441 if (updatedDiff == StyleDifferenceLayout)
442 setNeedsLayoutAndPrefWidthsRecalc();
443 else if (updatedDiff == StyleDifferenceLayoutPositionedMovementOnly)
444 setNeedsPositionedMovementLayout(&oldStyle);
445 else if (updatedDiff == StyleDifferenceSimplifiedLayoutAndPositionedMovement) {
446 setNeedsPositionedMovementLayout(&oldStyle);
447 setNeedsSimplifiedNormalFlowLayout();
448 } else if (updatedDiff == StyleDifferenceSimplifiedLayout)
449 setNeedsSimplifiedNormalFlowLayout();
452 if (updatedDiff == StyleDifferenceRepaintLayer || shouldRepaintForStyleDifference(updatedDiff)) {
453 // Do a repaint with the new style now, e.g., for example if we go from
454 // not having an outline to having an outline.
459 void RenderElement::didAttachChild(RenderObject& child, RenderObject*)
461 if (is<RenderText>(child))
462 downcast<RenderText>(child).styleDidChange(StyleDifferenceEqual, nullptr);
463 // SVG creates renderers for <g display="none">, as SVG requires children of hidden
464 // <g>s to have renderers - at least that's how our implementation works. Consider:
465 // <g display="none"><foreignObject><body style="position: relative">FOO...
466 // - requiresLayer() would return true for the <body>, creating a new RenderLayer
467 // - when the document is painted, both layers are painted. The <body> layer doesn't
468 // know that it's inside a "hidden SVG subtree", and thus paints, even if it shouldn't.
469 // To avoid the problem alltogether, detect early if we're inside a hidden SVG subtree
470 // and stop creating layers at all for these cases - they're not used anyways.
471 if (child.hasLayer() && !layerCreationAllowedForSubtree())
472 downcast<RenderLayerModelObject>(child).layer()->removeOnlyThisLayer();
473 SVGRenderSupport::childAdded(*this, child);
476 RenderObject* RenderElement::attachRendererInternal(RenderPtr<RenderObject> child, RenderObject* beforeChild)
478 child->setParent(this);
480 if (m_firstChild == beforeChild)
481 m_firstChild = child.get();
484 auto* previousSibling = beforeChild->previousSibling();
486 previousSibling->setNextSibling(child.get());
487 child->setPreviousSibling(previousSibling);
488 child->setNextSibling(beforeChild);
489 beforeChild->setPreviousSibling(child.get());
490 return child.release();
493 m_lastChild->setNextSibling(child.get());
494 child->setPreviousSibling(m_lastChild);
495 m_lastChild = child.get();
496 return child.release();
499 RenderPtr<RenderObject> RenderElement::detachRendererInternal(RenderObject& renderer)
501 auto* parent = renderer.parent();
503 auto* nextSibling = renderer.nextSibling();
505 if (renderer.previousSibling())
506 renderer.previousSibling()->setNextSibling(nextSibling);
508 nextSibling->setPreviousSibling(renderer.previousSibling());
510 if (parent->firstChild() == &renderer)
511 parent->m_firstChild = nextSibling;
512 if (parent->lastChild() == &renderer)
513 parent->m_lastChild = renderer.previousSibling();
515 renderer.setPreviousSibling(nullptr);
516 renderer.setNextSibling(nullptr);
517 renderer.setParent(nullptr);
518 return RenderPtr<RenderObject>(&renderer);
521 RenderBlock* RenderElement::containingBlockForFixedPosition() const
523 auto* renderer = parent();
524 while (renderer && !renderer->canContainFixedPositionObjects())
525 renderer = renderer->parent();
527 ASSERT(!renderer || !renderer->isAnonymousBlock());
528 return downcast<RenderBlock>(renderer);
531 RenderBlock* RenderElement::containingBlockForAbsolutePosition() const
533 // A relatively positioned RenderInline forwards its absolute positioned descendants to
534 // its nearest non-anonymous containing block (to avoid having a positioned objects list in all RenderInlines).
535 auto* renderer = isRenderInline() ? const_cast<RenderElement*>(downcast<RenderElement>(this)) : parent();
536 while (renderer && !renderer->canContainAbsolutelyPositionedObjects())
537 renderer = renderer->parent();
538 // Make sure we only return non-anonymous RenderBlock as containing block.
539 while (renderer && (!is<RenderBlock>(*renderer) || renderer->isAnonymousBlock()))
540 renderer = renderer->containingBlock();
541 return downcast<RenderBlock>(renderer);
544 static void addLayers(RenderElement& renderer, RenderLayer* parentLayer, RenderElement*& newObject, RenderLayer*& beforeChild)
546 if (renderer.hasLayer()) {
547 if (!beforeChild && newObject) {
548 // We need to figure out the layer that follows newObject. We only do
549 // this the first time we find a child layer, and then we update the
550 // pointer values for newObject and beforeChild used by everyone else.
551 beforeChild = newObject->parent()->findNextLayer(parentLayer, newObject);
554 parentLayer->addChild(downcast<RenderLayerModelObject>(renderer).layer(), beforeChild);
558 for (auto& child : childrenOfType<RenderElement>(renderer))
559 addLayers(child, parentLayer, newObject, beforeChild);
562 void RenderElement::addLayers(RenderLayer* parentLayer)
567 RenderElement* renderer = this;
568 RenderLayer* beforeChild = nullptr;
569 WebCore::addLayers(*this, parentLayer, renderer, beforeChild);
572 void RenderElement::removeLayers(RenderLayer* parentLayer)
578 parentLayer->removeChild(downcast<RenderLayerModelObject>(*this).layer());
582 for (auto& child : childrenOfType<RenderElement>(*this))
583 child.removeLayers(parentLayer);
586 void RenderElement::moveLayers(RenderLayer* oldParent, RenderLayer* newParent)
592 RenderLayer* layer = downcast<RenderLayerModelObject>(*this).layer();
593 ASSERT(oldParent == layer->parent());
595 oldParent->removeChild(layer);
596 newParent->addChild(layer);
600 for (auto& child : childrenOfType<RenderElement>(*this))
601 child.moveLayers(oldParent, newParent);
604 RenderLayer* RenderElement::findNextLayer(RenderLayer* parentLayer, RenderObject* startPoint, bool checkParent)
606 // Error check the parent layer passed in. If it's null, we can't find anything.
610 // Step 1: If our layer is a child of the desired parent, then return our layer.
611 RenderLayer* ourLayer = hasLayer() ? downcast<RenderLayerModelObject>(*this).layer() : nullptr;
612 if (ourLayer && ourLayer->parent() == parentLayer)
615 // Step 2: If we don't have a layer, or our layer is the desired parent, then descend
616 // into our siblings trying to find the next layer whose parent is the desired parent.
617 if (!ourLayer || ourLayer == parentLayer) {
618 for (RenderObject* child = startPoint ? startPoint->nextSibling() : firstChild(); child; child = child->nextSibling()) {
619 if (!is<RenderElement>(*child))
621 RenderLayer* nextLayer = downcast<RenderElement>(*child).findNextLayer(parentLayer, nullptr, false);
627 // Step 3: If our layer is the desired parent layer, then we're finished. We didn't
629 if (parentLayer == ourLayer)
632 // Step 4: If |checkParent| is set, climb up to our parent and check its siblings that
633 // follow us to see if we can locate a layer.
634 if (checkParent && parent())
635 return parent()->findNextLayer(parentLayer, this, true);
640 bool RenderElement::layerCreationAllowedForSubtree() const
642 RenderElement* parentRenderer = parent();
643 while (parentRenderer) {
644 if (parentRenderer->isSVGHiddenContainer())
646 parentRenderer = parentRenderer->parent();
652 void RenderElement::propagateStyleToAnonymousChildren(StylePropagationType propagationType)
654 // FIXME: We could save this call when the change only affected non-inherited properties.
655 for (auto& elementChild : childrenOfType<RenderElement>(*this)) {
656 if (!elementChild.isAnonymous() || elementChild.style().styleType() != NOPSEUDO)
659 if (propagationType == PropagateToBlockChildrenOnly && !is<RenderBlock>(elementChild))
662 #if ENABLE(FULLSCREEN_API)
663 if (elementChild.isRenderFullScreen() || elementChild.isRenderFullScreenPlaceholder())
667 // RenderFragmentedFlows are updated through the RenderView::styleDidChange function.
668 if (is<RenderFragmentedFlow>(elementChild))
671 auto newStyle = RenderStyle::createAnonymousStyleWithDisplay(style(), elementChild.style().display());
672 if (style().specifiesColumns()) {
673 if (elementChild.style().specifiesColumns())
674 newStyle.inheritColumnPropertiesFrom(style());
675 if (elementChild.style().columnSpan())
676 newStyle.setColumnSpan(ColumnSpanAll);
679 // Preserve the position style of anonymous block continuations as they can have relative or sticky position when
680 // they contain block descendants of relative or sticky positioned inlines.
681 if (elementChild.isInFlowPositioned() && elementChild.isContinuation())
682 newStyle.setPosition(elementChild.style().position());
684 updateAnonymousChildStyle(newStyle);
686 elementChild.setStyle(WTFMove(newStyle));
690 static inline bool rendererHasBackground(const RenderElement* renderer)
692 return renderer && renderer->hasBackground();
695 void RenderElement::invalidateCachedFirstLineStyle()
697 if (!m_hasValidCachedFirstLineStyle)
699 m_hasValidCachedFirstLineStyle = false;
700 // Invalidate the subtree as descendant's first line style may depend on ancestor's.
701 for (auto& descendant : descendantsOfType<RenderElement>(*this))
702 descendant.m_hasValidCachedFirstLineStyle = false;
705 void RenderElement::styleWillChange(StyleDifference diff, const RenderStyle& newStyle)
707 auto* oldStyle = hasInitializedStyle() ? &style() : nullptr;
709 // If our z-index changes value or our visibility changes,
710 // we need to dirty our stacking context's z-order list.
711 bool visibilityChanged = m_style.visibility() != newStyle.visibility()
712 || m_style.zIndex() != newStyle.zIndex()
713 || m_style.hasAutoZIndex() != newStyle.hasAutoZIndex();
714 #if ENABLE(DASHBOARD_SUPPORT)
715 if (visibilityChanged)
716 document().setAnnotatedRegionsDirty(true);
718 #if PLATFORM(IOS) && ENABLE(TOUCH_EVENTS)
719 if (visibilityChanged)
720 document().setTouchEventRegionsNeedUpdate();
722 if (visibilityChanged) {
723 if (AXObjectCache* cache = document().existingAXObjectCache())
724 cache->childrenChanged(parent(), this);
727 // Keep layer hierarchy visibility bits up to date if visibility changes.
728 if (m_style.visibility() != newStyle.visibility()) {
729 if (RenderLayer* layer = enclosingLayer()) {
730 if (newStyle.visibility() == VISIBLE)
731 layer->setHasVisibleContent();
732 else if (layer->hasVisibleContent() && (this == &layer->renderer() || layer->renderer().style().visibility() != VISIBLE)) {
733 layer->dirtyVisibleContentStatus();
734 if (diff > StyleDifferenceRepaintLayer)
740 if (m_parent && (newStyle.outlineSize() < m_style.outlineSize() || shouldRepaintForStyleDifference(diff)))
742 if (isFloating() && m_style.floating() != newStyle.floating()) {
743 // For changes in float styles, we need to conceivably remove ourselves
744 // from the floating objects list.
745 downcast<RenderBox>(*this).removeFloatingOrPositionedChildFromBlockLists();
746 } else if (isOutOfFlowPositioned() && m_style.position() != newStyle.position()) {
747 // For changes in positioning styles, we need to conceivably remove ourselves
748 // from the positioned objects list.
749 downcast<RenderBox>(*this).removeFloatingOrPositionedChildFromBlockLists();
752 s_affectsParentBlock = isFloatingOrOutOfFlowPositioned()
753 && (!newStyle.isFloating() && !newStyle.hasOutOfFlowPosition())
754 && parent() && (parent()->isRenderBlockFlow() || parent()->isRenderInline());
756 s_noLongerAffectsParentBlock = ((!isFloating() && newStyle.isFloating()) || (!isOutOfFlowPositioned() && newStyle.hasOutOfFlowPosition()))
757 && parent() && parent()->isRenderBlock();
760 if (diff == StyleDifferenceLayout || diff == StyleDifferenceLayoutPositionedMovementOnly) {
762 clearPositionedState();
764 if (newStyle.hasPseudoStyle(FIRST_LINE) || oldStyle->hasPseudoStyle(FIRST_LINE))
765 invalidateCachedFirstLineStyle();
767 setHorizontalWritingMode(true);
768 setHasVisibleBoxDecorations(false);
769 setHasOverflowClip(false);
770 setHasTransformRelatedProperty(false);
771 setHasReflection(false);
773 s_affectsParentBlock = false;
774 s_noLongerAffectsParentBlock = false;
777 bool newStyleSlowScroll = false;
778 if (newStyle.hasFixedBackgroundImage() && !settings().fixedBackgroundsPaintRelativeToDocument()) {
779 newStyleSlowScroll = true;
780 bool drawsRootBackground = isDocumentElementRenderer() || (isBody() && !rendererHasBackground(document().documentElement()->renderer()));
781 if (drawsRootBackground && newStyle.hasEntirelyFixedBackground() && view().compositor().supportsFixedRootBackgroundCompositing())
782 newStyleSlowScroll = false;
785 if (view().frameView().hasSlowRepaintObject(*this)) {
786 if (!newStyleSlowScroll)
787 view().frameView().removeSlowRepaintObject(*this);
788 } else if (newStyleSlowScroll)
789 view().frameView().addSlowRepaintObject(*this);
791 if (isDocumentElementRenderer() || isBody())
792 view().frameView().updateExtendBackgroundIfNecessary();
796 static bool areNonIdenticalCursorListsEqual(const RenderStyle* a, const RenderStyle* b)
798 ASSERT(a->cursors() != b->cursors());
799 return a->cursors() && b->cursors() && *a->cursors() == *b->cursors();
802 static inline bool areCursorsEqual(const RenderStyle* a, const RenderStyle* b)
804 return a->cursor() == b->cursor() && (a->cursors() == b->cursors() || areNonIdenticalCursorListsEqual(a, b));
808 void RenderElement::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
810 updateFillImages(oldStyle ? &oldStyle->backgroundLayers() : nullptr, m_style.backgroundLayers());
811 updateFillImages(oldStyle ? &oldStyle->maskLayers() : nullptr, m_style.maskLayers());
812 updateImage(oldStyle ? oldStyle->borderImage().image() : nullptr, m_style.borderImage().image());
813 updateImage(oldStyle ? oldStyle->maskBoxImage().image() : nullptr, m_style.maskBoxImage().image());
814 updateShapeImage(oldStyle ? oldStyle->shapeOutside() : nullptr, m_style.shapeOutside());
816 if (s_affectsParentBlock) {
817 // We have gone from not affecting the inline status of the parent flow to suddenly
818 // having an impact. See if there is a mismatch between the parent flow's
819 // childrenInline() state and our state.
820 setInline(style().isDisplayInlineType());
821 if (isInline() != parent()->childrenInline())
822 RenderTreeBuilder::current()->childFlowStateChangesAndAffectsParentBlock(*this);
825 if (s_noLongerAffectsParentBlock)
826 RenderTreeBuilder::current()->childFlowStateChangesAndNoLongerAffectsParentBlock(*this);
828 SVGRenderSupport::styleChanged(*this, oldStyle);
833 if (diff == StyleDifferenceLayout || diff == StyleDifferenceSimplifiedLayout) {
834 RenderCounter::rendererStyleChanged(*this, oldStyle, &m_style);
836 // If the object already needs layout, then setNeedsLayout won't do
837 // any work. But if the containing block has changed, then we may need
838 // to mark the new containing blocks for layout. The change that can
839 // directly affect the containing block of this object is a change to
840 // the position style.
841 if (needsLayout() && oldStyle->position() != m_style.position())
842 markContainingBlocksForLayout();
844 if (diff == StyleDifferenceLayout)
845 setNeedsLayoutAndPrefWidthsRecalc();
847 setNeedsSimplifiedNormalFlowLayout();
848 } else if (diff == StyleDifferenceSimplifiedLayoutAndPositionedMovement) {
849 setNeedsPositionedMovementLayout(oldStyle);
850 setNeedsSimplifiedNormalFlowLayout();
851 } else if (diff == StyleDifferenceLayoutPositionedMovementOnly)
852 setNeedsPositionedMovementLayout(oldStyle);
854 // Don't check for repaint here; we need to wait until the layer has been
855 // updated by subclasses before we know if we have to repaint (in setStyle()).
858 if (oldStyle && !areCursorsEqual(oldStyle, &style()))
859 frame().eventHandler().scheduleCursorUpdate();
861 bool hadOutlineAuto = oldStyle && oldStyle->outlineStyleIsAuto();
862 bool hasOutlineAuto = outlineStyleForRepaint().outlineStyleIsAuto();
863 if (hasOutlineAuto != hadOutlineAuto) {
864 updateOutlineAutoAncestor(hasOutlineAuto);
865 issueRepaintForOutlineAuto(hasOutlineAuto ? outlineStyleForRepaint().outlineSize() : oldStyle->outlineSize());
869 void RenderElement::insertedIntoTree()
871 // Keep our layer hierarchy updated. Optimize for the common case where we don't have any children
872 // and don't have a layer attached to ourselves.
873 RenderLayer* layer = nullptr;
874 if (firstChild() || hasLayer()) {
875 layer = parent()->enclosingLayer();
879 // If |this| is visible but this object was not, tell the layer it has some visible content
880 // that needs to be drawn and layer visibility optimization can't be used
881 if (parent()->style().visibility() != VISIBLE && style().visibility() == VISIBLE && !hasLayer()) {
883 layer = parent()->enclosingLayer();
885 layer->setHasVisibleContent();
888 RenderObject::insertedIntoTree();
891 void RenderElement::willBeRemovedFromTree()
893 // If we remove a visible child from an invisible parent, we don't know the layer visibility any more.
894 RenderLayer* layer = nullptr;
895 if (parent()->style().visibility() != VISIBLE && style().visibility() == VISIBLE && !hasLayer()) {
896 if ((layer = parent()->enclosingLayer()))
897 layer->dirtyVisibleContentStatus();
899 // Keep our layer hierarchy updated.
900 if (firstChild() || hasLayer()) {
902 layer = parent()->enclosingLayer();
906 if (isOutOfFlowPositioned() && parent()->childrenInline())
907 parent()->dirtyLinesFromChangedChild(*this);
909 RenderObject::willBeRemovedFromTree();
912 inline void RenderElement::clearSubtreeLayoutRootIfNeeded() const
914 if (renderTreeBeingDestroyed())
917 if (view().frameView().layoutContext().subtreeLayoutRoot() != this)
920 // Normally when a renderer is detached from the tree, the appropriate dirty bits get set
921 // which ensures that this renderer is no longer the layout root.
922 ASSERT_NOT_REACHED();
924 // This indicates a failure to layout the child, which is why
925 // the layout root is still set to |this|. Make sure to clear it
926 // since we are getting destroyed.
927 view().frameView().layoutContext().clearSubtreeLayoutRoot();
930 void RenderElement::willBeDestroyed()
932 if (m_style.hasFixedBackgroundImage() && !settings().fixedBackgroundsPaintRelativeToDocument())
933 view().frameView().removeSlowRepaintObject(*this);
935 unregisterForVisibleInViewportCallback();
937 if (hasCounterNodeMap())
938 RenderCounter::destroyCounterNodes(*this);
940 RenderObject::willBeDestroyed();
942 clearSubtreeLayoutRootIfNeeded();
944 if (hasInitializedStyle()) {
945 for (auto* bgLayer = &m_style.backgroundLayers(); bgLayer; bgLayer = bgLayer->next()) {
946 if (auto* backgroundImage = bgLayer->image())
947 backgroundImage->removeClient(this);
949 for (auto* maskLayer = &m_style.maskLayers(); maskLayer; maskLayer = maskLayer->next()) {
950 if (auto* maskImage = maskLayer->image())
951 maskImage->removeClient(this);
953 if (auto* borderImage = m_style.borderImage().image())
954 borderImage->removeClient(this);
955 if (auto* maskBoxImage = m_style.maskBoxImage().image())
956 maskBoxImage->removeClient(this);
957 if (auto shapeValue = m_style.shapeOutside()) {
958 if (auto shapeImage = shapeValue->image())
959 shapeImage->removeClient(this);
962 if (m_hasPausedImageAnimations)
963 view().removeRendererWithPausedImageAnimations(*this);
966 void RenderElement::setNeedsPositionedMovementLayout(const RenderStyle* oldStyle)
968 ASSERT(!isSetNeedsLayoutForbidden());
969 if (needsPositionedMovementLayout())
971 setNeedsPositionedMovementLayoutBit(true);
972 markContainingBlocksForLayout();
974 if (oldStyle && style().diffRequiresLayerRepaint(*oldStyle, downcast<RenderLayerModelObject>(*this).layer()->isComposited()))
975 setLayerNeedsFullRepaint();
977 setLayerNeedsFullRepaintForPositionedMovementLayout();
981 void RenderElement::clearChildNeedsLayout()
983 setNormalChildNeedsLayoutBit(false);
984 setPosChildNeedsLayoutBit(false);
985 setNeedsSimplifiedNormalFlowLayoutBit(false);
986 setNormalChildNeedsLayoutBit(false);
987 setNeedsPositionedMovementLayoutBit(false);
990 void RenderElement::setNeedsSimplifiedNormalFlowLayout()
992 ASSERT(!isSetNeedsLayoutForbidden());
993 if (needsSimplifiedNormalFlowLayout())
995 setNeedsSimplifiedNormalFlowLayoutBit(true);
996 markContainingBlocksForLayout();
998 setLayerNeedsFullRepaint();
1001 RenderElement* RenderElement::hoverAncestor() const
1006 static inline void paintPhase(RenderElement& element, PaintPhase phase, PaintInfo& paintInfo, const LayoutPoint& childPoint)
1008 paintInfo.phase = phase;
1009 element.paint(paintInfo, childPoint);
1012 void RenderElement::paintAsInlineBlock(PaintInfo& paintInfo, const LayoutPoint& childPoint)
1014 // Paint all phases atomically, as though the element established its own stacking context.
1015 // (See Appendix E.2, section 6.4 on inline block/table/replaced elements in the CSS2.1 specification.)
1016 // This is also used by other elements (e.g. flex items and grid items).
1017 PaintPhase paintPhaseToUse = isExcludedAndPlacedInBorder() ? paintInfo.phase : PaintPhaseForeground;
1018 if (paintInfo.phase == PaintPhaseSelection)
1019 paint(paintInfo, childPoint);
1020 else if (paintInfo.phase == paintPhaseToUse) {
1021 paintPhase(*this, PaintPhaseBlockBackground, paintInfo, childPoint);
1022 paintPhase(*this, PaintPhaseChildBlockBackgrounds, paintInfo, childPoint);
1023 paintPhase(*this, PaintPhaseFloat, paintInfo, childPoint);
1024 paintPhase(*this, PaintPhaseForeground, paintInfo, childPoint);
1025 paintPhase(*this, PaintPhaseOutline, paintInfo, childPoint);
1027 // Reset |paintInfo| to the original phase.
1028 paintInfo.phase = paintPhaseToUse;
1032 void RenderElement::layout()
1034 StackStats::LayoutCheckPoint layoutCheckPoint;
1035 ASSERT(needsLayout());
1036 for (auto* child = firstChild(); child; child = child->nextSibling()) {
1037 if (child->needsLayout())
1038 downcast<RenderElement>(*child).layout();
1039 ASSERT(!child->needsLayout());
1044 static bool mustRepaintFillLayers(const RenderElement& renderer, const FillLayer& layer)
1046 // Nobody will use multiple layers without wanting fancy positioning.
1050 // Make sure we have a valid image.
1051 auto* image = layer.image();
1052 if (!image || !image->canRender(&renderer, renderer.style().effectiveZoom()))
1055 if (!layer.xPosition().isZero() || !layer.yPosition().isZero())
1058 auto sizeType = layer.sizeType();
1060 if (sizeType == Contain || sizeType == Cover)
1063 if (sizeType == SizeLength) {
1064 auto size = layer.sizeLength();
1065 if (size.width.isPercentOrCalculated() || size.height.isPercentOrCalculated())
1067 // If the image has neither an intrinsic width nor an intrinsic height, its size is determined as for 'contain'.
1068 if ((size.width.isAuto() || size.height.isAuto()) && image->isGeneratedImage())
1070 } else if (image->usesImageContainerSize())
1076 static bool mustRepaintBackgroundOrBorder(const RenderElement& renderer)
1078 if (renderer.hasMask() && mustRepaintFillLayers(renderer, renderer.style().maskLayers()))
1081 // If we don't have a background/border/mask, then nothing to do.
1082 if (!renderer.hasVisibleBoxDecorations())
1085 if (mustRepaintFillLayers(renderer, renderer.style().backgroundLayers()))
1088 // Our fill layers are ok. Let's check border.
1089 if (renderer.style().hasBorder() && renderer.borderImageIsLoadedAndCanBeRendered())
1095 bool RenderElement::repaintAfterLayoutIfNeeded(const RenderLayerModelObject* repaintContainer, const LayoutRect& oldBounds, const LayoutRect& oldOutlineBox, const LayoutRect* newBoundsPtr, const LayoutRect* newOutlineBoxRectPtr)
1097 if (view().printing())
1098 return false; // Don't repaint if we're printing.
1100 // This ASSERT fails due to animations. See https://bugs.webkit.org/show_bug.cgi?id=37048
1101 // ASSERT(!newBoundsPtr || *newBoundsPtr == clippedOverflowRectForRepaint(repaintContainer));
1102 LayoutRect newBounds = newBoundsPtr ? *newBoundsPtr : clippedOverflowRectForRepaint(repaintContainer);
1103 LayoutRect newOutlineBox;
1105 bool fullRepaint = selfNeedsLayout();
1106 // Presumably a background or a border exists if border-fit:lines was specified.
1107 if (!fullRepaint && style().borderFit() == BorderFitLines)
1110 // This ASSERT fails due to animations. See https://bugs.webkit.org/show_bug.cgi?id=37048
1111 // ASSERT(!newOutlineBoxRectPtr || *newOutlineBoxRectPtr == outlineBoundsForRepaint(repaintContainer));
1112 newOutlineBox = newOutlineBoxRectPtr ? *newOutlineBoxRectPtr : outlineBoundsForRepaint(repaintContainer);
1113 fullRepaint = (newOutlineBox.location() != oldOutlineBox.location() || (mustRepaintBackgroundOrBorder(*this) && (newBounds != oldBounds || newOutlineBox != oldOutlineBox)));
1116 if (!repaintContainer)
1117 repaintContainer = &view();
1120 repaintUsingContainer(repaintContainer, oldBounds);
1121 if (newBounds != oldBounds)
1122 repaintUsingContainer(repaintContainer, newBounds);
1126 if (newBounds == oldBounds && newOutlineBox == oldOutlineBox)
1129 LayoutUnit deltaLeft = newBounds.x() - oldBounds.x();
1131 repaintUsingContainer(repaintContainer, LayoutRect(oldBounds.x(), oldBounds.y(), deltaLeft, oldBounds.height()));
1132 else if (deltaLeft < 0)
1133 repaintUsingContainer(repaintContainer, LayoutRect(newBounds.x(), newBounds.y(), -deltaLeft, newBounds.height()));
1135 LayoutUnit deltaRight = newBounds.maxX() - oldBounds.maxX();
1137 repaintUsingContainer(repaintContainer, LayoutRect(oldBounds.maxX(), newBounds.y(), deltaRight, newBounds.height()));
1138 else if (deltaRight < 0)
1139 repaintUsingContainer(repaintContainer, LayoutRect(newBounds.maxX(), oldBounds.y(), -deltaRight, oldBounds.height()));
1141 LayoutUnit deltaTop = newBounds.y() - oldBounds.y();
1143 repaintUsingContainer(repaintContainer, LayoutRect(oldBounds.x(), oldBounds.y(), oldBounds.width(), deltaTop));
1144 else if (deltaTop < 0)
1145 repaintUsingContainer(repaintContainer, LayoutRect(newBounds.x(), newBounds.y(), newBounds.width(), -deltaTop));
1147 LayoutUnit deltaBottom = newBounds.maxY() - oldBounds.maxY();
1148 if (deltaBottom > 0)
1149 repaintUsingContainer(repaintContainer, LayoutRect(newBounds.x(), oldBounds.maxY(), newBounds.width(), deltaBottom));
1150 else if (deltaBottom < 0)
1151 repaintUsingContainer(repaintContainer, LayoutRect(oldBounds.x(), newBounds.maxY(), oldBounds.width(), -deltaBottom));
1153 if (newOutlineBox == oldOutlineBox)
1156 // We didn't move, but we did change size. Invalidate the delta, which will consist of possibly
1157 // two rectangles (but typically only one).
1158 const RenderStyle& outlineStyle = outlineStyleForRepaint();
1159 LayoutUnit outlineWidth = outlineStyle.outlineSize();
1160 LayoutBoxExtent insetShadowExtent = style().getBoxShadowInsetExtent();
1161 LayoutUnit width = absoluteValue(newOutlineBox.width() - oldOutlineBox.width());
1163 LayoutUnit shadowLeft;
1164 LayoutUnit shadowRight;
1165 style().getBoxShadowHorizontalExtent(shadowLeft, shadowRight);
1166 LayoutUnit borderRight = is<RenderBox>(*this) ? downcast<RenderBox>(*this).borderRight() : LayoutUnit::fromPixel(0);
1167 LayoutUnit boxWidth = is<RenderBox>(*this) ? downcast<RenderBox>(*this).width() : LayoutUnit();
1168 LayoutUnit minInsetRightShadowExtent = std::min<LayoutUnit>(-insetShadowExtent.right(), std::min(newBounds.width(), oldBounds.width()));
1169 LayoutUnit borderWidth = std::max(borderRight, std::max(valueForLength(style().borderTopRightRadius().width, boxWidth), valueForLength(style().borderBottomRightRadius().width, boxWidth)));
1170 LayoutUnit decorationsWidth = std::max<LayoutUnit>(-outlineStyle.outlineOffset(), borderWidth + minInsetRightShadowExtent) + std::max(outlineWidth, shadowRight);
1171 LayoutRect rightRect(newOutlineBox.x() + std::min(newOutlineBox.width(), oldOutlineBox.width()) - decorationsWidth,
1173 width + decorationsWidth,
1174 std::max(newOutlineBox.height(), oldOutlineBox.height()));
1175 LayoutUnit right = std::min(newBounds.maxX(), oldBounds.maxX());
1176 if (rightRect.x() < right) {
1177 rightRect.setWidth(std::min(rightRect.width(), right - rightRect.x()));
1178 repaintUsingContainer(repaintContainer, rightRect);
1181 LayoutUnit height = absoluteValue(newOutlineBox.height() - oldOutlineBox.height());
1183 LayoutUnit shadowTop;
1184 LayoutUnit shadowBottom;
1185 style().getBoxShadowVerticalExtent(shadowTop, shadowBottom);
1186 LayoutUnit borderBottom = is<RenderBox>(*this) ? downcast<RenderBox>(*this).borderBottom() : LayoutUnit::fromPixel(0);
1187 LayoutUnit boxHeight = is<RenderBox>(*this) ? downcast<RenderBox>(*this).height() : LayoutUnit();
1188 LayoutUnit minInsetBottomShadowExtent = std::min<LayoutUnit>(-insetShadowExtent.bottom(), std::min(newBounds.height(), oldBounds.height()));
1189 LayoutUnit borderHeight = std::max(borderBottom, std::max(valueForLength(style().borderBottomLeftRadius().height, boxHeight),
1190 valueForLength(style().borderBottomRightRadius().height, boxHeight)));
1191 LayoutUnit decorationsHeight = std::max<LayoutUnit>(-outlineStyle.outlineOffset(), borderHeight + minInsetBottomShadowExtent) + std::max(outlineWidth, shadowBottom);
1192 LayoutRect bottomRect(newOutlineBox.x(),
1193 std::min(newOutlineBox.maxY(), oldOutlineBox.maxY()) - decorationsHeight,
1194 std::max(newOutlineBox.width(), oldOutlineBox.width()),
1195 height + decorationsHeight);
1196 LayoutUnit bottom = std::min(newBounds.maxY(), oldBounds.maxY());
1197 if (bottomRect.y() < bottom) {
1198 bottomRect.setHeight(std::min(bottomRect.height(), bottom - bottomRect.y()));
1199 repaintUsingContainer(repaintContainer, bottomRect);
1205 bool RenderElement::borderImageIsLoadedAndCanBeRendered() const
1207 ASSERT(style().hasBorder());
1209 StyleImage* borderImage = style().borderImage().image();
1210 return borderImage && borderImage->canRender(this, style().effectiveZoom()) && borderImage->isLoaded();
1213 bool RenderElement::mayCauseRepaintInsideViewport(const IntRect* optionalViewportRect) const
1215 auto& frameView = view().frameView();
1216 if (frameView.isOffscreen())
1219 if (!hasOverflowClip()) {
1220 // FIXME: Computing the overflow rect is expensive if any descendant has
1221 // its own self-painting layer. As a result, we prefer to abort early in
1222 // this case and assume it may cause us to repaint inside the viewport.
1223 if (!hasLayer() || downcast<RenderLayerModelObject>(*this).layer()->firstChild())
1227 // Compute viewport rect if it was not provided.
1228 const IntRect& visibleRect = optionalViewportRect ? *optionalViewportRect : frameView.windowToContents(frameView.windowClipRect());
1229 return visibleRect.intersects(enclosingIntRect(absoluteClippedOverflowRect()));
1232 bool RenderElement::isVisibleInDocumentRect(const IntRect& documentRect) const
1234 if (document().activeDOMObjectsAreSuspended())
1236 if (style().visibility() != VISIBLE)
1238 if (view().frameView().isOffscreen())
1241 // Use background rect if we are the root or if we are the body and the background is propagated to the root.
1242 // FIXME: This is overly conservative as the image may not be a background-image, in which case it will not
1243 // be propagated to the root. At this point, we unfortunately don't have access to the image anymore so we
1244 // can no longer check if it is a background image.
1245 bool backgroundIsPaintedByRoot = isDocumentElementRenderer();
1247 auto& rootRenderer = *parent(); // If <body> has a renderer then <html> does too.
1248 ASSERT(rootRenderer.isDocumentElementRenderer());
1249 ASSERT(is<HTMLHtmlElement>(rootRenderer.element()));
1250 // FIXME: Should share body background propagation code.
1251 backgroundIsPaintedByRoot = !rootRenderer.hasBackground();
1255 LayoutRect backgroundPaintingRect = backgroundIsPaintedByRoot ? view().backgroundRect() : absoluteClippedOverflowRect();
1256 if (!documentRect.intersects(enclosingIntRect(backgroundPaintingRect)))
1262 void RenderElement::registerForVisibleInViewportCallback()
1264 if (m_isRegisteredForVisibleInViewportCallback)
1266 m_isRegisteredForVisibleInViewportCallback = true;
1268 view().registerForVisibleInViewportCallback(*this);
1271 void RenderElement::unregisterForVisibleInViewportCallback()
1273 if (!m_isRegisteredForVisibleInViewportCallback)
1275 m_isRegisteredForVisibleInViewportCallback = false;
1277 view().unregisterForVisibleInViewportCallback(*this);
1280 void RenderElement::setVisibleInViewportState(VisibleInViewportState state)
1282 if (state == visibleInViewportState())
1284 m_visibleInViewportState = static_cast<unsigned>(state);
1285 visibleInViewportStateChanged();
1288 void RenderElement::visibleInViewportStateChanged()
1290 ASSERT_NOT_REACHED();
1293 bool RenderElement::isVisibleInViewport() const
1295 auto& frameView = view().frameView();
1296 auto visibleRect = frameView.windowToContents(frameView.windowClipRect());
1297 return isVisibleInDocumentRect(visibleRect);
1300 VisibleInViewportState RenderElement::imageFrameAvailable(CachedImage& image, ImageAnimatingState animatingState, const IntRect* changeRect)
1302 bool isVisible = isVisibleInViewport();
1304 if (!isVisible && animatingState == ImageAnimatingState::Yes)
1305 view().addRendererWithPausedImageAnimations(*this, image);
1307 // Static images should repaint even if they are outside the viewport rectangle
1308 // because they should be inside the TileCoverageRect.
1309 if (isVisible || animatingState == ImageAnimatingState::No)
1310 imageChanged(&image, changeRect);
1312 if (element() && image.image()->isBitmapImage())
1313 element()->dispatchWebKitImageReadyEventForTesting();
1315 return isVisible ? VisibleInViewportState::Yes : VisibleInViewportState::No;
1318 void RenderElement::didRemoveCachedImageClient(CachedImage& cachedImage)
1320 if (hasPausedImageAnimations())
1321 view().removeRendererWithPausedImageAnimations(*this, cachedImage);
1324 bool RenderElement::repaintForPausedImageAnimationsIfNeeded(const IntRect& visibleRect, CachedImage& cachedImage)
1326 ASSERT(m_hasPausedImageAnimations);
1327 if (!isVisibleInDocumentRect(visibleRect))
1332 if (auto* image = cachedImage.image()) {
1333 if (is<SVGImage>(image))
1334 downcast<SVGImage>(image)->scheduleStartAnimation();
1336 image->startAnimation();
1339 // For directly-composited animated GIFs it does not suffice to call repaint() to resume animation. We need to mark the image as changed.
1340 if (is<RenderBoxModelObject>(*this))
1341 downcast<RenderBoxModelObject>(*this).contentChanged(ImageChanged);
1346 const RenderStyle* RenderElement::getCachedPseudoStyle(PseudoId pseudo, const RenderStyle* parentStyle) const
1348 if (pseudo < FIRST_INTERNAL_PSEUDOID && !style().hasPseudoStyle(pseudo))
1351 RenderStyle* cachedStyle = style().getCachedPseudoStyle(pseudo);
1355 std::unique_ptr<RenderStyle> result = getUncachedPseudoStyle(PseudoStyleRequest(pseudo), parentStyle);
1357 return const_cast<RenderStyle&>(m_style).addCachedPseudoStyle(WTFMove(result));
1361 std::unique_ptr<RenderStyle> RenderElement::getUncachedPseudoStyle(const PseudoStyleRequest& pseudoStyleRequest, const RenderStyle* parentStyle, const RenderStyle* ownStyle) const
1363 if (pseudoStyleRequest.pseudoId < FIRST_INTERNAL_PSEUDOID && !ownStyle && !style().hasPseudoStyle(pseudoStyleRequest.pseudoId))
1368 parentStyle = &style();
1374 auto& styleResolver = element()->styleResolver();
1376 std::unique_ptr<RenderStyle> style = styleResolver.pseudoStyleForElement(*element(), pseudoStyleRequest, *parentStyle);
1379 Style::loadPendingResources(*style, document(), element());
1384 Color RenderElement::selectionColor(int colorProperty) const
1386 // If the element is unselectable, or we are only painting the selection,
1387 // don't override the foreground color with the selection foreground color.
1388 if (style().userSelect() == SELECT_NONE
1389 || (view().frameView().paintBehavior() & (PaintBehaviorSelectionOnly | PaintBehaviorSelectionAndBackgroundsOnly)))
1392 if (std::unique_ptr<RenderStyle> pseudoStyle = selectionPseudoStyle()) {
1393 Color color = pseudoStyle->visitedDependentColor(colorProperty);
1394 if (!color.isValid())
1395 color = pseudoStyle->visitedDependentColor(CSSPropertyColor);
1399 if (frame().selection().isFocusedAndActive())
1400 return theme().activeSelectionForegroundColor();
1401 return theme().inactiveSelectionForegroundColor();
1404 std::unique_ptr<RenderStyle> RenderElement::selectionPseudoStyle() const
1409 if (ShadowRoot* root = element()->containingShadowRoot()) {
1410 if (root->mode() == ShadowRootMode::UserAgent) {
1411 if (Element* shadowHost = element()->shadowHost())
1412 return shadowHost->renderer()->getUncachedPseudoStyle(PseudoStyleRequest(SELECTION));
1416 return getUncachedPseudoStyle(PseudoStyleRequest(SELECTION));
1419 Color RenderElement::selectionForegroundColor() const
1421 return selectionColor(CSSPropertyWebkitTextFillColor);
1424 Color RenderElement::selectionEmphasisMarkColor() const
1426 return selectionColor(CSSPropertyWebkitTextEmphasisColor);
1429 Color RenderElement::selectionBackgroundColor() const
1431 if (style().userSelect() == SELECT_NONE)
1434 if (frame().selection().shouldShowBlockCursor() && frame().selection().isCaret())
1435 return style().visitedDependentColor(CSSPropertyColor).blendWithWhite();
1437 std::unique_ptr<RenderStyle> pseudoStyle = selectionPseudoStyle();
1438 if (pseudoStyle && pseudoStyle->visitedDependentColor(CSSPropertyBackgroundColor).isValid())
1439 return pseudoStyle->visitedDependentColor(CSSPropertyBackgroundColor).blendWithWhite();
1441 if (frame().selection().isFocusedAndActive())
1442 return theme().activeSelectionBackgroundColor();
1443 return theme().inactiveSelectionBackgroundColor();
1446 bool RenderElement::getLeadingCorner(FloatPoint& point, bool& insideFixed) const
1448 if (!isInline() || isReplaced()) {
1449 point = localToAbsolute(FloatPoint(), UseTransforms, &insideFixed);
1453 // find the next text/image child, to get a position
1454 const RenderObject* o = this;
1456 const RenderObject* p = o;
1457 if (RenderObject* child = o->firstChildSlow())
1459 else if (o->nextSibling())
1460 o = o->nextSibling();
1462 RenderObject* next = 0;
1463 while (!next && o->parent()) {
1465 next = o->nextSibling();
1474 if (!o->isInline() || o->isReplaced()) {
1475 point = o->localToAbsolute(FloatPoint(), UseTransforms, &insideFixed);
1479 if (p->node() && p->node() == element() && is<RenderText>(*o) && !downcast<RenderText>(*o).firstTextBox()) {
1480 // do nothing - skip unrendered whitespace that is a child or next sibling of the anchor
1481 } else if (is<RenderText>(*o) || o->isReplaced()) {
1482 point = FloatPoint();
1483 if (is<RenderText>(*o) && downcast<RenderText>(*o).firstTextBox())
1484 point.move(downcast<RenderText>(*o).linesBoundingBox().x(), downcast<RenderText>(*o).topOfFirstText());
1485 else if (is<RenderBox>(*o))
1486 point.moveBy(downcast<RenderBox>(*o).location());
1487 point = o->container()->localToAbsolute(point, UseTransforms, &insideFixed);
1492 // If the target doesn't have any children or siblings that could be used to calculate the scroll position, we must be
1493 // at the end of the document. Scroll to the bottom. FIXME: who said anything about scrolling?
1494 if (!o && document().view()) {
1495 point = FloatPoint(0, document().view()->contentsHeight());
1501 bool RenderElement::getTrailingCorner(FloatPoint& point, bool& insideFixed) const
1503 if (!isInline() || isReplaced()) {
1504 point = localToAbsolute(LayoutPoint(downcast<RenderBox>(*this).size()), UseTransforms, &insideFixed);
1508 // find the last text/image child, to get a position
1509 const RenderObject* o = this;
1511 if (RenderObject* child = o->lastChildSlow())
1513 else if (o->previousSibling())
1514 o = o->previousSibling();
1516 RenderObject* prev = 0;
1521 prev = o->previousSibling();
1526 if (is<RenderText>(*o) || o->isReplaced()) {
1527 point = FloatPoint();
1528 if (is<RenderText>(*o)) {
1529 LayoutRect linesBox = downcast<RenderText>(*o).linesBoundingBox();
1530 if (!linesBox.maxX() && !linesBox.maxY())
1532 point.moveBy(linesBox.maxXMaxYCorner());
1534 point.moveBy(downcast<RenderBox>(*o).frameRect().maxXMaxYCorner());
1535 point = o->container()->localToAbsolute(point, UseTransforms, &insideFixed);
1542 LayoutRect RenderElement::absoluteAnchorRect(bool* insideFixed) const
1544 FloatPoint leading, trailing;
1545 bool leadingInFixed = false;
1546 bool trailingInFixed = false;
1547 getLeadingCorner(leading, leadingInFixed);
1548 getTrailingCorner(trailing, trailingInFixed);
1550 FloatPoint upperLeft = leading;
1551 FloatPoint lowerRight = trailing;
1553 // Vertical writing modes might mean the leading point is not in the top left
1554 if (!isInline() || isReplaced()) {
1555 upperLeft = FloatPoint(std::min(leading.x(), trailing.x()), std::min(leading.y(), trailing.y()));
1556 lowerRight = FloatPoint(std::max(leading.x(), trailing.x()), std::max(leading.y(), trailing.y()));
1557 } // Otherwise, it's not obvious what to do.
1560 // For now, just look at the leading corner. Handling one inside fixed and one not would be tricky.
1561 *insideFixed = leadingInFixed;
1564 return enclosingLayoutRect(FloatRect(upperLeft, lowerRight.expandedTo(upperLeft) - upperLeft));
1567 const RenderElement* RenderElement::enclosingRendererWithTextDecoration(TextDecoration textDecoration, bool firstLine) const
1569 const RenderElement* current = this;
1571 if (current->isRenderBlock())
1573 if (!current->isRenderInline() || current->isRubyText())
1576 const RenderStyle& styleToUse = firstLine ? current->firstLineStyle() : current->style();
1577 if (styleToUse.textDecoration() & textDecoration)
1579 current = current->parent();
1580 } while (current && (!current->element() || (!is<HTMLAnchorElement>(*current->element()) && !current->element()->hasTagName(HTMLNames::fontTag))));
1585 void RenderElement::drawLineForBoxSide(GraphicsContext& graphicsContext, const FloatRect& rect, BoxSide side, Color color, EBorderStyle borderStyle, float adjacentWidth1, float adjacentWidth2, bool antialias) const
1587 auto drawBorderRect = [&graphicsContext] (const FloatRect& rect)
1591 graphicsContext.drawRect(rect);
1594 auto drawLineFor = [this, &graphicsContext, color, antialias] (const FloatRect& rect, BoxSide side, EBorderStyle borderStyle, const FloatSize& adjacent)
1598 drawLineForBoxSide(graphicsContext, rect, side, color, borderStyle, adjacent.width(), adjacent.height(), antialias);
1601 float x1 = rect.x();
1602 float x2 = rect.maxX();
1603 float y1 = rect.y();
1604 float y2 = rect.maxY();
1607 if (side == BSTop || side == BSBottom) {
1608 thickness = y2 - y1;
1611 thickness = x2 - x1;
1614 // FIXME: We really would like this check to be an ASSERT as we don't want to draw empty borders. However
1615 // nothing guarantees that the following recursive calls to drawLineForBoxSide will have non-null dimensions.
1616 if (!thickness || !length)
1619 float deviceScaleFactor = document().deviceScaleFactor();
1620 if (borderStyle == DOUBLE && (thickness * deviceScaleFactor) < 3)
1621 borderStyle = SOLID;
1623 switch (borderStyle) {
1629 bool wasAntialiased = graphicsContext.shouldAntialias();
1630 StrokeStyle oldStrokeStyle = graphicsContext.strokeStyle();
1631 graphicsContext.setShouldAntialias(antialias);
1632 graphicsContext.setStrokeColor(color);
1633 graphicsContext.setStrokeThickness(thickness);
1634 graphicsContext.setStrokeStyle(borderStyle == DASHED ? DashedStroke : DottedStroke);
1635 graphicsContext.drawLine(roundPointToDevicePixels(LayoutPoint(x1, y1), deviceScaleFactor), roundPointToDevicePixels(LayoutPoint(x2, y2), deviceScaleFactor));
1636 graphicsContext.setShouldAntialias(wasAntialiased);
1637 graphicsContext.setStrokeStyle(oldStrokeStyle);
1641 float thirdOfThickness = ceilToDevicePixel(thickness / 3, deviceScaleFactor);
1642 ASSERT(thirdOfThickness);
1644 if (!adjacentWidth1 && !adjacentWidth2) {
1645 StrokeStyle oldStrokeStyle = graphicsContext.strokeStyle();
1646 graphicsContext.setStrokeStyle(NoStroke);
1647 graphicsContext.setFillColor(color);
1649 bool wasAntialiased = graphicsContext.shouldAntialias();
1650 graphicsContext.setShouldAntialias(antialias);
1655 drawBorderRect(snapRectToDevicePixels(x1, y1, length, thirdOfThickness, deviceScaleFactor));
1656 drawBorderRect(snapRectToDevicePixels(x1, y2 - thirdOfThickness, length, thirdOfThickness, deviceScaleFactor));
1660 drawBorderRect(snapRectToDevicePixels(x1, y1, thirdOfThickness, length, deviceScaleFactor));
1661 drawBorderRect(snapRectToDevicePixels(x2 - thirdOfThickness, y1, thirdOfThickness, length, deviceScaleFactor));
1665 graphicsContext.setShouldAntialias(wasAntialiased);
1666 graphicsContext.setStrokeStyle(oldStrokeStyle);
1668 float adjacent1BigThird = ceilToDevicePixel(adjacentWidth1 / 3, deviceScaleFactor);
1669 float adjacent2BigThird = ceilToDevicePixel(adjacentWidth2 / 3, deviceScaleFactor);
1671 float offset1 = floorToDevicePixel(fabs(adjacentWidth1) * 2 / 3, deviceScaleFactor);
1672 float offset2 = floorToDevicePixel(fabs(adjacentWidth2) * 2 / 3, deviceScaleFactor);
1674 float mitreOffset1 = adjacentWidth1 < 0 ? offset1 : 0;
1675 float mitreOffset2 = adjacentWidth1 > 0 ? offset1 : 0;
1676 float mitreOffset3 = adjacentWidth2 < 0 ? offset2 : 0;
1677 float mitreOffset4 = adjacentWidth2 > 0 ? offset2 : 0;
1679 FloatRect paintBorderRect;
1682 paintBorderRect = snapRectToDevicePixels(LayoutRect(x1 + mitreOffset1, y1, (x2 - mitreOffset3) - (x1 + mitreOffset1), thirdOfThickness), deviceScaleFactor);
1683 drawLineFor(paintBorderRect, side, SOLID, FloatSize(adjacent1BigThird, adjacent2BigThird));
1685 paintBorderRect = snapRectToDevicePixels(LayoutRect(x1 + mitreOffset2, y2 - thirdOfThickness, (x2 - mitreOffset4) - (x1 + mitreOffset2), thirdOfThickness), deviceScaleFactor);
1686 drawLineFor(paintBorderRect, side, SOLID, FloatSize(adjacent1BigThird, adjacent2BigThird));
1689 paintBorderRect = snapRectToDevicePixels(LayoutRect(x1, y1 + mitreOffset1, thirdOfThickness, (y2 - mitreOffset3) - (y1 + mitreOffset1)), deviceScaleFactor);
1690 drawLineFor(paintBorderRect, side, SOLID, FloatSize(adjacent1BigThird, adjacent2BigThird));
1692 paintBorderRect = snapRectToDevicePixels(LayoutRect(x2 - thirdOfThickness, y1 + mitreOffset2, thirdOfThickness, (y2 - mitreOffset4) - (y1 + mitreOffset2)), deviceScaleFactor);
1693 drawLineFor(paintBorderRect, side, SOLID, FloatSize(adjacent1BigThird, adjacent2BigThird));
1696 paintBorderRect = snapRectToDevicePixels(LayoutRect(x1 + mitreOffset2, y1, (x2 - mitreOffset4) - (x1 + mitreOffset2), thirdOfThickness), deviceScaleFactor);
1697 drawLineFor(paintBorderRect, side, SOLID, FloatSize(adjacent1BigThird, adjacent2BigThird));
1699 paintBorderRect = snapRectToDevicePixels(LayoutRect(x1 + mitreOffset1, y2 - thirdOfThickness, (x2 - mitreOffset3) - (x1 + mitreOffset1), thirdOfThickness), deviceScaleFactor);
1700 drawLineFor(paintBorderRect, side, SOLID, FloatSize(adjacent1BigThird, adjacent2BigThird));
1703 paintBorderRect = snapRectToDevicePixels(LayoutRect(x1, y1 + mitreOffset2, thirdOfThickness, (y2 - mitreOffset4) - (y1 + mitreOffset2)), deviceScaleFactor);
1704 drawLineFor(paintBorderRect, side, SOLID, FloatSize(adjacent1BigThird, adjacent2BigThird));
1706 paintBorderRect = snapRectToDevicePixels(LayoutRect(x2 - thirdOfThickness, y1 + mitreOffset1, thirdOfThickness, (y2 - mitreOffset3) - (y1 + mitreOffset1)), deviceScaleFactor);
1707 drawLineFor(paintBorderRect, side, SOLID, FloatSize(adjacent1BigThird, adjacent2BigThird));
1719 if (borderStyle == GROOVE) {
1727 float adjacent1BigHalf = ceilToDevicePixel(adjacentWidth1 / 2, deviceScaleFactor);
1728 float adjacent2BigHalf = ceilToDevicePixel(adjacentWidth2 / 2, deviceScaleFactor);
1730 float adjacent1SmallHalf = floorToDevicePixel(adjacentWidth1 / 2, deviceScaleFactor);
1731 float adjacent2SmallHalf = floorToDevicePixel(adjacentWidth2 / 2, deviceScaleFactor);
1738 if (((side == BSTop || side == BSLeft) && adjacentWidth1 < 0) || ((side == BSBottom || side == BSRight) && adjacentWidth1 > 0))
1739 offset1 = floorToDevicePixel(adjacentWidth1 / 2, deviceScaleFactor);
1741 if (((side == BSTop || side == BSLeft) && adjacentWidth2 < 0) || ((side == BSBottom || side == BSRight) && adjacentWidth2 > 0))
1742 offset2 = ceilToDevicePixel(adjacentWidth2 / 2, deviceScaleFactor);
1744 if (((side == BSTop || side == BSLeft) && adjacentWidth1 > 0) || ((side == BSBottom || side == BSRight) && adjacentWidth1 < 0))
1745 offset3 = floorToDevicePixel(fabs(adjacentWidth1) / 2, deviceScaleFactor);
1747 if (((side == BSTop || side == BSLeft) && adjacentWidth2 > 0) || ((side == BSBottom || side == BSRight) && adjacentWidth2 < 0))
1748 offset4 = ceilToDevicePixel(adjacentWidth2 / 2, deviceScaleFactor);
1750 float adjustedX = ceilToDevicePixel((x1 + x2) / 2, deviceScaleFactor);
1751 float adjustedY = ceilToDevicePixel((y1 + y2) / 2, deviceScaleFactor);
1752 // Quads can't use the default snapping rect functions.
1753 x1 = roundToDevicePixel(x1, deviceScaleFactor);
1754 x2 = roundToDevicePixel(x2, deviceScaleFactor);
1755 y1 = roundToDevicePixel(y1, deviceScaleFactor);
1756 y2 = roundToDevicePixel(y2, deviceScaleFactor);
1760 drawLineFor(FloatRect(FloatPoint(x1 + offset1, y1), FloatPoint(x2 - offset2, adjustedY)), side, s1, FloatSize(adjacent1BigHalf, adjacent2BigHalf));
1761 drawLineFor(FloatRect(FloatPoint(x1 + offset3, adjustedY), FloatPoint(x2 - offset4, y2)), side, s2, FloatSize(adjacent1SmallHalf, adjacent2SmallHalf));
1764 drawLineFor(FloatRect(FloatPoint(x1, y1 + offset1), FloatPoint(adjustedX, y2 - offset2)), side, s1, FloatSize(adjacent1BigHalf, adjacent2BigHalf));
1765 drawLineFor(FloatRect(FloatPoint(adjustedX, y1 + offset3), FloatPoint(x2, y2 - offset4)), side, s2, FloatSize(adjacent1SmallHalf, adjacent2SmallHalf));
1768 drawLineFor(FloatRect(FloatPoint(x1 + offset1, y1), FloatPoint(x2 - offset2, adjustedY)), side, s2, FloatSize(adjacent1BigHalf, adjacent2BigHalf));
1769 drawLineFor(FloatRect(FloatPoint(x1 + offset3, adjustedY), FloatPoint(x2 - offset4, y2)), side, s1, FloatSize(adjacent1SmallHalf, adjacent2SmallHalf));
1772 drawLineFor(FloatRect(FloatPoint(x1, y1 + offset1), FloatPoint(adjustedX, y2 - offset2)), side, s2, FloatSize(adjacent1BigHalf, adjacent2BigHalf));
1773 drawLineFor(FloatRect(FloatPoint(adjustedX, y1 + offset3), FloatPoint(x2, y2 - offset4)), side, s1, FloatSize(adjacent1SmallHalf, adjacent2SmallHalf));
1780 calculateBorderStyleColor(borderStyle, side, color);
1783 StrokeStyle oldStrokeStyle = graphicsContext.strokeStyle();
1786 if (!adjacentWidth1 && !adjacentWidth2) {
1787 graphicsContext.setStrokeStyle(NoStroke);
1788 graphicsContext.setFillColor(color);
1789 bool wasAntialiased = graphicsContext.shouldAntialias();
1790 graphicsContext.setShouldAntialias(antialias);
1791 drawBorderRect(snapRectToDevicePixels(x1, y1, x2 - x1, y2 - y1, deviceScaleFactor));
1792 graphicsContext.setShouldAntialias(wasAntialiased);
1793 graphicsContext.setStrokeStyle(oldStrokeStyle);
1797 // FIXME: These roundings should be replaced by ASSERT(device pixel positioned) when all the callers have transitioned to device pixels.
1798 x1 = roundToDevicePixel(x1, deviceScaleFactor);
1799 y1 = roundToDevicePixel(y1, deviceScaleFactor);
1800 x2 = roundToDevicePixel(x2, deviceScaleFactor);
1801 y2 = roundToDevicePixel(y2, deviceScaleFactor);
1803 Vector<FloatPoint> quad;
1804 quad.reserveInitialCapacity(4);
1807 quad.uncheckedAppend({ x1 + std::max<float>(-adjacentWidth1, 0), y1 });
1808 quad.uncheckedAppend({ x1 + std::max<float>( adjacentWidth1, 0), y2 });
1809 quad.uncheckedAppend({ x2 - std::max<float>( adjacentWidth2, 0), y2 });
1810 quad.uncheckedAppend({ x2 - std::max<float>(-adjacentWidth2, 0), y1 });
1813 quad.uncheckedAppend({ x1 + std::max<float>( adjacentWidth1, 0), y1 });
1814 quad.uncheckedAppend({ x1 + std::max<float>(-adjacentWidth1, 0), y2 });
1815 quad.uncheckedAppend({ x2 - std::max<float>(-adjacentWidth2, 0), y2 });
1816 quad.uncheckedAppend({ x2 - std::max<float>( adjacentWidth2, 0), y1 });
1819 quad.uncheckedAppend({ x1, y1 + std::max<float>(-adjacentWidth1, 0) });
1820 quad.uncheckedAppend({ x1, y2 - std::max<float>(-adjacentWidth2, 0) });
1821 quad.uncheckedAppend({ x2, y2 - std::max<float>( adjacentWidth2, 0) });
1822 quad.uncheckedAppend({ x2, y1 + std::max<float>( adjacentWidth1, 0) });
1825 quad.uncheckedAppend({ x1, y1 + std::max<float>( adjacentWidth1, 0) });
1826 quad.uncheckedAppend({ x1, y2 - std::max<float>( adjacentWidth2, 0) });
1827 quad.uncheckedAppend({ x2, y2 - std::max<float>(-adjacentWidth2, 0) });
1828 quad.uncheckedAppend({ x2, y1 + std::max<float>(-adjacentWidth1, 0) });
1832 graphicsContext.setStrokeStyle(NoStroke);
1833 graphicsContext.setFillColor(color);
1834 bool wasAntialiased = graphicsContext.shouldAntialias();
1835 graphicsContext.setShouldAntialias(antialias);
1836 graphicsContext.fillPath(Path::polygonPathFromPoints(quad));
1837 graphicsContext.setShouldAntialias(wasAntialiased);
1839 graphicsContext.setStrokeStyle(oldStrokeStyle);
1845 void RenderElement::paintFocusRing(PaintInfo& paintInfo, const RenderStyle& style, const Vector<LayoutRect>& focusRingRects)
1847 ASSERT(style.outlineStyleIsAuto());
1848 float outlineOffset = style.outlineOffset();
1849 Vector<FloatRect> pixelSnappedFocusRingRects;
1850 float deviceScaleFactor = document().deviceScaleFactor();
1851 for (auto rect : focusRingRects) {
1852 rect.inflate(outlineOffset);
1853 pixelSnappedFocusRingRects.append(snapRectToDevicePixels(rect, deviceScaleFactor));
1857 if (style.hasBorderRadius()) {
1858 Path path = PathUtilities::pathWithShrinkWrappedRectsForOutline(pixelSnappedFocusRingRects, style.border(), outlineOffset, style.direction(), style.writingMode(),
1859 document().deviceScaleFactor());
1860 if (path.isEmpty()) {
1861 for (auto rect : pixelSnappedFocusRingRects)
1864 paintInfo.context().drawFocusRing(path, page().focusController().timeSinceFocusWasSet(), needsRepaint);
1866 paintInfo.context().drawFocusRing(pixelSnappedFocusRingRects, page().focusController().timeSinceFocusWasSet(), needsRepaint);
1868 page().focusController().setFocusedElementNeedsRepaint();
1870 paintInfo.context().drawFocusRing(pixelSnappedFocusRingRects, style.outlineWidth(), style.outlineOffset(), style.visitedDependentColor(CSSPropertyOutlineColor));
1874 void RenderElement::paintOutline(PaintInfo& paintInfo, const LayoutRect& paintRect)
1876 GraphicsContext& graphicsContext = paintInfo.context();
1877 if (graphicsContext.paintingDisabled())
1883 auto& styleToUse = style();
1884 float outlineWidth = floorToDevicePixel(styleToUse.outlineWidth(), document().deviceScaleFactor());
1885 float outlineOffset = floorToDevicePixel(styleToUse.outlineOffset(), document().deviceScaleFactor());
1887 // Only paint the focus ring by hand if the theme isn't able to draw it.
1888 if (styleToUse.outlineStyleIsAuto() && !theme().supportsFocusRing(styleToUse)) {
1889 Vector<LayoutRect> focusRingRects;
1890 addFocusRingRects(focusRingRects, paintRect.location(), paintInfo.paintContainer);
1891 paintFocusRing(paintInfo, styleToUse, focusRingRects);
1894 if (hasOutlineAnnotation() && !styleToUse.outlineStyleIsAuto() && !theme().supportsFocusRing(styleToUse))
1895 addPDFURLRect(paintInfo, paintRect.location());
1897 if (styleToUse.outlineStyleIsAuto() || styleToUse.outlineStyle() == BNONE)
1900 FloatRect outer = paintRect;
1901 outer.inflate(outlineOffset + outlineWidth);
1902 FloatRect inner = outer;
1903 inner.inflate(-outlineWidth);
1905 // FIXME: This prevents outlines from painting inside the object. See bug 12042
1906 if (outer.isEmpty())
1909 EBorderStyle outlineStyle = styleToUse.outlineStyle();
1910 Color outlineColor = styleToUse.visitedDependentColor(CSSPropertyOutlineColor);
1912 bool useTransparencyLayer = !outlineColor.isOpaque();
1913 if (useTransparencyLayer) {
1914 if (outlineStyle == SOLID) {
1916 path.addRect(outer);
1917 path.addRect(inner);
1918 graphicsContext.setFillRule(RULE_EVENODD);
1919 graphicsContext.setFillColor(outlineColor);
1920 graphicsContext.fillPath(path);
1923 graphicsContext.beginTransparencyLayer(outlineColor.alphaAsFloat());
1924 outlineColor = outlineColor.opaqueColor();
1927 float leftOuter = outer.x();
1928 float leftInner = inner.x();
1929 float rightOuter = outer.maxX();
1930 float rightInner = std::min(inner.maxX(), rightOuter);
1931 float topOuter = outer.y();
1932 float topInner = inner.y();
1933 float bottomOuter = outer.maxY();
1934 float bottomInner = std::min(inner.maxY(), bottomOuter);
1936 drawLineForBoxSide(graphicsContext, FloatRect(FloatPoint(leftOuter, topOuter), FloatPoint(leftInner, bottomOuter)), BSLeft, outlineColor, outlineStyle, outlineWidth, outlineWidth);
1937 drawLineForBoxSide(graphicsContext, FloatRect(FloatPoint(leftOuter, topOuter), FloatPoint(rightOuter, topInner)), BSTop, outlineColor, outlineStyle, outlineWidth, outlineWidth);
1938 drawLineForBoxSide(graphicsContext, FloatRect(FloatPoint(rightInner, topOuter), FloatPoint(rightOuter, bottomOuter)), BSRight, outlineColor, outlineStyle, outlineWidth, outlineWidth);
1939 drawLineForBoxSide(graphicsContext, FloatRect(FloatPoint(leftOuter, bottomInner), FloatPoint(rightOuter, bottomOuter)), BSBottom, outlineColor, outlineStyle, outlineWidth, outlineWidth);
1941 if (useTransparencyLayer)
1942 graphicsContext.endTransparencyLayer();
1945 void RenderElement::issueRepaintForOutlineAuto(float outlineSize)
1947 LayoutRect repaintRect;
1948 Vector<LayoutRect> focusRingRects;
1949 addFocusRingRects(focusRingRects, LayoutPoint(), containerForRepaint());
1950 for (auto rect : focusRingRects) {
1951 rect.inflate(outlineSize);
1952 repaintRect.unite(rect);
1954 repaintRectangle(repaintRect);
1957 void RenderElement::updateOutlineAutoAncestor(bool hasOutlineAuto)
1959 for (auto& child : childrenOfType<RenderObject>(*this)) {
1960 if (hasOutlineAuto == child.hasOutlineAutoAncestor())
1962 child.setHasOutlineAutoAncestor(hasOutlineAuto);
1963 bool childHasOutlineAuto = child.outlineStyleForRepaint().outlineStyleIsAuto();
1964 if (childHasOutlineAuto)
1966 if (!is<RenderElement>(child))
1968 downcast<RenderElement>(child).updateOutlineAutoAncestor(hasOutlineAuto);
1970 if (is<RenderBoxModelObject>(*this)) {
1971 if (auto* continuation = downcast<RenderBoxModelObject>(*this).continuation())
1972 continuation->updateOutlineAutoAncestor(hasOutlineAuto);
1976 bool RenderElement::hasOutlineAnnotation() const
1978 return element() && element()->isLink() && document().printing();
1981 bool RenderElement::hasSelfPaintingLayer() const
1985 auto& layerModelObject = downcast<RenderLayerModelObject>(*this);
1986 return layerModelObject.hasSelfPaintingLayer();
1989 bool RenderElement::checkForRepaintDuringLayout() const
1991 if (document().view()->layoutContext().needsFullRepaint() || !everHadLayout() || hasSelfPaintingLayer())
1993 return !settings().repaintOutsideLayoutEnabled();
1996 RespectImageOrientationEnum RenderElement::shouldRespectImageOrientation() const
1998 #if USE(CG) || USE(CAIRO)
1999 // This can only be enabled for ports which honor the orientation flag in their drawing code.
2000 if (document().isImageDocument())
2001 return RespectImageOrientation;
2003 // Respect the image's orientation if it's being used as a full-page image or it's
2004 // an <img> and the setting to respect it everywhere is set.
2005 return settings().shouldRespectImageOrientation() && is<HTMLImageElement>(element()) ? RespectImageOrientation : DoNotRespectImageOrientation;
2008 void RenderElement::adjustFragmentedFlowStateOnContainingBlockChangeIfNeeded()
2010 if (fragmentedFlowState() == NotInsideFragmentedFlow)
2013 // Invalidate the containing block caches.
2014 if (is<RenderBlock>(*this))
2015 downcast<RenderBlock>(*this).resetEnclosingFragmentedFlowAndChildInfoIncludingDescendants();
2017 // Adjust the flow tread state on the subtree.
2018 setFragmentedFlowState(RenderObject::computedFragmentedFlowState(*this));
2019 for (auto& descendant : descendantsOfType<RenderObject>(*this))
2020 descendant.setFragmentedFlowState(RenderObject::computedFragmentedFlowState(descendant));
2023 void RenderElement::removeFromRenderFragmentedFlow()
2025 ASSERT(fragmentedFlowState() != NotInsideFragmentedFlow);
2026 // Sometimes we remove the element from the flow, but it's not destroyed at that time.
2027 // It's only until later when we actually destroy it and remove all the children from it.
2028 // Currently, that happens for firstLetter elements and list markers.
2029 // Pass in the flow thread so that we don't have to look it up for all the children.
2030 removeFromRenderFragmentedFlowIncludingDescendants(true);
2033 void RenderElement::removeFromRenderFragmentedFlowIncludingDescendants(bool shouldUpdateState)
2035 // Once we reach another flow thread we don't need to update the flow thread state
2036 // but we have to continue cleanup the flow thread info.
2037 if (isRenderFragmentedFlow())
2038 shouldUpdateState = false;
2040 for (auto& child : childrenOfType<RenderObject>(*this)) {
2041 if (is<RenderElement>(child)) {
2042 downcast<RenderElement>(child).removeFromRenderFragmentedFlowIncludingDescendants(shouldUpdateState);
2045 if (shouldUpdateState)
2046 child.setFragmentedFlowState(NotInsideFragmentedFlow);
2049 // We have to ask for our containing flow thread as it may be above the removed sub-tree.
2050 RenderFragmentedFlow* enclosingFragmentedFlow = this->enclosingFragmentedFlow();
2051 while (enclosingFragmentedFlow) {
2052 enclosingFragmentedFlow->removeFlowChildInfo(*this);
2054 if (enclosingFragmentedFlow->fragmentedFlowState() == NotInsideFragmentedFlow)
2056 auto* parent = enclosingFragmentedFlow->parent();
2059 enclosingFragmentedFlow = parent->enclosingFragmentedFlow();
2061 if (is<RenderBlock>(*this))
2062 downcast<RenderBlock>(*this).setCachedEnclosingFragmentedFlowNeedsUpdate();
2064 if (shouldUpdateState)
2065 setFragmentedFlowState(NotInsideFragmentedFlow);
2068 void RenderElement::resetEnclosingFragmentedFlowAndChildInfoIncludingDescendants(RenderFragmentedFlow* fragmentedFlow)
2071 fragmentedFlow->removeFlowChildInfo(*this);
2073 for (auto& child : childrenOfType<RenderElement>(*this))
2074 child.resetEnclosingFragmentedFlowAndChildInfoIncludingDescendants(fragmentedFlow);
2077 #if ENABLE(TEXT_AUTOSIZING)
2078 static RenderObject::BlockContentHeightType includeNonFixedHeight(const RenderObject& renderer)
2080 const RenderStyle& style = renderer.style();
2081 if (style.height().type() == Fixed) {
2082 if (is<RenderBlock>(renderer)) {
2083 // For fixed height styles, if the overflow size of the element spills out of the specified
2084 // height, assume we can apply text auto-sizing.
2085 if (style.overflowY() == OVISIBLE
2086 && style.height().value() < downcast<RenderBlock>(renderer).layoutOverflowRect().maxY())
2087 return RenderObject::OverflowHeight;
2089 return RenderObject::FixedHeight;
2091 return RenderObject::FlexibleHeight;
2094 void RenderElement::adjustComputedFontSizesOnBlocks(float size, float visibleWidth)
2096 Document* document = view().frameView().frame().document();
2100 Vector<int> depthStack;
2101 int currentDepth = 0;
2102 int newFixedDepth = 0;
2104 // We don't apply autosizing to nodes with fixed height normally.
2105 // But we apply it to nodes which are located deep enough
2106 // (nesting depth is greater than some const) inside of a parent block
2107 // which has fixed height but its content overflows intentionally.
2108 for (RenderObject* descendent = traverseNext(this, includeNonFixedHeight, currentDepth, newFixedDepth); descendent; descendent = descendent->traverseNext(this, includeNonFixedHeight, currentDepth, newFixedDepth)) {
2109 while (depthStack.size() > 0 && currentDepth <= depthStack[depthStack.size() - 1])
2110 depthStack.remove(depthStack.size() - 1);
2112 depthStack.append(newFixedDepth);
2114 int stackSize = depthStack.size();
2115 if (is<RenderBlockFlow>(*descendent) && !descendent->isListItem() && (!stackSize || currentDepth - depthStack[stackSize - 1] > TextAutoSizingFixedHeightDepth))
2116 downcast<RenderBlockFlow>(*descendent).adjustComputedFontSizes(size, visibleWidth);
2120 // Remove style from auto-sizing table that are no longer valid.
2121 document->textAutoSizing().updateRenderTree();
2124 void RenderElement::resetTextAutosizing()
2126 Document* document = view().frameView().frame().document();
2130 LOG(TextAutosizing, "RenderElement::resetTextAutosizing()");
2132 document->textAutoSizing().reset();
2134 Vector<int> depthStack;
2135 int currentDepth = 0;
2136 int newFixedDepth = 0;
2138 for (RenderObject* descendent = traverseNext(this, includeNonFixedHeight, currentDepth, newFixedDepth); descendent; descendent = descendent->traverseNext(this, includeNonFixedHeight, currentDepth, newFixedDepth)) {
2139 while (depthStack.size() > 0 && currentDepth <= depthStack[depthStack.size() - 1])
2140 depthStack.remove(depthStack.size() - 1);
2142 depthStack.append(newFixedDepth);
2144 int stackSize = depthStack.size();
2145 if (is<RenderBlockFlow>(*descendent) && !descendent->isListItem() && (!stackSize || currentDepth - depthStack[stackSize - 1] > TextAutoSizingFixedHeightDepth))
2146 downcast<RenderBlockFlow>(*descendent).resetComputedFontSize();
2150 #endif // ENABLE(TEXT_AUTOSIZING)