Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(437)

Side by Side Diff: Source/core/rendering/RenderObject.cpp

Issue 899163003: Move rendering/RenderObject to layout/LayoutObject. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/rendering/RenderObject.h ('k') | Source/core/rendering/RenderObjectChildList.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
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 Apple Inc. All rights reserv ed.
7 * Copyright (C) 2009 Google Inc. All rights reserved.
8 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo bile.com/)
9 *
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.
14 *
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.
19 *
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.
24 *
25 */
26
27 #include "config.h"
28 #include "core/rendering/RenderObject.h"
29
30 #include "core/HTMLNames.h"
31 #include "core/css/resolver/StyleResolver.h"
32 #include "core/dom/AXObjectCache.h"
33 #include "core/dom/ElementTraversal.h"
34 #include "core/dom/StyleEngine.h"
35 #include "core/dom/shadow/ShadowRoot.h"
36 #include "core/editing/EditingBoundary.h"
37 #include "core/editing/FrameSelection.h"
38 #include "core/editing/htmlediting.h"
39 #include "core/fetch/ResourceLoadPriorityOptimizer.h"
40 #include "core/fetch/ResourceLoader.h"
41 #include "core/frame/EventHandlerRegistry.h"
42 #include "core/frame/FrameView.h"
43 #include "core/frame/LocalFrame.h"
44 #include "core/frame/Settings.h"
45 #include "core/frame/UseCounter.h"
46 #include "core/html/HTMLAnchorElement.h"
47 #include "core/html/HTMLElement.h"
48 #include "core/html/HTMLHtmlElement.h"
49 #include "core/html/HTMLTableCellElement.h"
50 #include "core/html/HTMLTableElement.h"
51 #include "core/layout/HitTestResult.h"
52 #include "core/layout/Layer.h"
53 #include "core/layout/LayoutCounter.h"
54 #include "core/layout/LayoutTableCaption.h"
55 #include "core/layout/LayoutTableCell.h"
56 #include "core/layout/LayoutTableCol.h"
57 #include "core/layout/LayoutTableRow.h"
58 #include "core/layout/LayoutTheme.h"
59 #include "core/layout/compositing/CompositedLayerMapping.h"
60 #include "core/layout/compositing/LayerCompositor.h"
61 #include "core/page/AutoscrollController.h"
62 #include "core/page/EventHandler.h"
63 #include "core/page/Page.h"
64 #include "core/paint/ObjectPainter.h"
65 #include "core/rendering/RenderDeprecatedFlexibleBox.h"
66 #include "core/rendering/RenderFlexibleBox.h"
67 #include "core/rendering/RenderFlowThread.h"
68 #include "core/rendering/RenderGeometryMap.h"
69 #include "core/rendering/RenderGrid.h"
70 #include "core/rendering/RenderImage.h"
71 #include "core/rendering/RenderImageResourceStyleImage.h"
72 #include "core/rendering/RenderInline.h"
73 #include "core/rendering/RenderListItem.h"
74 #include "core/rendering/RenderMultiColumnSpannerPlaceholder.h"
75 #include "core/rendering/RenderObjectInlines.h"
76 #include "core/rendering/RenderPart.h"
77 #include "core/rendering/RenderScrollbarPart.h"
78 #include "core/rendering/RenderView.h"
79 #include "core/rendering/style/ContentData.h"
80 #include "core/rendering/style/ShadowList.h"
81 #include "platform/JSONValues.h"
82 #include "platform/Partitions.h"
83 #include "platform/RuntimeEnabledFeatures.h"
84 #include "platform/TraceEvent.h"
85 #include "platform/TracedValue.h"
86 #include "platform/geometry/TransformState.h"
87 #include "platform/graphics/GraphicsContext.h"
88 #include "platform/graphics/paint/DisplayItemList.h"
89 #include "wtf/RefCountedLeakCounter.h"
90 #include "wtf/text/StringBuilder.h"
91 #include "wtf/text/WTFString.h"
92 #include <algorithm>
93 #ifndef NDEBUG
94 #include <stdio.h>
95 #endif
96
97 namespace blink {
98
99 namespace {
100
101 static bool gModifyRenderTreeStructureAnyState = false;
102
103 } // namespace
104
105 using namespace HTMLNames;
106
107 #if ENABLE(ASSERT)
108
109 RenderObject::SetLayoutNeededForbiddenScope::SetLayoutNeededForbiddenScope(Rende rObject& renderObject)
110 : m_renderObject(renderObject)
111 , m_preexistingForbidden(m_renderObject.isSetNeedsLayoutForbidden())
112 {
113 m_renderObject.setNeedsLayoutIsForbidden(true);
114 }
115
116 RenderObject::SetLayoutNeededForbiddenScope::~SetLayoutNeededForbiddenScope()
117 {
118 m_renderObject.setNeedsLayoutIsForbidden(m_preexistingForbidden);
119 }
120 #endif
121
122 struct SameSizeAsRenderObject {
123 virtual ~SameSizeAsRenderObject() { } // Allocate vtable pointer.
124 void* pointers[5];
125 #if ENABLE(ASSERT)
126 unsigned m_debugBitfields : 2;
127 #endif
128 unsigned m_bitfields;
129 unsigned m_bitfields2;
130 LayoutRect rect; // Stores the previous paint invalidation rect.
131 LayoutPoint position; // Stores the previous position from the paint invalid ation container.
132 };
133
134 static_assert(sizeof(RenderObject) == sizeof(SameSizeAsRenderObject), "RenderObj ect should stay small");
135
136 bool RenderObject::s_affectsParentBlock = false;
137
138 typedef HashMap<const RenderObject*, LayoutRect> SelectionPaintInvalidationMap;
139 static SelectionPaintInvalidationMap* selectionPaintInvalidationMap = 0;
140
141 void* RenderObject::operator new(size_t sz)
142 {
143 ASSERT(isMainThread());
144 return partitionAlloc(Partitions::getRenderingPartition(), sz);
145 }
146
147 void RenderObject::operator delete(void* ptr)
148 {
149 ASSERT(isMainThread());
150 partitionFree(ptr);
151 }
152
153 RenderObject* RenderObject::createObject(Element* element, const RenderStyle& st yle)
154 {
155 ASSERT(isAllowedToModifyRenderTreeStructure(element->document()));
156
157 // Minimal support for content properties replacing an entire element.
158 // Works only if we have exactly one piece of content and it's a URL.
159 // Otherwise acts as if we didn't support this feature.
160 const ContentData* contentData = style.contentData();
161 if (contentData && !contentData->next() && contentData->isImage() && !elemen t->isPseudoElement()) {
162 RenderImage* image = new RenderImage(element);
163 // RenderImageResourceStyleImage requires a style being present on the i mage but we don't want to
164 // trigger a style change now as the node is not fully attached. Moving this code to style change
165 // doesn't make sense as it should be run once at renderer creation.
166 image->setStyleInternal(const_cast<RenderStyle*>(&style));
167 if (const StyleImage* styleImage = toImageContentData(contentData)->imag e()) {
168 image->setImageResource(RenderImageResourceStyleImage::create(const_ cast<StyleImage*>(styleImage)));
169 image->setIsGeneratedContent();
170 } else
171 image->setImageResource(RenderImageResource::create());
172 image->setStyleInternal(nullptr);
173 return image;
174 }
175
176 switch (style.display()) {
177 case NONE:
178 return 0;
179 case INLINE:
180 return new RenderInline(element);
181 case BLOCK:
182 case INLINE_BLOCK:
183 return new RenderBlockFlow(element);
184 case LIST_ITEM:
185 return new RenderListItem(element);
186 case TABLE:
187 case INLINE_TABLE:
188 return new LayoutTable(element);
189 case TABLE_ROW_GROUP:
190 case TABLE_HEADER_GROUP:
191 case TABLE_FOOTER_GROUP:
192 return new LayoutTableSection(element);
193 case TABLE_ROW:
194 return new LayoutTableRow(element);
195 case TABLE_COLUMN_GROUP:
196 case TABLE_COLUMN:
197 return new LayoutTableCol(element);
198 case TABLE_CELL:
199 return new LayoutTableCell(element);
200 case TABLE_CAPTION:
201 return new LayoutTableCaption(element);
202 case BOX:
203 case INLINE_BOX:
204 return new RenderDeprecatedFlexibleBox(*element);
205 case FLEX:
206 case INLINE_FLEX:
207 return new RenderFlexibleBox(element);
208 case GRID:
209 case INLINE_GRID:
210 return new RenderGrid(element);
211 }
212
213 return 0;
214 }
215
216 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, renderObjectCounter, ("Rend erObject"));
217 unsigned RenderObject::s_instanceCount = 0;
218
219 RenderObject::RenderObject(Node* node)
220 : ImageResourceClient()
221 , m_style(nullptr)
222 , m_node(node)
223 , m_parent(nullptr)
224 , m_previous(nullptr)
225 , m_next(nullptr)
226 #if ENABLE(ASSERT)
227 , m_hasAXObject(false)
228 , m_setNeedsLayoutForbidden(false)
229 #endif
230 , m_bitfields(node)
231 {
232 #ifndef NDEBUG
233 renderObjectCounter.increment();
234 #endif
235 ++s_instanceCount;
236 }
237
238 RenderObject::~RenderObject()
239 {
240 ASSERT(!m_hasAXObject);
241 #ifndef NDEBUG
242 renderObjectCounter.decrement();
243 #endif
244 --s_instanceCount;
245 }
246
247 String RenderObject::debugName() const
248 {
249 StringBuilder name;
250 name.append(renderName());
251
252 if (Node* node = this->node()) {
253 name.append(' ');
254 name.append(node->debugName());
255 }
256
257 return name.toString();
258 }
259
260 bool RenderObject::isDescendantOf(const RenderObject* obj) const
261 {
262 for (const RenderObject* r = this; r; r = r->m_parent) {
263 if (r == obj)
264 return true;
265 }
266 return false;
267 }
268
269 bool RenderObject::isHR() const
270 {
271 return isHTMLHRElement(node());
272 }
273
274 bool RenderObject::isLegend() const
275 {
276 return isHTMLLegendElement(node());
277 }
278
279 void RenderObject::setFlowThreadStateIncludingDescendants(FlowThreadState state)
280 {
281 for (RenderObject *object = this; object; object = object->nextInPreOrder(th is)) {
282 // If object is a fragmentation context it already updated the descendan ts flag accordingly.
283 if (object->isRenderFlowThread())
284 continue;
285 ASSERT(state != object->flowThreadState());
286 object->setFlowThreadState(state);
287 }
288 }
289
290 bool RenderObject::requiresAnonymousTableWrappers(const RenderObject* newChild) const
291 {
292 // Check should agree with:
293 // CSS 2.1 Tables: 17.2.1 Anonymous table objects
294 // http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes
295 if (newChild->isLayoutTableCol()) {
296 const LayoutTableCol* newTableColumn = toLayoutTableCol(newChild);
297 bool isColumnInColumnGroup = newTableColumn->isTableColumn() && isLayout TableCol();
298 return !isTable() && !isColumnInColumnGroup;
299 }
300 if (newChild->isTableCaption())
301 return !isTable();
302 if (newChild->isTableSection())
303 return !isTable();
304 if (newChild->isTableRow())
305 return !isTableSection();
306 if (newChild->isTableCell())
307 return !isTableRow();
308 return false;
309 }
310
311 void RenderObject::addChild(RenderObject* newChild, RenderObject* beforeChild)
312 {
313 ASSERT(isAllowedToModifyRenderTreeStructure(document()));
314
315 RenderObjectChildList* children = virtualChildren();
316 ASSERT(children);
317 if (!children)
318 return;
319
320 if (requiresAnonymousTableWrappers(newChild)) {
321 // Generate an anonymous table or reuse existing one from previous child
322 // Per: 17.2.1 Anonymous table objects 3. Generate missing parents
323 // http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes
324 LayoutTable* table;
325 RenderObject* afterChild = beforeChild ? beforeChild->previousSibling() : children->lastChild();
326 if (afterChild && afterChild->isAnonymous() && afterChild->isTable() && !afterChild->isBeforeContent())
327 table = toLayoutTable(afterChild);
328 else {
329 table = LayoutTable::createAnonymousWithParentRenderer(this);
330 addChild(table, beforeChild);
331 }
332 table->addChild(newChild);
333 } else
334 children->insertChildNode(this, newChild, beforeChild);
335
336 if (newChild->isText() && newChild->style()->textTransform() == CAPITALIZE)
337 toRenderText(newChild)->transformText();
338
339 // SVG creates renderers for <g display="none">, as SVG requires children of hidden
340 // <g>s to have renderers - at least that's how our implementation works. Co nsider:
341 // <g display="none"><foreignObject><body style="position: relative">FOO...
342 // - layerTypeRequired() would return true for the <body>, creating a new La yer
343 // - when the document is painted, both layers are painted. The <body> layer doesn't
344 // know that it's inside a "hidden SVG subtree", and thus paints, even if it shouldn't.
345 // To avoid the problem alltogether, detect early if we're inside a hidden S VG subtree
346 // and stop creating layers at all for these cases - they're not used anyway s.
347 if (newChild->hasLayer() && !layerCreationAllowedForSubtree())
348 toLayoutLayerModelObject(newChild)->layer()->removeOnlyThisLayer();
349 }
350
351 void RenderObject::removeChild(RenderObject* oldChild)
352 {
353 ASSERT(isAllowedToModifyRenderTreeStructure(document()));
354
355 RenderObjectChildList* children = virtualChildren();
356 ASSERT(children);
357 if (!children)
358 return;
359
360 children->removeChildNode(this, oldChild);
361 }
362
363 RenderObject* RenderObject::nextInPreOrder() const
364 {
365 if (RenderObject* o = slowFirstChild())
366 return o;
367
368 return nextInPreOrderAfterChildren();
369 }
370
371 RenderObject* RenderObject::nextInPreOrderAfterChildren() const
372 {
373 RenderObject* o = nextSibling();
374 if (!o) {
375 o = parent();
376 while (o && !o->nextSibling())
377 o = o->parent();
378 if (o)
379 o = o->nextSibling();
380 }
381
382 return o;
383 }
384
385 RenderObject* RenderObject::nextInPreOrder(const RenderObject* stayWithin) const
386 {
387 if (RenderObject* o = slowFirstChild())
388 return o;
389
390 return nextInPreOrderAfterChildren(stayWithin);
391 }
392
393 RenderObject* RenderObject::nextInPreOrderAfterChildren(const RenderObject* stay Within) const
394 {
395 if (this == stayWithin)
396 return 0;
397
398 const RenderObject* current = this;
399 RenderObject* next = current->nextSibling();
400 for (; !next; next = current->nextSibling()) {
401 current = current->parent();
402 if (!current || current == stayWithin)
403 return 0;
404 }
405 return next;
406 }
407
408 RenderObject* RenderObject::previousInPreOrder() const
409 {
410 if (RenderObject* o = previousSibling()) {
411 while (RenderObject* lastChild = o->slowLastChild())
412 o = lastChild;
413 return o;
414 }
415
416 return parent();
417 }
418
419 RenderObject* RenderObject::previousInPreOrder(const RenderObject* stayWithin) c onst
420 {
421 if (this == stayWithin)
422 return 0;
423
424 return previousInPreOrder();
425 }
426
427 RenderObject* RenderObject::childAt(unsigned index) const
428 {
429 RenderObject* child = slowFirstChild();
430 for (unsigned i = 0; child && i < index; i++)
431 child = child->nextSibling();
432 return child;
433 }
434
435 RenderObject* RenderObject::lastLeafChild() const
436 {
437 RenderObject* r = slowLastChild();
438 while (r) {
439 RenderObject* n = 0;
440 n = r->slowLastChild();
441 if (!n)
442 break;
443 r = n;
444 }
445 return r;
446 }
447
448 static void addLayers(RenderObject* obj, Layer* parentLayer, RenderObject*& newO bject,
449 Layer*& beforeChild)
450 {
451 if (obj->hasLayer()) {
452 if (!beforeChild && newObject) {
453 // We need to figure out the layer that follows newObject. We only d o
454 // this the first time we find a child layer, and then we update the
455 // pointer values for newObject and beforeChild used by everyone els e.
456 beforeChild = newObject->parent()->findNextLayer(parentLayer, newObj ect);
457 newObject = 0;
458 }
459 parentLayer->addChild(toLayoutLayerModelObject(obj)->layer(), beforeChil d);
460 return;
461 }
462
463 for (RenderObject* curr = obj->slowFirstChild(); curr; curr = curr->nextSibl ing())
464 addLayers(curr, parentLayer, newObject, beforeChild);
465 }
466
467 void RenderObject::addLayers(Layer* parentLayer)
468 {
469 if (!parentLayer)
470 return;
471
472 RenderObject* object = this;
473 Layer* beforeChild = 0;
474 blink::addLayers(this, parentLayer, object, beforeChild);
475 }
476
477 void RenderObject::removeLayers(Layer* parentLayer)
478 {
479 if (!parentLayer)
480 return;
481
482 if (hasLayer()) {
483 parentLayer->removeChild(toLayoutLayerModelObject(this)->layer());
484 return;
485 }
486
487 for (RenderObject* curr = slowFirstChild(); curr; curr = curr->nextSibling() )
488 curr->removeLayers(parentLayer);
489 }
490
491 void RenderObject::moveLayers(Layer* oldParent, Layer* newParent)
492 {
493 if (!newParent)
494 return;
495
496 if (hasLayer()) {
497 Layer* layer = toLayoutLayerModelObject(this)->layer();
498 ASSERT(oldParent == layer->parent());
499 if (oldParent)
500 oldParent->removeChild(layer);
501 newParent->addChild(layer);
502 return;
503 }
504
505 for (RenderObject* curr = slowFirstChild(); curr; curr = curr->nextSibling() )
506 curr->moveLayers(oldParent, newParent);
507 }
508
509 Layer* RenderObject::findNextLayer(Layer* parentLayer, RenderObject* startPoint,
510 bool checkParent)
511 {
512 // Error check the parent layer passed in. If it's null, we can't find anyth ing.
513 if (!parentLayer)
514 return 0;
515
516 // Step 1: If our layer is a child of the desired parent, then return our la yer.
517 Layer* ourLayer = hasLayer() ? toLayoutLayerModelObject(this)->layer() : 0;
518 if (ourLayer && ourLayer->parent() == parentLayer)
519 return ourLayer;
520
521 // Step 2: If we don't have a layer, or our layer is the desired parent, the n descend
522 // into our siblings trying to find the next layer whose parent is the desir ed parent.
523 if (!ourLayer || ourLayer == parentLayer) {
524 for (RenderObject* curr = startPoint ? startPoint->nextSibling() : slowF irstChild();
525 curr; curr = curr->nextSibling()) {
526 Layer* nextLayer = curr->findNextLayer(parentLayer, 0, false);
527 if (nextLayer)
528 return nextLayer;
529 }
530 }
531
532 // Step 3: If our layer is the desired parent layer, then we're finished. We didn't
533 // find anything.
534 if (parentLayer == ourLayer)
535 return 0;
536
537 // Step 4: If |checkParent| is set, climb up to our parent and check its sib lings that
538 // follow us to see if we can locate a layer.
539 if (checkParent && parent())
540 return parent()->findNextLayer(parentLayer, this, true);
541
542 return 0;
543 }
544
545 Layer* RenderObject::enclosingLayer() const
546 {
547 for (const RenderObject* current = this; current; current = current->parent( )) {
548 if (current->hasLayer())
549 return toLayoutLayerModelObject(current)->layer();
550 }
551 // FIXME: we should get rid of detached render subtrees, at which point this code should
552 // not be reached. crbug.com/411429
553 return 0;
554 }
555
556 bool RenderObject::scrollRectToVisible(const LayoutRect& rect, const ScrollAlign ment& alignX, const ScrollAlignment& alignY)
557 {
558 RenderBox* enclosingBox = this->enclosingBox();
559 if (!enclosingBox)
560 return false;
561
562 enclosingBox->scrollRectToVisible(rect, alignX, alignY);
563 return true;
564 }
565
566 RenderBox* RenderObject::enclosingBox() const
567 {
568 RenderObject* curr = const_cast<RenderObject*>(this);
569 while (curr) {
570 if (curr->isBox())
571 return toRenderBox(curr);
572 curr = curr->parent();
573 }
574
575 ASSERT_NOT_REACHED();
576 return 0;
577 }
578
579 RenderBoxModelObject* RenderObject::enclosingBoxModelObject() const
580 {
581 RenderObject* curr = const_cast<RenderObject*>(this);
582 while (curr) {
583 if (curr->isBoxModelObject())
584 return toRenderBoxModelObject(curr);
585 curr = curr->parent();
586 }
587
588 ASSERT_NOT_REACHED();
589 return 0;
590 }
591
592 RenderBox* RenderObject::enclosingScrollableBox() const
593 {
594 for (RenderObject* ancestor = parent(); ancestor; ancestor = ancestor->paren t()) {
595 if (!ancestor->isBox())
596 continue;
597
598 RenderBox* ancestorBox = toRenderBox(ancestor);
599 if (ancestorBox->canBeScrolledAndHasScrollableArea())
600 return ancestorBox;
601 }
602
603 return 0;
604 }
605
606 RenderFlowThread* RenderObject::locateFlowThreadContainingBlock() const
607 {
608 ASSERT(flowThreadState() != NotInsideFlowThread);
609
610 // See if we have the thread cached because we're in the middle of layout.
611 if (LayoutState* layoutState = view()->layoutState()) {
612 if (RenderFlowThread* flowThread = layoutState->flowThread())
613 return flowThread;
614 }
615
616 // Not in the middle of layout so have to find the thread the slow way.
617 RenderObject* curr = const_cast<RenderObject*>(this);
618 while (curr) {
619 if (curr->isRenderFlowThread())
620 return toRenderFlowThread(curr);
621 curr = curr->containingBlock();
622 }
623 return 0;
624 }
625
626 bool RenderObject::skipInvalidationWhenLaidOutChildren() const
627 {
628 if (!neededLayoutBecauseOfChildren())
629 return false;
630
631 // SVG renderers need to be invalidated when their children are laid out.
632 // RenderBlocks with line boxes are responsible to invalidate them so we can 't ignore them.
633 if (isSVG() || (isRenderBlockFlow() && toRenderBlockFlow(this)->firstLineBox ()))
634 return false;
635
636 return rendererHasNoBoxEffect();
637 }
638
639 RenderBlock* RenderObject::firstLineBlock() const
640 {
641 return 0;
642 }
643
644 static inline bool objectIsRelayoutBoundary(const RenderObject* object)
645 {
646 // FIXME: In future it may be possible to broaden these conditions in order to improve performance.
647 if (object->isTextControl())
648 return true;
649
650 if (object->isSVGRoot())
651 return true;
652
653 if (!object->hasOverflowClip())
654 return false;
655
656 if (object->style()->width().isIntrinsicOrAuto() || object->style()->height( ).isIntrinsicOrAuto() || object->style()->height().isPercent())
657 return false;
658
659 // Table parts can't be relayout roots since the table is responsible for la youting all the parts.
660 if (object->isTablePart())
661 return false;
662
663 return true;
664 }
665
666 void RenderObject::markContainingBlocksForLayout(bool scheduleRelayout, RenderOb ject* newRoot, SubtreeLayoutScope* layouter)
667 {
668 ASSERT(!scheduleRelayout || !newRoot);
669 ASSERT(!isSetNeedsLayoutForbidden());
670 ASSERT(!layouter || this != layouter->root());
671
672 RenderObject* object = container();
673 RenderObject* last = this;
674
675 bool simplifiedNormalFlowLayout = needsSimplifiedNormalFlowLayout() && !self NeedsLayout() && !normalChildNeedsLayout();
676
677 while (object) {
678 if (object->selfNeedsLayout())
679 return;
680
681 // Don't mark the outermost object of an unrooted subtree. That object w ill be
682 // marked when the subtree is added to the document.
683 RenderObject* container = object->container();
684 if (!container && !object->isRenderView())
685 return;
686 if (!last->isText() && last->style()->hasOutOfFlowPosition()) {
687 bool willSkipRelativelyPositionedInlines = !object->isRenderBlock() || object->isAnonymousBlock();
688 // Skip relatively positioned inlines and anonymous blocks to get to the enclosing RenderBlock.
689 while (object && (!object->isRenderBlock() || object->isAnonymousBlo ck()))
690 object = object->container();
691 if (!object || object->posChildNeedsLayout())
692 return;
693 if (willSkipRelativelyPositionedInlines)
694 container = object->container();
695 object->setPosChildNeedsLayout(true);
696 simplifiedNormalFlowLayout = true;
697 ASSERT(!object->isSetNeedsLayoutForbidden());
698 } else if (simplifiedNormalFlowLayout) {
699 if (object->needsSimplifiedNormalFlowLayout())
700 return;
701 object->setNeedsSimplifiedNormalFlowLayout(true);
702 ASSERT(!object->isSetNeedsLayoutForbidden());
703 } else {
704 if (object->normalChildNeedsLayout())
705 return;
706 object->setNormalChildNeedsLayout(true);
707 ASSERT(!object->isSetNeedsLayoutForbidden());
708 }
709
710 if (layouter) {
711 layouter->addRendererToLayout(object);
712 if (object == layouter->root())
713 return;
714 }
715
716 if (object == newRoot)
717 return;
718
719 last = object;
720 if (scheduleRelayout && objectIsRelayoutBoundary(last))
721 break;
722 object = container;
723 }
724
725 if (scheduleRelayout)
726 last->scheduleRelayout();
727 }
728
729 #if ENABLE(ASSERT)
730 void RenderObject::checkBlockPositionedObjectsNeedLayout()
731 {
732 ASSERT(!needsLayout());
733
734 if (isRenderBlock())
735 toRenderBlock(this)->checkPositionedObjectsNeedLayout();
736 }
737 #endif
738
739 void RenderObject::setPreferredLogicalWidthsDirty(MarkingBehavior markParents)
740 {
741 m_bitfields.setPreferredLogicalWidthsDirty(true);
742 if (markParents == MarkContainingBlockChain && (isText() || !style()->hasOut OfFlowPosition()))
743 invalidateContainerPreferredLogicalWidths();
744 }
745
746 void RenderObject::clearPreferredLogicalWidthsDirty()
747 {
748 m_bitfields.setPreferredLogicalWidthsDirty(false);
749 }
750
751 void RenderObject::invalidateContainerPreferredLogicalWidths()
752 {
753 // In order to avoid pathological behavior when inlines are deeply nested, w e do include them
754 // in the chain that we mark dirty (even though they're kind of irrelevant).
755 RenderObject* o = isTableCell() ? containingBlock() : container();
756 while (o && !o->preferredLogicalWidthsDirty()) {
757 // Don't invalidate the outermost object of an unrooted subtree. That ob ject will be
758 // invalidated when the subtree is added to the document.
759 RenderObject* container = o->isTableCell() ? o->containingBlock() : o->c ontainer();
760 if (!container && !o->isRenderView())
761 break;
762
763 o->m_bitfields.setPreferredLogicalWidthsDirty(true);
764 if (o->style()->hasOutOfFlowPosition())
765 // A positioned object has no effect on the min/max width of its con taining block ever.
766 // We can optimize this case and not go up any further.
767 break;
768 o = container;
769 }
770 }
771
772 RenderBlock* RenderObject::containerForFixedPosition(const LayoutLayerModelObjec t* paintInvalidationContainer, bool* paintInvalidationContainerSkipped) const
773 {
774 ASSERT(!paintInvalidationContainerSkipped || !*paintInvalidationContainerSki pped);
775 ASSERT(!isText());
776 ASSERT(style()->position() == FixedPosition);
777
778 RenderObject* ancestor = parent();
779 for (; ancestor && !ancestor->canContainFixedPositionObjects(); ancestor = a ncestor->parent()) {
780 if (paintInvalidationContainerSkipped && ancestor == paintInvalidationCo ntainer)
781 *paintInvalidationContainerSkipped = true;
782 }
783
784 ASSERT(!ancestor || !ancestor->isAnonymousBlock());
785 return toRenderBlock(ancestor);
786 }
787
788 RenderBlock* RenderObject::containingBlock() const
789 {
790 RenderObject* o = parent();
791 if (!o && isRenderScrollbarPart())
792 o = toRenderScrollbarPart(this)->rendererOwningScrollbar();
793 if (!isText() && m_style->position() == FixedPosition) {
794 return containerForFixedPosition();
795 } else if (!isText() && m_style->position() == AbsolutePosition) {
796 while (o) {
797 // For relpositioned inlines, we return the nearest non-anonymous en closing block. We don't try
798 // to return the inline itself. This allows us to avoid having a po sitioned objects
799 // list in all RenderInlines and lets us return a strongly-typed Ren derBlock* result
800 // from this method. The container() method can actually be used to obtain the
801 // inline directly.
802 if (o->style()->position() != StaticPosition && (!o->isInline() || o ->isReplaced()))
803 break;
804
805 if (o->canContainFixedPositionObjects())
806 break;
807
808 if (o->style()->hasInFlowPosition() && o->isInline() && !o->isReplac ed()) {
809 o = o->containingBlock();
810 break;
811 }
812
813 o = o->parent();
814 }
815
816 if (o && !o->isRenderBlock())
817 o = o->containingBlock();
818
819 while (o && o->isAnonymousBlock())
820 o = o->containingBlock();
821 } else if (isColumnSpanAll()) {
822 o = spannerPlaceholder()->containingBlock();
823 } else {
824 while (o && ((o->isInline() && !o->isReplaced()) || !o->isRenderBlock()) )
825 o = o->parent();
826 }
827
828 if (!o || !o->isRenderBlock())
829 return 0; // This can still happen in case of an orphaned tree
830
831 return toRenderBlock(o);
832 }
833
834 bool RenderObject::canRenderBorderImage() const
835 {
836 if (!style()->hasBorder())
837 return false;
838
839 StyleImage* borderImage = style()->borderImage().image();
840 return borderImage && borderImage->canRender(*this, style()->effectiveZoom() ) && borderImage->isLoaded();
841 }
842
843 bool RenderObject::mustInvalidateFillLayersPaintOnWidthChange(const FillLayer& l ayer) const
844 {
845 // Nobody will use multiple layers without wanting fancy positioning.
846 if (layer.next())
847 return true;
848
849 // Make sure we have a valid image.
850 StyleImage* img = layer.image();
851 if (!img || !img->canRender(*this, style()->effectiveZoom()))
852 return false;
853
854 if (layer.repeatX() != RepeatFill && layer.repeatX() != NoRepeatFill)
855 return true;
856
857 if (layer.xPosition().isPercent() && !layer.xPosition().isZero())
858 return true;
859
860 if (layer.backgroundXOrigin() != LeftEdge)
861 return true;
862
863 EFillSizeType sizeType = layer.sizeType();
864
865 if (sizeType == Contain || sizeType == Cover)
866 return true;
867
868 if (sizeType == SizeLength) {
869 if (layer.sizeLength().width().isPercent() && !layer.sizeLength().width( ).isZero())
870 return true;
871 if (img->isGeneratedImage() && layer.sizeLength().width().isAuto())
872 return true;
873 } else if (img->usesImageContainerSize()) {
874 return true;
875 }
876
877 return false;
878 }
879
880 bool RenderObject::mustInvalidateFillLayersPaintOnHeightChange(const FillLayer& layer) const
881 {
882 // Nobody will use multiple layers without wanting fancy positioning.
883 if (layer.next())
884 return true;
885
886 // Make sure we have a valid image.
887 StyleImage* img = layer.image();
888 if (!img || !img->canRender(*this, style()->effectiveZoom()))
889 return false;
890
891 if (layer.repeatY() != RepeatFill && layer.repeatY() != NoRepeatFill)
892 return true;
893
894 if (layer.yPosition().isPercent() && !layer.yPosition().isZero())
895 return true;
896
897 if (layer.backgroundYOrigin() != TopEdge)
898 return true;
899
900 EFillSizeType sizeType = layer.sizeType();
901
902 if (sizeType == Contain || sizeType == Cover)
903 return true;
904
905 if (sizeType == SizeLength) {
906 if (layer.sizeLength().height().isPercent() && !layer.sizeLength().heigh t().isZero())
907 return true;
908 if (img->isGeneratedImage() && layer.sizeLength().height().isAuto())
909 return true;
910 } else if (img->usesImageContainerSize()) {
911 return true;
912 }
913
914 return false;
915 }
916
917 bool RenderObject::mustInvalidateBackgroundOrBorderPaintOnWidthChange() const
918 {
919 if (hasMask() && mustInvalidateFillLayersPaintOnWidthChange(style()->maskLay ers()))
920 return true;
921
922 // If we don't have a background/border/mask, then nothing to do.
923 if (!hasBoxDecorationBackground())
924 return false;
925
926 if (mustInvalidateFillLayersPaintOnWidthChange(style()->backgroundLayers()))
927 return true;
928
929 // Our fill layers are ok. Let's check border.
930 if (style()->hasBorder() && canRenderBorderImage())
931 return true;
932
933 return false;
934 }
935
936 bool RenderObject::mustInvalidateBackgroundOrBorderPaintOnHeightChange() const
937 {
938 if (hasMask() && mustInvalidateFillLayersPaintOnHeightChange(style()->maskLa yers()))
939 return true;
940
941 // If we don't have a background/border/mask, then nothing to do.
942 if (!hasBoxDecorationBackground())
943 return false;
944
945 if (mustInvalidateFillLayersPaintOnHeightChange(style()->backgroundLayers()) )
946 return true;
947
948 // Our fill layers are ok. Let's check border.
949 if (style()->hasBorder() && canRenderBorderImage())
950 return true;
951
952 return false;
953 }
954
955 IntRect RenderObject::absoluteBoundingBoxRect() const
956 {
957 Vector<FloatQuad> quads;
958 absoluteQuads(quads);
959
960 size_t n = quads.size();
961 if (!n)
962 return IntRect();
963
964 IntRect result = quads[0].enclosingBoundingBox();
965 for (size_t i = 1; i < n; ++i)
966 result.unite(quads[i].enclosingBoundingBox());
967 return result;
968 }
969
970 IntRect RenderObject::absoluteBoundingBoxRectIgnoringTransforms() const
971 {
972 FloatPoint absPos = localToAbsolute();
973 Vector<IntRect> rects;
974 absoluteRects(rects, flooredLayoutPoint(absPos));
975
976 size_t n = rects.size();
977 if (!n)
978 return IntRect();
979
980 LayoutRect result = rects[0];
981 for (size_t i = 1; i < n; ++i)
982 result.unite(rects[i]);
983 return pixelSnappedIntRect(result);
984 }
985
986 IntRect RenderObject::absoluteFocusRingBoundingBoxRect() const
987 {
988 Vector<LayoutRect> rects;
989 const LayoutLayerModelObject* container = enclosingLayer()->renderer();
990 addFocusRingRects(rects, LayoutPoint(localToContainerPoint(FloatPoint(), con tainer)));
991 return container->localToAbsoluteQuad(FloatQuad(unionRect(rects))).enclosing BoundingBox();
992 }
993
994 FloatRect RenderObject::absoluteBoundingBoxRectForRange(const Range* range)
995 {
996 if (!range || !range->startContainer())
997 return FloatRect();
998
999 range->ownerDocument().updateLayout();
1000
1001 Vector<FloatQuad> quads;
1002 range->textQuads(quads);
1003
1004 FloatRect result;
1005 for (size_t i = 0; i < quads.size(); ++i)
1006 result.unite(quads[i].boundingBox());
1007
1008 return result;
1009 }
1010
1011 void RenderObject::addAbsoluteRectForLayer(LayoutRect& result)
1012 {
1013 if (hasLayer())
1014 result.unite(absoluteBoundingBoxRect());
1015 for (RenderObject* current = slowFirstChild(); current; current = current->n extSibling())
1016 current->addAbsoluteRectForLayer(result);
1017 }
1018
1019 LayoutRect RenderObject::paintingRootRect(LayoutRect& topLevelRect)
1020 {
1021 LayoutRect result = absoluteBoundingBoxRect();
1022 topLevelRect = result;
1023 for (RenderObject* current = slowFirstChild(); current; current = current->n extSibling())
1024 current->addAbsoluteRectForLayer(result);
1025 return result;
1026 }
1027
1028 void RenderObject::paint(const PaintInfo&, const LayoutPoint&)
1029 {
1030 }
1031
1032 const LayoutLayerModelObject* RenderObject::containerForPaintInvalidation() cons t
1033 {
1034 RELEASE_ASSERT(isRooted());
1035 return adjustCompositedContainerForSpecialAncestors(enclosingCompositedConta iner());
1036 }
1037
1038 const LayoutLayerModelObject* RenderObject::enclosingCompositedContainer() const
1039 {
1040 LayoutLayerModelObject* container = 0;
1041 // FIXME: CompositingState is not necessarily up to date for many callers of this function.
1042 DisableCompositingQueryAsserts disabler;
1043
1044 if (Layer* compositingLayer = enclosingLayer()->enclosingLayerForPaintInvali dationCrossingFrameBoundaries())
1045 container = compositingLayer->renderer();
1046 return container;
1047 }
1048
1049 const LayoutLayerModelObject* RenderObject::adjustCompositedContainerForSpecialA ncestors(const LayoutLayerModelObject* paintInvalidationContainer) const
1050 {
1051 if (paintInvalidationContainer)
1052 return paintInvalidationContainer;
1053
1054 RenderView* renderView = view();
1055 while (renderView->frame()->ownerRenderer())
1056 renderView = renderView->frame()->ownerRenderer()->view();
1057 return renderView;
1058 }
1059
1060 bool RenderObject::isPaintInvalidationContainer() const
1061 {
1062 return hasLayer() && toLayoutLayerModelObject(this)->layer()->isPaintInvalid ationContainer();
1063 }
1064
1065 template <typename T>
1066 void addJsonObjectForRect(TracedValue* value, const char* name, const T& rect)
1067 {
1068 value->beginDictionary(name);
1069 value->setDouble("x", rect.x());
1070 value->setDouble("y", rect.y());
1071 value->setDouble("width", rect.width());
1072 value->setDouble("height", rect.height());
1073 value->endDictionary();
1074 }
1075
1076 template <typename T>
1077 void addJsonObjectForPoint(TracedValue* value, const char* name, const T& point)
1078 {
1079 value->beginDictionary(name);
1080 value->setDouble("x", point.x());
1081 value->setDouble("y", point.y());
1082 value->endDictionary();
1083 }
1084
1085 static PassRefPtr<TraceEvent::ConvertableToTraceFormat> jsonObjectForPaintInvali dationInfo(const LayoutRect& rect, const String& invalidationReason)
1086 {
1087 RefPtr<TracedValue> value = TracedValue::create();
1088 addJsonObjectForRect(value.get(), "rect", rect);
1089 value->setString("invalidation_reason", invalidationReason);
1090 return value;
1091 }
1092
1093 LayoutRect RenderObject::computePaintInvalidationRect(const LayoutLayerModelObje ct* paintInvalidationContainer, const PaintInvalidationState* paintInvalidationS tate) const
1094 {
1095 return clippedOverflowRectForPaintInvalidation(paintInvalidationContainer, p aintInvalidationState);
1096 }
1097
1098 void RenderObject::invalidatePaintUsingContainer(const LayoutLayerModelObject* p aintInvalidationContainer, const LayoutRect& r, PaintInvalidationReason invalida tionReason) const
1099 {
1100 if (r.isEmpty())
1101 return;
1102
1103 if (RuntimeEnabledFeatures::slimmingPaintEnabled()) {
1104 if (Layer* container = enclosingLayer()->enclosingLayerForPaintInvalidat ionCrossingFrameBoundaries())
1105 invalidateDisplayItemClients(container->graphicsLayerBacking()->disp layItemList());
1106 }
1107
1108 RELEASE_ASSERT(isRooted());
1109
1110 // FIXME: Unify "devtools.timeline.invalidationTracking" and "blink.invalida tion". crbug.com/413527.
1111 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.invalidati onTracking"),
1112 "PaintInvalidationTracking",
1113 "data", InspectorPaintInvalidationTrackingEvent::data(this, paintInvalid ationContainer));
1114 TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("blink.invalidation"), "RenderObject: :invalidatePaintUsingContainer()",
1115 "object", this->debugName().ascii(),
1116 "info", jsonObjectForPaintInvalidationInfo(r, paintInvalidationReasonToS tring(invalidationReason)));
1117
1118 if (paintInvalidationContainer->isRenderView()) {
1119 toRenderView(paintInvalidationContainer)->invalidatePaintForRectangle(r, invalidationReason);
1120 return;
1121 }
1122
1123 if (paintInvalidationContainer->view()->usesCompositing()) {
1124 ASSERT(paintInvalidationContainer->isPaintInvalidationContainer());
1125 paintInvalidationContainer->setBackingNeedsPaintInvalidationInRect(r, in validationReason);
1126 }
1127 }
1128
1129 void RenderObject::invalidateDisplayItemClients(DisplayItemList* displayItemList ) const
1130 {
1131 displayItemList->invalidate(displayItemClient());
1132 }
1133
1134 LayoutRect RenderObject::boundsRectForPaintInvalidation(const LayoutLayerModelOb ject* paintInvalidationContainer, const PaintInvalidationState* paintInvalidatio nState) const
1135 {
1136 if (!paintInvalidationContainer)
1137 return computePaintInvalidationRect(paintInvalidationContainer, paintInv alidationState);
1138 return Layer::computePaintInvalidationRect(this, paintInvalidationContainer- >layer(), paintInvalidationState);
1139 }
1140
1141 void RenderObject::invalidatePaintRectangle(const LayoutRect& r) const
1142 {
1143 RELEASE_ASSERT(isRooted());
1144
1145 if (view()->document().printing())
1146 return; // Don't invalidate paints if we're printing.
1147
1148 LayoutRect dirtyRect(r);
1149
1150 const LayoutLayerModelObject* paintInvalidationContainer = containerForPaint Invalidation();
1151 Layer::mapRectToPaintInvalidationBacking(this, paintInvalidationContainer, d irtyRect);
1152 invalidatePaintUsingContainer(paintInvalidationContainer, dirtyRect, PaintIn validationRectangle);
1153 }
1154
1155 void RenderObject::invalidateTreeIfNeeded(const PaintInvalidationState& paintInv alidationState)
1156 {
1157 ASSERT(!needsLayout());
1158
1159 // If we didn't need paint invalidation then our children don't need as well .
1160 // Skip walking down the tree as everything should be fine below us.
1161 if (!shouldCheckForPaintInvalidation(paintInvalidationState))
1162 return;
1163
1164 invalidatePaintIfNeeded(paintInvalidationState, paintInvalidationState.paint InvalidationContainer());
1165 clearPaintInvalidationState(paintInvalidationState);
1166 invalidatePaintOfSubtreesIfNeeded(paintInvalidationState);
1167 }
1168
1169 void RenderObject::invalidatePaintOfSubtreesIfNeeded(const PaintInvalidationStat e& childPaintInvalidationState)
1170 {
1171 for (RenderObject* child = slowFirstChild(); child; child = child->nextSibli ng()) {
1172 if (!child->isOutOfFlowPositioned())
1173 child->invalidateTreeIfNeeded(childPaintInvalidationState);
1174 }
1175 }
1176
1177 static PassRefPtr<TraceEvent::ConvertableToTraceFormat> jsonObjectForOldAndNewRe cts(const LayoutRect& oldRect, const LayoutPoint& oldLocation, const LayoutRect& newRect, const LayoutPoint& newLocation)
1178 {
1179 RefPtr<TracedValue> value = TracedValue::create();
1180 addJsonObjectForRect(value.get(), "oldRect", oldRect);
1181 addJsonObjectForPoint(value.get(), "oldLocation", oldLocation);
1182 addJsonObjectForRect(value.get(), "newRect", newRect);
1183 addJsonObjectForPoint(value.get(), "newLocation", newLocation);
1184 return value;
1185 }
1186
1187 LayoutRect RenderObject::previousSelectionRectForPaintInvalidation() const
1188 {
1189 if (!selectionPaintInvalidationMap)
1190 return LayoutRect();
1191
1192 return selectionPaintInvalidationMap->get(this);
1193 }
1194
1195 void RenderObject::setPreviousSelectionRectForPaintInvalidation(const LayoutRect & selectionRect)
1196 {
1197 if (!selectionPaintInvalidationMap) {
1198 if (selectionRect.isEmpty())
1199 return;
1200 selectionPaintInvalidationMap = new SelectionPaintInvalidationMap();
1201 }
1202
1203 if (selectionRect.isEmpty())
1204 selectionPaintInvalidationMap->remove(this);
1205 else
1206 selectionPaintInvalidationMap->set(this, selectionRect);
1207 }
1208
1209 void RenderObject::invalidateSelectionIfNeeded(const LayoutLayerModelObject& pai ntInvalidationContainer, PaintInvalidationReason invalidationReason)
1210 {
1211 // Update selection rect when we are doing full invalidation (in case that t he object is moved, composite status changed, etc.)
1212 // or shouldInvalidationSelection is set (in case that the selection itself changed).
1213 bool fullInvalidation = view()->doingFullPaintInvalidation() || isFullPaintI nvalidationReason(invalidationReason);
1214 if (!fullInvalidation && !shouldInvalidateSelection())
1215 return;
1216
1217 LayoutRect oldSelectionRect = previousSelectionRectForPaintInvalidation();
1218 LayoutRect newSelectionRect = selectionRectForPaintInvalidation(&paintInvali dationContainer);
1219 setPreviousSelectionRectForPaintInvalidation(newSelectionRect);
1220
1221 if (fullInvalidation)
1222 return;
1223
1224 fullyInvalidatePaint(paintInvalidationContainer, PaintInvalidationSelection, oldSelectionRect, newSelectionRect);
1225 }
1226
1227 PaintInvalidationReason RenderObject::invalidatePaintIfNeeded(const PaintInvalid ationState& paintInvalidationState, const LayoutLayerModelObject& paintInvalidat ionContainer)
1228 {
1229 RenderView* v = view();
1230 if (v->document().printing())
1231 return PaintInvalidationNone; // Don't invalidate paints if we're printi ng.
1232
1233 const LayoutRect oldBounds = previousPaintInvalidationRect();
1234 const LayoutPoint oldLocation = previousPositionFromPaintInvalidationBacking ();
1235 const LayoutRect newBounds = boundsRectForPaintInvalidation(&paintInvalidati onContainer, &paintInvalidationState);
1236 const LayoutPoint newLocation = Layer::positionFromPaintInvalidationBacking( this, &paintInvalidationContainer, &paintInvalidationState);
1237 setPreviousPaintInvalidationRect(newBounds);
1238 setPreviousPositionFromPaintInvalidationBacking(newLocation);
1239
1240 PaintInvalidationReason invalidationReason = paintInvalidationReason(paintIn validationContainer, oldBounds, oldLocation, newBounds, newLocation);
1241
1242 // We need to invalidate the selection before checking for whether we are do ing a full invalidation.
1243 // This is because we need to update the old rect regardless.
1244 invalidateSelectionIfNeeded(paintInvalidationContainer, invalidationReason);
1245
1246 // If we are set to do a full paint invalidation that means the RenderView w ill issue
1247 // paint invalidations. We can then skip issuing of paint invalidations for the child
1248 // renderers as they'll be covered by the RenderView.
1249 if (view()->doingFullPaintInvalidation())
1250 return invalidationReason;
1251
1252 TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("blink.invalidation"), "RenderObject: :invalidatePaintIfNeeded()",
1253 "object", this->debugName().ascii(),
1254 "info", jsonObjectForOldAndNewRects(oldBounds, oldLocation, newBounds, n ewLocation));
1255
1256 if (invalidationReason == PaintInvalidationNone)
1257 return invalidationReason;
1258
1259 if (invalidationReason == PaintInvalidationIncremental) {
1260 incrementallyInvalidatePaint(paintInvalidationContainer, oldBounds, newB ounds, newLocation);
1261 return invalidationReason;
1262 }
1263
1264 fullyInvalidatePaint(paintInvalidationContainer, invalidationReason, oldBoun ds, newBounds);
1265 return invalidationReason;
1266 }
1267
1268 PaintInvalidationReason RenderObject::paintInvalidationReason(const LayoutLayerM odelObject& paintInvalidationContainer,
1269 const LayoutRect& oldBounds, const LayoutPoint& oldPositionFromPaintInvalida tionBacking,
1270 const LayoutRect& newBounds, const LayoutPoint& newPositionFromPaintInvalida tionBacking) const
1271 {
1272 // First check for InvalidationLocationChange to avoid it from being hidden by other
1273 // invalidation reasons because we'll need to force check for paint invalida tion for
1274 // children when location of this object changed.
1275 if (newPositionFromPaintInvalidationBacking != oldPositionFromPaintInvalidat ionBacking)
1276 return PaintInvalidationLocationChange;
1277
1278 if (shouldDoFullPaintInvalidation())
1279 return m_bitfields.fullPaintInvalidationReason();
1280
1281 // If the bounds are the same then we know that none of the statements below
1282 // can match, so we can early out since we will not need to do any
1283 // invalidation.
1284 if (oldBounds == newBounds)
1285 return PaintInvalidationNone;
1286
1287 // If we shifted, we don't know the exact reason so we are conservative and trigger a full invalidation. Shifting could
1288 // be caused by some layout property (left / top) or some in-flow renderer i nserted / removed before us in the tree.
1289 if (newBounds.location() != oldBounds.location())
1290 return PaintInvalidationBoundsChange;
1291
1292 // This covers the case where we mark containing blocks for layout
1293 // and they change size but don't have anything to paint. This is
1294 // a pretty common case for <body> as we add / remove children
1295 // (and the default background is done by FrameView).
1296 if (skipInvalidationWhenLaidOutChildren())
1297 return PaintInvalidationNone;
1298
1299 // If the size is zero on one of our bounds then we know we're going to have
1300 // to do a full invalidation of either old bounds or new bounds. If we fall
1301 // into the incremental invalidation we'll issue two invalidations instead
1302 // of one.
1303 if (oldBounds.isEmpty())
1304 return PaintInvalidationBecameVisible;
1305 if (newBounds.isEmpty())
1306 return PaintInvalidationBecameInvisible;
1307
1308 return PaintInvalidationIncremental;
1309 }
1310
1311 void RenderObject::incrementallyInvalidatePaint(const LayoutLayerModelObject& pa intInvalidationContainer, const LayoutRect& oldBounds, const LayoutRect& newBoun ds, const LayoutPoint& positionFromPaintInvalidationBacking)
1312 {
1313 ASSERT(oldBounds.location() == newBounds.location());
1314
1315 LayoutUnit deltaRight = newBounds.maxX() - oldBounds.maxX();
1316 if (deltaRight > 0)
1317 invalidatePaintUsingContainer(&paintInvalidationContainer, LayoutRect(ol dBounds.maxX(), newBounds.y(), deltaRight, newBounds.height()), PaintInvalidatio nIncremental);
1318 else if (deltaRight < 0)
1319 invalidatePaintUsingContainer(&paintInvalidationContainer, LayoutRect(ne wBounds.maxX(), oldBounds.y(), -deltaRight, oldBounds.height()), PaintInvalidati onIncremental);
1320
1321 LayoutUnit deltaBottom = newBounds.maxY() - oldBounds.maxY();
1322 if (deltaBottom > 0)
1323 invalidatePaintUsingContainer(&paintInvalidationContainer, LayoutRect(ne wBounds.x(), oldBounds.maxY(), newBounds.width(), deltaBottom), PaintInvalidatio nIncremental);
1324 else if (deltaBottom < 0)
1325 invalidatePaintUsingContainer(&paintInvalidationContainer, LayoutRect(ol dBounds.x(), newBounds.maxY(), oldBounds.width(), -deltaBottom), PaintInvalidati onIncremental);
1326 }
1327
1328 void RenderObject::fullyInvalidatePaint(const LayoutLayerModelObject& paintInval idationContainer, PaintInvalidationReason invalidationReason, const LayoutRect& oldBounds, const LayoutRect& newBounds)
1329 {
1330 // Otherwise do full paint invalidation.
1331 invalidatePaintUsingContainer(&paintInvalidationContainer, oldBounds, invali dationReason);
1332 if (newBounds != oldBounds)
1333 invalidatePaintUsingContainer(&paintInvalidationContainer, newBounds, in validationReason);
1334 }
1335
1336 void RenderObject::invalidatePaintForOverflow()
1337 {
1338 }
1339
1340 void RenderObject::invalidatePaintForOverflowIfNeeded()
1341 {
1342 if (shouldInvalidateOverflowForPaint())
1343 invalidatePaintForOverflow();
1344 }
1345
1346 LayoutRect RenderObject::rectWithOutlineForPaintInvalidation(const LayoutLayerMo delObject* paintInvalidationContainer, LayoutUnit outlineWidth, const PaintInval idationState* paintInvalidationState) const
1347 {
1348 LayoutRect r(clippedOverflowRectForPaintInvalidation(paintInvalidationContai ner, paintInvalidationState));
1349 r.inflate(outlineWidth);
1350 return r;
1351 }
1352
1353 LayoutRect RenderObject::absoluteClippedOverflowRect() const
1354 {
1355 return clippedOverflowRectForPaintInvalidation(view());
1356 }
1357
1358 LayoutRect RenderObject::clippedOverflowRectForPaintInvalidation(const LayoutLay erModelObject*, const PaintInvalidationState*) const
1359 {
1360 ASSERT_NOT_REACHED();
1361 return LayoutRect();
1362 }
1363
1364 void RenderObject::mapRectToPaintInvalidationBacking(const LayoutLayerModelObjec t* paintInvalidationContainer, LayoutRect& rect, const PaintInvalidationState* p aintInvalidationState) const
1365 {
1366 if (paintInvalidationContainer == this)
1367 return;
1368
1369 if (paintInvalidationState && paintInvalidationState->canMapToContainer(pain tInvalidationContainer)) {
1370 rect.move(paintInvalidationState->paintOffset());
1371 if (paintInvalidationState->isClipped())
1372 rect.intersect(paintInvalidationState->clipRect());
1373 return;
1374 }
1375
1376 if (RenderObject* o = parent()) {
1377 if (o->isRenderBlockFlow()) {
1378 RenderBlock* cb = toRenderBlock(o);
1379 if (cb->hasColumns())
1380 cb->adjustRectForColumns(rect);
1381 }
1382
1383 if (o->hasOverflowClip()) {
1384 RenderBox* boxParent = toRenderBox(o);
1385 boxParent->applyCachedClipAndScrollOffsetForPaintInvalidation(rect);
1386 if (rect.isEmpty())
1387 return;
1388 }
1389
1390 o->mapRectToPaintInvalidationBacking(paintInvalidationContainer, rect, p aintInvalidationState);
1391 }
1392 }
1393
1394 void RenderObject::dirtyLinesFromChangedChild(RenderObject*)
1395 {
1396 }
1397
1398 #ifndef NDEBUG
1399
1400 void RenderObject::showTreeForThis() const
1401 {
1402 if (node())
1403 node()->showTreeForThis();
1404 }
1405
1406 void RenderObject::showRenderTreeForThis() const
1407 {
1408 showRenderTree(this, 0);
1409 }
1410
1411 void RenderObject::showLineTreeForThis() const
1412 {
1413 if (containingBlock())
1414 containingBlock()->showLineTreeAndMark(0, 0, 0, 0, this);
1415 }
1416
1417 void RenderObject::showRenderObject() const
1418 {
1419 showRenderObject(0);
1420 }
1421
1422 void RenderObject::showRenderObject(int printedCharacters) const
1423 {
1424 printedCharacters += fprintf(stderr, "%s %p", renderName(), this);
1425
1426 if (isText() && toRenderText(this)->isTextFragment())
1427 printedCharacters += fprintf(stderr, " \"%s\" ", toRenderText(this)->tex t().ascii().data());
1428
1429 if (node()) {
1430 if (printedCharacters)
1431 for (; printedCharacters < showTreeCharacterOffset; printedCharacter s++)
1432 fputc(' ', stderr);
1433 fputc('\t', stderr);
1434 node()->showNode();
1435 } else
1436 fputc('\n', stderr);
1437 }
1438
1439 void RenderObject::showRenderTreeAndMark(const RenderObject* markedObject1, cons t char* markedLabel1, const RenderObject* markedObject2, const char* markedLabel 2, int depth) const
1440 {
1441 int printedCharacters = 0;
1442 if (markedObject1 == this && markedLabel1)
1443 printedCharacters += fprintf(stderr, "%s", markedLabel1);
1444 if (markedObject2 == this && markedLabel2)
1445 printedCharacters += fprintf(stderr, "%s", markedLabel2);
1446 for (; printedCharacters < depth * 2; printedCharacters++)
1447 fputc(' ', stderr);
1448
1449 showRenderObject(printedCharacters);
1450
1451 for (const RenderObject* child = slowFirstChild(); child; child = child->nex tSibling())
1452 child->showRenderTreeAndMark(markedObject1, markedLabel1, markedObject2, markedLabel2, depth + 1);
1453 }
1454
1455 #endif // NDEBUG
1456
1457 bool RenderObject::isSelectable() const
1458 {
1459 return !isInert() && !(style()->userSelect() == SELECT_NONE && style()->user Modify() == READ_ONLY);
1460 }
1461
1462 Color RenderObject::selectionBackgroundColor() const
1463 {
1464 if (!isSelectable())
1465 return Color::transparent;
1466
1467 if (RefPtr<RenderStyle> pseudoStyle = getUncachedPseudoStyleFromParentOrShad owHost())
1468 return resolveColor(*pseudoStyle, CSSPropertyBackgroundColor).blendWithW hite();
1469 return frame()->selection().isFocusedAndActive() ?
1470 LayoutTheme::theme().activeSelectionBackgroundColor() :
1471 LayoutTheme::theme().inactiveSelectionBackgroundColor();
1472 }
1473
1474 Color RenderObject::selectionColor(int colorProperty) const
1475 {
1476 // If the element is unselectable, or we are only painting the selection,
1477 // don't override the foreground color with the selection foreground color.
1478 if (!isSelectable() || (frame()->view()->paintBehavior() & PaintBehaviorSele ctionOnly))
1479 return resolveColor(colorProperty);
1480
1481 if (RefPtr<RenderStyle> pseudoStyle = getUncachedPseudoStyleFromParentOrShad owHost())
1482 return resolveColor(*pseudoStyle, colorProperty);
1483 if (!LayoutTheme::theme().supportsSelectionForegroundColors())
1484 return resolveColor(colorProperty);
1485 return frame()->selection().isFocusedAndActive() ?
1486 LayoutTheme::theme().activeSelectionForegroundColor() :
1487 LayoutTheme::theme().inactiveSelectionForegroundColor();
1488 }
1489
1490 Color RenderObject::selectionForegroundColor() const
1491 {
1492 return selectionColor(CSSPropertyWebkitTextFillColor);
1493 }
1494
1495 Color RenderObject::selectionEmphasisMarkColor() const
1496 {
1497 return selectionColor(CSSPropertyWebkitTextEmphasisColor);
1498 }
1499
1500 void RenderObject::selectionStartEnd(int& spos, int& epos) const
1501 {
1502 view()->selectionStartEnd(spos, epos);
1503 }
1504
1505 void RenderObject::handleDynamicFloatPositionChange()
1506 {
1507 // We have gone from not affecting the inline status of the parent flow to s uddenly
1508 // having an impact. See if there is a mismatch between the parent flow's
1509 // childrenInline() state and our state.
1510 setInline(style()->isDisplayInlineType());
1511 if (isInline() != parent()->childrenInline()) {
1512 if (!isInline())
1513 toRenderBoxModelObject(parent())->childBecameNonInline(this);
1514 else {
1515 // An anonymous block must be made to wrap this inline.
1516 RenderBlock* block = toRenderBlock(parent())->createAnonymousBlock() ;
1517 RenderObjectChildList* childlist = parent()->virtualChildren();
1518 childlist->insertChildNode(parent(), block, this);
1519 block->children()->appendChildNode(block, childlist->removeChildNode (parent(), this));
1520 }
1521 }
1522 }
1523
1524 StyleDifference RenderObject::adjustStyleDifference(StyleDifference diff) const
1525 {
1526 if (diff.transformChanged() && isSVG())
1527 diff.setNeedsFullLayout();
1528
1529 // If transform changed, and the layer does not paint into its own separate backing, then we need to invalidate paints.
1530 if (diff.transformChanged()) {
1531 // Text nodes share style with their parents but transforms don't apply to them,
1532 // hence the !isText() check.
1533 if (!isText() && (!hasLayer() || !toLayoutLayerModelObject(this)->layer( )->hasStyleDeterminedDirectCompositingReasons()))
1534 diff.setNeedsPaintInvalidationLayer();
1535 }
1536
1537 // If opacity or zIndex changed, and the layer does not paint into its own s eparate backing, then we need to invalidate paints (also
1538 // ignoring text nodes)
1539 if (diff.opacityChanged() || diff.zIndexChanged()) {
1540 if (!isText() && (!hasLayer() || !toLayoutLayerModelObject(this)->layer( )->hasStyleDeterminedDirectCompositingReasons()))
1541 diff.setNeedsPaintInvalidationLayer();
1542 }
1543
1544 // If filter changed, and the layer does not paint into its own separate bac king or it paints with filters, then we need to invalidate paints.
1545 if (diff.filterChanged() && hasLayer()) {
1546 Layer* layer = toLayoutLayerModelObject(this)->layer();
1547 if (!layer->hasStyleDeterminedDirectCompositingReasons() || layer->paint sWithFilters())
1548 diff.setNeedsPaintInvalidationLayer();
1549 }
1550
1551 if (diff.textOrColorChanged() && !diff.needsPaintInvalidation()) {
1552 if (style()->hasBorder() || style()->hasOutline()
1553 || (isText() && !toRenderText(this)->isAllCollapsibleWhitespace()))
1554 diff.setNeedsPaintInvalidationObject();
1555 }
1556
1557 // The answer to layerTypeRequired() for plugins, iframes, and canvas can ch ange without the actual
1558 // style changing, since it depends on whether we decide to composite these elements. When the
1559 // layer status of one of these elements changes, we need to force a layout.
1560 if (!diff.needsFullLayout() && style() && isLayoutLayerModelObject()) {
1561 bool requiresLayer = toLayoutLayerModelObject(this)->layerTypeRequired() != NoLayer;
1562 if (hasLayer() != requiresLayer)
1563 diff.setNeedsFullLayout();
1564 }
1565
1566 // If we have no layer(), just treat a PaintInvalidationLayer hint as a norm al paint invalidation.
1567 if (diff.needsPaintInvalidationLayer() && !hasLayer()) {
1568 diff.clearNeedsPaintInvalidation();
1569 diff.setNeedsPaintInvalidationObject();
1570 }
1571
1572 return diff;
1573 }
1574
1575 void RenderObject::setPseudoStyle(PassRefPtr<RenderStyle> pseudoStyle)
1576 {
1577 ASSERT(pseudoStyle->styleType() == BEFORE || pseudoStyle->styleType() == AFT ER || pseudoStyle->styleType() == FIRST_LETTER);
1578
1579 // FIXME: We should consider just making all pseudo items use an inherited s tyle.
1580
1581 // Images are special and must inherit the pseudoStyle so the width and heig ht of
1582 // the pseudo element doesn't change the size of the image. In all other cas es we
1583 // can just share the style.
1584 //
1585 // Quotes are also RenderInline, so we need to create an inherited style to avoid
1586 // getting an inline with positioning or an invalid display.
1587 //
1588 if (isImage() || isQuote()) {
1589 RefPtr<RenderStyle> style = RenderStyle::create();
1590 style->inheritFrom(pseudoStyle.get());
1591 setStyle(style.release());
1592 return;
1593 }
1594
1595 setStyle(pseudoStyle);
1596 }
1597
1598 void RenderObject::markContainingBlocksForOverflowRecalc()
1599 {
1600 for (RenderBlock* container = containingBlock(); container && !container->ch ildNeedsOverflowRecalcAfterStyleChange(); container = container->containingBlock ())
1601 container->setChildNeedsOverflowRecalcAfterStyleChange(true);
1602 }
1603
1604 void RenderObject::setNeedsOverflowRecalcAfterStyleChange()
1605 {
1606 bool neededRecalc = needsOverflowRecalcAfterStyleChange();
1607 setSelfNeedsOverflowRecalcAfterStyleChange(true);
1608 if (!neededRecalc)
1609 markContainingBlocksForOverflowRecalc();
1610 }
1611
1612 void RenderObject::setStyle(PassRefPtr<RenderStyle> style)
1613 {
1614 ASSERT(style);
1615
1616 if (m_style == style) {
1617 // We need to run through adjustStyleDifference() for iframes, plugins, and canvas so
1618 // style sharing is disabled for them. That should ensure that we never hit this code path.
1619 ASSERT(!isRenderIFrame() && !isEmbeddedObject() && !isCanvas());
1620 return;
1621 }
1622
1623 StyleDifference diff;
1624 if (m_style)
1625 diff = m_style->visualInvalidationDiff(*style);
1626
1627 diff = adjustStyleDifference(diff);
1628
1629 styleWillChange(diff, *style);
1630
1631 RefPtr<RenderStyle> oldStyle = m_style.release();
1632 setStyleInternal(style);
1633
1634 updateFillImages(oldStyle ? &oldStyle->backgroundLayers() : 0, m_style->back groundLayers());
1635 updateFillImages(oldStyle ? &oldStyle->maskLayers() : 0, m_style->maskLayers ());
1636
1637 updateImage(oldStyle ? oldStyle->borderImage().image() : 0, m_style->borderI mage().image());
1638 updateImage(oldStyle ? oldStyle->maskBoxImage().image() : 0, m_style->maskBo xImage().image());
1639
1640 updateShapeImage(oldStyle ? oldStyle->shapeOutside() : 0, m_style->shapeOuts ide());
1641
1642 bool doesNotNeedLayoutOrPaintInvalidation = !m_parent;
1643
1644 styleDidChange(diff, oldStyle.get());
1645
1646 // FIXME: |this| might be destroyed here. This can currently happen for a Re nderTextFragment when
1647 // its first-letter block gets an update in RenderTextFragment::styleDidChan ge. For RenderTextFragment(s),
1648 // we will safely bail out with the doesNotNeedLayoutOrPaintInvalidation fla g. We might want to broaden
1649 // this condition in the future as we move renderer changes out of layout an d into style changes.
1650 if (doesNotNeedLayoutOrPaintInvalidation)
1651 return;
1652
1653 // Now that the layer (if any) has been updated, we need to adjust the diff again,
1654 // check whether we should layout now, and decide if we need to invalidate p aints.
1655 StyleDifference updatedDiff = adjustStyleDifference(diff);
1656
1657 if (!diff.needsFullLayout()) {
1658 if (updatedDiff.needsFullLayout())
1659 setNeedsLayoutAndPrefWidthsRecalc();
1660 else if (updatedDiff.needsPositionedMovementLayout())
1661 setNeedsPositionedMovementLayout();
1662 }
1663
1664 if (diff.transformChanged() && !needsLayout()) {
1665 if (RenderBlock* container = containingBlock())
1666 container->setNeedsOverflowRecalcAfterStyleChange();
1667 }
1668
1669 if (updatedDiff.needsPaintInvalidationLayer())
1670 toLayoutLayerModelObject(this)->layer()->setShouldDoFullPaintInvalidatio nIncludingNonCompositingDescendants();
1671 else if (diff.needsPaintInvalidationObject() || updatedDiff.needsPaintInvali dationObject())
1672 setShouldDoFullPaintInvalidation();
1673 }
1674
1675 static inline bool rendererHasBackground(const RenderObject* renderer)
1676 {
1677 return renderer && renderer->hasBackground();
1678 }
1679
1680 void RenderObject::styleWillChange(StyleDifference diff, const RenderStyle& newS tyle)
1681 {
1682 if (m_style) {
1683 // If our z-index changes value or our visibility changes,
1684 // we need to dirty our stacking context's z-order list.
1685 bool visibilityChanged = m_style->visibility() != newStyle.visibility()
1686 || m_style->zIndex() != newStyle.zIndex()
1687 || m_style->hasAutoZIndex() != newStyle.hasAutoZIndex();
1688 if (visibilityChanged) {
1689 document().setAnnotatedRegionsDirty(true);
1690 if (AXObjectCache* cache = document().existingAXObjectCache())
1691 cache->childrenChanged(parent());
1692 }
1693
1694 // Keep layer hierarchy visibility bits up to date if visibility changes .
1695 if (m_style->visibility() != newStyle.visibility()) {
1696 // We might not have an enclosing layer yet because we might not be in the tree.
1697 if (Layer* layer = enclosingLayer())
1698 layer->potentiallyDirtyVisibleContentStatus(newStyle.visibility( ));
1699 }
1700
1701 if (isFloating() && (m_style->floating() != newStyle.floating()))
1702 // For changes in float styles, we need to conceivably remove oursel ves
1703 // from the floating objects list.
1704 toRenderBox(this)->removeFloatingOrPositionedChildFromBlockLists();
1705 else if (isOutOfFlowPositioned() && (m_style->position() != newStyle.pos ition()))
1706 // For changes in positioning styles, we need to conceivably remove ourselves
1707 // from the positioned objects list.
1708 toRenderBox(this)->removeFloatingOrPositionedChildFromBlockLists();
1709
1710 s_affectsParentBlock = isFloatingOrOutOfFlowPositioned()
1711 && (!newStyle.isFloating() && !newStyle.hasOutOfFlowPosition())
1712 && parent() && (parent()->isRenderBlockFlow() || parent()->isRenderI nline());
1713
1714 // Clearing these bits is required to avoid leaving stale renderers.
1715 // FIXME: We shouldn't need that hack if our logic was totally correct.
1716 if (diff.needsLayout()) {
1717 setFloating(false);
1718 clearPositionedState();
1719 }
1720 } else {
1721 s_affectsParentBlock = false;
1722 }
1723
1724 if (view()->frameView()) {
1725 bool shouldBlitOnFixedBackgroundImage = false;
1726 if (RuntimeEnabledFeatures::fastMobileScrollingEnabled()) {
1727 // On low-powered/mobile devices, preventing blitting on a scroll ca n cause noticeable delays
1728 // when scrolling a page with a fixed background image. As an optimi zation, assuming there are
1729 // no fixed positoned elements on the page, we can acclerate scrolli ng (via blitting) if we
1730 // ignore the CSS property "background-attachment: fixed".
1731 shouldBlitOnFixedBackgroundImage = true;
1732 }
1733 bool newStyleSlowScroll = !shouldBlitOnFixedBackgroundImage && newStyle. hasFixedBackgroundImage();
1734 bool oldStyleSlowScroll = m_style && !shouldBlitOnFixedBackgroundImage & & m_style->hasFixedBackgroundImage();
1735
1736 bool drawsRootBackground = isDocumentElement() || (isBody() && !renderer HasBackground(document().documentElement()->renderer()));
1737 if (drawsRootBackground && !shouldBlitOnFixedBackgroundImage) {
1738 if (view()->compositor()->supportsFixedRootBackgroundCompositing()) {
1739 if (newStyleSlowScroll && newStyle.hasEntirelyFixedBackground())
1740 newStyleSlowScroll = false;
1741
1742 if (oldStyleSlowScroll && m_style->hasEntirelyFixedBackground())
1743 oldStyleSlowScroll = false;
1744 }
1745 }
1746
1747 if (oldStyleSlowScroll != newStyleSlowScroll) {
1748 if (oldStyleSlowScroll)
1749 view()->frameView()->removeSlowRepaintObject();
1750 if (newStyleSlowScroll)
1751 view()->frameView()->addSlowRepaintObject();
1752 }
1753 }
1754
1755 // Elements with non-auto touch-action will send a SetTouchAction message
1756 // on touchstart in EventHandler::handleTouchEvent, and so effectively have
1757 // a touchstart handler that must be reported.
1758 //
1759 // Since a CSS property cannot be applied directly to a text node, a
1760 // handler will have already been added for its parent so ignore it.
1761 TouchAction oldTouchAction = m_style ? m_style->touchAction() : TouchActionA uto;
1762 if (node() && !node()->isTextNode() && (oldTouchAction == TouchActionAuto) ! = (newStyle.touchAction() == TouchActionAuto)) {
1763 EventHandlerRegistry& registry = document().frameHost()->eventHandlerReg istry();
1764 if (newStyle.touchAction() != TouchActionAuto)
1765 registry.didAddEventHandler(*node(), EventHandlerRegistry::TouchEven t);
1766 else
1767 registry.didRemoveEventHandler(*node(), EventHandlerRegistry::TouchE vent);
1768 }
1769 }
1770
1771 static bool areNonIdenticalCursorListsEqual(const RenderStyle* a, const RenderSt yle* b)
1772 {
1773 ASSERT(a->cursors() != b->cursors());
1774 return a->cursors() && b->cursors() && *a->cursors() == *b->cursors();
1775 }
1776
1777 static inline bool areCursorsEqual(const RenderStyle* a, const RenderStyle* b)
1778 {
1779 return a->cursor() == b->cursor() && (a->cursors() == b->cursors() || areNon IdenticalCursorListsEqual(a, b));
1780 }
1781
1782 void RenderObject::styleDidChange(StyleDifference diff, const RenderStyle* oldSt yle)
1783 {
1784 if (s_affectsParentBlock)
1785 handleDynamicFloatPositionChange();
1786
1787 if (!m_parent)
1788 return;
1789
1790 if (diff.needsFullLayout()) {
1791 LayoutCounter::rendererStyleChanged(*this, oldStyle, m_style.get());
1792
1793 // If the object already needs layout, then setNeedsLayout won't do
1794 // any work. But if the containing block has changed, then we may need
1795 // to mark the new containing blocks for layout. The change that can
1796 // directly affect the containing block of this object is a change to
1797 // the position style.
1798 if (needsLayout() && oldStyle->position() != m_style->position())
1799 markContainingBlocksForLayout();
1800
1801 // Ditto.
1802 if (needsOverflowRecalcAfterStyleChange() && oldStyle->position() != m_s tyle->position())
1803 markContainingBlocksForOverflowRecalc();
1804
1805 if (diff.needsFullLayout())
1806 setNeedsLayoutAndPrefWidthsRecalc();
1807 } else if (diff.needsPositionedMovementLayout())
1808 setNeedsPositionedMovementLayout();
1809
1810 // Don't check for paint invalidation here; we need to wait until the layer has been
1811 // updated by subclasses before we know if we have to invalidate paints (in setStyle()).
1812
1813 if (oldStyle && !areCursorsEqual(oldStyle, style())) {
1814 if (LocalFrame* frame = this->frame())
1815 frame->eventHandler().scheduleCursorUpdate();
1816 }
1817 }
1818
1819 void RenderObject::propagateStyleToAnonymousChildren(bool blockChildrenOnly)
1820 {
1821 // FIXME: We could save this call when the change only affected non-inherite d properties.
1822 for (RenderObject* child = slowFirstChild(); child; child = child->nextSibli ng()) {
1823 if (!child->isAnonymous() || child->style()->styleType() != NOPSEUDO)
1824 continue;
1825
1826 if (blockChildrenOnly && !child->isRenderBlock())
1827 continue;
1828
1829 if (child->isRenderFullScreen() || child->isRenderFullScreenPlaceholder( ))
1830 continue;
1831
1832 RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisp lay(style(), child->style()->display());
1833 if (!document().regionBasedColumnsEnabled()) {
1834 if (style()->specifiesColumns()) {
1835 if (child->style()->specifiesColumns())
1836 newStyle->inheritColumnPropertiesFrom(style());
1837 if (child->style()->columnSpan())
1838 newStyle->setColumnSpan(ColumnSpanAll);
1839 }
1840 }
1841
1842 // Preserve the position style of anonymous block continuations as they can have relative position when
1843 // they contain block descendants of relative positioned inlines.
1844 if (child->isRelPositioned() && toRenderBlock(child)->isAnonymousBlockCo ntinuation())
1845 newStyle->setPosition(child->style()->position());
1846
1847 updateAnonymousChildStyle(child, newStyle.get());
1848
1849 child->setStyle(newStyle.release());
1850 }
1851 }
1852
1853 void RenderObject::updateFillImages(const FillLayer* oldLayers, const FillLayer& newLayers)
1854 {
1855 // Optimize the common case
1856 if (oldLayers && !oldLayers->next() && !newLayers.next() && (oldLayers->imag e() == newLayers.image()))
1857 return;
1858
1859 // Go through the new layers and addClients first, to avoid removing all cli ents of an image.
1860 for (const FillLayer* currNew = &newLayers; currNew; currNew = currNew->next ()) {
1861 if (currNew->image())
1862 currNew->image()->addClient(this);
1863 }
1864
1865 for (const FillLayer* currOld = oldLayers; currOld; currOld = currOld->next( )) {
1866 if (currOld->image())
1867 currOld->image()->removeClient(this);
1868 }
1869 }
1870
1871 void RenderObject::updateImage(StyleImage* oldImage, StyleImage* newImage)
1872 {
1873 if (oldImage != newImage) {
1874 if (oldImage)
1875 oldImage->removeClient(this);
1876 if (newImage)
1877 newImage->addClient(this);
1878 }
1879 }
1880
1881 void RenderObject::updateShapeImage(const ShapeValue* oldShapeValue, const Shape Value* newShapeValue)
1882 {
1883 if (oldShapeValue || newShapeValue)
1884 updateImage(oldShapeValue ? oldShapeValue->image() : 0, newShapeValue ? newShapeValue->image() : 0);
1885 }
1886
1887 LayoutRect RenderObject::viewRect() const
1888 {
1889 return view()->viewRect();
1890 }
1891
1892 FloatPoint RenderObject::localToAbsolute(const FloatPoint& localPoint, MapCoordi natesFlags mode) const
1893 {
1894 TransformState transformState(TransformState::ApplyTransformDirection, local Point);
1895 mapLocalToContainer(0, transformState, mode | ApplyContainerFlip);
1896 transformState.flatten();
1897
1898 return transformState.lastPlanarPoint();
1899 }
1900
1901 FloatPoint RenderObject::absoluteToLocal(const FloatPoint& containerPoint, MapCo ordinatesFlags mode) const
1902 {
1903 TransformState transformState(TransformState::UnapplyInverseTransformDirecti on, containerPoint);
1904 mapAbsoluteToLocalPoint(mode, transformState);
1905 transformState.flatten();
1906
1907 return transformState.lastPlanarPoint();
1908 }
1909
1910 FloatQuad RenderObject::absoluteToLocalQuad(const FloatQuad& quad, MapCoordinate sFlags mode) const
1911 {
1912 TransformState transformState(TransformState::UnapplyInverseTransformDirecti on, quad.boundingBox().center(), quad);
1913 mapAbsoluteToLocalPoint(mode, transformState);
1914 transformState.flatten();
1915 return transformState.lastPlanarQuad();
1916 }
1917
1918 void RenderObject::mapLocalToContainer(const LayoutLayerModelObject* paintInvali dationContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed, const PaintInvalidationState* paintInvalidationState) const
1919 {
1920 if (paintInvalidationContainer == this)
1921 return;
1922
1923 RenderObject* o = parent();
1924 if (!o)
1925 return;
1926
1927 // FIXME: this should call offsetFromContainer to share code, but I'm not su re it's ever called.
1928 LayoutPoint centerPoint = roundedLayoutPoint(transformState.mappedPoint());
1929 if (mode & ApplyContainerFlip && o->isBox()) {
1930 if (o->style()->isFlippedBlocksWritingMode())
1931 transformState.move(toRenderBox(o)->flipForWritingModeIncludingColum ns(roundedLayoutPoint(transformState.mappedPoint())) - centerPoint);
1932 mode &= ~ApplyContainerFlip;
1933 }
1934
1935 transformState.move(o->columnOffset(roundedLayoutPoint(transformState.mapped Point())));
1936
1937 if (o->hasOverflowClip())
1938 transformState.move(-toRenderBox(o)->scrolledContentOffset());
1939
1940 o->mapLocalToContainer(paintInvalidationContainer, transformState, mode, was Fixed, paintInvalidationState);
1941 }
1942
1943 const RenderObject* RenderObject::pushMappingToContainer(const LayoutLayerModelO bject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
1944 {
1945 ASSERT_UNUSED(ancestorToStopAt, ancestorToStopAt != this);
1946
1947 RenderObject* container = parent();
1948 if (!container)
1949 return 0;
1950
1951 // FIXME: this should call offsetFromContainer to share code, but I'm not su re it's ever called.
1952 LayoutSize offset;
1953 if (container->hasOverflowClip())
1954 offset = -LayoutSize(toRenderBox(container)->scrolledContentOffset());
1955
1956 geometryMap.push(this, offset, hasColumns());
1957
1958 return container;
1959 }
1960
1961 void RenderObject::mapAbsoluteToLocalPoint(MapCoordinatesFlags mode, TransformSt ate& transformState) const
1962 {
1963 RenderObject* o = parent();
1964 if (o) {
1965 o->mapAbsoluteToLocalPoint(mode, transformState);
1966 if (o->hasOverflowClip())
1967 transformState.move(toRenderBox(o)->scrolledContentOffset());
1968 }
1969 }
1970
1971 bool RenderObject::shouldUseTransformFromContainer(const RenderObject* container Object) const
1972 {
1973 // hasTransform() indicates whether the object has transform, transform-styl e or perspective. We just care about transform,
1974 // so check the layer's transform directly.
1975 return (hasLayer() && toLayoutLayerModelObject(this)->layer()->transform()) || (containerObject && containerObject->style()->hasPerspective());
1976 }
1977
1978 void RenderObject::getTransformFromContainer(const RenderObject* containerObject , const LayoutSize& offsetInContainer, TransformationMatrix& transform) const
1979 {
1980 transform.makeIdentity();
1981 transform.translate(offsetInContainer.width().toFloat(), offsetInContainer.h eight().toFloat());
1982 Layer* layer = hasLayer() ? toLayoutLayerModelObject(this)->layer() : 0;
1983 if (layer && layer->transform())
1984 transform.multiply(layer->currentTransform());
1985
1986 if (containerObject && containerObject->hasLayer() && containerObject->style ()->hasPerspective()) {
1987 // Perpsective on the container affects us, so we have to factor it in h ere.
1988 ASSERT(containerObject->hasLayer());
1989 FloatPoint perspectiveOrigin = toLayoutLayerModelObject(containerObject) ->layer()->perspectiveOrigin();
1990
1991 TransformationMatrix perspectiveMatrix;
1992 perspectiveMatrix.applyPerspective(containerObject->style()->perspective ());
1993
1994 transform.translateRight3d(-perspectiveOrigin.x(), -perspectiveOrigin.y( ), 0);
1995 transform = perspectiveMatrix * transform;
1996 transform.translateRight3d(perspectiveOrigin.x(), perspectiveOrigin.y(), 0);
1997 }
1998 }
1999
2000 FloatQuad RenderObject::localToContainerQuad(const FloatQuad& localQuad, const L ayoutLayerModelObject* paintInvalidationContainer, MapCoordinatesFlags mode, boo l* wasFixed) const
2001 {
2002 // Track the point at the center of the quad's bounding box. As mapLocalToCo ntainer() calls offsetFromContainer(),
2003 // it will use that point as the reference point to decide which column's tr ansform to apply in multiple-column blocks.
2004 TransformState transformState(TransformState::ApplyTransformDirection, local Quad.boundingBox().center(), localQuad);
2005 mapLocalToContainer(paintInvalidationContainer, transformState, mode | Apply ContainerFlip | UseTransforms, wasFixed);
2006 transformState.flatten();
2007
2008 return transformState.lastPlanarQuad();
2009 }
2010
2011 FloatPoint RenderObject::localToContainerPoint(const FloatPoint& localPoint, con st LayoutLayerModelObject* paintInvalidationContainer, MapCoordinatesFlags mode, bool* wasFixed, const PaintInvalidationState* paintInvalidationState) const
2012 {
2013 TransformState transformState(TransformState::ApplyTransformDirection, local Point);
2014 mapLocalToContainer(paintInvalidationContainer, transformState, mode | Apply ContainerFlip | UseTransforms, wasFixed, paintInvalidationState);
2015 transformState.flatten();
2016
2017 return transformState.lastPlanarPoint();
2018 }
2019
2020 FloatPoint RenderObject::localToInvalidationBackingPoint(const LayoutPoint& loca lPoint, Layer** backingLayer)
2021 {
2022 const LayoutLayerModelObject* paintInvalidationContainer = containerForPaint Invalidation();
2023 ASSERT(paintInvalidationContainer);
2024 ASSERT(paintInvalidationContainer->layer());
2025
2026 if (backingLayer)
2027 *backingLayer = paintInvalidationContainer->layer();
2028 FloatPoint containerPoint = localToContainerPoint(FloatPoint(localPoint), pa intInvalidationContainer, TraverseDocumentBoundaries);
2029
2030 // A renderer can have no invalidation backing if it is from a detached fram e,
2031 // or when forced compositing is disabled.
2032 if (paintInvalidationContainer->layer()->compositingState() == NotComposited )
2033 return containerPoint;
2034
2035 Layer::mapPointToPaintBackingCoordinates(paintInvalidationContainer, contain erPoint);
2036 return containerPoint;
2037 }
2038
2039 LayoutSize RenderObject::offsetFromContainer(const RenderObject* o, const Layout Point& point, bool* offsetDependsOnPoint) const
2040 {
2041 ASSERT(o == container());
2042
2043 LayoutSize offset = o->columnOffset(point);
2044
2045 if (o->hasOverflowClip())
2046 offset -= toRenderBox(o)->scrolledContentOffset();
2047
2048 if (offsetDependsOnPoint)
2049 *offsetDependsOnPoint = hasColumns() || o->isRenderFlowThread();
2050
2051 return offset;
2052 }
2053
2054 LayoutSize RenderObject::offsetFromAncestorContainer(const RenderObject* contain er) const
2055 {
2056 if (container == this)
2057 return LayoutSize();
2058
2059 LayoutSize offset;
2060 LayoutPoint referencePoint;
2061 const RenderObject* currContainer = this;
2062 do {
2063 const RenderObject* nextContainer = currContainer->container();
2064 ASSERT(nextContainer); // This means we reached the top without finding container.
2065 if (!nextContainer)
2066 break;
2067 ASSERT(!currContainer->hasTransformRelatedProperty());
2068 LayoutSize currentOffset = currContainer->offsetFromContainer(nextContai ner, referencePoint);
2069 offset += currentOffset;
2070 referencePoint.move(currentOffset);
2071 currContainer = nextContainer;
2072 } while (currContainer != container);
2073
2074 return offset;
2075 }
2076
2077 LayoutRect RenderObject::localCaretRect(InlineBox*, int, LayoutUnit* extraWidthT oEndOfLine)
2078 {
2079 if (extraWidthToEndOfLine)
2080 *extraWidthToEndOfLine = 0;
2081
2082 return LayoutRect();
2083 }
2084
2085 void RenderObject::computeLayerHitTestRects(LayerHitTestRects& layerRects) const
2086 {
2087 // Figure out what layer our container is in. Any offset (or new layer) for this
2088 // renderer within it's container will be applied in addLayerHitTestRects.
2089 LayoutPoint layerOffset;
2090 const Layer* currentLayer = 0;
2091
2092 if (!hasLayer()) {
2093 RenderObject* container = this->container();
2094 currentLayer = container->enclosingLayer();
2095 if (container && currentLayer->renderer() != container) {
2096 layerOffset.move(container->offsetFromAncestorContainer(currentLayer ->renderer()));
2097 // If the layer itself is scrolled, we have to undo the subtraction of its scroll
2098 // offset since we want the offset relative to the scrolling content , not the
2099 // element itself.
2100 if (currentLayer->renderer()->hasOverflowClip())
2101 layerOffset.move(currentLayer->renderBox()->scrolledContentOffse t());
2102 }
2103 }
2104
2105 this->addLayerHitTestRects(layerRects, currentLayer, layerOffset, LayoutRect ());
2106 }
2107
2108 void RenderObject::addLayerHitTestRects(LayerHitTestRects& layerRects, const Lay er* currentLayer, const LayoutPoint& layerOffset, const LayoutRect& containerRec t) const
2109 {
2110 ASSERT(currentLayer);
2111 ASSERT(currentLayer == this->enclosingLayer());
2112
2113 // Compute the rects for this renderer only and add them to the results.
2114 // Note that we could avoid passing the offset and instead adjust each resul t, but this
2115 // seems slightly simpler.
2116 Vector<LayoutRect> ownRects;
2117 LayoutRect newContainerRect;
2118 computeSelfHitTestRects(ownRects, layerOffset);
2119
2120 // When we get to have a lot of rects on a layer, the performance cost of tr acking those
2121 // rects outweighs the benefit of doing compositor thread hit testing.
2122 // FIXME: This limit needs to be low due to the O(n^2) algorithm in
2123 // WebLayer::setTouchEventHandlerRegion - crbug.com/300282.
2124 const size_t maxRectsPerLayer = 100;
2125
2126 LayerHitTestRects::iterator iter = layerRects.find(currentLayer);
2127 Vector<LayoutRect>* iterValue;
2128 if (iter == layerRects.end())
2129 iterValue = &layerRects.add(currentLayer, Vector<LayoutRect>()).storedVa lue->value;
2130 else
2131 iterValue = &iter->value;
2132 for (size_t i = 0; i < ownRects.size(); i++) {
2133 if (!containerRect.contains(ownRects[i])) {
2134 iterValue->append(ownRects[i]);
2135 if (iterValue->size() > maxRectsPerLayer) {
2136 // Just mark the entire layer instead, and switch to walking the layer
2137 // tree instead of the render tree.
2138 layerRects.remove(currentLayer);
2139 currentLayer->addLayerHitTestRects(layerRects);
2140 return;
2141 }
2142 if (newContainerRect.isEmpty())
2143 newContainerRect = ownRects[i];
2144 }
2145 }
2146 if (newContainerRect.isEmpty())
2147 newContainerRect = containerRect;
2148
2149 // If it's possible for children to have rects outside our bounds, then we n eed to descend into
2150 // the children and compute them.
2151 // Ideally there would be other cases where we could detect that children co uldn't have rects
2152 // outside our bounds and prune the tree walk.
2153 // Note that we don't use Region here because Union is O(N) - better to just keep a list of
2154 // partially redundant rectangles. If we find examples where this is expensi ve, then we could
2155 // rewrite Region to be more efficient. See https://bugs.webkit.org/show_bug .cgi?id=100814.
2156 if (!isRenderView()) {
2157 for (RenderObject* curr = slowFirstChild(); curr; curr = curr->nextSibli ng()) {
2158 curr->addLayerHitTestRects(layerRects, currentLayer, layerOffset, n ewContainerRect);
2159 }
2160 }
2161 }
2162
2163 bool RenderObject::isRooted() const
2164 {
2165 const RenderObject* object = this;
2166 while (object->parent() && !object->hasLayer())
2167 object = object->parent();
2168 if (object->hasLayer())
2169 return toLayoutLayerModelObject(object)->layer()->root()->isRootLayer();
2170 return false;
2171 }
2172
2173 RenderObject* RenderObject::rendererForRootBackground()
2174 {
2175 ASSERT(isDocumentElement());
2176 if (!hasBackground() && isHTMLHtmlElement(node())) {
2177 // Locate the <body> element using the DOM. This is easier than trying
2178 // to crawl around a render tree with potential :before/:after content a nd
2179 // anonymous blocks created by inline <body> tags etc. We can locate the <body>
2180 // render object very easily via the DOM.
2181 HTMLElement* body = document().body();
2182 RenderObject* bodyObject = isHTMLBodyElement(body) ? body->renderer() : 0;
2183 if (bodyObject)
2184 return bodyObject;
2185 }
2186
2187 return this;
2188 }
2189
2190 RespectImageOrientationEnum RenderObject::shouldRespectImageOrientation() const
2191 {
2192 // Respect the image's orientation if it's being used as a full-page image o r it's
2193 // an <img> and the setting to respect it everywhere is set.
2194 return document().isImageDocument()
2195 || (document().settings() && document().settings()->shouldRespectImageOr ientation() && isHTMLImageElement(node())) ? RespectImageOrientation : DoNotResp ectImageOrientation;
2196 }
2197
2198 bool RenderObject::hasEntirelyFixedBackground() const
2199 {
2200 return m_style->hasEntirelyFixedBackground();
2201 }
2202
2203 RenderObject* RenderObject::container(const LayoutLayerModelObject* paintInvalid ationContainer, bool* paintInvalidationContainerSkipped) const
2204 {
2205 if (paintInvalidationContainerSkipped)
2206 *paintInvalidationContainerSkipped = false;
2207
2208 // This method is extremely similar to containingBlock(), but with a few not able
2209 // exceptions.
2210 // (1) It can be used on orphaned subtrees, i.e., it can be called safely ev en when
2211 // the object is not part of the primary document subtree yet.
2212 // (2) For normal flow elements, it just returns the parent.
2213 // (3) For absolute positioned elements, it will return a relative positione d inline.
2214 // containingBlock() simply skips relpositioned inlines and lets an enclosin g block handle
2215 // the layout of the positioned object. This does mean that computePosition edLogicalWidth and
2216 // computePositionedLogicalHeight have to use container().
2217 RenderObject* o = parent();
2218
2219 if (isText())
2220 return o;
2221
2222 EPosition pos = m_style->position();
2223 if (pos == FixedPosition) {
2224 return containerForFixedPosition(paintInvalidationContainer, paintInvali dationContainerSkipped);
2225 } else if (pos == AbsolutePosition) {
2226 // We technically just want our containing block, but
2227 // we may not have one if we're part of an uninstalled
2228 // subtree. We'll climb as high as we can though.
2229 while (o) {
2230 if (o->style()->position() != StaticPosition)
2231 break;
2232
2233 if (o->canContainFixedPositionObjects())
2234 break;
2235
2236 if (paintInvalidationContainerSkipped && o == paintInvalidationConta iner)
2237 *paintInvalidationContainerSkipped = true;
2238
2239 o = o->parent();
2240 }
2241 } else if (isColumnSpanAll()) {
2242 RenderObject* multicolContainer = spannerPlaceholder()->container();
2243 if (paintInvalidationContainerSkipped && paintInvalidationContainer) {
2244 // We jumped directly from the spanner to the multicol container. Ne ed to check if
2245 // we skipped |paintInvalidationContainer| on the way.
2246 for (RenderObject* walker = parent(); walker && walker != multicolCo ntainer; walker = walker->parent()) {
2247 if (walker == paintInvalidationContainer) {
2248 *paintInvalidationContainerSkipped = true;
2249 break;
2250 }
2251 }
2252 }
2253 return multicolContainer;
2254 }
2255
2256 return o;
2257 }
2258
2259 bool RenderObject::isSelectionBorder() const
2260 {
2261 SelectionState st = selectionState();
2262 return st == SelectionStart || st == SelectionEnd || st == SelectionBoth;
2263 }
2264
2265 inline void RenderObject::clearLayoutRootIfNeeded() const
2266 {
2267 if (frame()) {
2268 if (FrameView* view = frame()->view()) {
2269 if (view->layoutRoot() == this) {
2270 if (!documentBeingDestroyed())
2271 ASSERT_NOT_REACHED();
2272 // This indicates a failure to layout the child, which is why
2273 // the layout root is still set to |this|. Make sure to clear it
2274 // since we are getting destroyed.
2275 view->clearLayoutSubtreeRoot();
2276 }
2277 }
2278 }
2279 }
2280
2281 void RenderObject::willBeDestroyed()
2282 {
2283 // Destroy any leftover anonymous children.
2284 RenderObjectChildList* children = virtualChildren();
2285 if (children)
2286 children->destroyLeftoverChildren();
2287
2288 // If this renderer is being autoscrolled, stop the autoscrolling.
2289 if (LocalFrame* frame = this->frame()) {
2290 if (frame->page())
2291 frame->page()->autoscrollController().stopAutoscrollIfNeeded(this);
2292 }
2293
2294 // For accessibility management, notify the parent of the imminent change to its child set.
2295 // We do it now, before remove(), while the parent pointer is still availabl e.
2296 if (AXObjectCache* cache = document().existingAXObjectCache())
2297 cache->childrenChanged(this->parent());
2298
2299 remove();
2300
2301 // The remove() call above may invoke axObjectCache()->childrenChanged() on the parent, which may require the AX render
2302 // object for this renderer. So we remove the AX render object now, after th e renderer is removed.
2303 if (AXObjectCache* cache = document().existingAXObjectCache())
2304 cache->remove(this);
2305
2306 // If this renderer had a parent, remove should have destroyed any counters
2307 // attached to this renderer and marked the affected other counters for
2308 // reevaluation. This apparently redundant check is here for the case when
2309 // this renderer had no parent at the time remove() was called.
2310
2311 if (hasCounterNodeMap())
2312 LayoutCounter::destroyCounterNodes(*this);
2313
2314 // Remove the handler if node had touch-action set. Handlers are not added
2315 // for text nodes so don't try removing for one too. Need to check if
2316 // m_style is null in cases of partial construction. Any handler we added
2317 // previously may have already been removed by the Document independently.
2318 if (node() && !node()->isTextNode() && m_style && m_style->touchAction() != TouchActionAuto) {
2319 EventHandlerRegistry& registry = document().frameHost()->eventHandlerReg istry();
2320 if (registry.eventHandlerTargets(EventHandlerRegistry::TouchEvent)->cont ains(node()))
2321 registry.didRemoveEventHandler(*node(), EventHandlerRegistry::TouchE vent);
2322 }
2323
2324 setAncestorLineBoxDirty(false);
2325
2326 if (selectionPaintInvalidationMap)
2327 selectionPaintInvalidationMap->remove(this);
2328
2329 clearLayoutRootIfNeeded();
2330 }
2331
2332 void RenderObject::insertedIntoTree()
2333 {
2334 // FIXME: We should ASSERT(isRooted()) here but generated content makes some out-of-order insertion.
2335
2336 // Keep our layer hierarchy updated. Optimize for the common case where we d on't have any children
2337 // and don't have a layer attached to ourselves.
2338 Layer* layer = 0;
2339 if (slowFirstChild() || hasLayer()) {
2340 layer = parent()->enclosingLayer();
2341 addLayers(layer);
2342 }
2343
2344 // If |this| is visible but this object was not, tell the layer it has some visible content
2345 // that needs to be drawn and layer visibility optimization can't be used
2346 if (parent()->style()->visibility() != VISIBLE && style()->visibility() == V ISIBLE && !hasLayer()) {
2347 if (!layer)
2348 layer = parent()->enclosingLayer();
2349 if (layer)
2350 layer->dirtyVisibleContentStatus();
2351 }
2352
2353 if (!isFloating() && parent()->childrenInline())
2354 parent()->dirtyLinesFromChangedChild(this);
2355
2356 if (RenderFlowThread* flowThread = parent()->flowThreadContainingBlock())
2357 flowThread->flowThreadDescendantWasInserted(this);
2358 }
2359
2360 void RenderObject::willBeRemovedFromTree()
2361 {
2362 // FIXME: We should ASSERT(isRooted()) but we have some out-of-order removal s which would need to be fixed first.
2363
2364 // If we remove a visible child from an invisible parent, we don't know the layer visibility any more.
2365 Layer* layer = 0;
2366 if (parent()->style()->visibility() != VISIBLE && style()->visibility() == V ISIBLE && !hasLayer()) {
2367 layer = parent()->enclosingLayer();
2368 if (layer)
2369 layer->dirtyVisibleContentStatus();
2370 }
2371
2372 // Keep our layer hierarchy updated.
2373 if (slowFirstChild() || hasLayer()) {
2374 if (!layer)
2375 layer = parent()->enclosingLayer();
2376 removeLayers(layer);
2377 }
2378
2379 if (isOutOfFlowPositioned() && parent()->childrenInline())
2380 parent()->dirtyLinesFromChangedChild(this);
2381
2382 removeFromRenderFlowThread();
2383
2384 // Update cached boundaries in SVG renderers if a child is removed.
2385 if (parent()->isSVG())
2386 parent()->setNeedsBoundariesUpdate();
2387 }
2388
2389 void RenderObject::removeFromRenderFlowThread()
2390 {
2391 if (flowThreadState() == NotInsideFlowThread)
2392 return;
2393
2394 // Sometimes we remove the element from the flow, but it's not destroyed at that time.
2395 // It's only until later when we actually destroy it and remove all the chil dren from it.
2396 // Currently, that happens for firstLetter elements and list markers.
2397 // Pass in the flow thread so that we don't have to look it up for all the c hildren.
2398 // If we're a column spanner, we need to use our parent to find the flow thr ead, since a spanner
2399 // doesn't have the flow thread in its containing block chain. We still need to notify the flow
2400 // thread when the renderer removed happens to be a spanner, so that we get rid of the spanner
2401 // placeholder, and column sets around the placeholder get merged.
2402 RenderFlowThread* flowThread = isColumnSpanAll() ? parent()->flowThreadConta iningBlock() : flowThreadContainingBlock();
2403 removeFromRenderFlowThreadRecursive(flowThread);
2404 }
2405
2406 void RenderObject::removeFromRenderFlowThreadRecursive(RenderFlowThread* renderF lowThread)
2407 {
2408 if (const RenderObjectChildList* children = virtualChildren()) {
2409 for (RenderObject* child = children->firstChild(); child; child = child- >nextSibling())
2410 child->removeFromRenderFlowThreadRecursive(renderFlowThread);
2411 }
2412
2413 if (renderFlowThread && renderFlowThread != this)
2414 renderFlowThread->flowThreadDescendantWillBeRemoved(this);
2415 setFlowThreadState(NotInsideFlowThread);
2416 RELEASE_ASSERT(!spannerPlaceholder());
2417 }
2418
2419 void RenderObject::destroyAndCleanupAnonymousWrappers()
2420 {
2421 // If the tree is destroyed, there is no need for a clean-up phase.
2422 if (documentBeingDestroyed()) {
2423 destroy();
2424 return;
2425 }
2426
2427 RenderObject* destroyRoot = this;
2428 for (RenderObject* destroyRootParent = destroyRoot->parent(); destroyRootPar ent && destroyRootParent->isAnonymous(); destroyRoot = destroyRootParent, destro yRootParent = destroyRootParent->parent()) {
2429 // Anonymous block continuations are tracked and destroyed elsewhere (se e the bottom of RenderBlock::removeChild)
2430 if (destroyRootParent->isRenderBlock() && toRenderBlock(destroyRootParen t)->isAnonymousBlockContinuation())
2431 break;
2432 // A flow thread is tracked by its containing block. Whether its childre n are removed or not is irrelevant.
2433 if (destroyRootParent->isRenderFlowThread())
2434 break;
2435 // Column spans are tracked elsewhere.
2436 if (destroyRootParent->isAnonymousColumnSpanBlock())
2437 break;
2438
2439 if (destroyRootParent->slowFirstChild() != destroyRoot || destroyRootPar ent->slowLastChild() != destroyRoot)
2440 break; // Need to keep the anonymous parent, since it won't become e mpty by the removal of this renderer.
2441 }
2442
2443 destroyRoot->destroy();
2444
2445 // WARNING: |this| is deleted here.
2446 }
2447
2448 void RenderObject::destroy()
2449 {
2450 willBeDestroyed();
2451 postDestroy();
2452 }
2453
2454 void RenderObject::removeShapeImageClient(ShapeValue* shapeValue)
2455 {
2456 if (!shapeValue)
2457 return;
2458 if (StyleImage* shapeImage = shapeValue->image())
2459 shapeImage->removeClient(this);
2460 }
2461
2462 void RenderObject::postDestroy()
2463 {
2464 // It seems ugly that this is not in willBeDestroyed().
2465 if (m_style) {
2466 for (const FillLayer* bgLayer = &m_style->backgroundLayers(); bgLayer; b gLayer = bgLayer->next()) {
2467 if (StyleImage* backgroundImage = bgLayer->image())
2468 backgroundImage->removeClient(this);
2469 }
2470
2471 for (const FillLayer* maskLayer = &m_style->maskLayers(); maskLayer; mas kLayer = maskLayer->next()) {
2472 if (StyleImage* maskImage = maskLayer->image())
2473 maskImage->removeClient(this);
2474 }
2475
2476 if (StyleImage* borderImage = m_style->borderImage().image())
2477 borderImage->removeClient(this);
2478
2479 if (StyleImage* maskBoxImage = m_style->maskBoxImage().image())
2480 maskBoxImage->removeClient(this);
2481
2482 removeShapeImageClient(m_style->shapeOutside());
2483 }
2484 ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer()->removeRender Object(this);
2485 delete this;
2486 }
2487
2488 PositionWithAffinity RenderObject::positionForPoint(const LayoutPoint&)
2489 {
2490 return createPositionWithAffinity(caretMinOffset(), DOWNSTREAM);
2491 }
2492
2493 void RenderObject::updateDragState(bool dragOn)
2494 {
2495 bool valueChanged = (dragOn != isDragging());
2496 setIsDragging(dragOn);
2497 if (valueChanged && node()) {
2498 if (node()->isElementNode() && toElement(node())->childrenOrSiblingsAffe ctedByDrag())
2499 node()->setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonFor Tracing::create(StyleChangeReason::Drag));
2500 else if (style()->affectedByDrag())
2501 node()->setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTr acing::create(StyleChangeReason::Drag));
2502 }
2503 for (RenderObject* curr = slowFirstChild(); curr; curr = curr->nextSibling() )
2504 curr->updateDragState(dragOn);
2505 }
2506
2507 CompositingState RenderObject::compositingState() const
2508 {
2509 return hasLayer() ? toLayoutLayerModelObject(this)->layer()->compositingStat e() : NotComposited;
2510 }
2511
2512 CompositingReasons RenderObject::additionalCompositingReasons() const
2513 {
2514 return CompositingReasonNone;
2515 }
2516
2517 bool RenderObject::hitTest(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffse t, HitTestFilter hitTestFilter)
2518 {
2519 bool inside = false;
2520 if (hitTestFilter != HitTestSelf) {
2521 // First test the foreground layer (lines and inlines).
2522 inside = nodeAtPoint(request, result, locationInContainer, accumulatedOf fset, HitTestForeground);
2523
2524 // Test floats next.
2525 if (!inside)
2526 inside = nodeAtPoint(request, result, locationInContainer, accumulat edOffset, HitTestFloat);
2527
2528 // Finally test to see if the mouse is in the background (within a child block's background).
2529 if (!inside)
2530 inside = nodeAtPoint(request, result, locationInContainer, accumulat edOffset, HitTestChildBlockBackgrounds);
2531 }
2532
2533 // See if the mouse is inside us but not any of our descendants
2534 if (hitTestFilter != HitTestDescendants && !inside)
2535 inside = nodeAtPoint(request, result, locationInContainer, accumulatedOf fset, HitTestBlockBackground);
2536
2537 return inside;
2538 }
2539
2540 void RenderObject::updateHitTestResult(HitTestResult& result, const LayoutPoint& point)
2541 {
2542 if (result.innerNode())
2543 return;
2544
2545 Node* node = this->node();
2546
2547 // If we hit the anonymous renderers inside generated content we should
2548 // actually hit the generated content so walk up to the PseudoElement.
2549 if (!node && parent() && parent()->isBeforeOrAfterContent()) {
2550 for (RenderObject* renderer = parent(); renderer && !node; renderer = re nderer->parent())
2551 node = renderer->node();
2552 }
2553
2554 if (node) {
2555 result.setInnerNode(node);
2556 if (!result.innerNonSharedNode())
2557 result.setInnerNonSharedNode(node);
2558 result.setLocalPoint(point);
2559 }
2560 }
2561
2562 bool RenderObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitT estLocation& /*locationInContainer*/, const LayoutPoint& /*accumulatedOffset*/, HitTestAction)
2563 {
2564 return false;
2565 }
2566
2567 void RenderObject::scheduleRelayout()
2568 {
2569 if (isRenderView()) {
2570 FrameView* view = toRenderView(this)->frameView();
2571 if (view)
2572 view->scheduleRelayout();
2573 } else {
2574 if (isRooted()) {
2575 if (RenderView* renderView = view()) {
2576 if (FrameView* frameView = renderView->frameView())
2577 frameView->scheduleRelayoutOfSubtree(this);
2578 }
2579 }
2580 }
2581 }
2582
2583 void RenderObject::forceLayout()
2584 {
2585 setSelfNeedsLayout(true);
2586 setShouldDoFullPaintInvalidation();
2587 layout();
2588 }
2589
2590 // FIXME: Does this do anything different than forceLayout given that we don't w alk
2591 // the containing block chain. If not, we should change all callers to use force Layout.
2592 void RenderObject::forceChildLayout()
2593 {
2594 setNormalChildNeedsLayout(true);
2595 layout();
2596 }
2597
2598 enum StyleCacheState {
2599 Cached,
2600 Uncached
2601 };
2602
2603 static PassRefPtr<RenderStyle> firstLineStyleForCachedUncachedType(StyleCacheSta te type, const RenderObject* renderer, RenderStyle* style)
2604 {
2605 const RenderObject* rendererForFirstLineStyle = renderer;
2606 if (renderer->isBeforeOrAfterContent())
2607 rendererForFirstLineStyle = renderer->parent();
2608
2609 if (rendererForFirstLineStyle->isRenderBlockFlow() || rendererForFirstLineSt yle->isRenderButton()) {
2610 if (RenderBlock* firstLineBlock = rendererForFirstLineStyle->firstLineBl ock()) {
2611 if (type == Cached)
2612 return firstLineBlock->getCachedPseudoStyle(FIRST_LINE, style);
2613 return firstLineBlock->getUncachedPseudoStyle(PseudoStyleRequest(FIR ST_LINE), style, firstLineBlock == renderer ? style : 0);
2614 }
2615 } else if (!rendererForFirstLineStyle->isAnonymous() && rendererForFirstLine Style->isRenderInline()
2616 && !rendererForFirstLineStyle->node()->isFirstLetterPseudoElement()) {
2617 RenderStyle* parentStyle = rendererForFirstLineStyle->parent()->firstLin eStyle();
2618 if (parentStyle != rendererForFirstLineStyle->parent()->style()) {
2619 if (type == Cached) {
2620 // A first-line style is in effect. Cache a first-line style for ourselves.
2621 rendererForFirstLineStyle->style()->setHasPseudoStyle(FIRST_LINE _INHERITED);
2622 return rendererForFirstLineStyle->getCachedPseudoStyle(FIRST_LIN E_INHERITED, parentStyle);
2623 }
2624 return rendererForFirstLineStyle->getUncachedPseudoStyle(PseudoStyle Request(FIRST_LINE_INHERITED), parentStyle, style);
2625 }
2626 }
2627 return nullptr;
2628 }
2629
2630 PassRefPtr<RenderStyle> RenderObject::uncachedFirstLineStyle(RenderStyle* style) const
2631 {
2632 if (!document().styleEngine()->usesFirstLineRules())
2633 return nullptr;
2634
2635 ASSERT(!isText());
2636
2637 return firstLineStyleForCachedUncachedType(Uncached, this, style);
2638 }
2639
2640 RenderStyle* RenderObject::cachedFirstLineStyle() const
2641 {
2642 ASSERT(document().styleEngine()->usesFirstLineRules());
2643
2644 if (RefPtr<RenderStyle> style = firstLineStyleForCachedUncachedType(Cached, isText() ? parent() : this, m_style.get()))
2645 return style.get();
2646
2647 return m_style.get();
2648 }
2649
2650 RenderStyle* RenderObject::getCachedPseudoStyle(PseudoId pseudo, RenderStyle* pa rentStyle) const
2651 {
2652 if (pseudo < FIRST_INTERNAL_PSEUDOID && !style()->hasPseudoStyle(pseudo))
2653 return 0;
2654
2655 RenderStyle* cachedStyle = style()->getCachedPseudoStyle(pseudo);
2656 if (cachedStyle)
2657 return cachedStyle;
2658
2659 RefPtr<RenderStyle> result = getUncachedPseudoStyle(PseudoStyleRequest(pseud o), parentStyle);
2660 if (result)
2661 return style()->addCachedPseudoStyle(result.release());
2662 return 0;
2663 }
2664
2665 PassRefPtr<RenderStyle> RenderObject::getUncachedPseudoStyle(const PseudoStyleRe quest& pseudoStyleRequest, RenderStyle* parentStyle, RenderStyle* ownStyle) cons t
2666 {
2667 if (pseudoStyleRequest.pseudoId < FIRST_INTERNAL_PSEUDOID && !ownStyle && !s tyle()->hasPseudoStyle(pseudoStyleRequest.pseudoId))
2668 return nullptr;
2669
2670 if (!parentStyle) {
2671 ASSERT(!ownStyle);
2672 parentStyle = style();
2673 }
2674
2675 if (!node())
2676 return nullptr;
2677
2678 Element* element = Traversal<Element>::firstAncestorOrSelf(*node());
2679 if (!element)
2680 return nullptr;
2681
2682 if (pseudoStyleRequest.pseudoId == FIRST_LINE_INHERITED) {
2683 RefPtr<RenderStyle> result = document().ensureStyleResolver().styleForEl ement(element, parentStyle, DisallowStyleSharing);
2684 result->setStyleType(FIRST_LINE_INHERITED);
2685 return result.release();
2686 }
2687
2688 return document().ensureStyleResolver().pseudoStyleForElement(element, pseud oStyleRequest, parentStyle);
2689 }
2690
2691 PassRefPtr<RenderStyle> RenderObject::getUncachedPseudoStyleFromParentOrShadowHo st() const
2692 {
2693 if (!node())
2694 return nullptr;
2695
2696 if (ShadowRoot* root = node()->containingShadowRoot()) {
2697 if (root->type() == ShadowRoot::UserAgentShadowRoot) {
2698 if (Element* shadowHost = node()->shadowHost()) {
2699 return shadowHost->renderer()->getUncachedPseudoStyle(PseudoStyl eRequest(SELECTION));
2700 }
2701 }
2702 }
2703
2704 return getUncachedPseudoStyle(PseudoStyleRequest(SELECTION));
2705 }
2706
2707 void RenderObject::getTextDecorations(unsigned decorations, AppliedTextDecoratio n& underline, AppliedTextDecoration& overline, AppliedTextDecoration& linethroug h, bool quirksMode, bool firstlineStyle)
2708 {
2709 RenderObject* curr = this;
2710 RenderStyle* styleToUse = 0;
2711 unsigned currDecs = TextDecorationNone;
2712 Color resultColor;
2713 TextDecorationStyle resultStyle;
2714 do {
2715 styleToUse = curr->style(firstlineStyle);
2716 currDecs = styleToUse->textDecoration();
2717 currDecs &= decorations;
2718 resultColor = styleToUse->visitedDependentColor(CSSPropertyTextDecoratio nColor);
2719 resultStyle = styleToUse->textDecorationStyle();
2720 // Parameter 'decorations' is cast as an int to enable the bitwise opera tions below.
2721 if (currDecs) {
2722 if (currDecs & TextDecorationUnderline) {
2723 decorations &= ~TextDecorationUnderline;
2724 underline.color = resultColor;
2725 underline.style = resultStyle;
2726 }
2727 if (currDecs & TextDecorationOverline) {
2728 decorations &= ~TextDecorationOverline;
2729 overline.color = resultColor;
2730 overline.style = resultStyle;
2731 }
2732 if (currDecs & TextDecorationLineThrough) {
2733 decorations &= ~TextDecorationLineThrough;
2734 linethrough.color = resultColor;
2735 linethrough.style = resultStyle;
2736 }
2737 }
2738 if (curr->isRubyText())
2739 return;
2740 curr = curr->parent();
2741 if (curr && curr->isAnonymousBlock() && toRenderBlock(curr)->continuatio n())
2742 curr = toRenderBlock(curr)->continuation();
2743 } while (curr && decorations && (!quirksMode || !curr->node() || (!isHTMLAnc horElement(*curr->node()) && !isHTMLFontElement(*curr->node()))));
2744
2745 // If we bailed out, use the element we bailed out at (typically a <font> or <a> element).
2746 if (decorations && curr) {
2747 styleToUse = curr->style(firstlineStyle);
2748 resultColor = styleToUse->visitedDependentColor(CSSPropertyTextDecoratio nColor);
2749 if (decorations & TextDecorationUnderline) {
2750 underline.color = resultColor;
2751 underline.style = resultStyle;
2752 }
2753 if (decorations & TextDecorationOverline) {
2754 overline.color = resultColor;
2755 overline.style = resultStyle;
2756 }
2757 if (decorations & TextDecorationLineThrough) {
2758 linethrough.color = resultColor;
2759 linethrough.style = resultStyle;
2760 }
2761 }
2762 }
2763
2764 void RenderObject::addAnnotatedRegions(Vector<AnnotatedRegionValue>& regions)
2765 {
2766 // Convert the style regions to absolute coordinates.
2767 if (style()->visibility() != VISIBLE || !isBox())
2768 return;
2769
2770 if (style()->getDraggableRegionMode() == DraggableRegionNone)
2771 return;
2772
2773 RenderBox* box = toRenderBox(this);
2774 FloatRect localBounds(FloatPoint(), FloatSize(box->size()));
2775 FloatRect absBounds = localToAbsoluteQuad(localBounds).boundingBox();
2776
2777 AnnotatedRegionValue region;
2778 region.draggable = style()->getDraggableRegionMode() == DraggableRegionDrag;
2779 region.bounds = LayoutRect(absBounds);
2780 regions.append(region);
2781 }
2782
2783 void RenderObject::collectAnnotatedRegions(Vector<AnnotatedRegionValue>& regions )
2784 {
2785 // RenderTexts don't have their own style, they just use their parent's styl e,
2786 // so we don't want to include them.
2787 if (isText())
2788 return;
2789
2790 addAnnotatedRegions(regions);
2791 for (RenderObject* curr = slowFirstChild(); curr; curr = curr->nextSibling() )
2792 curr->collectAnnotatedRegions(regions);
2793 }
2794
2795 bool RenderObject::willRenderImage(ImageResource*)
2796 {
2797 // Without visibility we won't render (and therefore don't care about animat ion).
2798 if (style()->visibility() != VISIBLE)
2799 return false;
2800
2801 // We will not render a new image when Active DOM is suspended
2802 if (document().activeDOMObjectsAreSuspended())
2803 return false;
2804
2805 // If we're not in a window (i.e., we're dormant from being in a background tab)
2806 // then we don't want to render either.
2807 return document().view()->isVisible();
2808 }
2809
2810 bool RenderObject::getImageAnimationPolicy(ImageResource*, ImageAnimationPolicy& policy)
2811 {
2812 if (!document().settings())
2813 return false;
2814
2815 policy = document().settings()->imageAnimationPolicy();
2816 return true;
2817 }
2818
2819 int RenderObject::caretMinOffset() const
2820 {
2821 return 0;
2822 }
2823
2824 int RenderObject::caretMaxOffset() const
2825 {
2826 if (isReplaced())
2827 return node() ? std::max(1U, node()->countChildren()) : 1;
2828 if (isHR())
2829 return 1;
2830 return 0;
2831 }
2832
2833 int RenderObject::previousOffset(int current) const
2834 {
2835 return current - 1;
2836 }
2837
2838 int RenderObject::previousOffsetForBackwardDeletion(int current) const
2839 {
2840 return current - 1;
2841 }
2842
2843 int RenderObject::nextOffset(int current) const
2844 {
2845 return current + 1;
2846 }
2847
2848 bool RenderObject::isInert() const
2849 {
2850 const RenderObject* renderer = this;
2851 while (!renderer->node())
2852 renderer = renderer->parent();
2853 return renderer->node()->isInert();
2854 }
2855
2856 // touch-action applies to all elements with both width AND height properties.
2857 // According to the CSS Box Model Spec (http://dev.w3.org/csswg/css-box/#the-wid th-and-height-properties)
2858 // width applies to all elements but non-replaced inline elements, table rows, a nd row groups and
2859 // height applies to all elements but non-replaced inline elements, table column s, and column groups.
2860 bool RenderObject::supportsTouchAction() const
2861 {
2862 if (isInline() && !isReplaced())
2863 return false;
2864 if (isTableRow() || isLayoutTableCol())
2865 return false;
2866
2867 return true;
2868 }
2869
2870 void RenderObject::imageChanged(ImageResource* image, const IntRect* rect)
2871 {
2872 imageChanged(static_cast<WrappedImagePtr>(image), rect);
2873 }
2874
2875 Element* RenderObject::offsetParent() const
2876 {
2877 if (isDocumentElement() || isBody())
2878 return 0;
2879
2880 if (isOutOfFlowPositioned() && style()->position() == FixedPosition)
2881 return 0;
2882
2883 float effectiveZoom = style()->effectiveZoom();
2884 Node* node = 0;
2885 for (RenderObject* ancestor = parent(); ancestor; ancestor = ancestor->paren t()) {
2886 // Spec: http://www.w3.org/TR/cssom-view/#offset-attributes
2887
2888 node = ancestor->node();
2889
2890 if (!node)
2891 continue;
2892
2893 if (ancestor->isPositioned())
2894 break;
2895
2896 if (isHTMLBodyElement(*node))
2897 break;
2898
2899 if (!isPositioned() && (isHTMLTableElement(*node) || isHTMLTableCellElem ent(*node)))
2900 break;
2901
2902 // Webkit specific extension where offsetParent stops at zoom level chan ges.
2903 if (effectiveZoom != ancestor->style()->effectiveZoom())
2904 break;
2905 }
2906
2907 return node && node->isElementNode() ? toElement(node) : 0;
2908 }
2909
2910 PositionWithAffinity RenderObject::createPositionWithAffinity(int offset, EAffin ity affinity)
2911 {
2912 // If this is a non-anonymous renderer in an editable area, then it's simple .
2913 if (Node* node = nonPseudoNode()) {
2914 if (!node->hasEditableStyle()) {
2915 // If it can be found, we prefer a visually equivalent position that is editable.
2916 Position position = createLegacyEditingPosition(node, offset);
2917 Position candidate = position.downstream(CanCrossEditingBoundary);
2918 if (candidate.deprecatedNode()->hasEditableStyle())
2919 return PositionWithAffinity(candidate, affinity);
2920 candidate = position.upstream(CanCrossEditingBoundary);
2921 if (candidate.deprecatedNode()->hasEditableStyle())
2922 return PositionWithAffinity(candidate, affinity);
2923 }
2924 // FIXME: Eliminate legacy editing positions
2925 return PositionWithAffinity(createLegacyEditingPosition(node, offset), a ffinity);
2926 }
2927
2928 // We don't want to cross the boundary between editable and non-editable
2929 // regions of the document, but that is either impossible or at least
2930 // extremely unlikely in any normal case because we stop as soon as we
2931 // find a single non-anonymous renderer.
2932
2933 // Find a nearby non-anonymous renderer.
2934 RenderObject* child = this;
2935 while (RenderObject* parent = child->parent()) {
2936 // Find non-anonymous content after.
2937 for (RenderObject* renderer = child->nextInPreOrder(parent); renderer; r enderer = renderer->nextInPreOrder(parent)) {
2938 if (Node* node = renderer->nonPseudoNode())
2939 return PositionWithAffinity(firstPositionInOrBeforeNode(node), D OWNSTREAM);
2940 }
2941
2942 // Find non-anonymous content before.
2943 for (RenderObject* renderer = child->previousInPreOrder(); renderer; ren derer = renderer->previousInPreOrder()) {
2944 if (renderer == parent)
2945 break;
2946 if (Node* node = renderer->nonPseudoNode())
2947 return PositionWithAffinity(lastPositionInOrAfterNode(node), DOW NSTREAM);
2948 }
2949
2950 // Use the parent itself unless it too is anonymous.
2951 if (Node* node = parent->nonPseudoNode())
2952 return PositionWithAffinity(firstPositionInOrBeforeNode(node), DOWNS TREAM);
2953
2954 // Repeat at the next level up.
2955 child = parent;
2956 }
2957
2958 // Everything was anonymous. Give up.
2959 return PositionWithAffinity();
2960 }
2961
2962 PositionWithAffinity RenderObject::createPositionWithAffinity(const Position& po sition)
2963 {
2964 if (position.isNotNull())
2965 return PositionWithAffinity(position);
2966
2967 ASSERT(!node());
2968 return createPositionWithAffinity(0, DOWNSTREAM);
2969 }
2970
2971 CursorDirective RenderObject::getCursor(const LayoutPoint&, Cursor&) const
2972 {
2973 return SetCursorBasedOnStyle;
2974 }
2975
2976 bool RenderObject::canUpdateSelectionOnRootLineBoxes() const
2977 {
2978 if (needsLayout())
2979 return false;
2980
2981 const RenderBlock* containingBlock = this->containingBlock();
2982 return containingBlock ? !containingBlock->needsLayout() : false;
2983 }
2984
2985 // We only create "generated" child renderers like one for first-letter if:
2986 // - the firstLetterBlock can have children in the DOM and
2987 // - the block doesn't have any special assumption on its text children.
2988 // This correctly prevents form controls from having such renderers.
2989 bool RenderObject::canHaveGeneratedChildren() const
2990 {
2991 return canHaveChildren();
2992 }
2993
2994 void RenderObject::setNeedsBoundariesUpdate()
2995 {
2996 if (RenderObject* renderer = parent())
2997 renderer->setNeedsBoundariesUpdate();
2998 }
2999
3000 FloatRect RenderObject::objectBoundingBox() const
3001 {
3002 ASSERT_NOT_REACHED();
3003 return FloatRect();
3004 }
3005
3006 FloatRect RenderObject::strokeBoundingBox() const
3007 {
3008 ASSERT_NOT_REACHED();
3009 return FloatRect();
3010 }
3011
3012 // Returns the smallest rectangle enclosing all of the painted content
3013 // respecting clipping, masking, filters, opacity, stroke-width and markers
3014 FloatRect RenderObject::paintInvalidationRectInLocalCoordinates() const
3015 {
3016 ASSERT_NOT_REACHED();
3017 return FloatRect();
3018 }
3019
3020 AffineTransform RenderObject::localTransform() const
3021 {
3022 static const AffineTransform identity;
3023 return identity;
3024 }
3025
3026 const AffineTransform& RenderObject::localToParentTransform() const
3027 {
3028 static const AffineTransform identity;
3029 return identity;
3030 }
3031
3032 bool RenderObject::nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint&, HitTestAction)
3033 {
3034 ASSERT_NOT_REACHED();
3035 return false;
3036 }
3037
3038 bool RenderObject::isRelayoutBoundaryForInspector() const
3039 {
3040 return objectIsRelayoutBoundary(this);
3041 }
3042
3043 static PaintInvalidationReason documentLifecycleBasedPaintInvalidationReason(con st DocumentLifecycle& documentLifecycle)
3044 {
3045 switch (documentLifecycle.state()) {
3046 case DocumentLifecycle::InStyleRecalc:
3047 return PaintInvalidationStyleChange;
3048 case DocumentLifecycle::InPreLayout:
3049 case DocumentLifecycle::InPerformLayout:
3050 case DocumentLifecycle::AfterPerformLayout:
3051 return PaintInvalidationForcedByLayout;
3052 case DocumentLifecycle::InCompositingUpdate:
3053 return PaintInvalidationCompositingUpdate;
3054 default:
3055 return PaintInvalidationFull;
3056 }
3057 }
3058
3059 void RenderObject::setShouldDoFullPaintInvalidation(PaintInvalidationReason reas on)
3060 {
3061 // Only full invalidation reasons are allowed.
3062 ASSERT(isFullPaintInvalidationReason(reason));
3063
3064 if (m_bitfields.fullPaintInvalidationReason() == PaintInvalidationNone) {
3065 if (reason == PaintInvalidationFull)
3066 reason = documentLifecycleBasedPaintInvalidationReason(document().li fecycle());
3067 m_bitfields.setFullPaintInvalidationReason(reason);
3068 }
3069
3070 ASSERT(document().lifecycle().state() != DocumentLifecycle::InPaintInvalidat ion);
3071 frame()->page()->animator().scheduleVisualUpdate(); // In case that this is called outside of FrameView::updateLayoutAndStyleForPainting().
3072 markContainingBlockChainForPaintInvalidation();
3073 }
3074
3075 void RenderObject::setMayNeedPaintInvalidation()
3076 {
3077 if (mayNeedPaintInvalidation())
3078 return;
3079 m_bitfields.setMayNeedPaintInvalidation(true);
3080 // Make sure our parent is marked as needing invalidation.
3081 markContainingBlockChainForPaintInvalidation();
3082 frame()->page()->animator().scheduleVisualUpdate(); // In case that this is called outside of FrameView::updateLayoutAndStyleForPainting().
3083 }
3084
3085 void RenderObject::clearMayNeedPaintInvalidation()
3086 {
3087 m_bitfields.setMayNeedPaintInvalidation(false);
3088 }
3089
3090 void RenderObject::setSelfMayNeedPaintInvalidation()
3091 {
3092 m_bitfields.setMayNeedPaintInvalidation(true);
3093 }
3094
3095 void RenderObject::markContainingBlockChainForPaintInvalidation()
3096 {
3097 for (RenderObject* container = this->container(); container && !container->s houldCheckForPaintInvalidationRegardlessOfPaintInvalidationState(); container = container->container())
3098 container->setSelfMayNeedPaintInvalidation();
3099 }
3100
3101 void RenderObject::clearPaintInvalidationState(const PaintInvalidationState& pai ntInvalidationState)
3102 {
3103 // paintInvalidationStateIsDirty should be kept in sync with the
3104 // booleans that are cleared below.
3105 ASSERT(paintInvalidationState.forceCheckForPaintInvalidation() || paintInval idationStateIsDirty());
3106 clearShouldDoFullPaintInvalidation();
3107 setNeededLayoutBecauseOfChildren(false);
3108 setShouldInvalidateOverflowForPaint(false);
3109 clearLayoutDidGetCalledSinceLastFrame();
3110 clearMayNeedPaintInvalidation();
3111 clearShouldInvalidateSelection();
3112 }
3113
3114 bool RenderObject::isAllowedToModifyRenderTreeStructure(Document& document)
3115 {
3116 return DeprecatedDisableModifyRenderTreeStructureAsserts::canModifyRenderTre eStateInAnyState()
3117 || document.lifecycle().stateAllowsRenderTreeMutations();
3118 }
3119
3120 DeprecatedDisableModifyRenderTreeStructureAsserts::DeprecatedDisableModifyRender TreeStructureAsserts()
3121 : m_disabler(gModifyRenderTreeStructureAnyState, true)
3122 {
3123 }
3124
3125 bool DeprecatedDisableModifyRenderTreeStructureAsserts::canModifyRenderTreeState InAnyState()
3126 {
3127 return gModifyRenderTreeStructureAnyState;
3128 }
3129
3130 // Since we're only painting non-composited layers, we know that they all share the same paintInvalidationContainer.
3131 void RenderObject::invalidatePaintIncludingNonCompositingDescendants()
3132 {
3133 invalidatePaintIncludingNonCompositingDescendantsInternal(containerForPaintI nvalidation());
3134 }
3135
3136 void RenderObject::invalidatePaintIncludingNonCompositingDescendantsInternal(con st LayoutLayerModelObject* paintInvalidationContainer)
3137 {
3138 invalidatePaintUsingContainer(paintInvalidationContainer, previousPaintInval idationRect(), PaintInvalidationLayer);
3139
3140 for (RenderObject* child = slowFirstChild(); child; child = child->nextSibli ng()) {
3141 if (!child->isPaintInvalidationContainer())
3142 child->invalidatePaintIncludingNonCompositingDescendantsInternal(pai ntInvalidationContainer);
3143 }
3144 }
3145
3146
3147 } // namespace blink
3148
3149 #ifndef NDEBUG
3150
3151 void showTree(const blink::RenderObject* object)
3152 {
3153 if (object)
3154 object->showTreeForThis();
3155 }
3156
3157 void showLineTree(const blink::RenderObject* object)
3158 {
3159 if (object)
3160 object->showLineTreeForThis();
3161 }
3162
3163 void showRenderTree(const blink::RenderObject* object1)
3164 {
3165 showRenderTree(object1, 0);
3166 }
3167
3168 void showRenderTree(const blink::RenderObject* object1, const blink::RenderObjec t* object2)
3169 {
3170 if (object1) {
3171 const blink::RenderObject* root = object1;
3172 while (root->parent())
3173 root = root->parent();
3174 root->showRenderTreeAndMark(object1, "*", object2, "-", 0);
3175 }
3176 }
3177
3178 #endif
OLDNEW
« no previous file with comments | « Source/core/rendering/RenderObject.h ('k') | Source/core/rendering/RenderObjectChildList.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698