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 "AnimationController.h"
32 #include "EventHandler.h"
33 #include "FloatQuad.h"
34 #include "FlowThreadController.h"
35 #include "FrameSelection.h"
36 #include "FrameView.h"
37 #include "GeometryUtilities.h"
38 #include "GraphicsContext.h"
39 #include "HTMLAnchorElement.h"
40 #include "HTMLElement.h"
41 #include "HTMLImageElement.h"
42 #include "HTMLNames.h"
43 #include "HTMLTableCellElement.h"
44 #include "HTMLTableElement.h"
45 #include "HitTestResult.h"
46 #include "LogicalSelectionOffsetCaches.h"
47 #include "MainFrame.h"
49 #include "PseudoElement.h"
50 #include "RenderChildIterator.h"
51 #include "RenderCounter.h"
52 #include "RenderFlowThread.h"
53 #include "RenderGeometryMap.h"
54 #include "RenderInline.h"
55 #include "RenderIterator.h"
56 #include "RenderLayer.h"
57 #include "RenderLayerBacking.h"
58 #include "RenderMultiColumnFlowThread.h"
59 #include "RenderNamedFlowFragment.h"
60 #include "RenderNamedFlowThread.h"
61 #include "RenderRuby.h"
62 #include "RenderSVGResourceContainer.h"
63 #include "RenderScrollbarPart.h"
64 #include "RenderTableRow.h"
65 #include "RenderTableSection.h"
66 #include "RenderTheme.h"
67 #include "RenderView.h"
68 #include "RenderWidget.h"
69 #include "SVGRenderSupport.h"
71 #include "StyleResolver.h"
72 #include "TransformState.h"
73 #include "htmlediting.h"
76 #include <wtf/RefCountedLeakCounter.h>
79 #include "SelectionRect.h"
84 using namespace HTMLNames;
88 RenderObject::SetLayoutNeededForbiddenScope::SetLayoutNeededForbiddenScope(RenderObject* renderObject, bool isForbidden)
89 : m_renderObject(renderObject)
90 , m_preexistingForbidden(m_renderObject->isSetNeedsLayoutForbidden())
92 m_renderObject->setNeedsLayoutIsForbidden(isForbidden);
95 RenderObject::SetLayoutNeededForbiddenScope::~SetLayoutNeededForbiddenScope()
97 m_renderObject->setNeedsLayoutIsForbidden(m_preexistingForbidden);
101 struct SameSizeAsRenderObject {
102 virtual ~SameSizeAsRenderObject() { } // Allocate vtable pointer.
105 unsigned m_debugBitfields : 2;
107 unsigned m_bitfields;
110 COMPILE_ASSERT(sizeof(RenderObject) == sizeof(SameSizeAsRenderObject), RenderObject_should_stay_small);
112 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, renderObjectCounter, ("RenderObject"));
114 RenderObject::RenderObject(Node& node)
115 : CachedImageClient()
118 , m_previous(nullptr)
121 , m_hasAXObject(false)
122 , m_setNeedsLayoutForbidden(false)
126 if (RenderView* renderView = node.document().renderView())
127 renderView->didCreateRenderer();
129 renderObjectCounter.increment();
133 RenderObject::~RenderObject()
135 view().didDestroyRenderer();
137 ASSERT(!m_hasAXObject);
138 renderObjectCounter.decrement();
140 ASSERT(!hasRareData());
143 RenderTheme& RenderObject::theme() const
145 ASSERT(document().page());
146 return document().page()->theme();
149 bool RenderObject::isDescendantOf(const RenderObject* ancestor) const
151 for (const RenderObject* renderer = this; renderer; renderer = renderer->m_parent) {
152 if (renderer == ancestor)
158 bool RenderObject::isLegend() const
160 return node() && node()->hasTagName(legendTag);
163 bool RenderObject::isHTMLMarquee() const
165 return node() && node()->renderer() == this && node()->hasTagName(marqueeTag);
168 void RenderObject::setFlowThreadStateIncludingDescendants(FlowThreadState state)
170 setFlowThreadState(state);
172 if (!is<RenderElement>(*this))
175 for (auto& child : childrenOfType<RenderObject>(downcast<RenderElement>(*this))) {
176 // If the child is a fragmentation context it already updated the descendants flag accordingly.
177 if (child.isRenderFlowThread())
179 ASSERT(state != child.flowThreadState());
180 child.setFlowThreadStateIncludingDescendants(state);
184 void RenderObject::setParent(RenderElement* parent)
188 // Only update if our flow thread state is different from our new parent and if we're not a RenderFlowThread.
189 // A RenderFlowThread is always considered to be inside itself, so it never has to change its state
190 // in response to parent changes.
191 FlowThreadState newState = parent ? parent->flowThreadState() : NotInsideFlowThread;
192 if (newState != flowThreadState() && !isRenderFlowThread())
193 setFlowThreadStateIncludingDescendants(newState);
196 void RenderObject::removeFromParent()
199 parent()->removeChild(*this);
202 RenderObject* RenderObject::nextInPreOrder() const
204 if (RenderObject* o = firstChildSlow())
207 return nextInPreOrderAfterChildren();
210 RenderObject* RenderObject::nextInPreOrderAfterChildren() const
213 if (!(o = nextSibling())) {
215 while (o && !o->nextSibling())
218 o = o->nextSibling();
224 RenderObject* RenderObject::nextInPreOrder(const RenderObject* stayWithin) const
226 if (RenderObject* o = firstChildSlow())
229 return nextInPreOrderAfterChildren(stayWithin);
232 RenderObject* RenderObject::nextInPreOrderAfterChildren(const RenderObject* stayWithin) const
234 if (this == stayWithin)
237 const RenderObject* current = this;
239 while (!(next = current->nextSibling())) {
240 current = current->parent();
241 if (!current || current == stayWithin)
247 RenderObject* RenderObject::previousInPreOrder() const
249 if (RenderObject* o = previousSibling()) {
250 while (RenderObject* last = o->lastChildSlow())
258 RenderObject* RenderObject::previousInPreOrder(const RenderObject* stayWithin) const
260 if (this == stayWithin)
263 return previousInPreOrder();
266 RenderObject* RenderObject::childAt(unsigned index) const
268 RenderObject* child = firstChildSlow();
269 for (unsigned i = 0; child && i < index; i++)
270 child = child->nextSibling();
274 RenderObject* RenderObject::firstLeafChild() const
276 RenderObject* r = firstChildSlow();
278 RenderObject* n = nullptr;
279 n = r->firstChildSlow();
287 RenderObject* RenderObject::lastLeafChild() const
289 RenderObject* r = lastChildSlow();
291 RenderObject* n = nullptr;
292 n = r->lastChildSlow();
300 #if ENABLE(IOS_TEXT_AUTOSIZING)
302 // Non-recursive version of the DFS search.
303 RenderObject* RenderObject::traverseNext(const RenderObject* stayWithin, HeightTypeTraverseNextInclusionFunction inclusionFunction, int& currentDepth, int& newFixedDepth) const
305 BlockContentHeightType overflowType;
307 // Check for suitable children.
308 for (RenderObject* child = firstChildSlow(); child; child = child->nextSibling()) {
309 overflowType = inclusionFunction(*child);
310 if (overflowType != FixedHeight) {
312 if (overflowType == OverflowHeight)
313 newFixedDepth = currentDepth;
314 ASSERT(!stayWithin || child->isDescendantOf(stayWithin));
319 if (this == stayWithin)
322 // Now we traverse other nodes if they exist, otherwise
323 // we go to the parent node and try doing the same.
324 const RenderObject* n = this;
326 while (n && !n->nextSibling() && (!stayWithin || n->parent() != stayWithin)) {
332 for (RenderObject* sibling = n->nextSibling(); sibling; sibling = sibling->nextSibling()) {
333 overflowType = inclusionFunction(*sibling);
334 if (overflowType != FixedHeight) {
335 if (overflowType == OverflowHeight)
336 newFixedDepth = currentDepth;
337 ASSERT(!stayWithin || !n->nextSibling() || n->nextSibling()->isDescendantOf(stayWithin));
341 if (!stayWithin || n->parent() != stayWithin) {
350 #endif // ENABLE(IOS_TEXT_AUTOSIZING)
352 RenderLayer* RenderObject::enclosingLayer() const
354 for (auto& renderer : lineageOfType<RenderLayerModelObject>(*this)) {
355 if (renderer.hasLayer())
356 return renderer.layer();
361 bool RenderObject::scrollRectToVisible(const LayoutRect& rect, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
363 RenderLayer* enclosingLayer = this->enclosingLayer();
367 enclosingLayer->scrollRectToVisible(rect, alignX, alignY);
371 RenderBox& RenderObject::enclosingBox() const
373 return *lineageOfType<RenderBox>(const_cast<RenderObject&>(*this)).first();
376 RenderBoxModelObject& RenderObject::enclosingBoxModelObject() const
378 return *lineageOfType<RenderBoxModelObject>(const_cast<RenderObject&>(*this)).first();
381 bool RenderObject::fixedPositionedWithNamedFlowContainingBlock() const
383 return ((flowThreadState() == RenderObject::InsideOutOfFlowThread)
384 && (style().position() == FixedPosition)
385 && (containingBlock()->isOutOfFlowRenderFlowThread()));
388 static bool hasFixedPosInNamedFlowContainingBlock(const RenderObject* renderer)
390 ASSERT(renderer->flowThreadState() != RenderObject::NotInsideFlowThread);
392 RenderObject* curr = const_cast<RenderObject*>(renderer);
393 while (curr && !is<RenderView>(*curr)) {
394 if (curr->fixedPositionedWithNamedFlowContainingBlock())
396 curr = curr->containingBlock();
402 RenderBlock* RenderObject::firstLineBlock() const
407 static inline bool objectIsRelayoutBoundary(const RenderElement* object)
409 // FIXME: In future it may be possible to broaden these conditions in order to improve performance.
410 if (object->isRenderView())
413 if (object->isTextControl())
416 if (object->isSVGRoot())
419 if (!object->hasOverflowClip())
422 if (object->style().width().isIntrinsicOrAuto() || object->style().height().isIntrinsicOrAuto() || object->style().height().isPercentOrCalculated())
425 // Table parts can't be relayout roots since the table is responsible for layouting all the parts.
426 if (object->isTablePart())
432 void RenderObject::clearNeedsLayout()
434 m_bitfields.setNeedsLayout(false);
435 setEverHadLayout(true);
436 setPosChildNeedsLayoutBit(false);
437 setNeedsSimplifiedNormalFlowLayoutBit(false);
438 setNormalChildNeedsLayoutBit(false);
439 setNeedsPositionedMovementLayoutBit(false);
440 if (is<RenderElement>(*this))
441 downcast<RenderElement>(*this).setAncestorLineBoxDirty(false);
443 checkBlockPositionedObjectsNeedLayout();
447 static void scheduleRelayoutForSubtree(RenderElement& renderer)
449 if (is<RenderView>(renderer)) {
450 downcast<RenderView>(renderer).frameView().scheduleRelayout();
454 if (renderer.isRooted())
455 renderer.view().frameView().scheduleRelayoutOfSubtree(renderer);
458 void RenderObject::markContainingBlocksForLayout(ScheduleRelayout scheduleRelayout, RenderElement* newRoot)
460 ASSERT(scheduleRelayout == ScheduleRelayout::No || !newRoot);
461 ASSERT(!isSetNeedsLayoutForbidden());
463 auto ancestor = container();
465 bool simplifiedNormalFlowLayout = needsSimplifiedNormalFlowLayout() && !selfNeedsLayout() && !normalChildNeedsLayout();
466 bool hasOutOfFlowPosition = !isText() && style().hasOutOfFlowPosition();
470 // FIXME: Remove this once we remove the special cases for counters, quotes and mathml
471 // calling setNeedsLayout during preferred width computation.
472 SetLayoutNeededForbiddenScope layoutForbiddenScope(ancestor, isSetNeedsLayoutForbidden());
474 // Don't mark the outermost object of an unrooted subtree. That object will be
475 // marked when the subtree is added to the document.
476 auto container = ancestor->container();
477 if (!container && !ancestor->isRenderView())
479 if (hasOutOfFlowPosition) {
480 bool willSkipRelativelyPositionedInlines = !ancestor->isRenderBlock() || ancestor->isAnonymousBlock();
481 // Skip relatively positioned inlines and anonymous blocks to get to the enclosing RenderBlock.
482 while (ancestor && (!ancestor->isRenderBlock() || ancestor->isAnonymousBlock()))
483 ancestor = ancestor->container();
484 if (!ancestor || ancestor->posChildNeedsLayout())
486 if (willSkipRelativelyPositionedInlines)
487 container = ancestor->container();
488 ancestor->setPosChildNeedsLayoutBit(true);
489 simplifiedNormalFlowLayout = true;
490 } else if (simplifiedNormalFlowLayout) {
491 if (ancestor->needsSimplifiedNormalFlowLayout())
493 ancestor->setNeedsSimplifiedNormalFlowLayoutBit(true);
495 if (ancestor->normalChildNeedsLayout())
497 ancestor->setNormalChildNeedsLayoutBit(true);
499 ASSERT(!ancestor->isSetNeedsLayoutForbidden());
501 if (ancestor == newRoot)
504 if (scheduleRelayout == ScheduleRelayout::Yes && objectIsRelayoutBoundary(ancestor))
507 hasOutOfFlowPosition = ancestor->style().hasOutOfFlowPosition();
508 ancestor = container;
511 if (scheduleRelayout == ScheduleRelayout::Yes && ancestor)
512 scheduleRelayoutForSubtree(*ancestor);
516 void RenderObject::checkBlockPositionedObjectsNeedLayout()
518 ASSERT(!needsLayout());
520 if (is<RenderBlock>(*this))
521 downcast<RenderBlock>(*this).checkPositionedObjectsNeedLayout();
525 void RenderObject::setPreferredLogicalWidthsDirty(bool shouldBeDirty, MarkingBehavior markParents)
527 bool alreadyDirty = preferredLogicalWidthsDirty();
528 m_bitfields.setPreferredLogicalWidthsDirty(shouldBeDirty);
529 if (shouldBeDirty && !alreadyDirty && markParents == MarkContainingBlockChain && (isText() || !style().hasOutOfFlowPosition()))
530 invalidateContainerPreferredLogicalWidths();
533 void RenderObject::invalidateContainerPreferredLogicalWidths()
535 // In order to avoid pathological behavior when inlines are deeply nested, we do include them
536 // in the chain that we mark dirty (even though they're kind of irrelevant).
537 auto o = isTableCell() ? containingBlock() : container();
538 while (o && !o->preferredLogicalWidthsDirty()) {
539 // Don't invalidate the outermost object of an unrooted subtree. That object will be
540 // invalidated when the subtree is added to the document.
541 auto container = o->isTableCell() ? o->containingBlock() : o->container();
542 if (!container && !o->isRenderView())
545 o->m_bitfields.setPreferredLogicalWidthsDirty(true);
546 if (o->style().hasOutOfFlowPosition())
547 // A positioned object has no effect on the min/max width of its containing block ever.
548 // We can optimize this case and not go up any further.
554 void RenderObject::setLayerNeedsFullRepaint()
557 downcast<RenderLayerModelObject>(*this).layer()->setRepaintStatus(NeedsFullRepaint);
560 void RenderObject::setLayerNeedsFullRepaintForPositionedMovementLayout()
563 downcast<RenderLayerModelObject>(*this).layer()->setRepaintStatus(NeedsFullRepaintForPositionedMovementLayout);
566 RenderBlock* RenderObject::containingBlock() const
568 auto containingBlockForRenderer = [](const RenderObject& renderer)
570 auto& style = renderer.style();
571 if (style.position() == AbsolutePosition)
572 return renderer.containingBlockForAbsolutePosition();
573 if (style.position() == FixedPosition)
574 return renderer.containingBlockForFixedPosition();
575 return renderer.containingBlockForObjectInFlow();
578 if (is<RenderText>(*this))
579 return containingBlockForObjectInFlow();
581 if (!parent() && is<RenderScrollbarPart>(*this)) {
582 if (auto* renderer = downcast<RenderScrollbarPart>(*this).rendererOwningScrollbar())
583 return containingBlockForRenderer(*renderer);
586 return containingBlockForRenderer(*this);
589 RenderBlock* RenderObject::containingBlockForFixedPosition() const
591 auto* renderer = parent();
592 while (renderer && !renderer->canContainFixedPositionObjects())
593 renderer = renderer->parent();
595 ASSERT(!renderer || !renderer->isAnonymousBlock());
596 return downcast<RenderBlock>(renderer);
599 RenderBlock* RenderObject::containingBlockForAbsolutePosition() const
601 // RenderInlines forward their absolute positioned descendants to the containing block, so
602 // we need to start searching from 'this' and not from 'parent()'.
603 auto* renderer = isRenderInline() ? const_cast<RenderElement*>(downcast<RenderElement>(this)) : parent();
604 while (renderer && !renderer->canContainAbsolutelyPositionedObjects())
605 renderer = renderer->parent();
607 // For a relatively positioned inline, return its nearest non-anonymous containing block,
608 // not the inline itself, to avoid having a positioned objects list in all RenderInlines
609 // and use RenderBlock* as RenderElement::containingBlock's return type.
610 // Use RenderBlock::container() to obtain the inline.
611 if (renderer && !is<RenderBlock>(*renderer))
612 renderer = renderer->containingBlock();
614 while (renderer && renderer->isAnonymousBlock())
615 renderer = renderer->containingBlock();
617 return downcast<RenderBlock>(renderer);
620 RenderBlock* RenderObject::containingBlockForObjectInFlow() const
622 auto* renderer = parent();
623 while (renderer && ((renderer->isInline() && !renderer->isReplaced()) || !renderer->isRenderBlock()))
624 renderer = renderer->parent();
625 return downcast<RenderBlock>(renderer);
628 void RenderObject::addPDFURLRect(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
630 Vector<LayoutRect> focusRingRects;
631 addFocusRingRects(focusRingRects, paintOffset, paintInfo.paintContainer);
632 LayoutRect urlRect = unionRect(focusRingRects);
634 if (urlRect.isEmpty())
636 Node* node = this->node();
637 if (!is<Element>(node) || !node->isLink())
639 const AtomicString& href = downcast<Element>(*node).getAttribute(hrefAttr);
642 paintInfo.context().setURLForRect(node->document().completeURL(href), snappedIntRect(urlRect));
646 // This function is similar in spirit to RenderText::absoluteRectsForRange, but returns rectangles
647 // which are annotated with additional state which helps iOS draw selections in its unique way.
648 // No annotations are added in this class.
649 // FIXME: Move to RenderText with absoluteRectsForRange()?
650 void RenderObject::collectSelectionRects(Vector<SelectionRect>& rects, unsigned start, unsigned end)
652 Vector<FloatQuad> quads;
654 if (!firstChildSlow()) {
655 // FIXME: WebKit's position for an empty span after a BR is incorrect, so we can't trust
656 // quads for them. We don't need selection rects for those anyway though, since they
657 // are just empty containers. See <https://bugs.webkit.org/show_bug.cgi?id=49358>.
658 RenderObject* previous = previousSibling();
659 Node* node = this->node();
660 if (!previous || !previous->isBR() || !node || !node->isContainerNode() || !isInline()) {
661 // For inline elements we don't use absoluteQuads, since it takes into account continuations and leads to wrong results.
662 absoluteQuadsForSelection(quads);
665 unsigned offset = start;
666 for (RenderObject* child = childAt(start); child && offset < end; child = child->nextSibling(), ++offset)
667 child->absoluteQuads(quads);
670 unsigned numberOfQuads = quads.size();
671 for (unsigned i = 0; i < numberOfQuads; ++i)
672 rects.append(SelectionRect(quads[i].enclosingBoundingBox(), isHorizontalWritingMode(), view().pageNumberForBlockProgressionOffset(quads[i].enclosingBoundingBox().x())));
676 IntRect RenderObject::absoluteBoundingBoxRect(bool useTransforms, bool* wasFixed) const
679 Vector<FloatQuad> quads;
680 absoluteQuads(quads, wasFixed);
682 size_t n = quads.size();
686 IntRect result = quads[0].enclosingBoundingBox();
687 for (size_t i = 1; i < n; ++i)
688 result.unite(quads[i].enclosingBoundingBox());
692 FloatPoint absPos = localToAbsolute(FloatPoint(), 0 /* ignore transforms */, wasFixed);
693 Vector<IntRect> rects;
694 absoluteRects(rects, flooredLayoutPoint(absPos));
696 size_t n = rects.size();
700 LayoutRect result = rects[0];
701 for (size_t i = 1; i < n; ++i)
702 result.unite(rects[i]);
703 return snappedIntRect(result);
706 void RenderObject::absoluteFocusRingQuads(Vector<FloatQuad>& quads)
708 Vector<LayoutRect> rects;
709 // FIXME: addFocusRingRects() needs to be passed this transform-unaware
710 // localToAbsolute() offset here because RenderInline::addFocusRingRects()
711 // implicitly assumes that. This doesn't work correctly with transformed
713 FloatPoint absolutePoint = localToAbsolute();
714 addFocusRingRects(rects, flooredLayoutPoint(absolutePoint));
715 float deviceScaleFactor = document().deviceScaleFactor();
716 for (auto rect : rects) {
717 rect.moveBy(LayoutPoint(-absolutePoint));
718 quads.append(localToAbsoluteQuad(FloatQuad(snapRectToDevicePixels(rect, deviceScaleFactor))));
722 FloatRect RenderObject::absoluteBoundingBoxRectForRange(const Range* range)
727 range->ownerDocument().updateLayout();
729 Vector<FloatQuad> quads;
730 range->absoluteTextQuads(quads);
735 FloatRect result = quads[0].boundingBox();
736 for (size_t i = 1; i < quads.size(); ++i)
737 result.uniteEvenIfEmpty(quads[i].boundingBox());
742 void RenderObject::addAbsoluteRectForLayer(LayoutRect& result)
745 result.unite(absoluteBoundingBoxRectIgnoringTransforms());
747 if (!is<RenderElement>(*this))
750 for (auto& child : childrenOfType<RenderObject>(downcast<RenderElement>(*this)))
751 child.addAbsoluteRectForLayer(result);
754 // FIXME: change this to use the subtreePaint terminology
755 LayoutRect RenderObject::paintingRootRect(LayoutRect& topLevelRect)
757 LayoutRect result = absoluteBoundingBoxRectIgnoringTransforms();
758 topLevelRect = result;
759 if (is<RenderElement>(*this)) {
760 for (auto& child : childrenOfType<RenderObject>(downcast<RenderElement>(*this)))
761 child.addAbsoluteRectForLayer(result);
766 RenderLayerModelObject* RenderObject::containerForRepaint() const
768 RenderLayerModelObject* repaintContainer = nullptr;
770 if (view().usesCompositing()) {
771 if (RenderLayer* parentLayer = enclosingLayer()) {
772 RenderLayer* compLayer = parentLayer->enclosingCompositingLayerForRepaint();
774 repaintContainer = &compLayer->renderer();
777 if (view().hasSoftwareFilters()) {
778 if (RenderLayer* parentLayer = enclosingLayer()) {
779 RenderLayer* enclosingFilterLayer = parentLayer->enclosingFilterLayer();
780 if (enclosingFilterLayer)
781 return &enclosingFilterLayer->renderer();
785 // If we have a flow thread, then we need to do individual repaints within the RenderRegions instead.
786 // Return the flow thread as a repaint container in order to create a chokepoint that allows us to change
787 // repainting to do individual region repaints.
788 RenderFlowThread* parentRenderFlowThread = flowThreadContainingBlock();
789 if (parentRenderFlowThread) {
790 // If the element has a fixed positioned element with named flow as CB along the CB chain
791 // then the repaint container is not the flow thread.
792 if (hasFixedPosInNamedFlowContainingBlock(this))
793 return repaintContainer;
794 // If we have already found a repaint container then we will repaint into that container only if it is part of the same
795 // flow thread. Otherwise we will need to catch the repaint call and send it to the flow thread.
796 RenderFlowThread* repaintContainerFlowThread = repaintContainer ? repaintContainer->flowThreadContainingBlock() : nullptr;
797 if (!repaintContainerFlowThread || repaintContainerFlowThread != parentRenderFlowThread)
798 repaintContainer = parentRenderFlowThread;
800 return repaintContainer;
803 void RenderObject::propagateRepaintToParentWithOutlineAutoIfNeeded(const RenderLayerModelObject& repaintContainer, const LayoutRect& repaintRect) const
805 if (!hasOutlineAutoAncestor())
808 // FIXME: We should really propagate only when the the child renderer sticks out.
809 bool repaintRectNeedsConverting = false;
810 // Issue repaint on the renderer with outline: auto.
811 for (const auto* renderer = this; renderer; renderer = renderer->parent()) {
812 bool rendererHasOutlineAutoAncestor = renderer->hasOutlineAutoAncestor();
813 ASSERT(rendererHasOutlineAutoAncestor
814 || renderer->outlineStyleForRepaint().outlineStyleIsAuto()
815 || (is<RenderElement>(*renderer) && downcast<RenderElement>(*renderer).hasContinuation()));
816 if (renderer == &repaintContainer && rendererHasOutlineAutoAncestor)
817 repaintRectNeedsConverting = true;
818 if (rendererHasOutlineAutoAncestor)
820 // Issue repaint on the correct repaint container.
821 LayoutRect adjustedRepaintRect = repaintRect;
822 adjustedRepaintRect.inflate(renderer->outlineStyleForRepaint().outlineSize());
823 if (!repaintRectNeedsConverting)
824 repaintContainer.repaintRectangle(adjustedRepaintRect);
825 else if (is<RenderLayerModelObject>(renderer)) {
826 const auto& rendererWithOutline = downcast<RenderLayerModelObject>(*renderer);
827 adjustedRepaintRect = LayoutRect(repaintContainer.localToContainerQuad(FloatRect(adjustedRepaintRect), &rendererWithOutline).boundingBox());
828 rendererWithOutline.repaintRectangle(adjustedRepaintRect);
832 ASSERT_NOT_REACHED();
835 void RenderObject::repaintUsingContainer(const RenderLayerModelObject* repaintContainer, const LayoutRect& r, bool shouldClipToLayer) const
840 if (!repaintContainer)
841 repaintContainer = &view();
843 if (is<RenderFlowThread>(*repaintContainer)) {
844 downcast<RenderFlowThread>(*repaintContainer).repaintRectangleInRegions(r);
848 propagateRepaintToParentWithOutlineAutoIfNeeded(*repaintContainer, r);
850 if (repaintContainer->hasFilter() && repaintContainer->layer() && repaintContainer->layer()->requiresFullLayerImageForFilters()) {
851 repaintContainer->layer()->setFilterBackendNeedsRepaintingInRect(r);
855 if (repaintContainer->isRenderView()) {
856 RenderView& view = this->view();
857 ASSERT(repaintContainer == &view);
858 bool viewHasCompositedLayer = view.isComposited();
859 if (!viewHasCompositedLayer || view.layer()->backing()->paintsIntoWindow()) {
861 if (viewHasCompositedLayer && view.layer()->transform())
862 rect = LayoutRect(view.layer()->transform()->mapRect(snapRectToDevicePixels(rect, document().deviceScaleFactor())));
863 view.repaintViewRectangle(rect);
868 if (view().usesCompositing()) {
869 ASSERT(repaintContainer->isComposited());
870 repaintContainer->layer()->setBackingNeedsRepaintInRect(r, shouldClipToLayer ? GraphicsLayer::ClipToLayer : GraphicsLayer::DoNotClipToLayer);
874 void RenderObject::repaint() const
876 // Don't repaint if we're unrooted (note that view() still returns the view when unrooted)
880 const RenderView& view = this->view();
884 RenderLayerModelObject* repaintContainer = containerForRepaint();
885 repaintUsingContainer(repaintContainer, clippedOverflowRectForRepaint(repaintContainer));
888 void RenderObject::repaintRectangle(const LayoutRect& r, bool shouldClipToLayer) const
890 // Don't repaint if we're unrooted (note that view() still returns the view when unrooted)
894 const RenderView& view = this->view();
898 LayoutRect dirtyRect(r);
899 // FIXME: layoutDelta needs to be applied in parts before/after transforms and
900 // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
901 dirtyRect.move(view.layoutDelta());
903 RenderLayerModelObject* repaintContainer = containerForRepaint();
904 repaintUsingContainer(repaintContainer, computeRectForRepaint(dirtyRect, repaintContainer), shouldClipToLayer);
907 void RenderObject::repaintSlowRepaintObject() const
909 // Don't repaint if we're unrooted (note that view() still returns the view when unrooted)
913 const RenderView& view = this->view();
917 const RenderLayerModelObject* repaintContainer = containerForRepaint();
918 if (!repaintContainer)
919 repaintContainer = &view;
921 bool shouldClipToLayer = true;
923 // If this is the root background, we need to check if there is an extended background rect. If
924 // there is, then we should not allow painting to clip to the layer size.
925 if (isDocumentElementRenderer() || isBody()) {
926 shouldClipToLayer = !view.frameView().hasExtendedBackgroundRectForPainting();
927 repaintRect = snappedIntRect(view.backgroundRect());
929 repaintRect = snappedIntRect(clippedOverflowRectForRepaint(repaintContainer));
931 repaintUsingContainer(repaintContainer, repaintRect, shouldClipToLayer);
934 IntRect RenderObject::pixelSnappedAbsoluteClippedOverflowRect() const
936 return snappedIntRect(absoluteClippedOverflowRect());
939 bool RenderObject::hasSelfPaintingLayer() const
943 auto* layer = downcast<RenderLayerModelObject>(*this).layer();
946 return layer->isSelfPaintingLayer();
949 bool RenderObject::checkForRepaintDuringLayout() const
951 return !document().view()->needsFullRepaint() && everHadLayout() && !hasSelfPaintingLayer();
954 LayoutRect RenderObject::rectWithOutlineForRepaint(const RenderLayerModelObject* repaintContainer, LayoutUnit outlineWidth) const
956 LayoutRect r(clippedOverflowRectForRepaint(repaintContainer));
957 r.inflate(outlineWidth);
961 LayoutRect RenderObject::clippedOverflowRectForRepaint(const RenderLayerModelObject*) const
963 ASSERT_NOT_REACHED();
967 LayoutRect RenderObject::computeRectForRepaint(const LayoutRect& rect, const RenderLayerModelObject* repaintContainer, RepaintContext context) const
969 if (repaintContainer == this)
972 auto* parent = this->parent();
976 LayoutRect adjustedRect = rect;
977 if (parent->hasOverflowClip()) {
978 downcast<RenderBox>(*parent).applyCachedClipAndScrollOffsetForRepaint(adjustedRect);
979 if (adjustedRect.isEmpty())
982 return parent->computeRectForRepaint(adjustedRect, repaintContainer, context);
985 FloatRect RenderObject::computeFloatRectForRepaint(const FloatRect&, const RenderLayerModelObject*, bool) const
987 ASSERT_NOT_REACHED();
991 #if ENABLE(TREE_DEBUGGING)
993 static void showRenderTreeLegend()
995 fprintf(stderr, "\n(B)lock/(I)nline/I(N)line-block, (R)elative/A(B)solute/Fi(X)ed/Stick(Y) positioned, (O)verflow clipping, (A)nonymous, (G)enerated, (F)loating, has(L)ayer, (C)omposited, (D)irty layout, Dirty (S)tyle\n");
998 void RenderObject::showNodeTreeForThis() const
1002 node()->showTreeForThis();
1005 void RenderObject::showRenderTreeForThis() const
1007 const WebCore::RenderObject* root = this;
1008 while (root->parent())
1009 root = root->parent();
1010 showRenderTreeLegend();
1011 root->showRenderSubTreeAndMark(this, 1);
1014 void RenderObject::showLineTreeForThis() const
1016 if (!is<RenderBlockFlow>(*this))
1018 showRenderTreeLegend();
1019 showRenderObject(false, 1);
1020 downcast<RenderBlockFlow>(*this).showLineTreeAndMark(nullptr, 2);
1023 static const RenderFlowThread* flowThreadContainingBlockFromRenderer(const RenderObject* renderer)
1028 if (renderer->flowThreadState() == RenderObject::NotInsideFlowThread)
1031 if (is<RenderFlowThread>(*renderer))
1032 return downcast<RenderFlowThread>(renderer);
1034 if (is<RenderBlock>(*renderer))
1035 return downcast<RenderBlock>(*renderer).cachedFlowThreadContainingBlock();
1040 void RenderObject::showRegionsInformation() const
1042 const RenderFlowThread* ftcb = flowThreadContainingBlockFromRenderer(this);
1045 // Only the boxes have region range information.
1046 // Try to get the flow thread containing block information
1047 // from the containing block of this box.
1048 if (is<RenderBox>(*this))
1049 ftcb = flowThreadContainingBlockFromRenderer(containingBlock());
1055 RenderRegion* startRegion = nullptr;
1056 RenderRegion* endRegion = nullptr;
1057 ftcb->getRegionRangeForBox(downcast<RenderBox>(this), startRegion, endRegion);
1058 fprintf(stderr, " [Rs:%p Re:%p]", startRegion, endRegion);
1061 void RenderObject::showRenderObject(bool mark, int depth) const
1063 if (isInlineBlockOrInlineTable())
1065 else if (isInline())
1070 if (isPositioned()) {
1071 if (isRelPositioned())
1073 else if (isStickyPositioned())
1075 else if (isOutOfFlowPositioned()) {
1076 if (style().position() == AbsolutePosition)
1084 if (hasOverflowClip())
1094 if (isPseudoElement() || isAnonymous())
1121 if (node() && node()->needsStyleRecalc())
1126 int printedCharacters = 0;
1128 fprintf(stderr, "*");
1129 ++printedCharacters;
1132 while (++printedCharacters <= depth * 2)
1136 fprintf(stderr, "%s ", node()->nodeName().utf8().data());
1138 String name = renderName();
1139 // FIXME: Renderer's name should not include property value listing.
1140 int pos = name.find('(');
1142 fprintf(stderr, "%s", name.left(pos - 1).utf8().data());
1144 fprintf(stderr, "%s", name.utf8().data());
1146 if (is<RenderBox>(*this)) {
1147 FloatRect boxRect = downcast<RenderBox>(*this).frameRect();
1148 fprintf(stderr, " (%.2f, %.2f) (%.2f, %.2f)", boxRect.x(), boxRect.y(), boxRect.width(), boxRect.height());
1149 } else if (is<RenderInline>(*this) && isInFlowPositioned()) {
1150 FloatSize inlineOffset = downcast<RenderInline>(*this).offsetForInFlowPosition();
1151 fprintf(stderr, " (%.2f, %.2f)", inlineOffset.width(), inlineOffset.height());
1154 fprintf(stderr, " renderer->(%p)", this);
1156 fprintf(stderr, " node->(%p)", node());
1157 if (node()->isTextNode()) {
1158 String value = node()->nodeValue();
1159 fprintf(stderr, " length->(%u)", value.length());
1161 value.replaceWithLiteral('\\', "\\\\");
1162 value.replaceWithLiteral('\n', "\\n");
1164 const int maxPrintedLength = 80;
1165 if (value.length() > maxPrintedLength) {
1166 String substring = value.substring(0, maxPrintedLength);
1167 fprintf(stderr, " \"%s\"...", substring.utf8().data());
1169 fprintf(stderr, " \"%s\"", value.utf8().data());
1173 showRegionsInformation();
1174 fprintf(stderr, "\n");
1177 void RenderObject::showRenderSubTreeAndMark(const RenderObject* markedObject, int depth) const
1179 showRenderObject(markedObject == this, depth);
1180 if (is<RenderBlockFlow>(*this))
1181 downcast<RenderBlockFlow>(*this).showLineTreeAndMark(nullptr, depth + 1);
1183 for (const RenderObject* child = firstChildSlow(); child; child = child->nextSibling())
1184 child->showRenderSubTreeAndMark(markedObject, depth + 1);
1189 SelectionSubtreeRoot& RenderObject::selectionRoot() const
1191 RenderFlowThread* flowThread = flowThreadContainingBlock();
1195 if (is<RenderNamedFlowThread>(*flowThread))
1196 return downcast<RenderNamedFlowThread>(*flowThread);
1197 if (is<RenderMultiColumnFlowThread>(*flowThread)) {
1198 if (!flowThread->containingBlock())
1200 return flowThread->containingBlock()->selectionRoot();
1202 ASSERT_NOT_REACHED();
1206 void RenderObject::selectionStartEnd(int& spos, int& epos) const
1208 selectionRoot().selectionData().selectionStartEndPositions(spos, epos);
1211 FloatPoint RenderObject::localToAbsolute(const FloatPoint& localPoint, MapCoordinatesFlags mode, bool* wasFixed) const
1213 TransformState transformState(TransformState::ApplyTransformDirection, localPoint);
1214 mapLocalToContainer(nullptr, transformState, mode | ApplyContainerFlip, wasFixed);
1215 transformState.flatten();
1217 return transformState.lastPlanarPoint();
1220 FloatPoint RenderObject::absoluteToLocal(const FloatPoint& containerPoint, MapCoordinatesFlags mode) const
1222 TransformState transformState(TransformState::UnapplyInverseTransformDirection, containerPoint);
1223 mapAbsoluteToLocalPoint(mode, transformState);
1224 transformState.flatten();
1226 return transformState.lastPlanarPoint();
1229 FloatQuad RenderObject::absoluteToLocalQuad(const FloatQuad& quad, MapCoordinatesFlags mode) const
1231 TransformState transformState(TransformState::UnapplyInverseTransformDirection, quad.boundingBox().center(), quad);
1232 mapAbsoluteToLocalPoint(mode, transformState);
1233 transformState.flatten();
1234 return transformState.lastPlanarQuad();
1237 void RenderObject::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const
1239 if (repaintContainer == this)
1242 auto* parent = this->parent();
1246 // FIXME: this should call offsetFromContainer to share code, but I'm not sure it's ever called.
1247 LayoutPoint centerPoint(transformState.mappedPoint());
1248 if (mode & ApplyContainerFlip && is<RenderBox>(*parent)) {
1249 if (parent->style().isFlippedBlocksWritingMode())
1250 transformState.move(downcast<RenderBox>(parent)->flipForWritingMode(LayoutPoint(transformState.mappedPoint())) - centerPoint);
1251 mode &= ~ApplyContainerFlip;
1254 if (is<RenderBox>(*parent))
1255 transformState.move(-toLayoutSize(downcast<RenderBox>(*parent).scrollPosition()));
1257 parent->mapLocalToContainer(repaintContainer, transformState, mode, wasFixed);
1260 const RenderObject* RenderObject::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
1262 ASSERT_UNUSED(ancestorToStopAt, ancestorToStopAt != this);
1264 auto* container = parent();
1268 // FIXME: this should call offsetFromContainer to share code, but I'm not sure it's ever called.
1270 if (is<RenderBox>(*container))
1271 offset = -toLayoutSize(downcast<RenderBox>(*container).scrollPosition());
1273 geometryMap.push(this, offset, false);
1278 void RenderObject::mapAbsoluteToLocalPoint(MapCoordinatesFlags mode, TransformState& transformState) const
1280 if (auto* parent = this->parent()) {
1281 parent->mapAbsoluteToLocalPoint(mode, transformState);
1282 if (is<RenderBox>(*parent))
1283 transformState.move(toLayoutSize(downcast<RenderBox>(*parent).scrollPosition()));
1287 bool RenderObject::shouldUseTransformFromContainer(const RenderObject* containerObject) const
1289 #if ENABLE(3D_TRANSFORMS)
1290 return hasTransform() || (containerObject && containerObject->style().hasPerspective());
1292 UNUSED_PARAM(containerObject);
1293 return hasTransform();
1297 void RenderObject::getTransformFromContainer(const RenderObject* containerObject, const LayoutSize& offsetInContainer, TransformationMatrix& transform) const
1299 transform.makeIdentity();
1300 transform.translate(offsetInContainer.width(), offsetInContainer.height());
1302 if (hasLayer() && (layer = downcast<RenderLayerModelObject>(*this).layer()) && layer->transform())
1303 transform.multiply(layer->currentTransform());
1305 #if ENABLE(3D_TRANSFORMS)
1306 if (containerObject && containerObject->hasLayer() && containerObject->style().hasPerspective()) {
1307 // Perpsective on the container affects us, so we have to factor it in here.
1308 ASSERT(containerObject->hasLayer());
1309 FloatPoint perspectiveOrigin = downcast<RenderLayerModelObject>(*containerObject).layer()->perspectiveOrigin();
1311 TransformationMatrix perspectiveMatrix;
1312 perspectiveMatrix.applyPerspective(containerObject->style().perspective());
1314 transform.translateRight3d(-perspectiveOrigin.x(), -perspectiveOrigin.y(), 0);
1315 transform = perspectiveMatrix * transform;
1316 transform.translateRight3d(perspectiveOrigin.x(), perspectiveOrigin.y(), 0);
1319 UNUSED_PARAM(containerObject);
1323 FloatQuad RenderObject::localToContainerQuad(const FloatQuad& localQuad, const RenderLayerModelObject* repaintContainer, MapCoordinatesFlags mode, bool* wasFixed) const
1325 // Track the point at the center of the quad's bounding box. As mapLocalToContainer() calls offsetFromContainer(),
1326 // it will use that point as the reference point to decide which column's transform to apply in multiple-column blocks.
1327 TransformState transformState(TransformState::ApplyTransformDirection, localQuad.boundingBox().center(), localQuad);
1328 mapLocalToContainer(repaintContainer, transformState, mode | ApplyContainerFlip, wasFixed);
1329 transformState.flatten();
1331 return transformState.lastPlanarQuad();
1334 FloatPoint RenderObject::localToContainerPoint(const FloatPoint& localPoint, const RenderLayerModelObject* repaintContainer, MapCoordinatesFlags mode, bool* wasFixed) const
1336 TransformState transformState(TransformState::ApplyTransformDirection, localPoint);
1337 mapLocalToContainer(repaintContainer, transformState, mode | ApplyContainerFlip, wasFixed);
1338 transformState.flatten();
1340 return transformState.lastPlanarPoint();
1343 LayoutSize RenderObject::offsetFromContainer(RenderElement& container, const LayoutPoint&, bool* offsetDependsOnPoint) const
1345 ASSERT(&container == this->container());
1348 if (is<RenderBox>(container))
1349 offset -= toLayoutSize(downcast<RenderBox>(container).scrollPosition());
1351 if (offsetDependsOnPoint)
1352 *offsetDependsOnPoint = is<RenderFlowThread>(container);
1357 LayoutSize RenderObject::offsetFromAncestorContainer(RenderElement& container) const
1360 LayoutPoint referencePoint;
1361 const RenderObject* currContainer = this;
1363 RenderElement* nextContainer = currContainer->container();
1364 ASSERT(nextContainer); // This means we reached the top without finding container.
1367 ASSERT(!currContainer->hasTransform());
1368 LayoutSize currentOffset = currContainer->offsetFromContainer(*nextContainer, referencePoint);
1369 offset += currentOffset;
1370 referencePoint.move(currentOffset);
1371 currContainer = nextContainer;
1372 } while (currContainer != &container);
1377 LayoutRect RenderObject::localCaretRect(InlineBox*, int, LayoutUnit* extraWidthToEndOfLine)
1379 if (extraWidthToEndOfLine)
1380 *extraWidthToEndOfLine = 0;
1382 return LayoutRect();
1385 bool RenderObject::isRooted() const
1387 return isDescendantOf(&view());
1390 RespectImageOrientationEnum RenderObject::shouldRespectImageOrientation() const
1392 #if USE(CG) || USE(CAIRO)
1393 // This can only be enabled for ports which honor the orientation flag in their drawing code.
1394 if (document().isImageDocument())
1395 return RespectImageOrientation;
1397 // Respect the image's orientation if it's being used as a full-page image or it's
1398 // an <img> and the setting to respect it everywhere is set.
1399 return (frame().settings().shouldRespectImageOrientation() && is<HTMLImageElement>(node())) ? RespectImageOrientation : DoNotRespectImageOrientation;
1402 bool RenderObject::hasOutlineAnnotation() const
1404 return node() && node()->isLink() && document().printing();
1407 bool RenderObject::hasEntirelyFixedBackground() const
1409 return style().hasEntirelyFixedBackground();
1412 static inline RenderElement* containerForElement(const RenderObject& renderer, const RenderLayerModelObject* repaintContainer, bool* repaintContainerSkipped)
1414 // This method is extremely similar to containingBlock(), but with a few notable
1416 // (1) For normal flow elements, it just returns the parent.
1417 // (2) For absolute positioned elements, it will return a relative positioned inline, while
1418 // containingBlock() skips to the non-anonymous containing block.
1419 // This does mean that computePositionedLogicalWidth and computePositionedLogicalHeight have to use container().
1420 EPosition pos = renderer.style().position();
1421 auto* parent = renderer.parent();
1422 if (is<RenderText>(renderer) || (pos != FixedPosition && pos != AbsolutePosition))
1424 for (; parent && (pos == AbsolutePosition ? !parent->canContainAbsolutelyPositionedObjects() : !parent->canContainFixedPositionObjects()); parent = parent->parent()) {
1425 if (repaintContainerSkipped && repaintContainer == parent)
1426 *repaintContainerSkipped = true;
1431 RenderElement* RenderObject::container() const
1433 return containerForElement(*this, nullptr, nullptr);
1436 RenderElement* RenderObject::container(const RenderLayerModelObject* repaintContainer, bool& repaintContainerSkipped) const
1438 repaintContainerSkipped = false;
1439 return containerForElement(*this, repaintContainer, &repaintContainerSkipped);
1442 bool RenderObject::isSelectionBorder() const
1444 SelectionState st = selectionState();
1445 return st == SelectionStart
1446 || st == SelectionEnd
1447 || st == SelectionBoth
1448 || view().selectionUnsplitStart() == this
1449 || view().selectionUnsplitEnd() == this;
1452 void RenderObject::willBeDestroyed()
1454 // For accessibility management, notify the parent of the imminent change to its child set.
1455 // We do it now, before remove(), while the parent pointer is still available.
1456 if (AXObjectCache* cache = document().existingAXObjectCache())
1457 cache->childrenChanged(this->parent());
1461 ASSERT(documentBeingDestroyed() || !is<RenderElement>(*this) || !view().frameView().hasSlowRepaintObject(downcast<RenderElement>(*this)));
1463 // The remove() call above may invoke axObjectCache()->childrenChanged() on the parent, which may require the AX render
1464 // object for this renderer. So we remove the AX render object now, after the renderer is removed.
1465 if (AXObjectCache* cache = document().existingAXObjectCache())
1466 cache->remove(this);
1468 // FIXME: Would like to do this in RenderBoxModelObject, but the timing is so complicated that this can't easily
1469 // be moved into RenderBoxModelObject::destroy.
1472 downcast<RenderLayerModelObject>(*this).destroyLayer();
1478 void RenderObject::insertedIntoTree()
1480 // FIXME: We should ASSERT(isRooted()) here but generated content makes some out-of-order insertion.
1482 if (!isFloating() && parent()->childrenInline())
1483 parent()->dirtyLinesFromChangedChild(*this);
1485 if (RenderFlowThread* flowThread = flowThreadContainingBlock())
1486 flowThread->flowThreadDescendantInserted(this);
1489 void RenderObject::willBeRemovedFromTree()
1491 // FIXME: We should ASSERT(isRooted()) but we have some out-of-order removals which would need to be fixed first.
1493 removeFromRenderFlowThread();
1495 // Update cached boundaries in SVG renderers, if a child is removed.
1496 parent()->setNeedsBoundariesUpdate();
1499 void RenderObject::removeFromRenderFlowThread()
1501 if (flowThreadState() == NotInsideFlowThread)
1504 // Sometimes we remove the element from the flow, but it's not destroyed at that time.
1505 // It's only until later when we actually destroy it and remove all the children from it.
1506 // Currently, that happens for firstLetter elements and list markers.
1507 // Pass in the flow thread so that we don't have to look it up for all the children.
1508 removeFromRenderFlowThreadIncludingDescendants(true);
1511 void RenderObject::removeFromRenderFlowThreadIncludingDescendants(bool shouldUpdateState)
1513 // Once we reach another flow thread we don't need to update the flow thread state
1514 // but we have to continue cleanup the flow thread info.
1515 if (isRenderFlowThread())
1516 shouldUpdateState = false;
1518 if (is<RenderElement>(*this)) {
1519 for (auto& child : childrenOfType<RenderObject>(downcast<RenderElement>(*this)))
1520 child.removeFromRenderFlowThreadIncludingDescendants(shouldUpdateState);
1523 // We have to ask for our containing flow thread as it may be above the removed sub-tree.
1524 RenderFlowThread* flowThreadContainingBlock = this->flowThreadContainingBlock();
1525 while (flowThreadContainingBlock) {
1526 flowThreadContainingBlock->removeFlowChildInfo(this);
1527 if (flowThreadContainingBlock->flowThreadState() == NotInsideFlowThread)
1529 RenderObject* parent = flowThreadContainingBlock->parent();
1532 flowThreadContainingBlock = parent->flowThreadContainingBlock();
1534 if (is<RenderBlock>(*this))
1535 downcast<RenderBlock>(*this).setCachedFlowThreadContainingBlockNeedsUpdate();
1537 if (shouldUpdateState)
1538 setFlowThreadState(NotInsideFlowThread);
1541 void RenderObject::invalidateFlowThreadContainingBlockIncludingDescendants(RenderFlowThread* flowThread)
1543 if (flowThreadState() == NotInsideFlowThread)
1546 if (is<RenderBlock>(*this)) {
1547 RenderBlock& block = downcast<RenderBlock>(*this);
1549 if (block.cachedFlowThreadContainingBlockNeedsUpdate())
1552 flowThread = block.cachedFlowThreadContainingBlock();
1553 block.setCachedFlowThreadContainingBlockNeedsUpdate();
1557 flowThread->removeFlowChildInfo(this);
1559 if (!is<RenderElement>(*this))
1562 for (auto& child : childrenOfType<RenderObject>(downcast<RenderElement>(*this)))
1563 child.invalidateFlowThreadContainingBlockIncludingDescendants(flowThread);
1566 static void collapseAnonymousTableRowsIfNeeded(const RenderObject& rendererToBeDestroyed)
1568 if (!is<RenderTableRow>(rendererToBeDestroyed))
1571 auto& rowToBeDestroyed = downcast<RenderTableRow>(rendererToBeDestroyed);
1572 auto* section = downcast<RenderTableSection>(rowToBeDestroyed.parent());
1576 // All siblings generated?
1577 for (auto* current = section->firstRow(); current; current = current->nextRow()) {
1578 if (current == &rendererToBeDestroyed)
1580 if (!current->isAnonymous())
1584 RenderTableRow* rowToInsertInto = nullptr;
1585 auto* currentRow = section->firstRow();
1586 while (currentRow) {
1587 if (currentRow == &rendererToBeDestroyed) {
1588 currentRow = currentRow->nextRow();
1591 if (!rowToInsertInto) {
1592 rowToInsertInto = currentRow;
1593 currentRow = currentRow->nextRow();
1596 currentRow->moveAllChildrenTo(rowToInsertInto);
1597 auto* destroyThis = currentRow;
1598 currentRow = currentRow->nextRow();
1599 destroyThis->destroy();
1601 if (rowToInsertInto)
1602 rowToInsertInto->setNeedsLayout();
1605 void RenderObject::destroyAndCleanupAnonymousWrappers()
1607 // If the tree is destroyed, there is no need for a clean-up phase.
1608 if (documentBeingDestroyed()) {
1613 auto* destroyRoot = this;
1614 auto* destroyRootParent = destroyRoot->parent();
1615 while (destroyRootParent && destroyRootParent->isAnonymous()) {
1616 if (!destroyRootParent->isTableCell() && !destroyRootParent->isTableRow()
1617 && !destroyRootParent->isTableCaption() && !destroyRootParent->isTableSection() && !destroyRootParent->isTable())
1620 if (!(destroyRootParent->firstChild() == destroyRoot && destroyRootParent->lastChild() == destroyRoot))
1622 destroyRoot = destroyRootParent;
1623 destroyRootParent = destroyRootParent->parent();
1625 collapseAnonymousTableRowsIfNeeded(*destroyRoot);
1626 destroyRoot->destroy();
1627 // WARNING: |this| is deleted here.
1630 void RenderObject::destroy()
1632 m_bitfields.setBeingDestroyed(true);
1636 downcast<RenderBoxModelObject>(*this).layer()->willBeDestroyed();
1640 if (is<RenderWidget>(*this)) {
1641 downcast<RenderWidget>(*this).deref();
1647 VisiblePosition RenderObject::positionForPoint(const LayoutPoint&, const RenderRegion*)
1649 return createVisiblePosition(caretMinOffset(), DOWNSTREAM);
1652 void RenderObject::updateDragState(bool dragOn)
1654 bool valueChanged = (dragOn != isDragging());
1655 setIsDragging(dragOn);
1656 if (valueChanged && node() && (style().affectedByDrag() || (is<Element>(*node()) && downcast<Element>(*node()).childrenAffectedByDrag())))
1657 node()->setNeedsStyleRecalc();
1659 if (!is<RenderElement>(*this))
1662 for (auto& child : childrenOfType<RenderObject>(downcast<RenderElement>(*this)))
1663 child.updateDragState(dragOn);
1666 bool RenderObject::isComposited() const
1668 return hasLayer() && downcast<RenderLayerModelObject>(*this).layer()->isComposited();
1671 bool RenderObject::isAnonymousInlineBlock() const
1673 return isAnonymous() && style().display() == INLINE_BLOCK && style().styleType() == NOPSEUDO && isRenderBlockFlow() && !isRubyRun() && !isRubyBase() && !isRuby(parent());
1676 bool RenderObject::hitTest(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestFilter hitTestFilter)
1678 bool inside = false;
1679 if (hitTestFilter != HitTestSelf) {
1680 // First test the foreground layer (lines and inlines).
1681 inside = nodeAtPoint(request, result, locationInContainer, accumulatedOffset, HitTestForeground);
1683 // Test floats next.
1685 inside = nodeAtPoint(request, result, locationInContainer, accumulatedOffset, HitTestFloat);
1687 // Finally test to see if the mouse is in the background (within a child block's background).
1689 inside = nodeAtPoint(request, result, locationInContainer, accumulatedOffset, HitTestChildBlockBackgrounds);
1692 // See if the mouse is inside us but not any of our descendants
1693 if (hitTestFilter != HitTestDescendants && !inside)
1694 inside = nodeAtPoint(request, result, locationInContainer, accumulatedOffset, HitTestBlockBackground);
1699 void RenderObject::updateHitTestResult(HitTestResult& result, const LayoutPoint& point)
1701 if (result.innerNode())
1704 Node* node = this->node();
1706 // If we hit the anonymous renderers inside generated content we should
1707 // actually hit the generated content so walk up to the PseudoElement.
1708 if (!node && parent() && parent()->isBeforeOrAfterContent()) {
1709 for (auto* renderer = parent(); renderer && !node; renderer = renderer->parent())
1710 node = renderer->element();
1714 result.setInnerNode(node);
1715 if (!result.innerNonSharedNode())
1716 result.setInnerNonSharedNode(node);
1717 result.setLocalPoint(point);
1721 bool RenderObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& /*locationInContainer*/, const LayoutPoint& /*accumulatedOffset*/, HitTestAction)
1726 int RenderObject::innerLineHeight() const
1728 return style().computedLineHeight();
1731 static Color decorationColor(const RenderStyle* style)
1734 // Check for text decoration color first.
1735 result = style->visitedDependentColor(CSSPropertyWebkitTextDecorationColor);
1736 if (result.isValid())
1738 if (style->textStrokeWidth() > 0) {
1739 // Prefer stroke color if possible but not if it's fully transparent.
1740 result = style->visitedDependentColor(CSSPropertyWebkitTextStrokeColor);
1745 result = style->visitedDependentColor(CSSPropertyWebkitTextFillColor);
1749 void RenderObject::getTextDecorationColorsAndStyles(int decorations, Color& underlineColor, Color& overlineColor, Color& linethroughColor,
1750 TextDecorationStyle& underlineStyle, TextDecorationStyle& overlineStyle, TextDecorationStyle& linethroughStyle, bool firstlineStyle) const
1752 const RenderObject* current = this;
1753 const RenderStyle* styleToUse = nullptr;
1754 TextDecoration currDecs = TextDecorationNone;
1757 styleToUse = firstlineStyle ? ¤t->firstLineStyle() : ¤t->style();
1758 currDecs = styleToUse->textDecoration();
1759 resultColor = decorationColor(styleToUse);
1760 // Parameter 'decorations' is cast as an int to enable the bitwise operations below.
1762 if (currDecs & TextDecorationUnderline) {
1763 decorations &= ~TextDecorationUnderline;
1764 underlineColor = resultColor;
1765 underlineStyle = styleToUse->textDecorationStyle();
1767 if (currDecs & TextDecorationOverline) {
1768 decorations &= ~TextDecorationOverline;
1769 overlineColor = resultColor;
1770 overlineStyle = styleToUse->textDecorationStyle();
1772 if (currDecs & TextDecorationLineThrough) {
1773 decorations &= ~TextDecorationLineThrough;
1774 linethroughColor = resultColor;
1775 linethroughStyle = styleToUse->textDecorationStyle();
1778 if (current->isRubyText())
1780 current = current->parent();
1781 if (current && current->isAnonymousBlock() && downcast<RenderBlock>(*current).continuation())
1782 current = downcast<RenderBlock>(*current).continuation();
1783 } while (current && decorations && (!current->node() || (!is<HTMLAnchorElement>(*current->node()) && !current->node()->hasTagName(fontTag))));
1785 // If we bailed out, use the element we bailed out at (typically a <font> or <a> element).
1786 if (decorations && current) {
1787 styleToUse = firstlineStyle ? ¤t->firstLineStyle() : ¤t->style();
1788 resultColor = decorationColor(styleToUse);
1789 if (decorations & TextDecorationUnderline) {
1790 underlineColor = resultColor;
1791 underlineStyle = styleToUse->textDecorationStyle();
1793 if (decorations & TextDecorationOverline) {
1794 overlineColor = resultColor;
1795 overlineStyle = styleToUse->textDecorationStyle();
1797 if (decorations & TextDecorationLineThrough) {
1798 linethroughColor = resultColor;
1799 linethroughStyle = styleToUse->textDecorationStyle();
1804 #if ENABLE(DASHBOARD_SUPPORT)
1805 void RenderObject::addAnnotatedRegions(Vector<AnnotatedRegionValue>& regions)
1807 // Convert the style regions to absolute coordinates.
1808 if (style().visibility() != VISIBLE || !is<RenderBox>(*this))
1811 auto& box = downcast<RenderBox>(*this);
1812 FloatPoint absPos = localToAbsolute();
1814 const Vector<StyleDashboardRegion>& styleRegions = style().dashboardRegions();
1815 for (const auto& styleRegion : styleRegions) {
1816 LayoutUnit w = box.width();
1817 LayoutUnit h = box.height();
1819 AnnotatedRegionValue region;
1820 region.label = styleRegion.label;
1821 region.bounds = LayoutRect(styleRegion.offset.left().value(),
1822 styleRegion.offset.top().value(),
1823 w - styleRegion.offset.left().value() - styleRegion.offset.right().value(),
1824 h - styleRegion.offset.top().value() - styleRegion.offset.bottom().value());
1825 region.type = styleRegion.type;
1827 region.clip = region.bounds;
1828 computeAbsoluteRepaintRect(region.clip);
1829 if (region.clip.height() < 0) {
1830 region.clip.setHeight(0);
1831 region.clip.setWidth(0);
1834 region.bounds.setX(absPos.x() + styleRegion.offset.left().value());
1835 region.bounds.setY(absPos.y() + styleRegion.offset.top().value());
1837 regions.append(region);
1841 void RenderObject::collectAnnotatedRegions(Vector<AnnotatedRegionValue>& regions)
1843 // RenderTexts don't have their own style, they just use their parent's style,
1844 // so we don't want to include them.
1845 if (is<RenderText>(*this))
1848 addAnnotatedRegions(regions);
1849 for (RenderObject* current = downcast<RenderElement>(*this).firstChild(); current; current = current->nextSibling())
1850 current->collectAnnotatedRegions(regions);
1854 int RenderObject::caretMinOffset() const
1859 int RenderObject::caretMaxOffset() const
1862 return node() ? std::max(1U, node()->countChildNodes()) : 1;
1868 int RenderObject::previousOffset(int current) const
1873 int RenderObject::previousOffsetForBackwardDeletion(int current) const
1878 int RenderObject::nextOffset(int current) const
1883 void RenderObject::adjustRectForOutlineAndShadow(LayoutRect& rect) const
1885 LayoutUnit outlineSize = outlineStyleForRepaint().outlineSize();
1886 if (const ShadowData* boxShadow = style().boxShadow()) {
1887 boxShadow->adjustRectForShadow(rect, outlineSize);
1890 rect.inflate(outlineSize);
1893 void RenderObject::imageChanged(CachedImage* image, const IntRect* rect)
1895 imageChanged(static_cast<WrappedImagePtr>(image), rect);
1898 RenderBoxModelObject* RenderObject::offsetParent() const
1900 // If any of the following holds true return null and stop this algorithm:
1901 // A is the root element.
1902 // A is the HTML body element.
1903 // The computed value of the position property for element A is fixed.
1904 if (isDocumentElementRenderer() || isBody() || (isOutOfFlowPositioned() && style().position() == FixedPosition))
1907 // If A is an area HTML element which has a map HTML element somewhere in the ancestor
1908 // chain return the nearest ancestor map HTML element and stop this algorithm.
1909 // FIXME: Implement!
1911 // Return the nearest ancestor element of A for which at least one of the following is
1912 // true and stop this algorithm if such an ancestor is found:
1913 // * The computed value of the position property is not static.
1914 // * It is the HTML body element.
1915 // * The computed value of the position property of A is static and the ancestor
1916 // is one of the following HTML elements: td, th, or table.
1917 // * Our own extension: if there is a difference in the effective zoom
1919 bool skipTables = isPositioned();
1920 float currZoom = style().effectiveZoom();
1921 auto current = parent();
1922 while (current && (!current->element() || (!current->isPositioned() && !current->isBody())) && !is<RenderNamedFlowThread>(*current)) {
1923 Element* element = current->element();
1924 if (!skipTables && element && (is<HTMLTableElement>(*element) || is<HTMLTableCellElement>(*element)))
1927 float newZoom = current->style().effectiveZoom();
1928 if (currZoom != newZoom)
1931 current = current->parent();
1934 // CSS regions specification says that region flows should return the body element as their offsetParent.
1935 if (is<RenderNamedFlowThread>(current)) {
1936 auto* body = document().bodyOrFrameset();
1937 current = body ? body->renderer() : nullptr;
1940 return is<RenderBoxModelObject>(current) ? downcast<RenderBoxModelObject>(current) : nullptr;
1943 VisiblePosition RenderObject::createVisiblePosition(int offset, EAffinity affinity) const
1945 // If this is a non-anonymous renderer in an editable area, then it's simple.
1946 if (Node* node = nonPseudoNode()) {
1947 if (!node->hasEditableStyle()) {
1948 // If it can be found, we prefer a visually equivalent position that is editable.
1949 Position position = createLegacyEditingPosition(node, offset);
1950 Position candidate = position.downstream(CanCrossEditingBoundary);
1951 if (candidate.deprecatedNode()->hasEditableStyle())
1952 return VisiblePosition(candidate, affinity);
1953 candidate = position.upstream(CanCrossEditingBoundary);
1954 if (candidate.deprecatedNode()->hasEditableStyle())
1955 return VisiblePosition(candidate, affinity);
1957 // FIXME: Eliminate legacy editing positions
1958 return VisiblePosition(createLegacyEditingPosition(node, offset), affinity);
1961 // We don't want to cross the boundary between editable and non-editable
1962 // regions of the document, but that is either impossible or at least
1963 // extremely unlikely in any normal case because we stop as soon as we
1964 // find a single non-anonymous renderer.
1966 // Find a nearby non-anonymous renderer.
1967 const RenderObject* child = this;
1968 while (const auto parent = child->parent()) {
1969 // Find non-anonymous content after.
1970 const RenderObject* renderer = child;
1971 while ((renderer = renderer->nextInPreOrder(parent))) {
1972 if (Node* node = renderer->nonPseudoNode())
1973 return VisiblePosition(firstPositionInOrBeforeNode(node), DOWNSTREAM);
1976 // Find non-anonymous content before.
1978 while ((renderer = renderer->previousInPreOrder())) {
1979 if (renderer == parent)
1981 if (Node* node = renderer->nonPseudoNode())
1982 return VisiblePosition(lastPositionInOrAfterNode(node), DOWNSTREAM);
1985 // Use the parent itself unless it too is anonymous.
1986 if (Element* element = parent->nonPseudoElement())
1987 return VisiblePosition(firstPositionInOrBeforeNode(element), DOWNSTREAM);
1989 // Repeat at the next level up.
1993 // Everything was anonymous. Give up.
1994 return VisiblePosition();
1997 VisiblePosition RenderObject::createVisiblePosition(const Position& position) const
1999 if (position.isNotNull())
2000 return VisiblePosition(position);
2003 return createVisiblePosition(0, DOWNSTREAM);
2006 CursorDirective RenderObject::getCursor(const LayoutPoint&, Cursor&) const
2008 return SetCursorBasedOnStyle;
2011 bool RenderObject::canUpdateSelectionOnRootLineBoxes()
2016 RenderBlock* containingBlock = this->containingBlock();
2017 return containingBlock ? !containingBlock->needsLayout() : true;
2020 // We only create "generated" child renderers like one for first-letter if:
2021 // - the firstLetterBlock can have children in the DOM and
2022 // - the block doesn't have any special assumption on its text children.
2023 // This correctly prevents form controls from having such renderers.
2024 bool RenderObject::canHaveGeneratedChildren() const
2026 return canHaveChildren();
2029 Node* RenderObject::generatingPseudoHostElement() const
2031 return downcast<PseudoElement>(*node()).hostElement();
2034 void RenderObject::setNeedsBoundariesUpdate()
2036 if (auto renderer = parent())
2037 renderer->setNeedsBoundariesUpdate();
2040 FloatRect RenderObject::objectBoundingBox() const
2042 ASSERT_NOT_REACHED();
2046 FloatRect RenderObject::strokeBoundingBox() const
2048 ASSERT_NOT_REACHED();
2052 // Returns the smallest rectangle enclosing all of the painted content
2053 // respecting clipping, masking, filters, opacity, stroke-width and markers
2054 FloatRect RenderObject::repaintRectInLocalCoordinates() const
2056 ASSERT_NOT_REACHED();
2060 AffineTransform RenderObject::localTransform() const
2062 static const AffineTransform identity;
2066 const AffineTransform& RenderObject::localToParentTransform() const
2068 static const AffineTransform identity;
2072 bool RenderObject::nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint&, HitTestAction)
2074 ASSERT_NOT_REACHED();
2078 RenderNamedFlowFragment* RenderObject::currentRenderNamedFlowFragment() const
2080 RenderFlowThread* flowThread = flowThreadContainingBlock();
2081 if (!is<RenderNamedFlowThread>(flowThread))
2084 // FIXME: Once regions are fully integrated with the compositing system we should uncomment this assert.
2085 // This assert needs to be disabled because it's possible to ask for the ancestor clipping rectangle of
2086 // a layer without knowing the containing region in advance.
2087 // ASSERT(flowThread->currentRegion() && flowThread->currentRegion()->isRenderNamedFlowFragment());
2089 return downcast<RenderNamedFlowFragment>(flowThread->currentRegion());
2092 RenderFlowThread* RenderObject::locateFlowThreadContainingBlock() const
2094 RenderBlock* containingBlock = this->containingBlock();
2095 return containingBlock ? containingBlock->flowThreadContainingBlock() : nullptr;
2098 void RenderObject::calculateBorderStyleColor(const EBorderStyle& style, const BoxSide& side, Color& color)
2100 ASSERT(style == INSET || style == OUTSET);
2101 // This values were derived empirically.
2102 const RGBA32 baseDarkColor = 0xFF202020;
2103 const RGBA32 baseLightColor = 0xFFEBEBEB;
2104 enum Operation { Darken, Lighten };
2106 Operation operation = (side == BSTop || side == BSLeft) == (style == INSET) ? Darken : Lighten;
2108 // Here we will darken the border decoration color when needed. This will yield a similar behavior as in FF.
2109 if (operation == Darken) {
2110 if (differenceSquared(color, Color::black) > differenceSquared(baseDarkColor, Color::black))
2111 color = color.dark();
2113 if (differenceSquared(color, Color::white) > differenceSquared(baseLightColor, Color::white))
2114 color = color.light();
2118 void RenderObject::setIsDragging(bool isDragging)
2120 if (isDragging || hasRareData())
2121 ensureRareData().setIsDragging(isDragging);
2124 void RenderObject::setHasReflection(bool hasReflection)
2126 if (hasReflection || hasRareData())
2127 ensureRareData().setHasReflection(hasReflection);
2130 void RenderObject::setIsRenderFlowThread(bool isFlowThread)
2132 if (isFlowThread || hasRareData())
2133 ensureRareData().setIsRenderFlowThread(isFlowThread);
2136 void RenderObject::setHasOutlineAutoAncestor(bool hasOutlineAutoAncestor)
2138 if (hasOutlineAutoAncestor || hasRareData())
2139 ensureRareData().setHasOutlineAutoAncestor(hasOutlineAutoAncestor);
2142 void RenderObject::setIsRegisteredForVisibleInViewportCallback(bool registered)
2144 if (registered || hasRareData())
2145 ensureRareData().setIsRegisteredForVisibleInViewportCallback(registered);
2148 void RenderObject::setVisibleInViewportState(VisibleInViewportState visible)
2150 if (visible != VisibilityUnknown || hasRareData())
2151 ensureRareData().setVisibleInViewportState(visible);
2154 RenderObject::RareDataHash& RenderObject::rareDataMap()
2156 static NeverDestroyed<RareDataHash> map;
2160 RenderObject::RenderObjectRareData RenderObject::rareData() const
2163 return RenderObjectRareData();
2165 return rareDataMap().get(this);
2168 RenderObject::RenderObjectRareData& RenderObject::ensureRareData()
2170 setHasRareData(true);
2171 return rareDataMap().add(this, RenderObjectRareData()).iterator->value;
2174 void RenderObject::removeRareData()
2176 rareDataMap().remove(this);
2177 setHasRareData(false);
2180 #if ENABLE(TREE_DEBUGGING)
2182 void printRenderTreeForLiveDocuments()
2184 for (const auto* document : Document::allDocuments()) {
2185 if (!document->renderView() || document->inPageCache())
2187 if (document->frame() && document->frame()->isMainFrame())
2188 fprintf(stderr, "----------------------main frame--------------------------\n");
2189 fprintf(stderr, "%s", document->url().string().utf8().data());
2190 showRenderTree(document->renderView());
2194 void printLayerTreeForLiveDocuments()
2196 for (const auto* document : Document::allDocuments()) {
2197 if (!document->renderView() || document->inPageCache())
2199 if (document->frame() && document->frame()->isMainFrame())
2200 fprintf(stderr, "----------------------main frame--------------------------\n");
2201 fprintf(stderr, "%s", document->url().string().utf8().data());
2202 showLayerTree(document->renderView());
2206 #endif // ENABLE(TREE_DEBUGGING)
2208 } // namespace WebCore
2210 #if ENABLE(TREE_DEBUGGING)
2212 void showNodeTree(const WebCore::RenderObject* object)
2216 object->showNodeTreeForThis();
2219 void showLineTree(const WebCore::RenderObject* object)
2223 object->showLineTreeForThis();
2226 void showRenderTree(const WebCore::RenderObject* object)
2230 object->showRenderTreeForThis();