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_noLongerAffectsParentBlock = false;
99 inline RenderElement::RenderElement(ContainerNode& elementOrDocument, RenderStyle&& style, BaseTypeFlags baseTypeFlags)
100 : RenderObject(elementOrDocument)
101 , m_baseTypeFlags(baseTypeFlags)
102 , m_ancestorLineBoxDirty(false)
103 , m_hasInitializedStyle(false)
104 , m_renderInlineAlwaysCreatesLineBoxes(false)
105 , m_renderBoxNeedsLazyRepaint(false)
106 , m_hasPausedImageAnimations(false)
107 , m_hasCounterNodeMap(false)
108 , m_hasContinuationChainNode(false)
109 , m_isContinuation(false)
110 , m_isFirstLetter(false)
111 , m_hasValidCachedFirstLineStyle(false)
112 , m_renderBlockHasMarginBeforeQuirk(false)
113 , m_renderBlockHasMarginAfterQuirk(false)
114 , m_renderBlockShouldForceRelayoutChildren(false)
115 , m_renderBlockFlowHasMarkupTruncation(false)
116 , m_renderBlockFlowLineLayoutPath(RenderBlockFlow::UndeterminedPath)
117 , m_isRegisteredForVisibleInViewportCallback(false)
118 , m_visibleInViewportState(static_cast<unsigned>(VisibleInViewportState::Unknown))
119 , m_firstChild(nullptr)
120 , m_lastChild(nullptr)
121 , m_style(WTFMove(style))
125 RenderElement::RenderElement(Element& element, RenderStyle&& style, BaseTypeFlags baseTypeFlags)
126 : RenderElement(static_cast<ContainerNode&>(element), WTFMove(style), baseTypeFlags)
130 RenderElement::RenderElement(Document& document, RenderStyle&& style, BaseTypeFlags baseTypeFlags)
131 : RenderElement(static_cast<ContainerNode&>(document), WTFMove(style), baseTypeFlags)
135 RenderElement::~RenderElement()
137 // Do not add any code here. Add it to willBeDestroyed() instead.
138 ASSERT(!m_firstChild);
141 RenderPtr<RenderElement> RenderElement::createFor(Element& element, RenderStyle&& style, RendererCreationType creationType)
143 // Minimal support for content properties replacing an entire element.
144 // Works only if we have exactly one piece of content and it's a URL.
145 // Otherwise acts as if we didn't support this feature.
146 const ContentData* contentData = style.contentData();
147 if (creationType == CreateAllRenderers && contentData && !contentData->next() && is<ImageContentData>(*contentData) && !element.isPseudoElement()) {
148 Style::loadPendingResources(style, element.document(), &element);
149 auto& styleImage = downcast<ImageContentData>(*contentData).image();
150 auto image = createRenderer<RenderImage>(element, WTFMove(style), const_cast<StyleImage*>(&styleImage));
151 image->setIsGeneratedContent();
152 return WTFMove(image);
155 switch (style.display()) {
160 if (creationType == CreateAllRenderers)
161 return createRenderer<RenderInline>(element, WTFMove(style));
162 FALLTHROUGH; // Fieldsets should make a block flow if display:inline is set.
166 return createRenderer<RenderBlockFlow>(element, WTFMove(style));
168 return createRenderer<RenderListItem>(element, WTFMove(style));
172 case WEBKIT_INLINE_FLEX:
173 return createRenderer<RenderFlexibleBox>(element, WTFMove(style));
176 return createRenderer<RenderGrid>(element, WTFMove(style));
179 return createRenderer<RenderDeprecatedFlexibleBox>(element, WTFMove(style));
181 if (creationType == OnlyCreateBlockAndFlexboxRenderers)
182 return createRenderer<RenderBlockFlow>(element, WTFMove(style));
183 switch (style.display()) {
186 return createRenderer<RenderTable>(element, WTFMove(style));
188 return createRenderer<RenderTableCell>(element, WTFMove(style));
190 return createRenderer<RenderTableCaption>(element, WTFMove(style));
191 case TABLE_ROW_GROUP:
192 case TABLE_HEADER_GROUP:
193 case TABLE_FOOTER_GROUP:
194 return createRenderer<RenderTableSection>(element, WTFMove(style));
196 return createRenderer<RenderTableRow>(element, WTFMove(style));
197 case TABLE_COLUMN_GROUP:
199 return createRenderer<RenderTableCol>(element, WTFMove(style));
206 ASSERT_NOT_REACHED();
210 std::unique_ptr<RenderStyle> RenderElement::computeFirstLineStyle() const
212 ASSERT(view().usesFirstLineRules());
214 RenderElement& rendererForFirstLineStyle = isBeforeOrAfterContent() ? *parent() : const_cast<RenderElement&>(*this);
216 if (rendererForFirstLineStyle.isRenderBlockFlow() || rendererForFirstLineStyle.isRenderButton()) {
217 RenderBlock* firstLineBlock = rendererForFirstLineStyle.firstLineBlock();
220 auto* firstLineStyle = firstLineBlock->getCachedPseudoStyle(FIRST_LINE, &style());
223 return RenderStyle::clonePtr(*firstLineStyle);
226 if (!rendererForFirstLineStyle.isRenderInline())
229 auto& parentStyle = rendererForFirstLineStyle.parent()->firstLineStyle();
230 if (&parentStyle == &rendererForFirstLineStyle.parent()->style())
233 if (rendererForFirstLineStyle.isAnonymous()) {
234 auto* textRendererWithDisplayContentsParent = RenderText::findByDisplayContentsInlineWrapperCandidate(rendererForFirstLineStyle);
235 if (!textRendererWithDisplayContentsParent)
237 auto* composedTreeParentElement = textRendererWithDisplayContentsParent->textNode()->parentElementInComposedTree();
238 if (!composedTreeParentElement)
241 auto style = composedTreeParentElement->styleResolver().styleForElement(*composedTreeParentElement, &parentStyle).renderStyle;
242 ASSERT(style->display() == CONTENTS);
244 // We act as if there was an unstyled <span> around the text node. Only styling happens via inheritance.
245 auto firstLineStyle = RenderStyle::createPtr();
246 firstLineStyle->inheritFrom(*style);
247 return firstLineStyle;
250 return rendererForFirstLineStyle.element()->styleResolver().styleForElement(*element(), &parentStyle).renderStyle;
253 const RenderStyle& RenderElement::firstLineStyle() const
255 if (!view().usesFirstLineRules())
258 if (!m_hasValidCachedFirstLineStyle) {
259 auto firstLineStyle = computeFirstLineStyle();
260 if (firstLineStyle || hasRareData())
261 const_cast<RenderElement&>(*this).ensureRareData().cachedFirstLineStyle = WTFMove(firstLineStyle);
262 m_hasValidCachedFirstLineStyle = true;
265 return (hasRareData() && rareData().cachedFirstLineStyle) ? *rareData().cachedFirstLineStyle : style();
268 StyleDifference RenderElement::adjustStyleDifference(StyleDifference diff, unsigned contextSensitiveProperties) const
270 // If transform changed, and we are not composited, need to do a layout.
271 if (contextSensitiveProperties & ContextSensitivePropertyTransform) {
272 // FIXME: when transforms are taken into account for overflow, we will need to do a layout.
273 if (!hasLayer() || !downcast<RenderLayerModelObject>(*this).layer()->isComposited()) {
275 diff = std::max(diff, StyleDifferenceLayout);
277 // We need to set at least SimplifiedLayout, but if PositionedMovementOnly is already set
278 // then we actually need SimplifiedLayoutAndPositionedMovement.
279 diff = std::max(diff, (diff == StyleDifferenceLayoutPositionedMovementOnly) ? StyleDifferenceSimplifiedLayoutAndPositionedMovement : StyleDifferenceSimplifiedLayout);
283 diff = std::max(diff, StyleDifferenceRecompositeLayer);
286 if (contextSensitiveProperties & ContextSensitivePropertyOpacity) {
287 if (!hasLayer() || !downcast<RenderLayerModelObject>(*this).layer()->isComposited())
288 diff = std::max(diff, StyleDifferenceRepaintLayer);
290 diff = std::max(diff, StyleDifferenceRecompositeLayer);
293 if (contextSensitiveProperties & ContextSensitivePropertyClipPath) {
295 && downcast<RenderLayerModelObject>(*this).layer()->isComposited()
297 && RenderLayerCompositor::canCompositeClipPath(*downcast<RenderLayerModelObject>(*this).layer()))
298 diff = std::max(diff, StyleDifferenceRecompositeLayer);
300 diff = std::max(diff, StyleDifferenceRepaint);
303 if (contextSensitiveProperties & ContextSensitivePropertyWillChange) {
304 if (style().willChange() && style().willChange()->canTriggerCompositing())
305 diff = std::max(diff, StyleDifferenceRecompositeLayer);
308 if ((contextSensitiveProperties & ContextSensitivePropertyFilter) && hasLayer()) {
309 auto& layer = *downcast<RenderLayerModelObject>(*this).layer();
310 if (!layer.isComposited() || layer.paintsWithFilters())
311 diff = std::max(diff, StyleDifferenceRepaintLayer);
313 diff = std::max(diff, StyleDifferenceRecompositeLayer);
316 // The answer to requiresLayer() for plugins, iframes, and canvas can change without the actual
317 // style changing, since it depends on whether we decide to composite these elements. When the
318 // layer status of one of these elements changes, we need to force a layout.
319 if (diff < StyleDifferenceLayout && isRenderLayerModelObject()) {
320 if (hasLayer() != downcast<RenderLayerModelObject>(*this).requiresLayer())
321 diff = StyleDifferenceLayout;
324 // If we have no layer(), just treat a RepaintLayer hint as a normal Repaint.
325 if (diff == StyleDifferenceRepaintLayer && !hasLayer())
326 diff = StyleDifferenceRepaint;
331 inline bool RenderElement::hasImmediateNonWhitespaceTextChildOrBorderOrOutline() const
333 for (auto& child : childrenOfType<RenderObject>(*this)) {
334 if (is<RenderText>(child) && !downcast<RenderText>(child).isAllCollapsibleWhitespace())
336 if (child.style().hasOutline() || child.style().hasBorder())
342 inline bool RenderElement::shouldRepaintForStyleDifference(StyleDifference diff) const
344 return diff == StyleDifferenceRepaint || (diff == StyleDifferenceRepaintIfTextOrBorderOrOutline && hasImmediateNonWhitespaceTextChildOrBorderOrOutline());
347 void RenderElement::updateFillImages(const FillLayer* oldLayers, const FillLayer& newLayers)
349 // Optimize the common case.
350 if (FillLayer::imagesIdentical(oldLayers, &newLayers))
353 // Add before removing, to avoid removing all clients of an image that is in both sets.
354 for (auto* layer = &newLayers; layer; layer = layer->next()) {
356 layer->image()->addClient(this);
358 for (auto* layer = oldLayers; layer; layer = layer->next()) {
360 layer->image()->removeClient(this);
364 void RenderElement::updateImage(StyleImage* oldImage, StyleImage* newImage)
366 if (oldImage == newImage)
369 oldImage->removeClient(this);
371 newImage->addClient(this);
374 void RenderElement::updateShapeImage(const ShapeValue* oldShapeValue, const ShapeValue* newShapeValue)
376 if (oldShapeValue || newShapeValue)
377 updateImage(oldShapeValue ? oldShapeValue->image() : nullptr, newShapeValue ? newShapeValue->image() : nullptr);
380 void RenderElement::initializeStyle()
382 Style::loadPendingResources(m_style, document(), element());
384 styleWillChange(StyleDifferenceNewStyle, style());
385 m_hasInitializedStyle = true;
386 styleDidChange(StyleDifferenceNewStyle, nullptr);
388 // We shouldn't have any text children that would need styleDidChange at this point.
389 ASSERT(!childrenOfType<RenderText>(*this).first());
391 // It would be nice to assert that !parent() here, but some RenderLayer subrenderers
392 // have their parent set before getting a call to initializeStyle() :|
395 void RenderElement::setStyle(RenderStyle&& style, StyleDifference minimalStyleDifference)
397 // FIXME: Should change RenderView so it can use initializeStyle too.
398 // If we do that, we can assert m_hasInitializedStyle unconditionally,
399 // and remove the check of m_hasInitializedStyle below too.
400 ASSERT(m_hasInitializedStyle || isRenderView());
402 StyleDifference diff = StyleDifferenceEqual;
403 unsigned contextSensitiveProperties = ContextSensitivePropertyNone;
404 if (m_hasInitializedStyle)
405 diff = m_style.diff(style, contextSensitiveProperties);
407 diff = std::max(diff, minimalStyleDifference);
409 diff = adjustStyleDifference(diff, contextSensitiveProperties);
411 Style::loadPendingResources(style, document(), element());
413 styleWillChange(diff, style);
414 auto oldStyle = m_style.replace(WTFMove(style));
415 bool detachedFromParent = !parent();
417 // Make sure we invalidate the containing block cache for flows when the contianing block context changes
418 // so that styleDidChange can safely use RenderBlock::locateEnclosingFragmentedFlow()
419 if (oldStyle.position() != m_style.position())
420 adjustFragmentedFlowStateOnContainingBlockChangeIfNeeded();
422 styleDidChange(diff, &oldStyle);
424 // Text renderers use their parent style. Notify them about the change.
425 for (auto& child : childrenOfType<RenderText>(*this))
426 child.styleDidChange(diff, &oldStyle);
428 // FIXME: |this| might be destroyed here. This can currently happen for a RenderTextFragment when
429 // its first-letter block gets an update in RenderTextFragment::styleDidChange. For RenderTextFragment(s),
430 // we will safely bail out with the detachedFromParent flag. We might want to broaden this condition
431 // in the future as we move renderer changes out of layout and into style changes.
432 if (detachedFromParent)
435 // Now that the layer (if any) has been updated, we need to adjust the diff again,
436 // check whether we should layout now, and decide if we need to repaint.
437 StyleDifference updatedDiff = adjustStyleDifference(diff, contextSensitiveProperties);
439 if (diff <= StyleDifferenceLayoutPositionedMovementOnly) {
440 if (updatedDiff == StyleDifferenceLayout)
441 setNeedsLayoutAndPrefWidthsRecalc();
442 else if (updatedDiff == StyleDifferenceLayoutPositionedMovementOnly)
443 setNeedsPositionedMovementLayout(&oldStyle);
444 else if (updatedDiff == StyleDifferenceSimplifiedLayoutAndPositionedMovement) {
445 setNeedsPositionedMovementLayout(&oldStyle);
446 setNeedsSimplifiedNormalFlowLayout();
447 } else if (updatedDiff == StyleDifferenceSimplifiedLayout)
448 setNeedsSimplifiedNormalFlowLayout();
451 if (updatedDiff == StyleDifferenceRepaintLayer || shouldRepaintForStyleDifference(updatedDiff)) {
452 // Do a repaint with the new style now, e.g., for example if we go from
453 // not having an outline to having an outline.
458 void RenderElement::didAttachChild(RenderObject& child, RenderObject*)
460 if (is<RenderText>(child))
461 downcast<RenderText>(child).styleDidChange(StyleDifferenceEqual, nullptr);
462 // SVG creates renderers for <g display="none">, as SVG requires children of hidden
463 // <g>s to have renderers - at least that's how our implementation works. Consider:
464 // <g display="none"><foreignObject><body style="position: relative">FOO...
465 // - requiresLayer() would return true for the <body>, creating a new RenderLayer
466 // - when the document is painted, both layers are painted. The <body> layer doesn't
467 // know that it's inside a "hidden SVG subtree", and thus paints, even if it shouldn't.
468 // To avoid the problem alltogether, detect early if we're inside a hidden SVG subtree
469 // and stop creating layers at all for these cases - they're not used anyways.
470 if (child.hasLayer() && !layerCreationAllowedForSubtree())
471 downcast<RenderLayerModelObject>(child).layer()->removeOnlyThisLayer();
472 SVGRenderSupport::childAdded(*this, child);
475 RenderObject* RenderElement::attachRendererInternal(RenderPtr<RenderObject> child, RenderObject* beforeChild)
477 child->setParent(this);
479 if (m_firstChild == beforeChild)
480 m_firstChild = child.get();
483 auto* previousSibling = beforeChild->previousSibling();
485 previousSibling->setNextSibling(child.get());
486 child->setPreviousSibling(previousSibling);
487 child->setNextSibling(beforeChild);
488 beforeChild->setPreviousSibling(child.get());
489 return child.release();
492 m_lastChild->setNextSibling(child.get());
493 child->setPreviousSibling(m_lastChild);
494 m_lastChild = child.get();
495 return child.release();
498 RenderPtr<RenderObject> RenderElement::detachRendererInternal(RenderObject& renderer)
500 auto* parent = renderer.parent();
502 auto* nextSibling = renderer.nextSibling();
504 if (renderer.previousSibling())
505 renderer.previousSibling()->setNextSibling(nextSibling);
507 nextSibling->setPreviousSibling(renderer.previousSibling());
509 if (parent->firstChild() == &renderer)
510 parent->m_firstChild = nextSibling;
511 if (parent->lastChild() == &renderer)
512 parent->m_lastChild = renderer.previousSibling();
514 renderer.setPreviousSibling(nullptr);
515 renderer.setNextSibling(nullptr);
516 renderer.setParent(nullptr);
517 return RenderPtr<RenderObject>(&renderer);
520 RenderBlock* RenderElement::containingBlockForFixedPosition() const
522 auto* renderer = parent();
523 while (renderer && !renderer->canContainFixedPositionObjects())
524 renderer = renderer->parent();
526 ASSERT(!renderer || !renderer->isAnonymousBlock());
527 return downcast<RenderBlock>(renderer);
530 RenderBlock* RenderElement::containingBlockForAbsolutePosition() const
532 // A relatively positioned RenderInline forwards its absolute positioned descendants to
533 // its nearest non-anonymous containing block (to avoid having a positioned objects list in all RenderInlines).
534 auto* renderer = isRenderInline() ? const_cast<RenderElement*>(downcast<RenderElement>(this)) : parent();
535 while (renderer && !renderer->canContainAbsolutelyPositionedObjects())
536 renderer = renderer->parent();
537 // Make sure we only return non-anonymous RenderBlock as containing block.
538 while (renderer && (!is<RenderBlock>(*renderer) || renderer->isAnonymousBlock()))
539 renderer = renderer->containingBlock();
540 return downcast<RenderBlock>(renderer);
543 static void addLayers(RenderElement& renderer, RenderLayer* parentLayer, RenderElement*& newObject, RenderLayer*& beforeChild)
545 if (renderer.hasLayer()) {
546 if (!beforeChild && newObject) {
547 // We need to figure out the layer that follows newObject. We only do
548 // this the first time we find a child layer, and then we update the
549 // pointer values for newObject and beforeChild used by everyone else.
550 beforeChild = newObject->parent()->findNextLayer(parentLayer, newObject);
553 parentLayer->addChild(downcast<RenderLayerModelObject>(renderer).layer(), beforeChild);
557 for (auto& child : childrenOfType<RenderElement>(renderer))
558 addLayers(child, parentLayer, newObject, beforeChild);
561 void RenderElement::addLayers(RenderLayer* parentLayer)
566 RenderElement* renderer = this;
567 RenderLayer* beforeChild = nullptr;
568 WebCore::addLayers(*this, parentLayer, renderer, beforeChild);
571 void RenderElement::removeLayers(RenderLayer* parentLayer)
577 parentLayer->removeChild(downcast<RenderLayerModelObject>(*this).layer());
581 for (auto& child : childrenOfType<RenderElement>(*this))
582 child.removeLayers(parentLayer);
585 void RenderElement::moveLayers(RenderLayer* oldParent, RenderLayer* newParent)
591 RenderLayer* layer = downcast<RenderLayerModelObject>(*this).layer();
592 ASSERT(oldParent == layer->parent());
594 oldParent->removeChild(layer);
595 newParent->addChild(layer);
599 for (auto& child : childrenOfType<RenderElement>(*this))
600 child.moveLayers(oldParent, newParent);
603 RenderLayer* RenderElement::findNextLayer(RenderLayer* parentLayer, RenderObject* startPoint, bool checkParent)
605 // Error check the parent layer passed in. If it's null, we can't find anything.
609 // Step 1: If our layer is a child of the desired parent, then return our layer.
610 RenderLayer* ourLayer = hasLayer() ? downcast<RenderLayerModelObject>(*this).layer() : nullptr;
611 if (ourLayer && ourLayer->parent() == parentLayer)
614 // Step 2: If we don't have a layer, or our layer is the desired parent, then descend
615 // into our siblings trying to find the next layer whose parent is the desired parent.
616 if (!ourLayer || ourLayer == parentLayer) {
617 for (RenderObject* child = startPoint ? startPoint->nextSibling() : firstChild(); child; child = child->nextSibling()) {
618 if (!is<RenderElement>(*child))
620 RenderLayer* nextLayer = downcast<RenderElement>(*child).findNextLayer(parentLayer, nullptr, false);
626 // Step 3: If our layer is the desired parent layer, then we're finished. We didn't
628 if (parentLayer == ourLayer)
631 // Step 4: If |checkParent| is set, climb up to our parent and check its siblings that
632 // follow us to see if we can locate a layer.
633 if (checkParent && parent())
634 return parent()->findNextLayer(parentLayer, this, true);
639 bool RenderElement::layerCreationAllowedForSubtree() const
641 RenderElement* parentRenderer = parent();
642 while (parentRenderer) {
643 if (parentRenderer->isSVGHiddenContainer())
645 parentRenderer = parentRenderer->parent();
651 void RenderElement::propagateStyleToAnonymousChildren(StylePropagationType propagationType)
653 // FIXME: We could save this call when the change only affected non-inherited properties.
654 for (auto& elementChild : childrenOfType<RenderElement>(*this)) {
655 if (!elementChild.isAnonymous() || elementChild.style().styleType() != NOPSEUDO)
658 if (propagationType == PropagateToBlockChildrenOnly && !is<RenderBlock>(elementChild))
661 #if ENABLE(FULLSCREEN_API)
662 if (elementChild.isRenderFullScreen() || elementChild.isRenderFullScreenPlaceholder())
666 // RenderFragmentedFlows are updated through the RenderView::styleDidChange function.
667 if (is<RenderFragmentedFlow>(elementChild))
670 auto newStyle = RenderStyle::createAnonymousStyleWithDisplay(style(), elementChild.style().display());
671 if (style().specifiesColumns()) {
672 if (elementChild.style().specifiesColumns())
673 newStyle.inheritColumnPropertiesFrom(style());
674 if (elementChild.style().columnSpan())
675 newStyle.setColumnSpan(ColumnSpanAll);
678 // Preserve the position style of anonymous block continuations as they can have relative or sticky position when
679 // they contain block descendants of relative or sticky positioned inlines.
680 if (elementChild.isInFlowPositioned() && elementChild.isContinuation())
681 newStyle.setPosition(elementChild.style().position());
683 updateAnonymousChildStyle(newStyle);
685 elementChild.setStyle(WTFMove(newStyle));
689 static inline bool rendererHasBackground(const RenderElement* renderer)
691 return renderer && renderer->hasBackground();
694 void RenderElement::invalidateCachedFirstLineStyle()
696 if (!m_hasValidCachedFirstLineStyle)
698 m_hasValidCachedFirstLineStyle = false;
699 // Invalidate the subtree as descendant's first line style may depend on ancestor's.
700 for (auto& descendant : descendantsOfType<RenderElement>(*this))
701 descendant.m_hasValidCachedFirstLineStyle = false;
704 void RenderElement::styleWillChange(StyleDifference diff, const RenderStyle& newStyle)
706 auto* oldStyle = hasInitializedStyle() ? &style() : nullptr;
708 // If our z-index changes value or our visibility changes,
709 // we need to dirty our stacking context's z-order list.
710 bool visibilityChanged = m_style.visibility() != newStyle.visibility()
711 || m_style.zIndex() != newStyle.zIndex()
712 || m_style.hasAutoZIndex() != newStyle.hasAutoZIndex();
713 #if ENABLE(DASHBOARD_SUPPORT)
714 if (visibilityChanged)
715 document().setAnnotatedRegionsDirty(true);
717 #if PLATFORM(IOS) && ENABLE(TOUCH_EVENTS)
718 if (visibilityChanged)
719 document().setTouchEventRegionsNeedUpdate();
721 if (visibilityChanged) {
722 if (AXObjectCache* cache = document().existingAXObjectCache())
723 cache->childrenChanged(parent(), this);
726 // Keep layer hierarchy visibility bits up to date if visibility changes.
727 if (m_style.visibility() != newStyle.visibility()) {
728 if (RenderLayer* layer = enclosingLayer()) {
729 if (newStyle.visibility() == VISIBLE)
730 layer->setHasVisibleContent();
731 else if (layer->hasVisibleContent() && (this == &layer->renderer() || layer->renderer().style().visibility() != VISIBLE)) {
732 layer->dirtyVisibleContentStatus();
733 if (diff > StyleDifferenceRepaintLayer)
739 if (m_parent && (newStyle.outlineSize() < m_style.outlineSize() || shouldRepaintForStyleDifference(diff)))
741 if (isFloating() && m_style.floating() != newStyle.floating()) {
742 // For changes in float styles, we need to conceivably remove ourselves
743 // from the floating objects list.
744 downcast<RenderBox>(*this).removeFloatingOrPositionedChildFromBlockLists();
745 } else if (isOutOfFlowPositioned() && m_style.position() != newStyle.position()) {
746 // For changes in positioning styles, we need to conceivably remove ourselves
747 // from the positioned objects list.
748 downcast<RenderBox>(*this).removeFloatingOrPositionedChildFromBlockLists();
751 s_noLongerAffectsParentBlock = ((!isFloating() && newStyle.isFloating()) || (!isOutOfFlowPositioned() && newStyle.hasOutOfFlowPosition()))
752 && parent() && parent()->isRenderBlock();
755 if (diff == StyleDifferenceLayout || diff == StyleDifferenceLayoutPositionedMovementOnly) {
757 clearPositionedState();
759 if (newStyle.hasPseudoStyle(FIRST_LINE) || oldStyle->hasPseudoStyle(FIRST_LINE))
760 invalidateCachedFirstLineStyle();
762 setHorizontalWritingMode(true);
763 setHasVisibleBoxDecorations(false);
764 setHasOverflowClip(false);
765 setHasTransformRelatedProperty(false);
766 setHasReflection(false);
768 s_noLongerAffectsParentBlock = false;
770 bool newStyleSlowScroll = false;
771 if (newStyle.hasFixedBackgroundImage() && !settings().fixedBackgroundsPaintRelativeToDocument()) {
772 newStyleSlowScroll = true;
773 bool drawsRootBackground = isDocumentElementRenderer() || (isBody() && !rendererHasBackground(document().documentElement()->renderer()));
774 if (drawsRootBackground && newStyle.hasEntirelyFixedBackground() && view().compositor().supportsFixedRootBackgroundCompositing())
775 newStyleSlowScroll = false;
778 if (view().frameView().hasSlowRepaintObject(*this)) {
779 if (!newStyleSlowScroll)
780 view().frameView().removeSlowRepaintObject(*this);
781 } else if (newStyleSlowScroll)
782 view().frameView().addSlowRepaintObject(*this);
784 if (isDocumentElementRenderer() || isBody())
785 view().frameView().updateExtendBackgroundIfNecessary();
789 static bool areNonIdenticalCursorListsEqual(const RenderStyle* a, const RenderStyle* b)
791 ASSERT(a->cursors() != b->cursors());
792 return a->cursors() && b->cursors() && *a->cursors() == *b->cursors();
795 static inline bool areCursorsEqual(const RenderStyle* a, const RenderStyle* b)
797 return a->cursor() == b->cursor() && (a->cursors() == b->cursors() || areNonIdenticalCursorListsEqual(a, b));
801 void RenderElement::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
803 updateFillImages(oldStyle ? &oldStyle->backgroundLayers() : nullptr, m_style.backgroundLayers());
804 updateFillImages(oldStyle ? &oldStyle->maskLayers() : nullptr, m_style.maskLayers());
805 updateImage(oldStyle ? oldStyle->borderImage().image() : nullptr, m_style.borderImage().image());
806 updateImage(oldStyle ? oldStyle->maskBoxImage().image() : nullptr, m_style.maskBoxImage().image());
807 updateShapeImage(oldStyle ? oldStyle->shapeOutside() : nullptr, m_style.shapeOutside());
809 bool affectsParentBlock = oldStyle && (oldStyle->isFloating() || oldStyle->hasOutOfFlowPosition())
810 && !style().isFloating() && !style().hasOutOfFlowPosition()
811 && parent() && (parent()->isRenderBlockFlow() || parent()->isRenderInline());
812 if (affectsParentBlock) {
813 // We have gone from not affecting the inline status of the parent flow to suddenly
814 // having an impact. See if there is a mismatch between the parent flow's
815 // childrenInline() state and our state.
816 setInline(style().isDisplayInlineType());
817 if (isInline() != parent()->childrenInline())
818 RenderTreeBuilder::current()->childFlowStateChangesAndAffectsParentBlock(*this);
821 if (s_noLongerAffectsParentBlock)
822 RenderTreeBuilder::current()->childFlowStateChangesAndNoLongerAffectsParentBlock(*this);
824 SVGRenderSupport::styleChanged(*this, oldStyle);
829 if (diff == StyleDifferenceLayout || diff == StyleDifferenceSimplifiedLayout) {
830 RenderCounter::rendererStyleChanged(*this, oldStyle, &m_style);
832 // If the object already needs layout, then setNeedsLayout won't do
833 // any work. But if the containing block has changed, then we may need
834 // to mark the new containing blocks for layout. The change that can
835 // directly affect the containing block of this object is a change to
836 // the position style.
837 if (needsLayout() && oldStyle->position() != m_style.position())
838 markContainingBlocksForLayout();
840 if (diff == StyleDifferenceLayout)
841 setNeedsLayoutAndPrefWidthsRecalc();
843 setNeedsSimplifiedNormalFlowLayout();
844 } else if (diff == StyleDifferenceSimplifiedLayoutAndPositionedMovement) {
845 setNeedsPositionedMovementLayout(oldStyle);
846 setNeedsSimplifiedNormalFlowLayout();
847 } else if (diff == StyleDifferenceLayoutPositionedMovementOnly)
848 setNeedsPositionedMovementLayout(oldStyle);
850 // Don't check for repaint here; we need to wait until the layer has been
851 // updated by subclasses before we know if we have to repaint (in setStyle()).
854 if (oldStyle && !areCursorsEqual(oldStyle, &style()))
855 frame().eventHandler().scheduleCursorUpdate();
857 bool hadOutlineAuto = oldStyle && oldStyle->outlineStyleIsAuto();
858 bool hasOutlineAuto = outlineStyleForRepaint().outlineStyleIsAuto();
859 if (hasOutlineAuto != hadOutlineAuto) {
860 updateOutlineAutoAncestor(hasOutlineAuto);
861 issueRepaintForOutlineAuto(hasOutlineAuto ? outlineStyleForRepaint().outlineSize() : oldStyle->outlineSize());
865 void RenderElement::insertedIntoTree()
867 // Keep our layer hierarchy updated. Optimize for the common case where we don't have any children
868 // and don't have a layer attached to ourselves.
869 RenderLayer* layer = nullptr;
870 if (firstChild() || hasLayer()) {
871 layer = parent()->enclosingLayer();
875 // If |this| is visible but this object was not, tell the layer it has some visible content
876 // that needs to be drawn and layer visibility optimization can't be used
877 if (parent()->style().visibility() != VISIBLE && style().visibility() == VISIBLE && !hasLayer()) {
879 layer = parent()->enclosingLayer();
881 layer->setHasVisibleContent();
884 RenderObject::insertedIntoTree();
887 void RenderElement::willBeRemovedFromTree()
889 // If we remove a visible child from an invisible parent, we don't know the layer visibility any more.
890 RenderLayer* layer = nullptr;
891 if (parent()->style().visibility() != VISIBLE && style().visibility() == VISIBLE && !hasLayer()) {
892 if ((layer = parent()->enclosingLayer()))
893 layer->dirtyVisibleContentStatus();
895 // Keep our layer hierarchy updated.
896 if (firstChild() || hasLayer()) {
898 layer = parent()->enclosingLayer();
902 if (isOutOfFlowPositioned() && parent()->childrenInline())
903 parent()->dirtyLinesFromChangedChild(*this);
905 RenderObject::willBeRemovedFromTree();
908 inline void RenderElement::clearSubtreeLayoutRootIfNeeded() const
910 if (renderTreeBeingDestroyed())
913 if (view().frameView().layoutContext().subtreeLayoutRoot() != this)
916 // Normally when a renderer is detached from the tree, the appropriate dirty bits get set
917 // which ensures that this renderer is no longer the layout root.
918 ASSERT_NOT_REACHED();
920 // This indicates a failure to layout the child, which is why
921 // the layout root is still set to |this|. Make sure to clear it
922 // since we are getting destroyed.
923 view().frameView().layoutContext().clearSubtreeLayoutRoot();
926 void RenderElement::willBeDestroyed()
928 if (m_style.hasFixedBackgroundImage() && !settings().fixedBackgroundsPaintRelativeToDocument())
929 view().frameView().removeSlowRepaintObject(*this);
931 unregisterForVisibleInViewportCallback();
933 if (hasCounterNodeMap())
934 RenderCounter::destroyCounterNodes(*this);
936 RenderObject::willBeDestroyed();
938 clearSubtreeLayoutRootIfNeeded();
940 if (hasInitializedStyle()) {
941 for (auto* bgLayer = &m_style.backgroundLayers(); bgLayer; bgLayer = bgLayer->next()) {
942 if (auto* backgroundImage = bgLayer->image())
943 backgroundImage->removeClient(this);
945 for (auto* maskLayer = &m_style.maskLayers(); maskLayer; maskLayer = maskLayer->next()) {
946 if (auto* maskImage = maskLayer->image())
947 maskImage->removeClient(this);
949 if (auto* borderImage = m_style.borderImage().image())
950 borderImage->removeClient(this);
951 if (auto* maskBoxImage = m_style.maskBoxImage().image())
952 maskBoxImage->removeClient(this);
953 if (auto shapeValue = m_style.shapeOutside()) {
954 if (auto shapeImage = shapeValue->image())
955 shapeImage->removeClient(this);
958 if (m_hasPausedImageAnimations)
959 view().removeRendererWithPausedImageAnimations(*this);
962 void RenderElement::setNeedsPositionedMovementLayout(const RenderStyle* oldStyle)
964 ASSERT(!isSetNeedsLayoutForbidden());
965 if (needsPositionedMovementLayout())
967 setNeedsPositionedMovementLayoutBit(true);
968 markContainingBlocksForLayout();
970 if (oldStyle && style().diffRequiresLayerRepaint(*oldStyle, downcast<RenderLayerModelObject>(*this).layer()->isComposited()))
971 setLayerNeedsFullRepaint();
973 setLayerNeedsFullRepaintForPositionedMovementLayout();
977 void RenderElement::clearChildNeedsLayout()
979 setNormalChildNeedsLayoutBit(false);
980 setPosChildNeedsLayoutBit(false);
981 setNeedsSimplifiedNormalFlowLayoutBit(false);
982 setNormalChildNeedsLayoutBit(false);
983 setNeedsPositionedMovementLayoutBit(false);
986 void RenderElement::setNeedsSimplifiedNormalFlowLayout()
988 ASSERT(!isSetNeedsLayoutForbidden());
989 if (needsSimplifiedNormalFlowLayout())
991 setNeedsSimplifiedNormalFlowLayoutBit(true);
992 markContainingBlocksForLayout();
994 setLayerNeedsFullRepaint();
997 RenderElement* RenderElement::hoverAncestor() const
1002 static inline void paintPhase(RenderElement& element, PaintPhase phase, PaintInfo& paintInfo, const LayoutPoint& childPoint)
1004 paintInfo.phase = phase;
1005 element.paint(paintInfo, childPoint);
1008 void RenderElement::paintAsInlineBlock(PaintInfo& paintInfo, const LayoutPoint& childPoint)
1010 // Paint all phases atomically, as though the element established its own stacking context.
1011 // (See Appendix E.2, section 6.4 on inline block/table/replaced elements in the CSS2.1 specification.)
1012 // This is also used by other elements (e.g. flex items and grid items).
1013 PaintPhase paintPhaseToUse = isExcludedAndPlacedInBorder() ? paintInfo.phase : PaintPhaseForeground;
1014 if (paintInfo.phase == PaintPhaseSelection)
1015 paint(paintInfo, childPoint);
1016 else if (paintInfo.phase == paintPhaseToUse) {
1017 paintPhase(*this, PaintPhaseBlockBackground, paintInfo, childPoint);
1018 paintPhase(*this, PaintPhaseChildBlockBackgrounds, paintInfo, childPoint);
1019 paintPhase(*this, PaintPhaseFloat, paintInfo, childPoint);
1020 paintPhase(*this, PaintPhaseForeground, paintInfo, childPoint);
1021 paintPhase(*this, PaintPhaseOutline, paintInfo, childPoint);
1023 // Reset |paintInfo| to the original phase.
1024 paintInfo.phase = paintPhaseToUse;
1028 void RenderElement::layout()
1030 StackStats::LayoutCheckPoint layoutCheckPoint;
1031 ASSERT(needsLayout());
1032 for (auto* child = firstChild(); child; child = child->nextSibling()) {
1033 if (child->needsLayout())
1034 downcast<RenderElement>(*child).layout();
1035 ASSERT(!child->needsLayout());
1040 static bool mustRepaintFillLayers(const RenderElement& renderer, const FillLayer& layer)
1042 // Nobody will use multiple layers without wanting fancy positioning.
1046 // Make sure we have a valid image.
1047 auto* image = layer.image();
1048 if (!image || !image->canRender(&renderer, renderer.style().effectiveZoom()))
1051 if (!layer.xPosition().isZero() || !layer.yPosition().isZero())
1054 auto sizeType = layer.sizeType();
1056 if (sizeType == Contain || sizeType == Cover)
1059 if (sizeType == SizeLength) {
1060 auto size = layer.sizeLength();
1061 if (size.width.isPercentOrCalculated() || size.height.isPercentOrCalculated())
1063 // If the image has neither an intrinsic width nor an intrinsic height, its size is determined as for 'contain'.
1064 if ((size.width.isAuto() || size.height.isAuto()) && image->isGeneratedImage())
1066 } else if (image->usesImageContainerSize())
1072 static bool mustRepaintBackgroundOrBorder(const RenderElement& renderer)
1074 if (renderer.hasMask() && mustRepaintFillLayers(renderer, renderer.style().maskLayers()))
1077 // If we don't have a background/border/mask, then nothing to do.
1078 if (!renderer.hasVisibleBoxDecorations())
1081 if (mustRepaintFillLayers(renderer, renderer.style().backgroundLayers()))
1084 // Our fill layers are ok. Let's check border.
1085 if (renderer.style().hasBorder() && renderer.borderImageIsLoadedAndCanBeRendered())
1091 bool RenderElement::repaintAfterLayoutIfNeeded(const RenderLayerModelObject* repaintContainer, const LayoutRect& oldBounds, const LayoutRect& oldOutlineBox, const LayoutRect* newBoundsPtr, const LayoutRect* newOutlineBoxRectPtr)
1093 if (view().printing())
1094 return false; // Don't repaint if we're printing.
1096 // This ASSERT fails due to animations. See https://bugs.webkit.org/show_bug.cgi?id=37048
1097 // ASSERT(!newBoundsPtr || *newBoundsPtr == clippedOverflowRectForRepaint(repaintContainer));
1098 LayoutRect newBounds = newBoundsPtr ? *newBoundsPtr : clippedOverflowRectForRepaint(repaintContainer);
1099 LayoutRect newOutlineBox;
1101 bool fullRepaint = selfNeedsLayout();
1102 // Presumably a background or a border exists if border-fit:lines was specified.
1103 if (!fullRepaint && style().borderFit() == BorderFitLines)
1106 // This ASSERT fails due to animations. See https://bugs.webkit.org/show_bug.cgi?id=37048
1107 // ASSERT(!newOutlineBoxRectPtr || *newOutlineBoxRectPtr == outlineBoundsForRepaint(repaintContainer));
1108 newOutlineBox = newOutlineBoxRectPtr ? *newOutlineBoxRectPtr : outlineBoundsForRepaint(repaintContainer);
1109 fullRepaint = (newOutlineBox.location() != oldOutlineBox.location() || (mustRepaintBackgroundOrBorder(*this) && (newBounds != oldBounds || newOutlineBox != oldOutlineBox)));
1112 if (!repaintContainer)
1113 repaintContainer = &view();
1116 repaintUsingContainer(repaintContainer, oldBounds);
1117 if (newBounds != oldBounds)
1118 repaintUsingContainer(repaintContainer, newBounds);
1122 if (newBounds == oldBounds && newOutlineBox == oldOutlineBox)
1125 LayoutUnit deltaLeft = newBounds.x() - oldBounds.x();
1127 repaintUsingContainer(repaintContainer, LayoutRect(oldBounds.x(), oldBounds.y(), deltaLeft, oldBounds.height()));
1128 else if (deltaLeft < 0)
1129 repaintUsingContainer(repaintContainer, LayoutRect(newBounds.x(), newBounds.y(), -deltaLeft, newBounds.height()));
1131 LayoutUnit deltaRight = newBounds.maxX() - oldBounds.maxX();
1133 repaintUsingContainer(repaintContainer, LayoutRect(oldBounds.maxX(), newBounds.y(), deltaRight, newBounds.height()));
1134 else if (deltaRight < 0)
1135 repaintUsingContainer(repaintContainer, LayoutRect(newBounds.maxX(), oldBounds.y(), -deltaRight, oldBounds.height()));
1137 LayoutUnit deltaTop = newBounds.y() - oldBounds.y();
1139 repaintUsingContainer(repaintContainer, LayoutRect(oldBounds.x(), oldBounds.y(), oldBounds.width(), deltaTop));
1140 else if (deltaTop < 0)
1141 repaintUsingContainer(repaintContainer, LayoutRect(newBounds.x(), newBounds.y(), newBounds.width(), -deltaTop));
1143 LayoutUnit deltaBottom = newBounds.maxY() - oldBounds.maxY();
1144 if (deltaBottom > 0)
1145 repaintUsingContainer(repaintContainer, LayoutRect(newBounds.x(), oldBounds.maxY(), newBounds.width(), deltaBottom));
1146 else if (deltaBottom < 0)
1147 repaintUsingContainer(repaintContainer, LayoutRect(oldBounds.x(), newBounds.maxY(), oldBounds.width(), -deltaBottom));
1149 if (newOutlineBox == oldOutlineBox)
1152 // We didn't move, but we did change size. Invalidate the delta, which will consist of possibly
1153 // two rectangles (but typically only one).
1154 const RenderStyle& outlineStyle = outlineStyleForRepaint();
1155 LayoutUnit outlineWidth = outlineStyle.outlineSize();
1156 LayoutBoxExtent insetShadowExtent = style().getBoxShadowInsetExtent();
1157 LayoutUnit width = absoluteValue(newOutlineBox.width() - oldOutlineBox.width());
1159 LayoutUnit shadowLeft;
1160 LayoutUnit shadowRight;
1161 style().getBoxShadowHorizontalExtent(shadowLeft, shadowRight);
1162 LayoutUnit borderRight = is<RenderBox>(*this) ? downcast<RenderBox>(*this).borderRight() : LayoutUnit::fromPixel(0);
1163 LayoutUnit boxWidth = is<RenderBox>(*this) ? downcast<RenderBox>(*this).width() : LayoutUnit();
1164 LayoutUnit minInsetRightShadowExtent = std::min<LayoutUnit>(-insetShadowExtent.right(), std::min(newBounds.width(), oldBounds.width()));
1165 LayoutUnit borderWidth = std::max(borderRight, std::max(valueForLength(style().borderTopRightRadius().width, boxWidth), valueForLength(style().borderBottomRightRadius().width, boxWidth)));
1166 LayoutUnit decorationsWidth = std::max<LayoutUnit>(-outlineStyle.outlineOffset(), borderWidth + minInsetRightShadowExtent) + std::max(outlineWidth, shadowRight);
1167 LayoutRect rightRect(newOutlineBox.x() + std::min(newOutlineBox.width(), oldOutlineBox.width()) - decorationsWidth,
1169 width + decorationsWidth,
1170 std::max(newOutlineBox.height(), oldOutlineBox.height()));
1171 LayoutUnit right = std::min(newBounds.maxX(), oldBounds.maxX());
1172 if (rightRect.x() < right) {
1173 rightRect.setWidth(std::min(rightRect.width(), right - rightRect.x()));
1174 repaintUsingContainer(repaintContainer, rightRect);
1177 LayoutUnit height = absoluteValue(newOutlineBox.height() - oldOutlineBox.height());
1179 LayoutUnit shadowTop;
1180 LayoutUnit shadowBottom;
1181 style().getBoxShadowVerticalExtent(shadowTop, shadowBottom);
1182 LayoutUnit borderBottom = is<RenderBox>(*this) ? downcast<RenderBox>(*this).borderBottom() : LayoutUnit::fromPixel(0);
1183 LayoutUnit boxHeight = is<RenderBox>(*this) ? downcast<RenderBox>(*this).height() : LayoutUnit();
1184 LayoutUnit minInsetBottomShadowExtent = std::min<LayoutUnit>(-insetShadowExtent.bottom(), std::min(newBounds.height(), oldBounds.height()));
1185 LayoutUnit borderHeight = std::max(borderBottom, std::max(valueForLength(style().borderBottomLeftRadius().height, boxHeight),
1186 valueForLength(style().borderBottomRightRadius().height, boxHeight)));
1187 LayoutUnit decorationsHeight = std::max<LayoutUnit>(-outlineStyle.outlineOffset(), borderHeight + minInsetBottomShadowExtent) + std::max(outlineWidth, shadowBottom);
1188 LayoutRect bottomRect(newOutlineBox.x(),
1189 std::min(newOutlineBox.maxY(), oldOutlineBox.maxY()) - decorationsHeight,
1190 std::max(newOutlineBox.width(), oldOutlineBox.width()),
1191 height + decorationsHeight);
1192 LayoutUnit bottom = std::min(newBounds.maxY(), oldBounds.maxY());
1193 if (bottomRect.y() < bottom) {
1194 bottomRect.setHeight(std::min(bottomRect.height(), bottom - bottomRect.y()));
1195 repaintUsingContainer(repaintContainer, bottomRect);
1201 bool RenderElement::borderImageIsLoadedAndCanBeRendered() const
1203 ASSERT(style().hasBorder());
1205 StyleImage* borderImage = style().borderImage().image();
1206 return borderImage && borderImage->canRender(this, style().effectiveZoom()) && borderImage->isLoaded();
1209 bool RenderElement::mayCauseRepaintInsideViewport(const IntRect* optionalViewportRect) const
1211 auto& frameView = view().frameView();
1212 if (frameView.isOffscreen())
1215 if (!hasOverflowClip()) {
1216 // FIXME: Computing the overflow rect is expensive if any descendant has
1217 // its own self-painting layer. As a result, we prefer to abort early in
1218 // this case and assume it may cause us to repaint inside the viewport.
1219 if (!hasLayer() || downcast<RenderLayerModelObject>(*this).layer()->firstChild())
1223 // Compute viewport rect if it was not provided.
1224 const IntRect& visibleRect = optionalViewportRect ? *optionalViewportRect : frameView.windowToContents(frameView.windowClipRect());
1225 return visibleRect.intersects(enclosingIntRect(absoluteClippedOverflowRect()));
1228 bool RenderElement::isVisibleInDocumentRect(const IntRect& documentRect) const
1230 if (document().activeDOMObjectsAreSuspended())
1232 if (style().visibility() != VISIBLE)
1234 if (view().frameView().isOffscreen())
1237 // Use background rect if we are the root or if we are the body and the background is propagated to the root.
1238 // FIXME: This is overly conservative as the image may not be a background-image, in which case it will not
1239 // be propagated to the root. At this point, we unfortunately don't have access to the image anymore so we
1240 // can no longer check if it is a background image.
1241 bool backgroundIsPaintedByRoot = isDocumentElementRenderer();
1243 auto& rootRenderer = *parent(); // If <body> has a renderer then <html> does too.
1244 ASSERT(rootRenderer.isDocumentElementRenderer());
1245 ASSERT(is<HTMLHtmlElement>(rootRenderer.element()));
1246 // FIXME: Should share body background propagation code.
1247 backgroundIsPaintedByRoot = !rootRenderer.hasBackground();
1251 LayoutRect backgroundPaintingRect = backgroundIsPaintedByRoot ? view().backgroundRect() : absoluteClippedOverflowRect();
1252 if (!documentRect.intersects(enclosingIntRect(backgroundPaintingRect)))
1258 void RenderElement::registerForVisibleInViewportCallback()
1260 if (m_isRegisteredForVisibleInViewportCallback)
1262 m_isRegisteredForVisibleInViewportCallback = true;
1264 view().registerForVisibleInViewportCallback(*this);
1267 void RenderElement::unregisterForVisibleInViewportCallback()
1269 if (!m_isRegisteredForVisibleInViewportCallback)
1271 m_isRegisteredForVisibleInViewportCallback = false;
1273 view().unregisterForVisibleInViewportCallback(*this);
1276 void RenderElement::setVisibleInViewportState(VisibleInViewportState state)
1278 if (state == visibleInViewportState())
1280 m_visibleInViewportState = static_cast<unsigned>(state);
1281 visibleInViewportStateChanged();
1284 void RenderElement::visibleInViewportStateChanged()
1286 ASSERT_NOT_REACHED();
1289 bool RenderElement::isVisibleInViewport() const
1291 auto& frameView = view().frameView();
1292 auto visibleRect = frameView.windowToContents(frameView.windowClipRect());
1293 return isVisibleInDocumentRect(visibleRect);
1296 VisibleInViewportState RenderElement::imageFrameAvailable(CachedImage& image, ImageAnimatingState animatingState, const IntRect* changeRect)
1298 bool isVisible = isVisibleInViewport();
1300 if (!isVisible && animatingState == ImageAnimatingState::Yes)
1301 view().addRendererWithPausedImageAnimations(*this, image);
1303 // Static images should repaint even if they are outside the viewport rectangle
1304 // because they should be inside the TileCoverageRect.
1305 if (isVisible || animatingState == ImageAnimatingState::No)
1306 imageChanged(&image, changeRect);
1308 if (element() && image.image()->isBitmapImage())
1309 element()->dispatchWebKitImageReadyEventForTesting();
1311 return isVisible ? VisibleInViewportState::Yes : VisibleInViewportState::No;
1314 void RenderElement::didRemoveCachedImageClient(CachedImage& cachedImage)
1316 if (hasPausedImageAnimations())
1317 view().removeRendererWithPausedImageAnimations(*this, cachedImage);
1320 bool RenderElement::repaintForPausedImageAnimationsIfNeeded(const IntRect& visibleRect, CachedImage& cachedImage)
1322 ASSERT(m_hasPausedImageAnimations);
1323 if (!isVisibleInDocumentRect(visibleRect))
1328 if (auto* image = cachedImage.image()) {
1329 if (is<SVGImage>(image))
1330 downcast<SVGImage>(image)->scheduleStartAnimation();
1332 image->startAnimation();
1335 // For directly-composited animated GIFs it does not suffice to call repaint() to resume animation. We need to mark the image as changed.
1336 if (is<RenderBoxModelObject>(*this))
1337 downcast<RenderBoxModelObject>(*this).contentChanged(ImageChanged);
1342 const RenderStyle* RenderElement::getCachedPseudoStyle(PseudoId pseudo, const RenderStyle* parentStyle) const
1344 if (pseudo < FIRST_INTERNAL_PSEUDOID && !style().hasPseudoStyle(pseudo))
1347 RenderStyle* cachedStyle = style().getCachedPseudoStyle(pseudo);
1351 std::unique_ptr<RenderStyle> result = getUncachedPseudoStyle(PseudoStyleRequest(pseudo), parentStyle);
1353 return const_cast<RenderStyle&>(m_style).addCachedPseudoStyle(WTFMove(result));
1357 std::unique_ptr<RenderStyle> RenderElement::getUncachedPseudoStyle(const PseudoStyleRequest& pseudoStyleRequest, const RenderStyle* parentStyle, const RenderStyle* ownStyle) const
1359 if (pseudoStyleRequest.pseudoId < FIRST_INTERNAL_PSEUDOID && !ownStyle && !style().hasPseudoStyle(pseudoStyleRequest.pseudoId))
1364 parentStyle = &style();
1370 auto& styleResolver = element()->styleResolver();
1372 std::unique_ptr<RenderStyle> style = styleResolver.pseudoStyleForElement(*element(), pseudoStyleRequest, *parentStyle);
1375 Style::loadPendingResources(*style, document(), element());
1380 Color RenderElement::selectionColor(int colorProperty) const
1382 // If the element is unselectable, or we are only painting the selection,
1383 // don't override the foreground color with the selection foreground color.
1384 if (style().userSelect() == SELECT_NONE
1385 || (view().frameView().paintBehavior() & (PaintBehaviorSelectionOnly | PaintBehaviorSelectionAndBackgroundsOnly)))
1388 if (std::unique_ptr<RenderStyle> pseudoStyle = selectionPseudoStyle()) {
1389 Color color = pseudoStyle->visitedDependentColor(colorProperty);
1390 if (!color.isValid())
1391 color = pseudoStyle->visitedDependentColor(CSSPropertyColor);
1395 if (frame().selection().isFocusedAndActive())
1396 return theme().activeSelectionForegroundColor();
1397 return theme().inactiveSelectionForegroundColor();
1400 std::unique_ptr<RenderStyle> RenderElement::selectionPseudoStyle() const
1405 if (ShadowRoot* root = element()->containingShadowRoot()) {
1406 if (root->mode() == ShadowRootMode::UserAgent) {
1407 if (Element* shadowHost = element()->shadowHost())
1408 return shadowHost->renderer()->getUncachedPseudoStyle(PseudoStyleRequest(SELECTION));
1412 return getUncachedPseudoStyle(PseudoStyleRequest(SELECTION));
1415 Color RenderElement::selectionForegroundColor() const
1417 return selectionColor(CSSPropertyWebkitTextFillColor);
1420 Color RenderElement::selectionEmphasisMarkColor() const
1422 return selectionColor(CSSPropertyWebkitTextEmphasisColor);
1425 Color RenderElement::selectionBackgroundColor() const
1427 if (style().userSelect() == SELECT_NONE)
1430 if (frame().selection().shouldShowBlockCursor() && frame().selection().isCaret())
1431 return style().visitedDependentColor(CSSPropertyColor).blendWithWhite();
1433 std::unique_ptr<RenderStyle> pseudoStyle = selectionPseudoStyle();
1434 if (pseudoStyle && pseudoStyle->visitedDependentColor(CSSPropertyBackgroundColor).isValid())
1435 return pseudoStyle->visitedDependentColor(CSSPropertyBackgroundColor).blendWithWhite();
1437 if (frame().selection().isFocusedAndActive())
1438 return theme().activeSelectionBackgroundColor();
1439 return theme().inactiveSelectionBackgroundColor();
1442 bool RenderElement::getLeadingCorner(FloatPoint& point, bool& insideFixed) const
1444 if (!isInline() || isReplaced()) {
1445 point = localToAbsolute(FloatPoint(), UseTransforms, &insideFixed);
1449 // find the next text/image child, to get a position
1450 const RenderObject* o = this;
1452 const RenderObject* p = o;
1453 if (RenderObject* child = o->firstChildSlow())
1455 else if (o->nextSibling())
1456 o = o->nextSibling();
1458 RenderObject* next = 0;
1459 while (!next && o->parent()) {
1461 next = o->nextSibling();
1470 if (!o->isInline() || o->isReplaced()) {
1471 point = o->localToAbsolute(FloatPoint(), UseTransforms, &insideFixed);
1475 if (p->node() && p->node() == element() && is<RenderText>(*o) && !downcast<RenderText>(*o).firstTextBox()) {
1476 // do nothing - skip unrendered whitespace that is a child or next sibling of the anchor
1477 } else if (is<RenderText>(*o) || o->isReplaced()) {
1478 point = FloatPoint();
1479 if (is<RenderText>(*o) && downcast<RenderText>(*o).firstTextBox())
1480 point.move(downcast<RenderText>(*o).linesBoundingBox().x(), downcast<RenderText>(*o).topOfFirstText());
1481 else if (is<RenderBox>(*o))
1482 point.moveBy(downcast<RenderBox>(*o).location());
1483 point = o->container()->localToAbsolute(point, UseTransforms, &insideFixed);
1488 // If the target doesn't have any children or siblings that could be used to calculate the scroll position, we must be
1489 // at the end of the document. Scroll to the bottom. FIXME: who said anything about scrolling?
1490 if (!o && document().view()) {
1491 point = FloatPoint(0, document().view()->contentsHeight());
1497 bool RenderElement::getTrailingCorner(FloatPoint& point, bool& insideFixed) const
1499 if (!isInline() || isReplaced()) {
1500 point = localToAbsolute(LayoutPoint(downcast<RenderBox>(*this).size()), UseTransforms, &insideFixed);
1504 // find the last text/image child, to get a position
1505 const RenderObject* o = this;
1507 if (RenderObject* child = o->lastChildSlow())
1509 else if (o->previousSibling())
1510 o = o->previousSibling();
1512 RenderObject* prev = 0;
1517 prev = o->previousSibling();
1522 if (is<RenderText>(*o) || o->isReplaced()) {
1523 point = FloatPoint();
1524 if (is<RenderText>(*o)) {
1525 LayoutRect linesBox = downcast<RenderText>(*o).linesBoundingBox();
1526 if (!linesBox.maxX() && !linesBox.maxY())
1528 point.moveBy(linesBox.maxXMaxYCorner());
1530 point.moveBy(downcast<RenderBox>(*o).frameRect().maxXMaxYCorner());
1531 point = o->container()->localToAbsolute(point, UseTransforms, &insideFixed);
1538 LayoutRect RenderElement::absoluteAnchorRect(bool* insideFixed) const
1540 FloatPoint leading, trailing;
1541 bool leadingInFixed = false;
1542 bool trailingInFixed = false;
1543 getLeadingCorner(leading, leadingInFixed);
1544 getTrailingCorner(trailing, trailingInFixed);
1546 FloatPoint upperLeft = leading;
1547 FloatPoint lowerRight = trailing;
1549 // Vertical writing modes might mean the leading point is not in the top left
1550 if (!isInline() || isReplaced()) {
1551 upperLeft = FloatPoint(std::min(leading.x(), trailing.x()), std::min(leading.y(), trailing.y()));
1552 lowerRight = FloatPoint(std::max(leading.x(), trailing.x()), std::max(leading.y(), trailing.y()));
1553 } // Otherwise, it's not obvious what to do.
1556 // For now, just look at the leading corner. Handling one inside fixed and one not would be tricky.
1557 *insideFixed = leadingInFixed;
1560 return enclosingLayoutRect(FloatRect(upperLeft, lowerRight.expandedTo(upperLeft) - upperLeft));
1563 const RenderElement* RenderElement::enclosingRendererWithTextDecoration(TextDecoration textDecoration, bool firstLine) const
1565 const RenderElement* current = this;
1567 if (current->isRenderBlock())
1569 if (!current->isRenderInline() || current->isRubyText())
1572 const RenderStyle& styleToUse = firstLine ? current->firstLineStyle() : current->style();
1573 if (styleToUse.textDecoration() & textDecoration)
1575 current = current->parent();
1576 } while (current && (!current->element() || (!is<HTMLAnchorElement>(*current->element()) && !current->element()->hasTagName(HTMLNames::fontTag))));
1581 void RenderElement::drawLineForBoxSide(GraphicsContext& graphicsContext, const FloatRect& rect, BoxSide side, Color color, EBorderStyle borderStyle, float adjacentWidth1, float adjacentWidth2, bool antialias) const
1583 auto drawBorderRect = [&graphicsContext] (const FloatRect& rect)
1587 graphicsContext.drawRect(rect);
1590 auto drawLineFor = [this, &graphicsContext, color, antialias] (const FloatRect& rect, BoxSide side, EBorderStyle borderStyle, const FloatSize& adjacent)
1594 drawLineForBoxSide(graphicsContext, rect, side, color, borderStyle, adjacent.width(), adjacent.height(), antialias);
1597 float x1 = rect.x();
1598 float x2 = rect.maxX();
1599 float y1 = rect.y();
1600 float y2 = rect.maxY();
1603 if (side == BSTop || side == BSBottom) {
1604 thickness = y2 - y1;
1607 thickness = x2 - x1;
1610 // FIXME: We really would like this check to be an ASSERT as we don't want to draw empty borders. However
1611 // nothing guarantees that the following recursive calls to drawLineForBoxSide will have non-null dimensions.
1612 if (!thickness || !length)
1615 float deviceScaleFactor = document().deviceScaleFactor();
1616 if (borderStyle == DOUBLE && (thickness * deviceScaleFactor) < 3)
1617 borderStyle = SOLID;
1619 switch (borderStyle) {
1625 bool wasAntialiased = graphicsContext.shouldAntialias();
1626 StrokeStyle oldStrokeStyle = graphicsContext.strokeStyle();
1627 graphicsContext.setShouldAntialias(antialias);
1628 graphicsContext.setStrokeColor(color);
1629 graphicsContext.setStrokeThickness(thickness);
1630 graphicsContext.setStrokeStyle(borderStyle == DASHED ? DashedStroke : DottedStroke);
1631 graphicsContext.drawLine(roundPointToDevicePixels(LayoutPoint(x1, y1), deviceScaleFactor), roundPointToDevicePixels(LayoutPoint(x2, y2), deviceScaleFactor));
1632 graphicsContext.setShouldAntialias(wasAntialiased);
1633 graphicsContext.setStrokeStyle(oldStrokeStyle);
1637 float thirdOfThickness = ceilToDevicePixel(thickness / 3, deviceScaleFactor);
1638 ASSERT(thirdOfThickness);
1640 if (!adjacentWidth1 && !adjacentWidth2) {
1641 StrokeStyle oldStrokeStyle = graphicsContext.strokeStyle();
1642 graphicsContext.setStrokeStyle(NoStroke);
1643 graphicsContext.setFillColor(color);
1645 bool wasAntialiased = graphicsContext.shouldAntialias();
1646 graphicsContext.setShouldAntialias(antialias);
1651 drawBorderRect(snapRectToDevicePixels(x1, y1, length, thirdOfThickness, deviceScaleFactor));
1652 drawBorderRect(snapRectToDevicePixels(x1, y2 - thirdOfThickness, length, thirdOfThickness, deviceScaleFactor));
1656 drawBorderRect(snapRectToDevicePixels(x1, y1, thirdOfThickness, length, deviceScaleFactor));
1657 drawBorderRect(snapRectToDevicePixels(x2 - thirdOfThickness, y1, thirdOfThickness, length, deviceScaleFactor));
1661 graphicsContext.setShouldAntialias(wasAntialiased);
1662 graphicsContext.setStrokeStyle(oldStrokeStyle);
1664 float adjacent1BigThird = ceilToDevicePixel(adjacentWidth1 / 3, deviceScaleFactor);
1665 float adjacent2BigThird = ceilToDevicePixel(adjacentWidth2 / 3, deviceScaleFactor);
1667 float offset1 = floorToDevicePixel(fabs(adjacentWidth1) * 2 / 3, deviceScaleFactor);
1668 float offset2 = floorToDevicePixel(fabs(adjacentWidth2) * 2 / 3, deviceScaleFactor);
1670 float mitreOffset1 = adjacentWidth1 < 0 ? offset1 : 0;
1671 float mitreOffset2 = adjacentWidth1 > 0 ? offset1 : 0;
1672 float mitreOffset3 = adjacentWidth2 < 0 ? offset2 : 0;
1673 float mitreOffset4 = adjacentWidth2 > 0 ? offset2 : 0;
1675 FloatRect paintBorderRect;
1678 paintBorderRect = snapRectToDevicePixels(LayoutRect(x1 + mitreOffset1, y1, (x2 - mitreOffset3) - (x1 + mitreOffset1), thirdOfThickness), deviceScaleFactor);
1679 drawLineFor(paintBorderRect, side, SOLID, FloatSize(adjacent1BigThird, adjacent2BigThird));
1681 paintBorderRect = snapRectToDevicePixels(LayoutRect(x1 + mitreOffset2, y2 - thirdOfThickness, (x2 - mitreOffset4) - (x1 + mitreOffset2), thirdOfThickness), deviceScaleFactor);
1682 drawLineFor(paintBorderRect, side, SOLID, FloatSize(adjacent1BigThird, adjacent2BigThird));
1685 paintBorderRect = snapRectToDevicePixels(LayoutRect(x1, y1 + mitreOffset1, thirdOfThickness, (y2 - mitreOffset3) - (y1 + mitreOffset1)), deviceScaleFactor);
1686 drawLineFor(paintBorderRect, side, SOLID, FloatSize(adjacent1BigThird, adjacent2BigThird));
1688 paintBorderRect = snapRectToDevicePixels(LayoutRect(x2 - thirdOfThickness, y1 + mitreOffset2, thirdOfThickness, (y2 - mitreOffset4) - (y1 + mitreOffset2)), deviceScaleFactor);
1689 drawLineFor(paintBorderRect, side, SOLID, FloatSize(adjacent1BigThird, adjacent2BigThird));
1692 paintBorderRect = snapRectToDevicePixels(LayoutRect(x1 + mitreOffset2, y1, (x2 - mitreOffset4) - (x1 + mitreOffset2), thirdOfThickness), deviceScaleFactor);
1693 drawLineFor(paintBorderRect, side, SOLID, FloatSize(adjacent1BigThird, adjacent2BigThird));
1695 paintBorderRect = snapRectToDevicePixels(LayoutRect(x1 + mitreOffset1, y2 - thirdOfThickness, (x2 - mitreOffset3) - (x1 + mitreOffset1), thirdOfThickness), deviceScaleFactor);
1696 drawLineFor(paintBorderRect, side, SOLID, FloatSize(adjacent1BigThird, adjacent2BigThird));
1699 paintBorderRect = snapRectToDevicePixels(LayoutRect(x1, y1 + mitreOffset2, thirdOfThickness, (y2 - mitreOffset4) - (y1 + mitreOffset2)), deviceScaleFactor);
1700 drawLineFor(paintBorderRect, side, SOLID, FloatSize(adjacent1BigThird, adjacent2BigThird));
1702 paintBorderRect = snapRectToDevicePixels(LayoutRect(x2 - thirdOfThickness, y1 + mitreOffset1, thirdOfThickness, (y2 - mitreOffset3) - (y1 + mitreOffset1)), deviceScaleFactor);
1703 drawLineFor(paintBorderRect, side, SOLID, FloatSize(adjacent1BigThird, adjacent2BigThird));
1715 if (borderStyle == GROOVE) {
1723 float adjacent1BigHalf = ceilToDevicePixel(adjacentWidth1 / 2, deviceScaleFactor);
1724 float adjacent2BigHalf = ceilToDevicePixel(adjacentWidth2 / 2, deviceScaleFactor);
1726 float adjacent1SmallHalf = floorToDevicePixel(adjacentWidth1 / 2, deviceScaleFactor);
1727 float adjacent2SmallHalf = floorToDevicePixel(adjacentWidth2 / 2, deviceScaleFactor);
1734 if (((side == BSTop || side == BSLeft) && adjacentWidth1 < 0) || ((side == BSBottom || side == BSRight) && adjacentWidth1 > 0))
1735 offset1 = floorToDevicePixel(adjacentWidth1 / 2, deviceScaleFactor);
1737 if (((side == BSTop || side == BSLeft) && adjacentWidth2 < 0) || ((side == BSBottom || side == BSRight) && adjacentWidth2 > 0))
1738 offset2 = ceilToDevicePixel(adjacentWidth2 / 2, deviceScaleFactor);
1740 if (((side == BSTop || side == BSLeft) && adjacentWidth1 > 0) || ((side == BSBottom || side == BSRight) && adjacentWidth1 < 0))
1741 offset3 = floorToDevicePixel(fabs(adjacentWidth1) / 2, deviceScaleFactor);
1743 if (((side == BSTop || side == BSLeft) && adjacentWidth2 > 0) || ((side == BSBottom || side == BSRight) && adjacentWidth2 < 0))
1744 offset4 = ceilToDevicePixel(adjacentWidth2 / 2, deviceScaleFactor);
1746 float adjustedX = ceilToDevicePixel((x1 + x2) / 2, deviceScaleFactor);
1747 float adjustedY = ceilToDevicePixel((y1 + y2) / 2, deviceScaleFactor);
1748 // Quads can't use the default snapping rect functions.
1749 x1 = roundToDevicePixel(x1, deviceScaleFactor);
1750 x2 = roundToDevicePixel(x2, deviceScaleFactor);
1751 y1 = roundToDevicePixel(y1, deviceScaleFactor);
1752 y2 = roundToDevicePixel(y2, deviceScaleFactor);
1756 drawLineFor(FloatRect(FloatPoint(x1 + offset1, y1), FloatPoint(x2 - offset2, adjustedY)), side, s1, FloatSize(adjacent1BigHalf, adjacent2BigHalf));
1757 drawLineFor(FloatRect(FloatPoint(x1 + offset3, adjustedY), FloatPoint(x2 - offset4, y2)), side, s2, FloatSize(adjacent1SmallHalf, adjacent2SmallHalf));
1760 drawLineFor(FloatRect(FloatPoint(x1, y1 + offset1), FloatPoint(adjustedX, y2 - offset2)), side, s1, FloatSize(adjacent1BigHalf, adjacent2BigHalf));
1761 drawLineFor(FloatRect(FloatPoint(adjustedX, y1 + offset3), FloatPoint(x2, y2 - offset4)), side, s2, FloatSize(adjacent1SmallHalf, adjacent2SmallHalf));
1764 drawLineFor(FloatRect(FloatPoint(x1 + offset1, y1), FloatPoint(x2 - offset2, adjustedY)), side, s2, FloatSize(adjacent1BigHalf, adjacent2BigHalf));
1765 drawLineFor(FloatRect(FloatPoint(x1 + offset3, adjustedY), FloatPoint(x2 - offset4, y2)), side, s1, FloatSize(adjacent1SmallHalf, adjacent2SmallHalf));
1768 drawLineFor(FloatRect(FloatPoint(x1, y1 + offset1), FloatPoint(adjustedX, y2 - offset2)), side, s2, FloatSize(adjacent1BigHalf, adjacent2BigHalf));
1769 drawLineFor(FloatRect(FloatPoint(adjustedX, y1 + offset3), FloatPoint(x2, y2 - offset4)), side, s1, FloatSize(adjacent1SmallHalf, adjacent2SmallHalf));
1776 calculateBorderStyleColor(borderStyle, side, color);
1779 StrokeStyle oldStrokeStyle = graphicsContext.strokeStyle();
1782 if (!adjacentWidth1 && !adjacentWidth2) {
1783 graphicsContext.setStrokeStyle(NoStroke);
1784 graphicsContext.setFillColor(color);
1785 bool wasAntialiased = graphicsContext.shouldAntialias();
1786 graphicsContext.setShouldAntialias(antialias);
1787 drawBorderRect(snapRectToDevicePixels(x1, y1, x2 - x1, y2 - y1, deviceScaleFactor));
1788 graphicsContext.setShouldAntialias(wasAntialiased);
1789 graphicsContext.setStrokeStyle(oldStrokeStyle);
1793 // FIXME: These roundings should be replaced by ASSERT(device pixel positioned) when all the callers have transitioned to device pixels.
1794 x1 = roundToDevicePixel(x1, deviceScaleFactor);
1795 y1 = roundToDevicePixel(y1, deviceScaleFactor);
1796 x2 = roundToDevicePixel(x2, deviceScaleFactor);
1797 y2 = roundToDevicePixel(y2, deviceScaleFactor);
1799 Vector<FloatPoint> quad;
1800 quad.reserveInitialCapacity(4);
1803 quad.uncheckedAppend({ x1 + std::max<float>(-adjacentWidth1, 0), y1 });
1804 quad.uncheckedAppend({ x1 + std::max<float>( adjacentWidth1, 0), y2 });
1805 quad.uncheckedAppend({ x2 - std::max<float>( adjacentWidth2, 0), y2 });
1806 quad.uncheckedAppend({ x2 - std::max<float>(-adjacentWidth2, 0), y1 });
1809 quad.uncheckedAppend({ x1 + std::max<float>( adjacentWidth1, 0), y1 });
1810 quad.uncheckedAppend({ x1 + std::max<float>(-adjacentWidth1, 0), y2 });
1811 quad.uncheckedAppend({ x2 - std::max<float>(-adjacentWidth2, 0), y2 });
1812 quad.uncheckedAppend({ x2 - std::max<float>( adjacentWidth2, 0), y1 });
1815 quad.uncheckedAppend({ x1, y1 + std::max<float>(-adjacentWidth1, 0) });
1816 quad.uncheckedAppend({ x1, y2 - std::max<float>(-adjacentWidth2, 0) });
1817 quad.uncheckedAppend({ x2, y2 - std::max<float>( adjacentWidth2, 0) });
1818 quad.uncheckedAppend({ x2, y1 + std::max<float>( adjacentWidth1, 0) });
1821 quad.uncheckedAppend({ x1, y1 + std::max<float>( adjacentWidth1, 0) });
1822 quad.uncheckedAppend({ x1, y2 - std::max<float>( adjacentWidth2, 0) });
1823 quad.uncheckedAppend({ x2, y2 - std::max<float>(-adjacentWidth2, 0) });
1824 quad.uncheckedAppend({ x2, y1 + std::max<float>(-adjacentWidth1, 0) });
1828 graphicsContext.setStrokeStyle(NoStroke);
1829 graphicsContext.setFillColor(color);
1830 bool wasAntialiased = graphicsContext.shouldAntialias();
1831 graphicsContext.setShouldAntialias(antialias);
1832 graphicsContext.fillPath(Path::polygonPathFromPoints(quad));
1833 graphicsContext.setShouldAntialias(wasAntialiased);
1835 graphicsContext.setStrokeStyle(oldStrokeStyle);
1841 void RenderElement::paintFocusRing(PaintInfo& paintInfo, const RenderStyle& style, const Vector<LayoutRect>& focusRingRects)
1843 ASSERT(style.outlineStyleIsAuto());
1844 float outlineOffset = style.outlineOffset();
1845 Vector<FloatRect> pixelSnappedFocusRingRects;
1846 float deviceScaleFactor = document().deviceScaleFactor();
1847 for (auto rect : focusRingRects) {
1848 rect.inflate(outlineOffset);
1849 pixelSnappedFocusRingRects.append(snapRectToDevicePixels(rect, deviceScaleFactor));
1853 if (style.hasBorderRadius()) {
1854 Path path = PathUtilities::pathWithShrinkWrappedRectsForOutline(pixelSnappedFocusRingRects, style.border(), outlineOffset, style.direction(), style.writingMode(),
1855 document().deviceScaleFactor());
1856 if (path.isEmpty()) {
1857 for (auto rect : pixelSnappedFocusRingRects)
1860 paintInfo.context().drawFocusRing(path, page().focusController().timeSinceFocusWasSet(), needsRepaint);
1862 paintInfo.context().drawFocusRing(pixelSnappedFocusRingRects, page().focusController().timeSinceFocusWasSet(), needsRepaint);
1864 page().focusController().setFocusedElementNeedsRepaint();
1866 paintInfo.context().drawFocusRing(pixelSnappedFocusRingRects, style.outlineWidth(), style.outlineOffset(), style.visitedDependentColor(CSSPropertyOutlineColor));
1870 void RenderElement::paintOutline(PaintInfo& paintInfo, const LayoutRect& paintRect)
1872 GraphicsContext& graphicsContext = paintInfo.context();
1873 if (graphicsContext.paintingDisabled())
1879 auto& styleToUse = style();
1880 float outlineWidth = floorToDevicePixel(styleToUse.outlineWidth(), document().deviceScaleFactor());
1881 float outlineOffset = floorToDevicePixel(styleToUse.outlineOffset(), document().deviceScaleFactor());
1883 // Only paint the focus ring by hand if the theme isn't able to draw it.
1884 if (styleToUse.outlineStyleIsAuto() && !theme().supportsFocusRing(styleToUse)) {
1885 Vector<LayoutRect> focusRingRects;
1886 addFocusRingRects(focusRingRects, paintRect.location(), paintInfo.paintContainer);
1887 paintFocusRing(paintInfo, styleToUse, focusRingRects);
1890 if (hasOutlineAnnotation() && !styleToUse.outlineStyleIsAuto() && !theme().supportsFocusRing(styleToUse))
1891 addPDFURLRect(paintInfo, paintRect.location());
1893 if (styleToUse.outlineStyleIsAuto() || styleToUse.outlineStyle() == BNONE)
1896 FloatRect outer = paintRect;
1897 outer.inflate(outlineOffset + outlineWidth);
1898 FloatRect inner = outer;
1899 inner.inflate(-outlineWidth);
1901 // FIXME: This prevents outlines from painting inside the object. See bug 12042
1902 if (outer.isEmpty())
1905 EBorderStyle outlineStyle = styleToUse.outlineStyle();
1906 Color outlineColor = styleToUse.visitedDependentColor(CSSPropertyOutlineColor);
1908 bool useTransparencyLayer = !outlineColor.isOpaque();
1909 if (useTransparencyLayer) {
1910 if (outlineStyle == SOLID) {
1912 path.addRect(outer);
1913 path.addRect(inner);
1914 graphicsContext.setFillRule(RULE_EVENODD);
1915 graphicsContext.setFillColor(outlineColor);
1916 graphicsContext.fillPath(path);
1919 graphicsContext.beginTransparencyLayer(outlineColor.alphaAsFloat());
1920 outlineColor = outlineColor.opaqueColor();
1923 float leftOuter = outer.x();
1924 float leftInner = inner.x();
1925 float rightOuter = outer.maxX();
1926 float rightInner = std::min(inner.maxX(), rightOuter);
1927 float topOuter = outer.y();
1928 float topInner = inner.y();
1929 float bottomOuter = outer.maxY();
1930 float bottomInner = std::min(inner.maxY(), bottomOuter);
1932 drawLineForBoxSide(graphicsContext, FloatRect(FloatPoint(leftOuter, topOuter), FloatPoint(leftInner, bottomOuter)), BSLeft, outlineColor, outlineStyle, outlineWidth, outlineWidth);
1933 drawLineForBoxSide(graphicsContext, FloatRect(FloatPoint(leftOuter, topOuter), FloatPoint(rightOuter, topInner)), BSTop, outlineColor, outlineStyle, outlineWidth, outlineWidth);
1934 drawLineForBoxSide(graphicsContext, FloatRect(FloatPoint(rightInner, topOuter), FloatPoint(rightOuter, bottomOuter)), BSRight, outlineColor, outlineStyle, outlineWidth, outlineWidth);
1935 drawLineForBoxSide(graphicsContext, FloatRect(FloatPoint(leftOuter, bottomInner), FloatPoint(rightOuter, bottomOuter)), BSBottom, outlineColor, outlineStyle, outlineWidth, outlineWidth);
1937 if (useTransparencyLayer)
1938 graphicsContext.endTransparencyLayer();
1941 void RenderElement::issueRepaintForOutlineAuto(float outlineSize)
1943 LayoutRect repaintRect;
1944 Vector<LayoutRect> focusRingRects;
1945 addFocusRingRects(focusRingRects, LayoutPoint(), containerForRepaint());
1946 for (auto rect : focusRingRects) {
1947 rect.inflate(outlineSize);
1948 repaintRect.unite(rect);
1950 repaintRectangle(repaintRect);
1953 void RenderElement::updateOutlineAutoAncestor(bool hasOutlineAuto)
1955 for (auto& child : childrenOfType<RenderObject>(*this)) {
1956 if (hasOutlineAuto == child.hasOutlineAutoAncestor())
1958 child.setHasOutlineAutoAncestor(hasOutlineAuto);
1959 bool childHasOutlineAuto = child.outlineStyleForRepaint().outlineStyleIsAuto();
1960 if (childHasOutlineAuto)
1962 if (!is<RenderElement>(child))
1964 downcast<RenderElement>(child).updateOutlineAutoAncestor(hasOutlineAuto);
1966 if (is<RenderBoxModelObject>(*this)) {
1967 if (auto* continuation = downcast<RenderBoxModelObject>(*this).continuation())
1968 continuation->updateOutlineAutoAncestor(hasOutlineAuto);
1972 bool RenderElement::hasOutlineAnnotation() const
1974 return element() && element()->isLink() && document().printing();
1977 bool RenderElement::hasSelfPaintingLayer() const
1981 auto& layerModelObject = downcast<RenderLayerModelObject>(*this);
1982 return layerModelObject.hasSelfPaintingLayer();
1985 bool RenderElement::checkForRepaintDuringLayout() const
1987 if (document().view()->layoutContext().needsFullRepaint() || !everHadLayout() || hasSelfPaintingLayer())
1989 return !settings().repaintOutsideLayoutEnabled();
1992 RespectImageOrientationEnum RenderElement::shouldRespectImageOrientation() const
1994 #if USE(CG) || USE(CAIRO)
1995 // This can only be enabled for ports which honor the orientation flag in their drawing code.
1996 if (document().isImageDocument())
1997 return RespectImageOrientation;
1999 // Respect the image's orientation if it's being used as a full-page image or it's
2000 // an <img> and the setting to respect it everywhere is set.
2001 return settings().shouldRespectImageOrientation() && is<HTMLImageElement>(element()) ? RespectImageOrientation : DoNotRespectImageOrientation;
2004 void RenderElement::adjustFragmentedFlowStateOnContainingBlockChangeIfNeeded()
2006 if (fragmentedFlowState() == NotInsideFragmentedFlow)
2009 // Invalidate the containing block caches.
2010 if (is<RenderBlock>(*this))
2011 downcast<RenderBlock>(*this).resetEnclosingFragmentedFlowAndChildInfoIncludingDescendants();
2013 // Adjust the flow tread state on the subtree.
2014 setFragmentedFlowState(RenderObject::computedFragmentedFlowState(*this));
2015 for (auto& descendant : descendantsOfType<RenderObject>(*this))
2016 descendant.setFragmentedFlowState(RenderObject::computedFragmentedFlowState(descendant));
2019 void RenderElement::removeFromRenderFragmentedFlow()
2021 ASSERT(fragmentedFlowState() != NotInsideFragmentedFlow);
2022 // Sometimes we remove the element from the flow, but it's not destroyed at that time.
2023 // It's only until later when we actually destroy it and remove all the children from it.
2024 // Currently, that happens for firstLetter elements and list markers.
2025 // Pass in the flow thread so that we don't have to look it up for all the children.
2026 removeFromRenderFragmentedFlowIncludingDescendants(true);
2029 void RenderElement::removeFromRenderFragmentedFlowIncludingDescendants(bool shouldUpdateState)
2031 // Once we reach another flow thread we don't need to update the flow thread state
2032 // but we have to continue cleanup the flow thread info.
2033 if (isRenderFragmentedFlow())
2034 shouldUpdateState = false;
2036 for (auto& child : childrenOfType<RenderObject>(*this)) {
2037 if (is<RenderElement>(child)) {
2038 downcast<RenderElement>(child).removeFromRenderFragmentedFlowIncludingDescendants(shouldUpdateState);
2041 if (shouldUpdateState)
2042 child.setFragmentedFlowState(NotInsideFragmentedFlow);
2045 // We have to ask for our containing flow thread as it may be above the removed sub-tree.
2046 RenderFragmentedFlow* enclosingFragmentedFlow = this->enclosingFragmentedFlow();
2047 while (enclosingFragmentedFlow) {
2048 enclosingFragmentedFlow->removeFlowChildInfo(*this);
2050 if (enclosingFragmentedFlow->fragmentedFlowState() == NotInsideFragmentedFlow)
2052 auto* parent = enclosingFragmentedFlow->parent();
2055 enclosingFragmentedFlow = parent->enclosingFragmentedFlow();
2057 if (is<RenderBlock>(*this))
2058 downcast<RenderBlock>(*this).setCachedEnclosingFragmentedFlowNeedsUpdate();
2060 if (shouldUpdateState)
2061 setFragmentedFlowState(NotInsideFragmentedFlow);
2064 void RenderElement::resetEnclosingFragmentedFlowAndChildInfoIncludingDescendants(RenderFragmentedFlow* fragmentedFlow)
2067 fragmentedFlow->removeFlowChildInfo(*this);
2069 for (auto& child : childrenOfType<RenderElement>(*this))
2070 child.resetEnclosingFragmentedFlowAndChildInfoIncludingDescendants(fragmentedFlow);
2073 #if ENABLE(TEXT_AUTOSIZING)
2074 static RenderObject::BlockContentHeightType includeNonFixedHeight(const RenderObject& renderer)
2076 const RenderStyle& style = renderer.style();
2077 if (style.height().type() == Fixed) {
2078 if (is<RenderBlock>(renderer)) {
2079 // For fixed height styles, if the overflow size of the element spills out of the specified
2080 // height, assume we can apply text auto-sizing.
2081 if (style.overflowY() == OVISIBLE
2082 && style.height().value() < downcast<RenderBlock>(renderer).layoutOverflowRect().maxY())
2083 return RenderObject::OverflowHeight;
2085 return RenderObject::FixedHeight;
2087 return RenderObject::FlexibleHeight;
2090 void RenderElement::adjustComputedFontSizesOnBlocks(float size, float visibleWidth)
2092 Document* document = view().frameView().frame().document();
2096 Vector<int> depthStack;
2097 int currentDepth = 0;
2098 int newFixedDepth = 0;
2100 // We don't apply autosizing to nodes with fixed height normally.
2101 // But we apply it to nodes which are located deep enough
2102 // (nesting depth is greater than some const) inside of a parent block
2103 // which has fixed height but its content overflows intentionally.
2104 for (RenderObject* descendent = traverseNext(this, includeNonFixedHeight, currentDepth, newFixedDepth); descendent; descendent = descendent->traverseNext(this, includeNonFixedHeight, currentDepth, newFixedDepth)) {
2105 while (depthStack.size() > 0 && currentDepth <= depthStack[depthStack.size() - 1])
2106 depthStack.remove(depthStack.size() - 1);
2108 depthStack.append(newFixedDepth);
2110 int stackSize = depthStack.size();
2111 if (is<RenderBlockFlow>(*descendent) && !descendent->isListItem() && (!stackSize || currentDepth - depthStack[stackSize - 1] > TextAutoSizingFixedHeightDepth))
2112 downcast<RenderBlockFlow>(*descendent).adjustComputedFontSizes(size, visibleWidth);
2116 // Remove style from auto-sizing table that are no longer valid.
2117 document->textAutoSizing().updateRenderTree();
2120 void RenderElement::resetTextAutosizing()
2122 Document* document = view().frameView().frame().document();
2126 LOG(TextAutosizing, "RenderElement::resetTextAutosizing()");
2128 document->textAutoSizing().reset();
2130 Vector<int> depthStack;
2131 int currentDepth = 0;
2132 int newFixedDepth = 0;
2134 for (RenderObject* descendent = traverseNext(this, includeNonFixedHeight, currentDepth, newFixedDepth); descendent; descendent = descendent->traverseNext(this, includeNonFixedHeight, currentDepth, newFixedDepth)) {
2135 while (depthStack.size() > 0 && currentDepth <= depthStack[depthStack.size() - 1])
2136 depthStack.remove(depthStack.size() - 1);
2138 depthStack.append(newFixedDepth);
2140 int stackSize = depthStack.size();
2141 if (is<RenderBlockFlow>(*descendent) && !descendent->isListItem() && (!stackSize || currentDepth - depthStack[stackSize - 1] > TextAutoSizingFixedHeightDepth))
2142 downcast<RenderBlockFlow>(*descendent).resetComputedFontSize();
2146 #endif // ENABLE(TEXT_AUTOSIZING)