2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2000 Dirk Mueller (mueller@kde.org)
5 * (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com)
6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2011, 2013 Apple Inc. All rights reserved.
7 * Copyright (C) 2009 Google Inc. All rights reserved.
8 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
20 * You should have received a copy of the GNU Library General Public License
21 * along with this library; see the file COPYING.LIB. If not, write to
22 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 * Boston, MA 02110-1301, USA.
28 #include "RenderObject.h"
30 #include "AXObjectCache.h"
31 #include "CSSAnimationController.h"
33 #include "FloatQuad.h"
34 #include "FrameSelection.h"
35 #include "FrameView.h"
36 #include "GeometryUtilities.h"
37 #include "GraphicsContext.h"
38 #include "HTMLElement.h"
39 #include "HTMLNames.h"
40 #include "HTMLTableCellElement.h"
41 #include "HTMLTableElement.h"
42 #include "HitTestResult.h"
43 #include "LogicalSelectionOffsetCaches.h"
44 #include "MainFrame.h"
46 #include "PseudoElement.h"
47 #include "RenderChildIterator.h"
48 #include "RenderCounter.h"
49 #include "RenderFragmentedFlow.h"
50 #include "RenderGeometryMap.h"
51 #include "RenderInline.h"
52 #include "RenderIterator.h"
53 #include "RenderLayer.h"
54 #include "RenderLayerBacking.h"
55 #include "RenderMultiColumnFlow.h"
56 #include "RenderRuby.h"
57 #include "RenderSVGBlock.h"
58 #include "RenderSVGInline.h"
59 #include "RenderSVGModelObject.h"
60 #include "RenderSVGResourceContainer.h"
61 #include "RenderSVGRoot.h"
62 #include "RenderScrollbarPart.h"
63 #include "RenderTableRow.h"
64 #include "RenderTheme.h"
65 #include "RenderView.h"
66 #include "RenderWidget.h"
67 #include "SVGRenderSupport.h"
68 #include "StyleResolver.h"
69 #include "TransformState.h"
72 #include <wtf/RefCountedLeakCounter.h>
73 #include <wtf/text/TextStream.h>
76 #include "SelectionRect.h"
81 using namespace HTMLNames;
85 RenderObject::SetLayoutNeededForbiddenScope::SetLayoutNeededForbiddenScope(RenderObject* renderObject, bool isForbidden)
86 : m_renderObject(renderObject)
87 , m_preexistingForbidden(m_renderObject->isSetNeedsLayoutForbidden())
89 m_renderObject->setNeedsLayoutIsForbidden(isForbidden);
92 RenderObject::SetLayoutNeededForbiddenScope::~SetLayoutNeededForbiddenScope()
94 m_renderObject->setNeedsLayoutIsForbidden(m_preexistingForbidden);
98 struct SameSizeAsRenderObject {
99 virtual ~SameSizeAsRenderObject() { } // Allocate vtable pointer.
102 unsigned m_debugBitfields : 2;
104 unsigned m_bitfields;
107 COMPILE_ASSERT(sizeof(RenderObject) == sizeof(SameSizeAsRenderObject), RenderObject_should_stay_small);
109 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, renderObjectCounter, ("RenderObject"));
111 RenderObject::RenderObject(Node& node)
112 : CachedImageClient()
115 , m_previous(nullptr)
118 , m_hasAXObject(false)
119 , m_setNeedsLayoutForbidden(false)
123 if (RenderView* renderView = node.document().renderView())
124 renderView->didCreateRenderer();
126 renderObjectCounter.increment();
130 RenderObject::~RenderObject()
132 view().didDestroyRenderer();
134 ASSERT(!m_hasAXObject);
135 renderObjectCounter.decrement();
137 ASSERT(!hasRareData());
140 RenderTheme& RenderObject::theme() const
142 return RenderTheme::singleton();
145 bool RenderObject::isDescendantOf(const RenderObject* ancestor) const
147 for (const RenderObject* renderer = this; renderer; renderer = renderer->m_parent) {
148 if (renderer == ancestor)
154 bool RenderObject::isLegend() const
156 return node() && node()->hasTagName(legendTag);
160 bool RenderObject::isFieldset() const
162 return node() && node()->hasTagName(fieldsetTag);
165 bool RenderObject::isHTMLMarquee() const
167 return node() && node()->renderer() == this && node()->hasTagName(marqueeTag);
170 void RenderObject::setFragmentedFlowStateIncludingDescendants(FragmentedFlowState state)
172 setFragmentedFlowState(state);
174 if (!is<RenderElement>(*this))
177 for (auto& child : childrenOfType<RenderObject>(downcast<RenderElement>(*this))) {
178 // If the child is a fragmentation context it already updated the descendants flag accordingly.
179 if (child.isRenderFragmentedFlow())
181 ASSERT(state != child.fragmentedFlowState());
182 child.setFragmentedFlowStateIncludingDescendants(state);
186 RenderObject::FragmentedFlowState RenderObject::computedFragmentedFlowState(const RenderObject& renderer)
188 if (!renderer.parent())
189 return renderer.fragmentedFlowState();
191 auto inheritedFlowState = RenderObject::NotInsideFragmentedFlow;
192 if (is<RenderText>(renderer))
193 inheritedFlowState = renderer.parent()->fragmentedFlowState();
194 else if (is<RenderSVGBlock>(renderer) || is<RenderSVGInline>(renderer) || is<RenderSVGModelObject>(renderer)) {
195 // containingBlock() skips svg boundary (SVG root is a RenderReplaced).
196 if (auto* svgRoot = SVGRenderSupport::findTreeRootObject(downcast<RenderElement>(renderer)))
197 inheritedFlowState = svgRoot->fragmentedFlowState();
198 } else if (auto* container = renderer.container())
199 inheritedFlowState = container->fragmentedFlowState();
201 // Splitting lines or doing continuation, so just keep the current state.
202 inheritedFlowState = renderer.fragmentedFlowState();
204 return inheritedFlowState;
207 void RenderObject::initializeFragmentedFlowStateOnInsertion()
211 // A RenderFragmentedFlow is always considered to be inside itself, so it never has to change its state in response to parent changes.
212 if (isRenderFragmentedFlow())
215 auto computedState = computedFragmentedFlowState(*this);
216 if (fragmentedFlowState() == computedState)
219 setFragmentedFlowStateIncludingDescendants(computedState);
222 void RenderObject::resetFragmentedFlowStateOnRemoval()
224 if (fragmentedFlowState() == NotInsideFragmentedFlow)
227 if (!renderTreeBeingDestroyed() && is<RenderElement>(*this)) {
228 downcast<RenderElement>(*this).removeFromRenderFragmentedFlow();
232 // A RenderFragmentedFlow is always considered to be inside itself, so it never has to change its state in response to parent changes.
233 if (isRenderFragmentedFlow())
236 setFragmentedFlowStateIncludingDescendants(NotInsideFragmentedFlow);
239 void RenderObject::setParent(RenderElement* parent)
244 void RenderObject::removeFromParentAndDestroy()
247 m_parent->removeAndDestroyChild(*this);
250 RenderObject* RenderObject::nextInPreOrder() const
252 if (RenderObject* o = firstChildSlow())
255 return nextInPreOrderAfterChildren();
258 RenderObject* RenderObject::nextInPreOrderAfterChildren() const
261 if (!(o = nextSibling())) {
263 while (o && !o->nextSibling())
266 o = o->nextSibling();
272 RenderObject* RenderObject::nextInPreOrder(const RenderObject* stayWithin) const
274 if (RenderObject* o = firstChildSlow())
277 return nextInPreOrderAfterChildren(stayWithin);
280 RenderObject* RenderObject::nextInPreOrderAfterChildren(const RenderObject* stayWithin) const
282 if (this == stayWithin)
285 const RenderObject* current = this;
287 while (!(next = current->nextSibling())) {
288 current = current->parent();
289 if (!current || current == stayWithin)
295 RenderObject* RenderObject::previousInPreOrder() const
297 if (RenderObject* o = previousSibling()) {
298 while (RenderObject* last = o->lastChildSlow())
306 RenderObject* RenderObject::previousInPreOrder(const RenderObject* stayWithin) const
308 if (this == stayWithin)
311 return previousInPreOrder();
314 RenderObject* RenderObject::childAt(unsigned index) const
316 RenderObject* child = firstChildSlow();
317 for (unsigned i = 0; child && i < index; i++)
318 child = child->nextSibling();
322 RenderObject* RenderObject::firstLeafChild() const
324 RenderObject* r = firstChildSlow();
326 RenderObject* n = nullptr;
327 n = r->firstChildSlow();
335 RenderObject* RenderObject::lastLeafChild() const
337 RenderObject* r = lastChildSlow();
339 RenderObject* n = nullptr;
340 n = r->lastChildSlow();
348 #if ENABLE(TEXT_AUTOSIZING)
350 // Non-recursive version of the DFS search.
351 RenderObject* RenderObject::traverseNext(const RenderObject* stayWithin, HeightTypeTraverseNextInclusionFunction inclusionFunction, int& currentDepth, int& newFixedDepth) const
353 BlockContentHeightType overflowType;
355 // Check for suitable children.
356 for (RenderObject* child = firstChildSlow(); child; child = child->nextSibling()) {
357 overflowType = inclusionFunction(*child);
358 if (overflowType != FixedHeight) {
360 if (overflowType == OverflowHeight)
361 newFixedDepth = currentDepth;
362 ASSERT(!stayWithin || child->isDescendantOf(stayWithin));
367 if (this == stayWithin)
370 // Now we traverse other nodes if they exist, otherwise
371 // we go to the parent node and try doing the same.
372 const RenderObject* n = this;
374 while (n && !n->nextSibling() && (!stayWithin || n->parent() != stayWithin)) {
380 for (RenderObject* sibling = n->nextSibling(); sibling; sibling = sibling->nextSibling()) {
381 overflowType = inclusionFunction(*sibling);
382 if (overflowType != FixedHeight) {
383 if (overflowType == OverflowHeight)
384 newFixedDepth = currentDepth;
385 ASSERT(!stayWithin || !n->nextSibling() || n->nextSibling()->isDescendantOf(stayWithin));
389 if (!stayWithin || n->parent() != stayWithin) {
398 #endif // ENABLE(TEXT_AUTOSIZING)
400 RenderLayer* RenderObject::enclosingLayer() const
402 for (auto& renderer : lineageOfType<RenderLayerModelObject>(*this)) {
403 if (renderer.hasLayer())
404 return renderer.layer();
409 bool RenderObject::scrollRectToVisible(SelectionRevealMode revealMode, const LayoutRect& absoluteRect, bool insideFixed, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
411 if (revealMode == SelectionRevealMode::DoNotReveal)
414 RenderLayer* enclosingLayer = this->enclosingLayer();
418 enclosingLayer->scrollRectToVisible(revealMode, absoluteRect, insideFixed, alignX, alignY);
422 RenderBox& RenderObject::enclosingBox() const
424 return *lineageOfType<RenderBox>(const_cast<RenderObject&>(*this)).first();
427 RenderBoxModelObject& RenderObject::enclosingBoxModelObject() const
429 return *lineageOfType<RenderBoxModelObject>(const_cast<RenderObject&>(*this)).first();
432 RenderBlock* RenderObject::firstLineBlock() const
437 static inline bool objectIsRelayoutBoundary(const RenderElement* object)
439 // FIXME: In future it may be possible to broaden these conditions in order to improve performance.
440 if (object->isRenderView())
443 if (object->isTextControl())
446 if (object->isSVGRoot())
449 if (!object->hasOverflowClip())
452 if (object->style().width().isIntrinsicOrAuto() || object->style().height().isIntrinsicOrAuto() || object->style().height().isPercentOrCalculated())
455 // Table parts can't be relayout roots since the table is responsible for layouting all the parts.
456 if (object->isTablePart())
462 void RenderObject::clearNeedsLayout()
464 m_bitfields.setNeedsLayout(false);
465 setEverHadLayout(true);
466 setPosChildNeedsLayoutBit(false);
467 setNeedsSimplifiedNormalFlowLayoutBit(false);
468 setNormalChildNeedsLayoutBit(false);
469 setNeedsPositionedMovementLayoutBit(false);
470 if (is<RenderElement>(*this))
471 downcast<RenderElement>(*this).setAncestorLineBoxDirty(false);
473 checkBlockPositionedObjectsNeedLayout();
477 static void scheduleRelayoutForSubtree(RenderElement& renderer)
479 if (is<RenderView>(renderer)) {
480 downcast<RenderView>(renderer).frameView().scheduleRelayout();
484 if (renderer.isRooted())
485 renderer.view().frameView().scheduleRelayoutOfSubtree(renderer);
488 void RenderObject::markContainingBlocksForLayout(ScheduleRelayout scheduleRelayout, RenderElement* newRoot)
490 ASSERT(scheduleRelayout == ScheduleRelayout::No || !newRoot);
491 ASSERT(!isSetNeedsLayoutForbidden());
493 auto ancestor = container();
495 bool simplifiedNormalFlowLayout = needsSimplifiedNormalFlowLayout() && !selfNeedsLayout() && !normalChildNeedsLayout();
496 bool hasOutOfFlowPosition = !isText() && style().hasOutOfFlowPosition();
500 // FIXME: Remove this once we remove the special cases for counters, quotes and mathml
501 // calling setNeedsLayout during preferred width computation.
502 SetLayoutNeededForbiddenScope layoutForbiddenScope(ancestor, isSetNeedsLayoutForbidden());
504 // Don't mark the outermost object of an unrooted subtree. That object will be
505 // marked when the subtree is added to the document.
506 auto container = ancestor->container();
507 if (!container && !ancestor->isRenderView())
509 if (hasOutOfFlowPosition) {
510 bool willSkipRelativelyPositionedInlines = !ancestor->isRenderBlock() || ancestor->isAnonymousBlock();
511 // Skip relatively positioned inlines and anonymous blocks to get to the enclosing RenderBlock.
512 while (ancestor && (!ancestor->isRenderBlock() || ancestor->isAnonymousBlock()))
513 ancestor = ancestor->container();
514 if (!ancestor || ancestor->posChildNeedsLayout())
516 if (willSkipRelativelyPositionedInlines)
517 container = ancestor->container();
518 ancestor->setPosChildNeedsLayoutBit(true);
519 simplifiedNormalFlowLayout = true;
520 } else if (simplifiedNormalFlowLayout) {
521 if (ancestor->needsSimplifiedNormalFlowLayout())
523 ancestor->setNeedsSimplifiedNormalFlowLayoutBit(true);
525 if (ancestor->normalChildNeedsLayout())
527 ancestor->setNormalChildNeedsLayoutBit(true);
529 ASSERT(!ancestor->isSetNeedsLayoutForbidden());
531 if (ancestor == newRoot)
534 if (scheduleRelayout == ScheduleRelayout::Yes && objectIsRelayoutBoundary(ancestor))
537 hasOutOfFlowPosition = ancestor->style().hasOutOfFlowPosition();
538 ancestor = container;
541 if (scheduleRelayout == ScheduleRelayout::Yes && ancestor)
542 scheduleRelayoutForSubtree(*ancestor);
546 void RenderObject::checkBlockPositionedObjectsNeedLayout()
548 ASSERT(!needsLayout());
550 if (is<RenderBlock>(*this))
551 downcast<RenderBlock>(*this).checkPositionedObjectsNeedLayout();
555 void RenderObject::setPreferredLogicalWidthsDirty(bool shouldBeDirty, MarkingBehavior markParents)
557 bool alreadyDirty = preferredLogicalWidthsDirty();
558 m_bitfields.setPreferredLogicalWidthsDirty(shouldBeDirty);
559 if (shouldBeDirty && !alreadyDirty && markParents == MarkContainingBlockChain && (isText() || !style().hasOutOfFlowPosition()))
560 invalidateContainerPreferredLogicalWidths();
563 void RenderObject::invalidateContainerPreferredLogicalWidths()
565 // In order to avoid pathological behavior when inlines are deeply nested, we do include them
566 // in the chain that we mark dirty (even though they're kind of irrelevant).
567 auto o = isTableCell() ? containingBlock() : container();
568 while (o && !o->preferredLogicalWidthsDirty()) {
569 // Don't invalidate the outermost object of an unrooted subtree. That object will be
570 // invalidated when the subtree is added to the document.
571 auto container = o->isTableCell() ? o->containingBlock() : o->container();
572 if (!container && !o->isRenderView())
575 o->m_bitfields.setPreferredLogicalWidthsDirty(true);
576 if (o->style().hasOutOfFlowPosition())
577 // A positioned object has no effect on the min/max width of its containing block ever.
578 // We can optimize this case and not go up any further.
584 void RenderObject::setLayerNeedsFullRepaint()
587 downcast<RenderLayerModelObject>(*this).layer()->setRepaintStatus(NeedsFullRepaint);
590 void RenderObject::setLayerNeedsFullRepaintForPositionedMovementLayout()
593 downcast<RenderLayerModelObject>(*this).layer()->setRepaintStatus(NeedsFullRepaintForPositionedMovementLayout);
596 RenderBlock* RenderObject::containingBlock() const
598 auto containingBlockForRenderer = [](const RenderElement& renderer)
600 auto& style = renderer.style();
601 if (style.position() == AbsolutePosition)
602 return renderer.containingBlockForAbsolutePosition();
603 if (style.position() == FixedPosition)
604 return renderer.containingBlockForFixedPosition();
605 return renderer.containingBlockForObjectInFlow();
608 if (is<RenderText>(*this))
609 return containingBlockForObjectInFlow();
611 if (!parent() && is<RenderScrollbarPart>(*this)) {
612 if (auto* scrollbarPart = downcast<RenderScrollbarPart>(*this).rendererOwningScrollbar())
613 return containingBlockForRenderer(*scrollbarPart);
616 return containingBlockForRenderer(downcast<RenderElement>(*this));
619 RenderBlock* RenderObject::containingBlockForObjectInFlow() const
621 auto* renderer = parent();
622 while (renderer && ((renderer->isInline() && !renderer->isReplaced()) || !renderer->isRenderBlock()))
623 renderer = renderer->parent();
624 return downcast<RenderBlock>(renderer);
627 void RenderObject::addPDFURLRect(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
629 Vector<LayoutRect> focusRingRects;
630 addFocusRingRects(focusRingRects, paintOffset, paintInfo.paintContainer);
631 LayoutRect urlRect = unionRect(focusRingRects);
633 if (urlRect.isEmpty())
635 Node* node = this->node();
636 if (!is<Element>(node) || !node->isLink())
638 Element& element = downcast<Element>(*node);
639 const AtomicString& href = element.getAttribute(hrefAttr);
643 if (paintInfo.context().supportsInternalLinks()) {
644 String outAnchorName;
645 Element* linkTarget = element.findAnchorElementForLink(outAnchorName);
647 paintInfo.context().setDestinationForRect(outAnchorName, urlRect);
652 paintInfo.context().setURLForRect(node->document().completeURL(href), urlRect);
657 // This function is similar in spirit to RenderText::absoluteRectsForRange, but returns rectangles
658 // which are annotated with additional state which helps iOS draw selections in its unique way.
659 // No annotations are added in this class.
660 // FIXME: Move to RenderText with absoluteRectsForRange()?
661 void RenderObject::collectSelectionRects(Vector<SelectionRect>& rects, unsigned start, unsigned end)
663 Vector<FloatQuad> quads;
665 if (!firstChildSlow()) {
666 // FIXME: WebKit's position for an empty span after a BR is incorrect, so we can't trust
667 // quads for them. We don't need selection rects for those anyway though, since they
668 // are just empty containers. See <https://bugs.webkit.org/show_bug.cgi?id=49358>.
669 RenderObject* previous = previousSibling();
670 Node* node = this->node();
671 if (!previous || !previous->isBR() || !node || !node->isContainerNode() || !isInline()) {
672 // For inline elements we don't use absoluteQuads, since it takes into account continuations and leads to wrong results.
673 absoluteQuadsForSelection(quads);
676 unsigned offset = start;
677 for (RenderObject* child = childAt(start); child && offset < end; child = child->nextSibling(), ++offset)
678 child->absoluteQuads(quads);
681 unsigned numberOfQuads = quads.size();
682 for (unsigned i = 0; i < numberOfQuads; ++i)
683 rects.append(SelectionRect(quads[i].enclosingBoundingBox(), isHorizontalWritingMode(), view().pageNumberForBlockProgressionOffset(quads[i].enclosingBoundingBox().x())));
687 IntRect RenderObject::absoluteBoundingBoxRect(bool useTransforms, bool* wasFixed) const
690 Vector<FloatQuad> quads;
691 absoluteQuads(quads, wasFixed);
693 size_t n = quads.size();
697 IntRect result = quads[0].enclosingBoundingBox();
698 for (size_t i = 1; i < n; ++i)
699 result.unite(quads[i].enclosingBoundingBox());
703 FloatPoint absPos = localToAbsolute(FloatPoint(), 0 /* ignore transforms */, wasFixed);
704 Vector<IntRect> rects;
705 absoluteRects(rects, flooredLayoutPoint(absPos));
707 size_t n = rects.size();
711 LayoutRect result = rects[0];
712 for (size_t i = 1; i < n; ++i)
713 result.unite(rects[i]);
714 return snappedIntRect(result);
717 void RenderObject::absoluteFocusRingQuads(Vector<FloatQuad>& quads)
719 Vector<LayoutRect> rects;
720 // FIXME: addFocusRingRects() needs to be passed this transform-unaware
721 // localToAbsolute() offset here because RenderInline::addFocusRingRects()
722 // implicitly assumes that. This doesn't work correctly with transformed
724 FloatPoint absolutePoint = localToAbsolute();
725 addFocusRingRects(rects, flooredLayoutPoint(absolutePoint));
726 float deviceScaleFactor = document().deviceScaleFactor();
727 for (auto rect : rects) {
728 rect.moveBy(LayoutPoint(-absolutePoint));
729 quads.append(localToAbsoluteQuad(FloatQuad(snapRectToDevicePixels(rect, deviceScaleFactor))));
733 FloatRect RenderObject::absoluteBoundingBoxRectForRange(const Range* range)
738 range->ownerDocument().updateLayout();
740 Vector<FloatQuad> quads;
741 range->absoluteTextQuads(quads);
746 FloatRect result = quads[0].boundingBox();
747 for (size_t i = 1; i < quads.size(); ++i)
748 result.uniteEvenIfEmpty(quads[i].boundingBox());
753 void RenderObject::addAbsoluteRectForLayer(LayoutRect& result)
756 result.unite(absoluteBoundingBoxRectIgnoringTransforms());
758 if (!is<RenderElement>(*this))
761 for (auto& child : childrenOfType<RenderObject>(downcast<RenderElement>(*this)))
762 child.addAbsoluteRectForLayer(result);
765 // FIXME: change this to use the subtreePaint terminology
766 LayoutRect RenderObject::paintingRootRect(LayoutRect& topLevelRect)
768 LayoutRect result = absoluteBoundingBoxRectIgnoringTransforms();
769 topLevelRect = result;
770 if (is<RenderElement>(*this)) {
771 for (auto& child : childrenOfType<RenderObject>(downcast<RenderElement>(*this)))
772 child.addAbsoluteRectForLayer(result);
777 RenderLayerModelObject* RenderObject::containerForRepaint() const
779 RenderLayerModelObject* repaintContainer = nullptr;
781 if (view().usesCompositing()) {
782 if (RenderLayer* parentLayer = enclosingLayer()) {
783 RenderLayer* compLayer = parentLayer->enclosingCompositingLayerForRepaint();
785 repaintContainer = &compLayer->renderer();
788 if (view().hasSoftwareFilters()) {
789 if (RenderLayer* parentLayer = enclosingLayer()) {
790 RenderLayer* enclosingFilterLayer = parentLayer->enclosingFilterLayer();
791 if (enclosingFilterLayer)
792 return &enclosingFilterLayer->renderer();
796 // If we have a flow thread, then we need to do individual repaints within the RenderFragmentContainers instead.
797 // Return the flow thread as a repaint container in order to create a chokepoint that allows us to change
798 // repainting to do individual region repaints.
799 RenderFragmentedFlow* parentRenderFragmentedFlow = enclosingFragmentedFlow();
800 if (parentRenderFragmentedFlow) {
801 // If we have already found a repaint container then we will repaint into that container only if it is part of the same
802 // flow thread. Otherwise we will need to catch the repaint call and send it to the flow thread.
803 RenderFragmentedFlow* repaintContainerFragmentedFlow = repaintContainer ? repaintContainer->enclosingFragmentedFlow() : nullptr;
804 if (!repaintContainerFragmentedFlow || repaintContainerFragmentedFlow != parentRenderFragmentedFlow)
805 repaintContainer = parentRenderFragmentedFlow;
807 return repaintContainer;
810 void RenderObject::propagateRepaintToParentWithOutlineAutoIfNeeded(const RenderLayerModelObject& repaintContainer, const LayoutRect& repaintRect) const
812 if (!hasOutlineAutoAncestor())
815 // FIXME: We should really propagate only when the the child renderer sticks out.
816 bool repaintRectNeedsConverting = false;
817 // Issue repaint on the renderer with outline: auto.
818 for (const auto* renderer = this; renderer; renderer = renderer->parent()) {
819 bool rendererHasOutlineAutoAncestor = renderer->hasOutlineAutoAncestor();
820 ASSERT(rendererHasOutlineAutoAncestor
821 || renderer->outlineStyleForRepaint().outlineStyleIsAuto()
822 || (is<RenderElement>(*renderer) && downcast<RenderElement>(*renderer).hasContinuation()));
823 if (renderer == &repaintContainer && rendererHasOutlineAutoAncestor)
824 repaintRectNeedsConverting = true;
825 if (rendererHasOutlineAutoAncestor)
827 // Issue repaint on the correct repaint container.
828 LayoutRect adjustedRepaintRect = repaintRect;
829 adjustedRepaintRect.inflate(renderer->outlineStyleForRepaint().outlineSize());
830 if (!repaintRectNeedsConverting)
831 repaintContainer.repaintRectangle(adjustedRepaintRect);
832 else if (is<RenderLayerModelObject>(renderer)) {
833 const auto& rendererWithOutline = downcast<RenderLayerModelObject>(*renderer);
834 adjustedRepaintRect = LayoutRect(repaintContainer.localToContainerQuad(FloatRect(adjustedRepaintRect), &rendererWithOutline).boundingBox());
835 rendererWithOutline.repaintRectangle(adjustedRepaintRect);
839 ASSERT_NOT_REACHED();
842 void RenderObject::repaintUsingContainer(const RenderLayerModelObject* repaintContainer, const LayoutRect& r, bool shouldClipToLayer) const
847 if (!repaintContainer)
848 repaintContainer = &view();
850 if (is<RenderFragmentedFlow>(*repaintContainer)) {
851 downcast<RenderFragmentedFlow>(*repaintContainer).repaintRectangleInFragments(r);
855 propagateRepaintToParentWithOutlineAutoIfNeeded(*repaintContainer, r);
857 if (repaintContainer->hasFilter() && repaintContainer->layer() && repaintContainer->layer()->requiresFullLayerImageForFilters()) {
858 repaintContainer->layer()->setFilterBackendNeedsRepaintingInRect(r);
862 if (repaintContainer->isRenderView()) {
863 RenderView& view = this->view();
864 ASSERT(repaintContainer == &view);
865 bool viewHasCompositedLayer = view.isComposited();
866 if (!viewHasCompositedLayer || view.layer()->backing()->paintsIntoWindow()) {
868 if (viewHasCompositedLayer && view.layer()->transform())
869 rect = LayoutRect(view.layer()->transform()->mapRect(snapRectToDevicePixels(rect, document().deviceScaleFactor())));
870 view.repaintViewRectangle(rect);
875 if (view().usesCompositing()) {
876 ASSERT(repaintContainer->isComposited());
877 repaintContainer->layer()->setBackingNeedsRepaintInRect(r, shouldClipToLayer ? GraphicsLayer::ClipToLayer : GraphicsLayer::DoNotClipToLayer);
881 void RenderObject::repaint() const
883 // Don't repaint if we're unrooted (note that view() still returns the view when unrooted)
887 const RenderView& view = this->view();
891 RenderLayerModelObject* repaintContainer = containerForRepaint();
892 repaintUsingContainer(repaintContainer, clippedOverflowRectForRepaint(repaintContainer));
895 void RenderObject::repaintRectangle(const LayoutRect& r, bool shouldClipToLayer) const
897 // Don't repaint if we're unrooted (note that view() still returns the view when unrooted)
901 const RenderView& view = this->view();
905 LayoutRect dirtyRect(r);
906 // FIXME: layoutDelta needs to be applied in parts before/after transforms and
907 // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
908 dirtyRect.move(view.layoutDelta());
910 RenderLayerModelObject* repaintContainer = containerForRepaint();
911 repaintUsingContainer(repaintContainer, computeRectForRepaint(dirtyRect, repaintContainer), shouldClipToLayer);
914 void RenderObject::repaintSlowRepaintObject() const
916 // Don't repaint if we're unrooted (note that view() still returns the view when unrooted)
920 const RenderView& view = this->view();
924 const RenderLayerModelObject* repaintContainer = containerForRepaint();
926 bool shouldClipToLayer = true;
928 // If this is the root background, we need to check if there is an extended background rect. If
929 // there is, then we should not allow painting to clip to the layer size.
930 if (isDocumentElementRenderer() || isBody()) {
931 shouldClipToLayer = !view.frameView().hasExtendedBackgroundRectForPainting();
932 repaintRect = snappedIntRect(view.backgroundRect());
934 repaintRect = snappedIntRect(clippedOverflowRectForRepaint(repaintContainer));
936 repaintUsingContainer(repaintContainer, repaintRect, shouldClipToLayer);
939 IntRect RenderObject::pixelSnappedAbsoluteClippedOverflowRect() const
941 return snappedIntRect(absoluteClippedOverflowRect());
944 LayoutRect RenderObject::rectWithOutlineForRepaint(const RenderLayerModelObject* repaintContainer, LayoutUnit outlineWidth) const
946 LayoutRect r(clippedOverflowRectForRepaint(repaintContainer));
947 r.inflate(outlineWidth);
951 LayoutRect RenderObject::clippedOverflowRectForRepaint(const RenderLayerModelObject*) const
953 ASSERT_NOT_REACHED();
957 LayoutRect RenderObject::computeRectForRepaint(const LayoutRect& rect, const RenderLayerModelObject* repaintContainer, RepaintContext context) const
959 if (repaintContainer == this)
962 auto* parent = this->parent();
966 LayoutRect adjustedRect = rect;
967 if (parent->hasOverflowClip()) {
968 downcast<RenderBox>(*parent).applyCachedClipAndScrollPositionForRepaint(adjustedRect);
969 if (adjustedRect.isEmpty())
972 return parent->computeRectForRepaint(adjustedRect, repaintContainer, context);
975 FloatRect RenderObject::computeFloatRectForRepaint(const FloatRect&, const RenderLayerModelObject*, bool) const
977 ASSERT_NOT_REACHED();
981 #if ENABLE(TREE_DEBUGGING)
983 static void outputRenderTreeLegend(TextStream& stream)
986 stream << "(B)lock/(I)nline/I(N)line-block, (A)bsolute/Fi(X)ed/(R)elative/Stic(K)y, (F)loating, (O)verflow clip, Anon(Y)mous, (G)enerated, has(L)ayer, (C)omposited, (+)Dirty style, (+)Dirty layout";
990 void RenderObject::showNodeTreeForThis() const
994 node()->showTreeForThis();
997 void RenderObject::showRenderTreeForThis() const
999 const WebCore::RenderObject* root = this;
1000 while (root->parent())
1001 root = root->parent();
1002 TextStream stream(TextStream::LineMode::MultipleLine, TextStream::Formatting::SVGStyleRect);
1003 outputRenderTreeLegend(stream);
1004 root->outputRenderSubTreeAndMark(stream, this, 1);
1005 WTFLogAlways("%s", stream.release().utf8().data());
1008 void RenderObject::showLineTreeForThis() const
1010 if (!is<RenderBlockFlow>(*this))
1012 TextStream stream(TextStream::LineMode::MultipleLine, TextStream::Formatting::SVGStyleRect);
1013 outputRenderTreeLegend(stream);
1014 outputRenderObject(stream, false, 1);
1015 downcast<RenderBlockFlow>(*this).outputLineTreeAndMark(stream, nullptr, 2);
1016 WTFLogAlways("%s", stream.release().utf8().data());
1019 static const RenderFragmentedFlow* enclosingFragmentedFlowFromRenderer(const RenderObject* renderer)
1024 if (renderer->fragmentedFlowState() == RenderObject::NotInsideFragmentedFlow)
1027 if (is<RenderFragmentedFlow>(*renderer))
1028 return downcast<RenderFragmentedFlow>(renderer);
1030 if (is<RenderBlock>(*renderer))
1031 return downcast<RenderBlock>(*renderer).cachedEnclosingFragmentedFlow();
1036 void RenderObject::outputRegionsInformation(TextStream& stream) const
1038 const RenderFragmentedFlow* ftcb = enclosingFragmentedFlowFromRenderer(this);
1041 // Only the boxes have region range information.
1042 // Try to get the flow thread containing block information
1043 // from the containing block of this box.
1044 if (is<RenderBox>(*this))
1045 ftcb = enclosingFragmentedFlowFromRenderer(containingBlock());
1051 RenderFragmentContainer* startRegion = nullptr;
1052 RenderFragmentContainer* endRegion = nullptr;
1053 ftcb->getFragmentRangeForBox(downcast<RenderBox>(this), startRegion, endRegion);
1054 stream << " [Rs:" << startRegion << " Re:" << endRegion << "]";
1057 void RenderObject::outputRenderObject(TextStream& stream, bool mark, int depth) const
1059 if (isInlineBlockOrInlineTable())
1061 else if (isInline())
1066 if (isPositioned()) {
1067 if (isRelPositioned())
1069 else if (isStickyPositioned())
1071 else if (isOutOfFlowPositioned()) {
1072 if (style().position() == AbsolutePosition)
1085 if (hasOverflowClip())
1095 if (isPseudoElement() || isAnonymous())
1112 if (node() && node()->needsStyleRecalc())
1122 int printedCharacters = 0;
1125 ++printedCharacters;
1128 while (++printedCharacters <= depth * 2)
1132 stream << node()->nodeName().utf8().data() << " ";
1134 String name = renderName();
1135 // FIXME: Renderer's name should not include property value listing.
1136 int pos = name.find('(');
1138 stream << name.left(pos - 1).utf8().data();
1140 stream << name.utf8().data();
1142 if (is<RenderBox>(*this)) {
1143 auto& renderBox = downcast<RenderBox>(*this);
1144 FloatRect boxRect = renderBox.frameRect();
1145 if (renderBox.isInFlowPositioned())
1146 boxRect.move(renderBox.offsetForInFlowPosition());
1147 stream << " " << boxRect;
1148 } else if (is<RenderInline>(*this) && isInFlowPositioned()) {
1149 FloatSize inlineOffset = downcast<RenderInline>(*this).offsetForInFlowPosition();
1150 stream << " (" << inlineOffset.width() << ", " << inlineOffset.height() << ")";
1153 stream << " renderer->(" << this << ")";
1155 stream << " node->(" << node() << ")";
1156 if (node()->isTextNode()) {
1157 String value = node()->nodeValue();
1158 stream << " length->(" << value.length() << ")";
1160 value.replaceWithLiteral('\\', "\\\\");
1161 value.replaceWithLiteral('\n', "\\n");
1163 const int maxPrintedLength = 80;
1164 if (value.length() > maxPrintedLength) {
1165 String substring = value.substring(0, maxPrintedLength);
1166 stream << " \"" << substring.utf8().data() << "\"...";
1168 stream << " \"" << value.utf8().data() << "\"";
1171 if (is<RenderBoxModelObject>(*this)) {
1172 auto& renderer = downcast<RenderBoxModelObject>(*this);
1173 if (renderer.hasContinuation())
1174 stream << " continuation->(" << renderer.continuation() << ")";
1176 outputRegionsInformation(stream);
1177 if (needsLayout()) {
1178 stream << " layout->";
1179 if (selfNeedsLayout())
1181 if (normalChildNeedsLayout())
1182 stream << "[normal child]";
1183 if (posChildNeedsLayout())
1184 stream << "[positioned child]";
1185 if (needsSimplifiedNormalFlowLayout())
1186 stream << "[simplified]";
1187 if (needsPositionedMovementLayout())
1188 stream << "[positioned movement]";
1193 void RenderObject::outputRenderSubTreeAndMark(TextStream& stream, const RenderObject* markedObject, int depth) const
1195 outputRenderObject(stream, markedObject == this, depth);
1196 if (is<RenderBlockFlow>(*this))
1197 downcast<RenderBlockFlow>(*this).outputLineTreeAndMark(stream, nullptr, depth + 1);
1199 for (auto* child = firstChildSlow(); child; child = child->nextSibling())
1200 child->outputRenderSubTreeAndMark(stream, markedObject, depth + 1);
1205 FloatPoint RenderObject::localToAbsolute(const FloatPoint& localPoint, MapCoordinatesFlags mode, bool* wasFixed) const
1207 TransformState transformState(TransformState::ApplyTransformDirection, localPoint);
1208 mapLocalToContainer(nullptr, transformState, mode | ApplyContainerFlip, wasFixed);
1209 transformState.flatten();
1211 return transformState.lastPlanarPoint();
1214 FloatPoint RenderObject::absoluteToLocal(const FloatPoint& containerPoint, MapCoordinatesFlags mode) const
1216 TransformState transformState(TransformState::UnapplyInverseTransformDirection, containerPoint);
1217 mapAbsoluteToLocalPoint(mode, transformState);
1218 transformState.flatten();
1220 return transformState.lastPlanarPoint();
1223 FloatQuad RenderObject::absoluteToLocalQuad(const FloatQuad& quad, MapCoordinatesFlags mode) const
1225 TransformState transformState(TransformState::UnapplyInverseTransformDirection, quad.boundingBox().center(), quad);
1226 mapAbsoluteToLocalPoint(mode, transformState);
1227 transformState.flatten();
1228 return transformState.lastPlanarQuad();
1231 void RenderObject::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const
1233 if (repaintContainer == this)
1236 auto* parent = this->parent();
1240 // FIXME: this should call offsetFromContainer to share code, but I'm not sure it's ever called.
1241 LayoutPoint centerPoint(transformState.mappedPoint());
1242 if (mode & ApplyContainerFlip && is<RenderBox>(*parent)) {
1243 if (parent->style().isFlippedBlocksWritingMode())
1244 transformState.move(downcast<RenderBox>(parent)->flipForWritingMode(LayoutPoint(transformState.mappedPoint())) - centerPoint);
1245 mode &= ~ApplyContainerFlip;
1248 if (is<RenderBox>(*parent))
1249 transformState.move(-toLayoutSize(downcast<RenderBox>(*parent).scrollPosition()));
1251 parent->mapLocalToContainer(repaintContainer, transformState, mode, wasFixed);
1254 const RenderObject* RenderObject::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
1256 ASSERT_UNUSED(ancestorToStopAt, ancestorToStopAt != this);
1258 auto* container = parent();
1262 // FIXME: this should call offsetFromContainer to share code, but I'm not sure it's ever called.
1264 if (is<RenderBox>(*container))
1265 offset = -toLayoutSize(downcast<RenderBox>(*container).scrollPosition());
1267 geometryMap.push(this, offset, false);
1272 void RenderObject::mapAbsoluteToLocalPoint(MapCoordinatesFlags mode, TransformState& transformState) const
1274 if (auto* parent = this->parent()) {
1275 parent->mapAbsoluteToLocalPoint(mode, transformState);
1276 if (is<RenderBox>(*parent))
1277 transformState.move(toLayoutSize(downcast<RenderBox>(*parent).scrollPosition()));
1281 bool RenderObject::shouldUseTransformFromContainer(const RenderObject* containerObject) const
1283 #if ENABLE(3D_TRANSFORMS)
1284 return hasTransform() || (containerObject && containerObject->style().hasPerspective());
1286 UNUSED_PARAM(containerObject);
1287 return hasTransform();
1291 void RenderObject::getTransformFromContainer(const RenderObject* containerObject, const LayoutSize& offsetInContainer, TransformationMatrix& transform) const
1293 transform.makeIdentity();
1294 transform.translate(offsetInContainer.width(), offsetInContainer.height());
1296 if (hasLayer() && (layer = downcast<RenderLayerModelObject>(*this).layer()) && layer->transform())
1297 transform.multiply(layer->currentTransform());
1299 #if ENABLE(3D_TRANSFORMS)
1300 if (containerObject && containerObject->hasLayer() && containerObject->style().hasPerspective()) {
1301 // Perpsective on the container affects us, so we have to factor it in here.
1302 ASSERT(containerObject->hasLayer());
1303 FloatPoint perspectiveOrigin = downcast<RenderLayerModelObject>(*containerObject).layer()->perspectiveOrigin();
1305 TransformationMatrix perspectiveMatrix;
1306 perspectiveMatrix.applyPerspective(containerObject->style().perspective());
1308 transform.translateRight3d(-perspectiveOrigin.x(), -perspectiveOrigin.y(), 0);
1309 transform = perspectiveMatrix * transform;
1310 transform.translateRight3d(perspectiveOrigin.x(), perspectiveOrigin.y(), 0);
1313 UNUSED_PARAM(containerObject);
1317 FloatQuad RenderObject::localToContainerQuad(const FloatQuad& localQuad, const RenderLayerModelObject* repaintContainer, MapCoordinatesFlags mode, bool* wasFixed) const
1319 // Track the point at the center of the quad's bounding box. As mapLocalToContainer() calls offsetFromContainer(),
1320 // it will use that point as the reference point to decide which column's transform to apply in multiple-column blocks.
1321 TransformState transformState(TransformState::ApplyTransformDirection, localQuad.boundingBox().center(), localQuad);
1322 mapLocalToContainer(repaintContainer, transformState, mode | ApplyContainerFlip, wasFixed);
1323 transformState.flatten();
1325 return transformState.lastPlanarQuad();
1328 FloatPoint RenderObject::localToContainerPoint(const FloatPoint& localPoint, const RenderLayerModelObject* repaintContainer, MapCoordinatesFlags mode, bool* wasFixed) const
1330 TransformState transformState(TransformState::ApplyTransformDirection, localPoint);
1331 mapLocalToContainer(repaintContainer, transformState, mode | ApplyContainerFlip, wasFixed);
1332 transformState.flatten();
1334 return transformState.lastPlanarPoint();
1337 LayoutSize RenderObject::offsetFromContainer(RenderElement& container, const LayoutPoint&, bool* offsetDependsOnPoint) const
1339 ASSERT(&container == this->container());
1342 if (is<RenderBox>(container))
1343 offset -= toLayoutSize(downcast<RenderBox>(container).scrollPosition());
1345 if (offsetDependsOnPoint)
1346 *offsetDependsOnPoint = is<RenderFragmentedFlow>(container);
1351 LayoutSize RenderObject::offsetFromAncestorContainer(RenderElement& container) const
1354 LayoutPoint referencePoint;
1355 const RenderObject* currContainer = this;
1357 RenderElement* nextContainer = currContainer->container();
1358 ASSERT(nextContainer); // This means we reached the top without finding container.
1361 ASSERT(!currContainer->hasTransform());
1362 LayoutSize currentOffset = currContainer->offsetFromContainer(*nextContainer, referencePoint);
1363 offset += currentOffset;
1364 referencePoint.move(currentOffset);
1365 currContainer = nextContainer;
1366 } while (currContainer != &container);
1371 LayoutRect RenderObject::localCaretRect(InlineBox*, unsigned, LayoutUnit* extraWidthToEndOfLine)
1373 if (extraWidthToEndOfLine)
1374 *extraWidthToEndOfLine = 0;
1376 return LayoutRect();
1379 bool RenderObject::isRooted() const
1381 return isDescendantOf(&view());
1384 static inline RenderElement* containerForElement(const RenderObject& renderer, const RenderLayerModelObject* repaintContainer, bool* repaintContainerSkipped)
1386 // This method is extremely similar to containingBlock(), but with a few notable
1388 // (1) For normal flow elements, it just returns the parent.
1389 // (2) For absolute positioned elements, it will return a relative positioned inline, while
1390 // containingBlock() skips to the non-anonymous containing block.
1391 // This does mean that computePositionedLogicalWidth and computePositionedLogicalHeight have to use container().
1392 EPosition pos = renderer.style().position();
1393 auto* parent = renderer.parent();
1394 if (is<RenderText>(renderer) || (pos != FixedPosition && pos != AbsolutePosition))
1396 for (; parent && (pos == AbsolutePosition ? !parent->canContainAbsolutelyPositionedObjects() : !parent->canContainFixedPositionObjects()); parent = parent->parent()) {
1397 if (repaintContainerSkipped && repaintContainer == parent)
1398 *repaintContainerSkipped = true;
1403 RenderElement* RenderObject::container() const
1405 return containerForElement(*this, nullptr, nullptr);
1408 RenderElement* RenderObject::container(const RenderLayerModelObject* repaintContainer, bool& repaintContainerSkipped) const
1410 repaintContainerSkipped = false;
1411 return containerForElement(*this, repaintContainer, &repaintContainerSkipped);
1414 bool RenderObject::isSelectionBorder() const
1416 SelectionState st = selectionState();
1417 return st == SelectionStart
1418 || st == SelectionEnd
1419 || st == SelectionBoth
1420 || view().selectionUnsplitStart() == this
1421 || view().selectionUnsplitEnd() == this;
1424 void RenderObject::willBeDestroyed()
1426 // For accessibility management, notify the parent of the imminent change to its child set.
1427 // We do it now, before remove(), while the parent pointer is still available.
1428 if (AXObjectCache* cache = document().existingAXObjectCache())
1429 cache->childrenChanged(this->parent());
1432 // FIXME: We should have always been removed from the parent before being destroyed.
1433 auto takenThis = m_parent->takeChild(*this);
1434 auto* leakedPtr = takenThis.leakPtr();
1435 UNUSED_PARAM(leakedPtr);
1438 ASSERT(renderTreeBeingDestroyed() || !is<RenderElement>(*this) || !view().frameView().hasSlowRepaintObject(downcast<RenderElement>(*this)));
1440 // The remove() call above may invoke axObjectCache()->childrenChanged() on the parent, which may require the AX render
1441 // object for this renderer. So we remove the AX render object now, after the renderer is removed.
1442 if (AXObjectCache* cache = document().existingAXObjectCache())
1443 cache->remove(this);
1445 // FIXME: Would like to do this in RenderBoxModelObject, but the timing is so complicated that this can't easily
1446 // be moved into RenderLayerModelObject::willBeDestroyed().
1447 // FIXME: Is this still true?
1450 downcast<RenderLayerModelObject>(*this).destroyLayer();
1456 void RenderObject::insertedIntoTree()
1458 // FIXME: We should ASSERT(isRooted()) here but generated content makes some out-of-order insertion.
1460 if (!isFloating() && parent()->childrenInline())
1461 parent()->dirtyLinesFromChangedChild(*this);
1463 if (RenderFragmentedFlow* fragmentedFlow = enclosingFragmentedFlow())
1464 fragmentedFlow->fragmentedFlowDescendantInserted(*this);
1467 void RenderObject::willBeRemovedFromTree()
1469 // FIXME: We should ASSERT(isRooted()) but we have some out-of-order removals which would need to be fixed first.
1470 // Update cached boundaries in SVG renderers, if a child is removed.
1471 parent()->setNeedsBoundariesUpdate();
1474 void RenderObject::destroyAndCleanupAnonymousWrappers()
1476 // If the tree is destroyed, there is no need for a clean-up phase.
1477 if (renderTreeBeingDestroyed()) {
1482 auto* destroyRoot = this;
1483 auto* destroyRootParent = destroyRoot->parent();
1484 while (destroyRootParent && destroyRootParent->isAnonymous()) {
1485 if (!destroyRootParent->isTableCell() && !destroyRootParent->isTableRow()
1486 && !destroyRootParent->isTableCaption() && !destroyRootParent->isTableSection() && !destroyRootParent->isTable())
1489 if (!(destroyRootParent->firstChild() == destroyRoot && destroyRootParent->lastChild() == destroyRoot))
1491 destroyRoot = destroyRootParent;
1492 destroyRootParent = destroyRootParent->parent();
1495 if (is<RenderTableRow>(*destroyRoot)) {
1496 downcast<RenderTableRow>(*destroyRoot).destroyAndCollapseAnonymousSiblingRows();
1500 destroyRoot->destroy();
1501 // WARNING: |this| is deleted here.
1504 void RenderObject::destroy()
1506 ASSERT(!m_bitfields.beingDestroyed());
1507 m_bitfields.setBeingDestroyed(true);
1511 downcast<RenderBoxModelObject>(*this).layer()->willBeDestroyed();
1515 if (is<RenderWidget>(*this)) {
1516 downcast<RenderWidget>(*this).deref();
1522 Position RenderObject::positionForPoint(const LayoutPoint& point)
1524 // FIXME: This should just create a Position object instead (webkit.org/b/168566).
1525 return positionForPoint(point, nullptr).deepEquivalent();
1528 VisiblePosition RenderObject::positionForPoint(const LayoutPoint&, const RenderFragmentContainer*)
1530 return createVisiblePosition(caretMinOffset(), DOWNSTREAM);
1533 void RenderObject::updateDragState(bool dragOn)
1535 bool valueChanged = (dragOn != isDragging());
1536 setIsDragging(dragOn);
1538 if (!is<RenderElement>(*this))
1540 auto& renderElement = downcast<RenderElement>(*this);
1542 if (valueChanged && renderElement.element() && (style().affectedByDrag() || renderElement.element()->childrenAffectedByDrag()))
1543 renderElement.element()->invalidateStyleForSubtree();
1545 for (auto& child : childrenOfType<RenderObject>(renderElement))
1546 child.updateDragState(dragOn);
1549 bool RenderObject::isComposited() const
1551 return hasLayer() && downcast<RenderLayerModelObject>(*this).layer()->isComposited();
1554 bool RenderObject::hitTest(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestFilter hitTestFilter)
1556 bool inside = false;
1557 if (hitTestFilter != HitTestSelf) {
1558 // First test the foreground layer (lines and inlines).
1559 inside = nodeAtPoint(request, result, locationInContainer, accumulatedOffset, HitTestForeground);
1561 // Test floats next.
1563 inside = nodeAtPoint(request, result, locationInContainer, accumulatedOffset, HitTestFloat);
1565 // Finally test to see if the mouse is in the background (within a child block's background).
1567 inside = nodeAtPoint(request, result, locationInContainer, accumulatedOffset, HitTestChildBlockBackgrounds);
1570 // See if the mouse is inside us but not any of our descendants
1571 if (hitTestFilter != HitTestDescendants && !inside)
1572 inside = nodeAtPoint(request, result, locationInContainer, accumulatedOffset, HitTestBlockBackground);
1577 void RenderObject::updateHitTestResult(HitTestResult& result, const LayoutPoint& point)
1579 if (result.innerNode())
1582 Node* node = this->node();
1584 // If we hit the anonymous renderers inside generated content we should
1585 // actually hit the generated content so walk up to the PseudoElement.
1586 if (!node && parent() && parent()->isBeforeOrAfterContent()) {
1587 for (auto* renderer = parent(); renderer && !node; renderer = renderer->parent())
1588 node = renderer->element();
1592 result.setInnerNode(node);
1593 if (!result.innerNonSharedNode())
1594 result.setInnerNonSharedNode(node);
1595 result.setLocalPoint(point);
1599 bool RenderObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& /*locationInContainer*/, const LayoutPoint& /*accumulatedOffset*/, HitTestAction)
1604 int RenderObject::innerLineHeight() const
1606 return style().computedLineHeight();
1609 #if ENABLE(DASHBOARD_SUPPORT)
1610 void RenderObject::addAnnotatedRegions(Vector<AnnotatedRegionValue>& regions)
1612 // Convert the style regions to absolute coordinates.
1613 if (style().visibility() != VISIBLE || !is<RenderBox>(*this))
1616 auto& box = downcast<RenderBox>(*this);
1617 FloatPoint absPos = localToAbsolute();
1619 const Vector<StyleDashboardRegion>& styleRegions = style().dashboardRegions();
1620 for (const auto& styleRegion : styleRegions) {
1621 LayoutUnit w = box.width();
1622 LayoutUnit h = box.height();
1624 AnnotatedRegionValue region;
1625 region.label = styleRegion.label;
1626 region.bounds = LayoutRect(styleRegion.offset.left().value(),
1627 styleRegion.offset.top().value(),
1628 w - styleRegion.offset.left().value() - styleRegion.offset.right().value(),
1629 h - styleRegion.offset.top().value() - styleRegion.offset.bottom().value());
1630 region.type = styleRegion.type;
1632 region.clip = computeAbsoluteRepaintRect(region.bounds);
1633 if (region.clip.height() < 0) {
1634 region.clip.setHeight(0);
1635 region.clip.setWidth(0);
1638 region.bounds.setX(absPos.x() + styleRegion.offset.left().value());
1639 region.bounds.setY(absPos.y() + styleRegion.offset.top().value());
1641 regions.append(region);
1645 void RenderObject::collectAnnotatedRegions(Vector<AnnotatedRegionValue>& regions)
1647 // RenderTexts don't have their own style, they just use their parent's style,
1648 // so we don't want to include them.
1649 if (is<RenderText>(*this))
1652 addAnnotatedRegions(regions);
1653 for (RenderObject* current = downcast<RenderElement>(*this).firstChild(); current; current = current->nextSibling())
1654 current->collectAnnotatedRegions(regions);
1658 int RenderObject::caretMinOffset() const
1663 int RenderObject::caretMaxOffset() const
1666 return node() ? std::max(1U, node()->countChildNodes()) : 1;
1672 int RenderObject::previousOffset(int current) const
1677 int RenderObject::previousOffsetForBackwardDeletion(int current) const
1682 int RenderObject::nextOffset(int current) const
1687 void RenderObject::adjustRectForOutlineAndShadow(LayoutRect& rect) const
1689 LayoutUnit outlineSize = outlineStyleForRepaint().outlineSize();
1690 if (const ShadowData* boxShadow = style().boxShadow()) {
1691 boxShadow->adjustRectForShadow(rect, outlineSize);
1694 rect.inflate(outlineSize);
1697 void RenderObject::imageChanged(CachedImage* image, const IntRect* rect)
1699 imageChanged(static_cast<WrappedImagePtr>(image), rect);
1702 RenderBoxModelObject* RenderObject::offsetParent() const
1704 // If any of the following holds true return null and stop this algorithm:
1705 // A is the root element.
1706 // A is the HTML body element.
1707 // The computed value of the position property for element A is fixed.
1708 if (isDocumentElementRenderer() || isBody() || (isOutOfFlowPositioned() && style().position() == FixedPosition))
1711 // If A is an area HTML element which has a map HTML element somewhere in the ancestor
1712 // chain return the nearest ancestor map HTML element and stop this algorithm.
1713 // FIXME: Implement!
1715 // Return the nearest ancestor element of A for which at least one of the following is
1716 // true and stop this algorithm if such an ancestor is found:
1717 // * The computed value of the position property is not static.
1718 // * It is the HTML body element.
1719 // * The computed value of the position property of A is static and the ancestor
1720 // is one of the following HTML elements: td, th, or table.
1721 // * Our own extension: if there is a difference in the effective zoom
1723 bool skipTables = isPositioned();
1724 float currZoom = style().effectiveZoom();
1725 auto current = parent();
1726 while (current && (!current->element() || (!current->isPositioned() && !current->isBody()))) {
1727 Element* element = current->element();
1728 if (!skipTables && element && (is<HTMLTableElement>(*element) || is<HTMLTableCellElement>(*element)))
1731 float newZoom = current->style().effectiveZoom();
1732 if (currZoom != newZoom)
1735 current = current->parent();
1738 return is<RenderBoxModelObject>(current) ? downcast<RenderBoxModelObject>(current) : nullptr;
1741 VisiblePosition RenderObject::createVisiblePosition(int offset, EAffinity affinity) const
1743 // If this is a non-anonymous renderer in an editable area, then it's simple.
1744 if (Node* node = nonPseudoNode()) {
1745 if (!node->hasEditableStyle()) {
1746 // If it can be found, we prefer a visually equivalent position that is editable.
1747 Position position = createLegacyEditingPosition(node, offset);
1748 Position candidate = position.downstream(CanCrossEditingBoundary);
1749 if (candidate.deprecatedNode()->hasEditableStyle())
1750 return VisiblePosition(candidate, affinity);
1751 candidate = position.upstream(CanCrossEditingBoundary);
1752 if (candidate.deprecatedNode()->hasEditableStyle())
1753 return VisiblePosition(candidate, affinity);
1755 // FIXME: Eliminate legacy editing positions
1756 return VisiblePosition(createLegacyEditingPosition(node, offset), affinity);
1759 // We don't want to cross the boundary between editable and non-editable
1760 // regions of the document, but that is either impossible or at least
1761 // extremely unlikely in any normal case because we stop as soon as we
1762 // find a single non-anonymous renderer.
1764 // Find a nearby non-anonymous renderer.
1765 const RenderObject* child = this;
1766 while (const auto parent = child->parent()) {
1767 // Find non-anonymous content after.
1768 const RenderObject* renderer = child;
1769 while ((renderer = renderer->nextInPreOrder(parent))) {
1770 if (Node* node = renderer->nonPseudoNode())
1771 return VisiblePosition(firstPositionInOrBeforeNode(node), DOWNSTREAM);
1774 // Find non-anonymous content before.
1776 while ((renderer = renderer->previousInPreOrder())) {
1777 if (renderer == parent)
1779 if (Node* node = renderer->nonPseudoNode())
1780 return VisiblePosition(lastPositionInOrAfterNode(node), DOWNSTREAM);
1783 // Use the parent itself unless it too is anonymous.
1784 if (Element* element = parent->nonPseudoElement())
1785 return VisiblePosition(firstPositionInOrBeforeNode(element), DOWNSTREAM);
1787 // Repeat at the next level up.
1791 // Everything was anonymous. Give up.
1792 return VisiblePosition();
1795 VisiblePosition RenderObject::createVisiblePosition(const Position& position) const
1797 if (position.isNotNull())
1798 return VisiblePosition(position);
1801 return createVisiblePosition(0, DOWNSTREAM);
1804 CursorDirective RenderObject::getCursor(const LayoutPoint&, Cursor&) const
1806 return SetCursorBasedOnStyle;
1809 bool RenderObject::canUpdateSelectionOnRootLineBoxes()
1814 RenderBlock* containingBlock = this->containingBlock();
1815 return containingBlock ? !containingBlock->needsLayout() : true;
1818 // We only create "generated" child renderers like one for first-letter if:
1819 // - the firstLetterBlock can have children in the DOM and
1820 // - the block doesn't have any special assumption on its text children.
1821 // This correctly prevents form controls from having such renderers.
1822 bool RenderObject::canHaveGeneratedChildren() const
1824 return canHaveChildren();
1827 Node* RenderObject::generatingPseudoHostElement() const
1829 return downcast<PseudoElement>(*node()).hostElement();
1832 void RenderObject::setNeedsBoundariesUpdate()
1834 if (auto renderer = parent())
1835 renderer->setNeedsBoundariesUpdate();
1838 FloatRect RenderObject::objectBoundingBox() const
1840 ASSERT_NOT_REACHED();
1844 FloatRect RenderObject::strokeBoundingBox() const
1846 ASSERT_NOT_REACHED();
1850 // Returns the smallest rectangle enclosing all of the painted content
1851 // respecting clipping, masking, filters, opacity, stroke-width and markers
1852 FloatRect RenderObject::repaintRectInLocalCoordinates() const
1854 ASSERT_NOT_REACHED();
1858 AffineTransform RenderObject::localTransform() const
1860 static const AffineTransform identity;
1864 const AffineTransform& RenderObject::localToParentTransform() const
1866 static const AffineTransform identity;
1870 bool RenderObject::nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint&, HitTestAction)
1872 ASSERT_NOT_REACHED();
1876 RenderFragmentedFlow* RenderObject::locateEnclosingFragmentedFlow() const
1878 RenderBlock* containingBlock = this->containingBlock();
1879 return containingBlock ? containingBlock->enclosingFragmentedFlow() : nullptr;
1882 void RenderObject::calculateBorderStyleColor(const EBorderStyle& style, const BoxSide& side, Color& color)
1884 ASSERT(style == INSET || style == OUTSET);
1885 // This values were derived empirically.
1886 const RGBA32 baseDarkColor = 0xFF202020;
1887 const RGBA32 baseLightColor = 0xFFEBEBEB;
1888 enum Operation { Darken, Lighten };
1890 Operation operation = (side == BSTop || side == BSLeft) == (style == INSET) ? Darken : Lighten;
1892 // Here we will darken the border decoration color when needed. This will yield a similar behavior as in FF.
1893 if (operation == Darken) {
1894 if (differenceSquared(color, Color::black) > differenceSquared(baseDarkColor, Color::black))
1895 color = color.dark();
1897 if (differenceSquared(color, Color::white) > differenceSquared(baseLightColor, Color::white))
1898 color = color.light();
1902 void RenderObject::setIsDragging(bool isDragging)
1904 if (isDragging || hasRareData())
1905 ensureRareData().setIsDragging(isDragging);
1908 void RenderObject::setHasReflection(bool hasReflection)
1910 if (hasReflection || hasRareData())
1911 ensureRareData().setHasReflection(hasReflection);
1914 void RenderObject::setIsRenderFragmentedFlow(bool isFragmentedFlow)
1916 if (isFragmentedFlow || hasRareData())
1917 ensureRareData().setIsRenderFragmentedFlow(isFragmentedFlow);
1920 void RenderObject::setHasOutlineAutoAncestor(bool hasOutlineAutoAncestor)
1922 if (hasOutlineAutoAncestor || hasRareData())
1923 ensureRareData().setHasOutlineAutoAncestor(hasOutlineAutoAncestor);
1926 RenderObject::RareDataMap& RenderObject::rareDataMap()
1928 static NeverDestroyed<RareDataMap> map;
1932 const RenderObject::RenderObjectRareData& RenderObject::rareData() const
1934 ASSERT(hasRareData());
1935 return *rareDataMap().get(this);
1938 RenderObject::RenderObjectRareData& RenderObject::ensureRareData()
1940 setHasRareData(true);
1941 return *rareDataMap().ensure(this, [] { return std::make_unique<RenderObjectRareData>(); }).iterator->value;
1944 void RenderObject::removeRareData()
1946 rareDataMap().remove(this);
1947 setHasRareData(false);
1950 #if ENABLE(TREE_DEBUGGING)
1952 void printRenderTreeForLiveDocuments()
1954 for (const auto* document : Document::allDocuments()) {
1955 if (!document->renderView())
1957 if (document->frame() && document->frame()->isMainFrame())
1958 fprintf(stderr, "----------------------main frame--------------------------\n");
1959 fprintf(stderr, "%s", document->url().string().utf8().data());
1960 showRenderTree(document->renderView());
1964 void printLayerTreeForLiveDocuments()
1966 for (const auto* document : Document::allDocuments()) {
1967 if (!document->renderView())
1969 if (document->frame() && document->frame()->isMainFrame())
1970 fprintf(stderr, "----------------------main frame--------------------------\n");
1971 fprintf(stderr, "%s", document->url().string().utf8().data());
1972 showLayerTree(document->renderView());
1976 #endif // ENABLE(TREE_DEBUGGING)
1978 } // namespace WebCore
1980 #if ENABLE(TREE_DEBUGGING)
1982 void showNodeTree(const WebCore::RenderObject* object)
1986 object->showNodeTreeForThis();
1989 void showLineTree(const WebCore::RenderObject* object)
1993 object->showLineTreeForThis();
1996 void showRenderTree(const WebCore::RenderObject* object)
2000 object->showRenderTreeForThis();