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.
7  *               All rights reserved.
8  * Copyright (C) 2009 Google Inc. All rights reserved.
9  * Copyright (C) 2009 Torch Mobile Inc. All rights reserved.
10  *               (http://www.torchmobile.com/)
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Library General Public
14  * License as published by the Free Software Foundation; either
15  * version 2 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public License
23  * along with this library; see the file COPYING.LIB.  If not, write to
24  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25  * Boston, MA 02110-1301, USA.
26  *
27  */
28 
29 #include "third_party/blink/renderer/core/layout/layout_object.h"
30 
31 #include <algorithm>
32 #include <memory>
33 #include <utility>
34 
35 #include "base/allocator/partition_allocator/partition_alloc.h"
36 #include "cc/base/features.h"
37 #include "third_party/blink/public/mojom/scroll/scroll_into_view_params.mojom-blink.h"
38 #include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
39 #include "third_party/blink/renderer/core/animation/element_animations.h"
40 #include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
41 #include "third_party/blink/renderer/core/css/style_change_reason.h"
42 #include "third_party/blink/renderer/core/css/style_engine.h"
43 #include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
44 #include "third_party/blink/renderer/core/dom/element_traversal.h"
45 #include "third_party/blink/renderer/core/dom/first_letter_pseudo_element.h"
46 #include "third_party/blink/renderer/core/dom/shadow_root.h"
47 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
48 #include "third_party/blink/renderer/core/editing/ephemeral_range.h"
49 #include "third_party/blink/renderer/core/editing/frame_selection.h"
50 #include "third_party/blink/renderer/core/editing/layout_selection.h"
51 #include "third_party/blink/renderer/core/editing/position_with_affinity.h"
52 #include "third_party/blink/renderer/core/editing/text_affinity.h"
53 #include "third_party/blink/renderer/core/editing/visible_units.h"
54 #include "third_party/blink/renderer/core/frame/deprecated_schedule_style_recalc_during_layout.h"
55 #include "third_party/blink/renderer/core/frame/event_handler_registry.h"
56 #include "third_party/blink/renderer/core/frame/local_frame.h"
57 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
58 #include "third_party/blink/renderer/core/frame/settings.h"
59 #include "third_party/blink/renderer/core/html/forms/html_select_element.h"
60 #include "third_party/blink/renderer/core/html/html_element.h"
61 #include "third_party/blink/renderer/core/html/html_html_element.h"
62 #include "third_party/blink/renderer/core/html/html_table_cell_element.h"
63 #include "third_party/blink/renderer/core/html/html_table_element.h"
64 #include "third_party/blink/renderer/core/html/image_document.h"
65 #include "third_party/blink/renderer/core/input/event_handler.h"
66 #include "third_party/blink/renderer/core/intersection_observer/element_intersection_observer_data.h"
67 #include "third_party/blink/renderer/core/layout/geometry/transform_state.h"
68 #include "third_party/blink/renderer/core/layout/hit_test_result.h"
69 #include "third_party/blink/renderer/core/layout/layout_counter.h"
70 #include "third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.h"
71 #include "third_party/blink/renderer/core/layout/layout_deprecated_flexible_box.h"
72 #include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
73 #include "third_party/blink/renderer/core/layout/layout_fieldset.h"
74 #include "third_party/blink/renderer/core/layout/layout_flexible_box.h"
75 #include "third_party/blink/renderer/core/layout/layout_flow_thread.h"
76 #include "third_party/blink/renderer/core/layout/layout_grid.h"
77 #include "third_party/blink/renderer/core/layout/layout_image.h"
78 #include "third_party/blink/renderer/core/layout/layout_image_resource_style_image.h"
79 #include "third_party/blink/renderer/core/layout/layout_inline.h"
80 #include "third_party/blink/renderer/core/layout/layout_list_item.h"
81 #include "third_party/blink/renderer/core/layout/layout_list_marker.h"
82 #include "third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h"
83 #include "third_party/blink/renderer/core/layout/layout_object_factory.h"
84 #include "third_party/blink/renderer/core/layout/layout_text_fragment.h"
85 #include "third_party/blink/renderer/core/layout/layout_theme.h"
86 #include "third_party/blink/renderer/core/layout/layout_view.h"
87 #include "third_party/blink/renderer/core/layout/ng/custom/layout_ng_custom.h"
88 #include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h"
89 #include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h"
90 #include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
91 #include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
92 #include "third_party/blink/renderer/core/layout/ng/ng_unpositioned_float.h"
93 #include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.h"
94 #include "third_party/blink/renderer/core/layout/svg/svg_resources.h"
95 #include "third_party/blink/renderer/core/layout/svg/svg_resources_cache.h"
96 #include "third_party/blink/renderer/core/page/autoscroll_controller.h"
97 #include "third_party/blink/renderer/core/page/page.h"
98 #include "third_party/blink/renderer/core/paint/image_element_timing.h"
99 #include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
100 #include "third_party/blink/renderer/core/paint/object_paint_invalidator.h"
101 #include "third_party/blink/renderer/core/paint/paint_layer.h"
102 #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
103 #include "third_party/blink/renderer/core/paint/paint_timing_detector.h"
104 #include "third_party/blink/renderer/core/scroll/smooth_scroll_sequencer.h"
105 #include "third_party/blink/renderer/core/style/content_data.h"
106 #include "third_party/blink/renderer/core/style/cursor_data.h"
107 #include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
108 #include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
109 #include "third_party/blink/renderer/platform/graphics/paint/property_tree_state.h"
110 #include "third_party/blink/renderer/platform/graphics/touch_action.h"
111 #include "third_party/blink/renderer/platform/instrumentation/instance_counters.h"
112 #include "third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h"
113 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
114 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
115 #include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
116 #include "third_party/blink/renderer/platform/wtf/size_assertions.h"
117 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
118 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
119 
120 namespace blink {
121 
122 namespace {
123 
124 // In order for an image to be rendered from the content property, there can be
125 // at most one piece of image content data, followed by some optional
126 // alternative text.
ShouldUseContentData(const ContentData * content_data)127 bool ShouldUseContentData(const ContentData* content_data) {
128   if (!content_data)
129     return false;
130   if (!content_data->IsImage())
131     return false;
132   if (content_data->Next() && !content_data->Next()->IsAltText())
133     return false;
134 
135   return true;
136 }
137 
138 template <typename Predicate>
FindAncestorByPredicate(const LayoutObject * descendant,LayoutObject::AncestorSkipInfo * skip_info,Predicate predicate)139 LayoutObject* FindAncestorByPredicate(const LayoutObject* descendant,
140                                       LayoutObject::AncestorSkipInfo* skip_info,
141                                       Predicate predicate) {
142   for (auto* object = descendant->Parent(); object; object = object->Parent()) {
143     if (predicate(object))
144       return object;
145     if (skip_info)
146       skip_info->Update(*object);
147 
148     // According to the HTML standard, a rendered legend is a child of a
149     // fieldset. However a rendered legend is a child of an anonymous fieldset
150     // content box in a LayoutObject tree.  NG fragment trees follow the
151     // structure of the standard.
152     //
153     // The following code resolves this inconsistency, and we skip anonymous
154     // fieldset content boxes if |descendant| is in a rendered legend.
155     if (UNLIKELY(object->IsRenderedLegend())) {
156       LayoutObject* legend_parent = object->Parent();
157       if (legend_parent->IsAnonymous()) {
158         if (skip_info)
159           skip_info->Update(*legend_parent);
160         object = legend_parent;
161       }
162     }
163   }
164   return nullptr;
165 }
166 
167 }  // namespace
168 
169 static int g_allow_destroying_layout_object_in_finalizer = 0;
170 
171 AllowDestroyingLayoutObjectInFinalizerScope::
AllowDestroyingLayoutObjectInFinalizerScope()172     AllowDestroyingLayoutObjectInFinalizerScope() {
173   ++g_allow_destroying_layout_object_in_finalizer;
174 }
175 AllowDestroyingLayoutObjectInFinalizerScope::
~AllowDestroyingLayoutObjectInFinalizerScope()176     ~AllowDestroyingLayoutObjectInFinalizerScope() {
177   CHECK_GT(g_allow_destroying_layout_object_in_finalizer, 0);
178   --g_allow_destroying_layout_object_in_finalizer;
179 }
180 
181 #if DCHECK_IS_ON()
182 
SetLayoutNeededForbiddenScope(LayoutObject & layout_object)183 LayoutObject::SetLayoutNeededForbiddenScope::SetLayoutNeededForbiddenScope(
184     LayoutObject& layout_object)
185     : layout_object_(layout_object),
186       preexisting_forbidden_(layout_object_.IsSetNeedsLayoutForbidden()) {
187   layout_object_.SetNeedsLayoutIsForbidden(true);
188 }
189 
~SetLayoutNeededForbiddenScope()190 LayoutObject::SetLayoutNeededForbiddenScope::~SetLayoutNeededForbiddenScope() {
191   layout_object_.SetNeedsLayoutIsForbidden(preexisting_forbidden_);
192 }
193 #endif
194 
195 struct SameSizeAsLayoutObject : ImageResourceObserver, DisplayItemClient {
196   // Normally this field uses the gap between DisplayItemClient and
197   // LayoutObject's other fields.
198   uint8_t paint_invalidation_reason_;
199 #if DCHECK_IS_ON()
200   unsigned debug_bitfields_;
201 #endif
202   unsigned bitfields_;
203   unsigned bitfields2_;
204   unsigned bitfields3_;
205   void* pointers[4];
206   Member<void*> members[1];
207   // The following fields are in FragmentData.
208   PhysicalOffset paint_offset_;
209   std::unique_ptr<int> rare_data_;
210 #if DCHECK_IS_ON()
211   bool is_destroyed_;
212 #endif
213 };
214 
215 ASSERT_SIZE(LayoutObject, SameSizeAsLayoutObject);
216 
217 bool LayoutObject::affects_parent_block_ = false;
218 
operator new(size_t sz)219 void* LayoutObject::operator new(size_t sz) {
220   DCHECK(IsMainThread());
221   return WTF::Partitions::LayoutPartition()->Alloc(
222       sz, WTF_HEAP_PROFILER_TYPE_NAME(LayoutObject));
223 }
224 
operator delete(void * ptr)225 void LayoutObject::operator delete(void* ptr) {
226   DCHECK(IsMainThread());
227   WTF::Partitions::LayoutPartition()->Free(ptr);
228 }
229 
CreateObject(Element * element,const ComputedStyle & style,LegacyLayout legacy)230 LayoutObject* LayoutObject::CreateObject(Element* element,
231                                          const ComputedStyle& style,
232                                          LegacyLayout legacy) {
233   DCHECK(IsAllowedToModifyLayoutTreeStructure(element->GetDocument()));
234 
235   // Minimal support for content properties replacing an entire element.
236   // Works only if we have exactly one piece of content and it's a URL, with
237   // some optional alternative text. Otherwise acts as if we didn't support this
238   // feature.
239   const ContentData* content_data = style.GetContentData();
240   if (!element->IsPseudoElement() && ShouldUseContentData(content_data)) {
241     LayoutImage* image = new LayoutImage(element);
242     // LayoutImageResourceStyleImage requires a style being present on the
243     // image but we don't want to trigger a style change now as the node is
244     // not fully attached. Moving this code to style change doesn't make sense
245     // as it should be run once at layoutObject creation.
246     image->SetStyleInternal(const_cast<ComputedStyle*>(&style));
247     if (const StyleImage* style_image =
248             To<ImageContentData>(content_data)->GetImage()) {
249       image->SetImageResource(
250           MakeGarbageCollected<LayoutImageResourceStyleImage>(
251               const_cast<StyleImage*>(style_image)));
252       image->SetIsGeneratedContent();
253     } else {
254       image->SetImageResource(MakeGarbageCollected<LayoutImageResource>());
255     }
256     image->SetStyleInternal(nullptr);
257     return image;
258   } else if (element->GetPseudoId() == kPseudoIdMarker) {
259     return LayoutObjectFactory::CreateListMarker(*element, style, legacy);
260   }
261 
262   switch (style.Display()) {
263     case EDisplay::kNone:
264     case EDisplay::kContents:
265       return nullptr;
266     case EDisplay::kInline:
267       return new LayoutInline(element);
268     case EDisplay::kBlock:
269     case EDisplay::kFlowRoot:
270     case EDisplay::kInlineBlock:
271     case EDisplay::kListItem:
272       return LayoutObjectFactory::CreateBlockFlow(*element, style, legacy);
273     case EDisplay::kTable:
274     case EDisplay::kInlineTable:
275       return LayoutObjectFactory::CreateTable(*element, style, legacy);
276     case EDisplay::kTableRowGroup:
277     case EDisplay::kTableHeaderGroup:
278     case EDisplay::kTableFooterGroup:
279       return LayoutObjectFactory::CreateTableSection(*element, style, legacy);
280     case EDisplay::kTableRow:
281       return LayoutObjectFactory::CreateTableRow(*element, style, legacy);
282     case EDisplay::kTableColumnGroup:
283     case EDisplay::kTableColumn:
284       return LayoutObjectFactory::CreateTableColumn(*element, style, legacy);
285     case EDisplay::kTableCell:
286       return LayoutObjectFactory::CreateTableCell(*element, style, legacy);
287     case EDisplay::kTableCaption:
288       return LayoutObjectFactory::CreateTableCaption(*element, style, legacy);
289     case EDisplay::kWebkitBox:
290     case EDisplay::kWebkitInlineBox:
291       if (style.IsDeprecatedWebkitBoxWithVerticalLineClamp()) {
292         return LayoutObjectFactory::CreateBlockForLineClamp(*element, style,
293                                                             legacy);
294       }
295       if (RuntimeEnabledFeatures::LayoutNGWebkitBoxEnabled())
296         return LayoutObjectFactory::CreateFlexibleBox(*element, style, legacy);
297       UseCounter::Count(element->GetDocument(),
298                         WebFeature::kLegacyLayoutByFlexBox);
299       return new LayoutFlexibleBox(element);
300     case EDisplay::kFlex:
301     case EDisplay::kInlineFlex:
302       UseCounter::Count(element->GetDocument(), WebFeature::kCSSFlexibleBox);
303       return LayoutObjectFactory::CreateFlexibleBox(*element, style, legacy);
304     case EDisplay::kGrid:
305     case EDisplay::kInlineGrid:
306       UseCounter::Count(element->GetDocument(), WebFeature::kCSSGridLayout);
307       return LayoutObjectFactory::CreateGrid(*element, style, legacy);
308     case EDisplay::kMath:
309     case EDisplay::kBlockMath:
310       return LayoutObjectFactory::CreateMath(*element, style, legacy);
311     case EDisplay::kLayoutCustom:
312     case EDisplay::kInlineLayoutCustom:
313       DCHECK(RuntimeEnabledFeatures::LayoutNGEnabled());
314       return new LayoutNGCustom(element);
315   }
316 
317   NOTREACHED();
318   return nullptr;
319 }
320 
LayoutObject(Node * node)321 LayoutObject::LayoutObject(Node* node)
322     : full_paint_invalidation_reason_(PaintInvalidationReason::kNone),
323 #if DCHECK_IS_ON()
324       has_ax_object_(false),
325       set_needs_layout_forbidden_(false),
326       as_image_observer_count_(0),
327 #endif
328       bitfields_(node),
329       style_(nullptr),
330       node_(node),
331       parent_(nullptr),
332       previous_(nullptr),
333       next_(nullptr) {
334   InstanceCounters::IncrementCounter(InstanceCounters::kLayoutObjectCounter);
335   if (node_)
336     GetFrameView()->IncrementLayoutObjectCount();
337 
338   if (UNLIKELY(!IsLayoutNGObject())) {
339     if (const auto* element = DynamicTo<Element>(GetNode())) {
340       if (element->ShouldForceLegacyLayout())
341         SetForceLegacyLayout();
342     }
343   }
344 }
345 
~LayoutObject()346 LayoutObject::~LayoutObject() {
347 #if DCHECK_IS_ON()
348   DCHECK(!has_ax_object_);
349   DCHECK(BeingDestroyed());
350 #endif
351   InstanceCounters::DecrementCounter(InstanceCounters::kLayoutObjectCounter);
352 #if DCHECK_IS_ON()
353   is_destroyed_ = true;
354 #endif
355 }
356 
IsDescendantOf(const LayoutObject * obj) const357 bool LayoutObject::IsDescendantOf(const LayoutObject* obj) const {
358   NOT_DESTROYED();
359   for (const LayoutObject* r = this; r; r = r->parent_) {
360     if (r == obj)
361       return true;
362   }
363   return false;
364 }
365 
IsHR() const366 bool LayoutObject::IsHR() const {
367   NOT_DESTROYED();
368   return IsA<HTMLHRElement>(GetNode());
369 }
370 
IsStyleGenerated() const371 bool LayoutObject::IsStyleGenerated() const {
372   NOT_DESTROYED();
373   if (const auto* layout_text_fragment = DynamicTo<LayoutTextFragment>(this))
374     return !layout_text_fragment->AssociatedTextNode();
375 
376   const Node* node = GetNode();
377   return !node || node->IsPseudoElement();
378 }
379 
SetIsInsideFlowThreadIncludingDescendants(bool inside_flow_thread)380 void LayoutObject::SetIsInsideFlowThreadIncludingDescendants(
381     bool inside_flow_thread) {
382   NOT_DESTROYED();
383   LayoutObject* next;
384   for (LayoutObject* object = this; object; object = next) {
385     // If object is a fragmentation context it already updated the descendants
386     // flag accordingly.
387     if (object->IsLayoutFlowThread()) {
388       next = object->NextInPreOrderAfterChildren(this);
389       continue;
390     }
391     next = object->NextInPreOrder(this);
392     DCHECK_NE(inside_flow_thread, object->IsInsideFlowThread());
393     object->SetIsInsideFlowThread(inside_flow_thread);
394   }
395 }
396 
RequiresAnonymousTableWrappers(const LayoutObject * new_child) const397 bool LayoutObject::RequiresAnonymousTableWrappers(
398     const LayoutObject* new_child) const {
399   NOT_DESTROYED();
400   // Check should agree with:
401   // CSS 2.1 Tables: 17.2.1 Anonymous table objects
402   // http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes
403   if (new_child->IsLayoutTableCol()) {
404     bool is_column_in_column_group =
405         new_child->StyleRef().Display() == EDisplay::kTableColumn &&
406         IsLayoutTableCol();
407     return !IsTable() && !is_column_in_column_group;
408   }
409   if (new_child->IsTableCaption())
410     return !IsTable();
411   if (new_child->IsTableSection())
412     return !IsTable();
413   if (new_child->IsTableRow())
414     return !IsTableSection();
415   if (new_child->IsTableCell())
416     return !IsTableRow();
417   return false;
418 }
419 
420 #if DCHECK_IS_ON()
421 
AssertClearedPaintInvalidationFlags() const422 void LayoutObject::AssertClearedPaintInvalidationFlags() const {
423   NOT_DESTROYED();
424   if (!PaintInvalidationStateIsDirty() || ChildPrePaintBlockedByDisplayLock())
425     return;
426   // NG text objects are exempt, as pre-paint walking doesn't visit those with
427   // no paint effects (only white-space, for instance).
428   if ((IsText() && IsLayoutNGObject()) ||
429       // and culled inline boxes too.
430       (IsInLayoutNGInlineFormattingContext() && IsLayoutInline()))
431     return;
432   ShowLayoutTreeForThis();
433   NOTREACHED();
434 }
435 
436 #endif  // DCHECK_IS_ON()
437 
438 DISABLE_CFI_PERF
AddChild(LayoutObject * new_child,LayoutObject * before_child)439 void LayoutObject::AddChild(LayoutObject* new_child,
440                             LayoutObject* before_child) {
441   NOT_DESTROYED();
442   DCHECK(IsAllowedToModifyLayoutTreeStructure(GetDocument()));
443 
444   LayoutObjectChildList* children = VirtualChildren();
445   DCHECK(children);
446   if (!children)
447     return;
448 
449   if (RequiresAnonymousTableWrappers(new_child)) {
450     // Generate an anonymous table or reuse existing one from previous child
451     // Per: 17.2.1 Anonymous table objects 3. Generate missing parents
452     // http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes
453     LayoutObject* table;
454     LayoutObject* after_child =
455         before_child ? before_child->PreviousSibling() : children->LastChild();
456     if (after_child && after_child->IsAnonymous() && after_child->IsTable() &&
457         !after_child->IsBeforeContent()) {
458       table = after_child;
459     } else {
460       table = LayoutObjectFactory::CreateAnonymousTableWithParent(*this);
461       children->InsertChildNode(this, table, before_child);
462     }
463     table->AddChild(new_child);
464   } else {
465     children->InsertChildNode(this, new_child, before_child);
466   }
467 
468   if (new_child->IsText() &&
469       new_child->StyleRef().TextTransform() == ETextTransform::kCapitalize)
470     To<LayoutText>(new_child)->TransformText();
471 }
472 
RemoveChild(LayoutObject * old_child)473 void LayoutObject::RemoveChild(LayoutObject* old_child) {
474   NOT_DESTROYED();
475   DCHECK(IsAllowedToModifyLayoutTreeStructure(GetDocument()));
476 
477   LayoutObjectChildList* children = VirtualChildren();
478   DCHECK(children);
479   if (!children)
480     return;
481 
482   children->RemoveChildNode(this, old_child);
483 }
484 
NotifyPriorityScrollAnchorStatusChanged()485 void LayoutObject::NotifyPriorityScrollAnchorStatusChanged() {
486   NOT_DESTROYED();
487   if (!Parent())
488     return;
489   for (auto* layer = Parent()->EnclosingLayer(); layer;
490        layer = layer->Parent()) {
491     if (PaintLayerScrollableArea* scrollable_area =
492             layer->GetScrollableArea()) {
493       DCHECK(scrollable_area->GetScrollAnchor());
494       scrollable_area->GetScrollAnchor()->ClearSelf();
495     }
496   }
497 }
498 
RegisterSubtreeChangeListenerOnDescendants(bool value)499 void LayoutObject::RegisterSubtreeChangeListenerOnDescendants(bool value) {
500   NOT_DESTROYED();
501   // If we're set to the same value then we're done as that means it's
502   // set down the tree that way already.
503   if (bitfields_.SubtreeChangeListenerRegistered() == value)
504     return;
505 
506   bitfields_.SetSubtreeChangeListenerRegistered(value);
507 
508   for (LayoutObject* curr = SlowFirstChild(); curr; curr = curr->NextSibling())
509     curr->RegisterSubtreeChangeListenerOnDescendants(value);
510 }
511 
NotifyAncestorsOfSubtreeChange()512 void LayoutObject::NotifyAncestorsOfSubtreeChange() {
513   NOT_DESTROYED();
514   if (bitfields_.NotifiedOfSubtreeChange())
515     return;
516 
517   bitfields_.SetNotifiedOfSubtreeChange(true);
518   if (Parent())
519     Parent()->NotifyAncestorsOfSubtreeChange();
520 }
521 
NotifyOfSubtreeChange()522 void LayoutObject::NotifyOfSubtreeChange() {
523   NOT_DESTROYED();
524   if (!bitfields_.SubtreeChangeListenerRegistered())
525     return;
526   if (bitfields_.NotifiedOfSubtreeChange())
527     return;
528 
529   NotifyAncestorsOfSubtreeChange();
530 
531   // We can modify the layout tree during layout which means that we may
532   // try to schedule this during performLayout. This should no longer
533   // happen when crbug.com/370457 is fixed.
534   DeprecatedScheduleStyleRecalcDuringLayout marker(GetDocument().Lifecycle());
535   GetDocument().ScheduleLayoutTreeUpdateIfNeeded();
536 }
537 
HandleSubtreeModifications()538 void LayoutObject::HandleSubtreeModifications() {
539   NOT_DESTROYED();
540   DCHECK(WasNotifiedOfSubtreeChange());
541   DCHECK(GetDocument().Lifecycle().StateAllowsLayoutTreeNotifications());
542 
543   if (ConsumesSubtreeChangeNotification())
544     SubtreeDidChange();
545 
546   bitfields_.SetNotifiedOfSubtreeChange(false);
547 
548   for (LayoutObject* object = SlowFirstChild(); object;
549        object = object->NextSibling()) {
550     if (!object->WasNotifiedOfSubtreeChange())
551       continue;
552     object->HandleSubtreeModifications();
553   }
554 }
555 
NextInPreOrder() const556 LayoutObject* LayoutObject::NextInPreOrder() const {
557   NOT_DESTROYED();
558   if (LayoutObject* o = SlowFirstChild())
559     return o;
560 
561   return NextInPreOrderAfterChildren();
562 }
563 
HasClipRelatedProperty() const564 bool LayoutObject::HasClipRelatedProperty() const {
565   NOT_DESTROYED();
566   // This function detects a bunch of properties that can potentially affect
567   // clip inheritance chain. However such generalization is practically useless
568   // because these properties change clip inheritance in different way that
569   // needs to be handled explicitly.
570   // CSS clip applies clip to the current element and all descendants.
571   // CSS overflow clip applies only to containing-block descendants.
572   // CSS contain:paint applies to all descendants by making itself a containing
573   // block for all descendants.
574   // CSS clip-path/mask/filter induces a stacking context and applies inherited
575   // clip to that stacking context, while resetting clip for descendants. This
576   // special behavior is already handled elsewhere.
577   if (HasClip() || HasNonVisibleOverflow())
578     return true;
579   // Paint containment establishes isolation which creates clip isolation nodes.
580   // Style & Layout containment also establish isolation (see
581   // |NeedsIsolationNodes| in PaintPropertyTreeBuilder).
582   if (ShouldApplyPaintContainment() ||
583       (ShouldApplyStyleContainment() && ShouldApplyLayoutContainment())) {
584     return true;
585   }
586   if (IsBox() && To<LayoutBox>(this)->HasControlClip())
587     return true;
588   return false;
589 }
590 
IsRenderedLegendInternal() const591 bool LayoutObject::IsRenderedLegendInternal() const {
592   NOT_DESTROYED();
593   DCHECK(IsBox());
594   DCHECK(IsRenderedLegendCandidate());
595 
596   const auto* parent = Parent();
597   // We may not be inserted into the tree yet.
598   if (!parent)
599     return false;
600   if (RuntimeEnabledFeatures::LayoutNGFieldsetEnabled()) {
601     // If there is a rendered legend, it will be found inside the anonymous
602     // fieldset wrapper. If the anonymous fieldset wrapper is a multi-column,
603     // the rendered legend will be found inside the multi-column flow thread.
604     if (parent->IsLayoutFlowThread())
605       parent = parent->Parent();
606     if (parent->IsAnonymous() && parent->Parent()->IsLayoutNGFieldset())
607       parent = parent->Parent();
608   }
609   const auto* parent_layout_block = DynamicTo<LayoutBlock>(parent);
610   return parent_layout_block && IsA<HTMLFieldSetElement>(parent->GetNode()) &&
611          LayoutFieldset::FindInFlowLegend(*parent_layout_block) == this;
612 }
613 
NextInPreOrderAfterChildren() const614 LayoutObject* LayoutObject::NextInPreOrderAfterChildren() const {
615   NOT_DESTROYED();
616   LayoutObject* o = NextSibling();
617   if (!o) {
618     o = Parent();
619     while (o && !o->NextSibling())
620       o = o->Parent();
621     if (o)
622       o = o->NextSibling();
623   }
624 
625   return o;
626 }
627 
NextInPreOrder(const LayoutObject * stay_within) const628 LayoutObject* LayoutObject::NextInPreOrder(
629     const LayoutObject* stay_within) const {
630   NOT_DESTROYED();
631   if (LayoutObject* o = SlowFirstChild())
632     return o;
633 
634   return NextInPreOrderAfterChildren(stay_within);
635 }
636 
PreviousInPostOrder(const LayoutObject * stay_within) const637 LayoutObject* LayoutObject::PreviousInPostOrder(
638     const LayoutObject* stay_within) const {
639   NOT_DESTROYED();
640   if (LayoutObject* o = SlowLastChild())
641     return o;
642 
643   return PreviousInPostOrderBeforeChildren(stay_within);
644 }
645 
NextInPreOrderAfterChildren(const LayoutObject * stay_within) const646 LayoutObject* LayoutObject::NextInPreOrderAfterChildren(
647     const LayoutObject* stay_within) const {
648   NOT_DESTROYED();
649   if (this == stay_within)
650     return nullptr;
651 
652   const LayoutObject* current = this;
653   LayoutObject* next = current->NextSibling();
654   for (; !next; next = current->NextSibling()) {
655     current = current->Parent();
656     if (!current || current == stay_within)
657       return nullptr;
658   }
659   return next;
660 }
661 
PreviousInPostOrderBeforeChildren(const LayoutObject * stay_within) const662 LayoutObject* LayoutObject::PreviousInPostOrderBeforeChildren(
663     const LayoutObject* stay_within) const {
664   NOT_DESTROYED();
665   if (this == stay_within)
666     return nullptr;
667 
668   const LayoutObject* current = this;
669   LayoutObject* previous = current->PreviousSibling();
670   for (; !previous; previous = current->PreviousSibling()) {
671     current = current->Parent();
672     if (!current || current == stay_within)
673       return nullptr;
674   }
675   return previous;
676 }
677 
PreviousInPreOrder() const678 LayoutObject* LayoutObject::PreviousInPreOrder() const {
679   NOT_DESTROYED();
680   if (LayoutObject* o = PreviousSibling()) {
681     while (LayoutObject* last_child = o->SlowLastChild())
682       o = last_child;
683     return o;
684   }
685 
686   return Parent();
687 }
688 
PreviousInPreOrder(const LayoutObject * stay_within) const689 LayoutObject* LayoutObject::PreviousInPreOrder(
690     const LayoutObject* stay_within) const {
691   NOT_DESTROYED();
692   if (this == stay_within)
693     return nullptr;
694 
695   return PreviousInPreOrder();
696 }
697 
LastLeafChild() const698 LayoutObject* LayoutObject::LastLeafChild() const {
699   NOT_DESTROYED();
700   LayoutObject* r = SlowLastChild();
701   while (r) {
702     LayoutObject* n = nullptr;
703     n = r->SlowLastChild();
704     if (!n)
705       break;
706     r = n;
707   }
708   return r;
709 }
710 
AddLayers(LayoutObject * obj,PaintLayer * parent_layer,LayoutObject * & new_object,PaintLayer * & before_child)711 static void AddLayers(LayoutObject* obj,
712                       PaintLayer* parent_layer,
713                       LayoutObject*& new_object,
714                       PaintLayer*& before_child) {
715   if (obj->HasLayer()) {
716     if (!before_child && new_object) {
717       // We need to figure out the layer that follows newObject. We only do
718       // this the first time we find a child layer, and then we update the
719       // pointer values for newObject and beforeChild used by everyone else.
720       before_child =
721           new_object->Parent()->FindNextLayer(parent_layer, new_object);
722       new_object = nullptr;
723     }
724     parent_layer->AddChild(To<LayoutBoxModelObject>(obj)->Layer(),
725                            before_child);
726     return;
727   }
728 
729   for (LayoutObject* curr = obj->SlowFirstChild(); curr;
730        curr = curr->NextSibling())
731     AddLayers(curr, parent_layer, new_object, before_child);
732 }
733 
AddLayers(PaintLayer * parent_layer)734 void LayoutObject::AddLayers(PaintLayer* parent_layer) {
735   NOT_DESTROYED();
736   if (!parent_layer)
737     return;
738 
739   LayoutObject* object = this;
740   PaintLayer* before_child = nullptr;
741   blink::AddLayers(this, parent_layer, object, before_child);
742 }
743 
RemoveLayers(PaintLayer * parent_layer)744 void LayoutObject::RemoveLayers(PaintLayer* parent_layer) {
745   NOT_DESTROYED();
746   if (!parent_layer)
747     return;
748 
749   if (HasLayer()) {
750     parent_layer->RemoveChild(To<LayoutBoxModelObject>(this)->Layer());
751     return;
752   }
753 
754   for (LayoutObject* curr = SlowFirstChild(); curr; curr = curr->NextSibling())
755     curr->RemoveLayers(parent_layer);
756 }
757 
MoveLayers(PaintLayer * old_parent,PaintLayer * new_parent)758 void LayoutObject::MoveLayers(PaintLayer* old_parent, PaintLayer* new_parent) {
759   NOT_DESTROYED();
760   if (!new_parent)
761     return;
762 
763   if (HasLayer()) {
764     PaintLayer* layer = To<LayoutBoxModelObject>(this)->Layer();
765     DCHECK_EQ(old_parent, layer->Parent());
766     if (old_parent)
767       old_parent->RemoveChild(layer);
768     new_parent->AddChild(layer);
769     return;
770   }
771 
772   for (LayoutObject* curr = SlowFirstChild(); curr; curr = curr->NextSibling())
773     curr->MoveLayers(old_parent, new_parent);
774 }
775 
FindNextLayer(PaintLayer * parent_layer,LayoutObject * start_point,bool check_parent)776 PaintLayer* LayoutObject::FindNextLayer(PaintLayer* parent_layer,
777                                         LayoutObject* start_point,
778                                         bool check_parent) {
779   NOT_DESTROYED();
780   // Error check the parent layer passed in. If it's null, we can't find
781   // anything.
782   if (!parent_layer)
783     return nullptr;
784 
785   // Step 1: If our layer is a child of the desired parent, then return our
786   // layer.
787   PaintLayer* our_layer =
788       HasLayer() ? To<LayoutBoxModelObject>(this)->Layer() : nullptr;
789   if (our_layer && our_layer->Parent() == parent_layer)
790     return our_layer;
791 
792   // Step 2: If we don't have a layer, or our layer is the desired parent, then
793   // descend into our siblings trying to find the next layer whose parent is the
794   // desired parent.
795   if (!our_layer || our_layer == parent_layer) {
796     for (LayoutObject* curr = start_point ? start_point->NextSibling()
797                                           : SlowFirstChild();
798          curr; curr = curr->NextSibling()) {
799       PaintLayer* next_layer =
800           curr->FindNextLayer(parent_layer, nullptr, false);
801       if (next_layer)
802         return next_layer;
803     }
804   }
805 
806   // Step 3: If our layer is the desired parent layer, then we're finished. We
807   // didn't find anything.
808   if (parent_layer == our_layer)
809     return nullptr;
810 
811   // Step 4: If |checkParent| is set, climb up to our parent and check its
812   // siblings that follow us to see if we can locate a layer.
813   if (check_parent && Parent())
814     return Parent()->FindNextLayer(parent_layer, this, true);
815 
816   return nullptr;
817 }
818 
EnclosingLayer() const819 PaintLayer* LayoutObject::EnclosingLayer() const {
820   NOT_DESTROYED();
821   for (const LayoutObject* current = this; current;
822        current = current->Parent()) {
823     if (current->HasLayer())
824       return To<LayoutBoxModelObject>(current)->Layer();
825   }
826   // TODO(crbug.com/365897): we should get rid of detached layout subtrees, at
827   // which point this code should not be reached.
828   return nullptr;
829 }
830 
PaintingLayer() const831 PaintLayer* LayoutObject::PaintingLayer() const {
832   NOT_DESTROYED();
833   auto FindContainer = [](const LayoutObject& object) -> const LayoutObject* {
834     if (object.IsRenderedLegend())
835       return LayoutFieldset::FindLegendContainingBlock(To<LayoutBox>(object));
836     // Use ContainingBlock() instead of ParentCrossingFrames() for floating
837     // objects to omit any self-painting layers of inline objects that don't
838     // paint the floating object. This is only needed for inline-level floats
839     // not managed by LayoutNG. LayoutNG floats are painted by the correct
840     // painting layer.
841     if (object.IsFloating() && !object.IsInLayoutNGInlineFormattingContext())
842       return object.ContainingBlock();
843     return object.ParentCrossingFrames();
844   };
845 
846   for (const LayoutObject* current = this; current;
847        current = FindContainer(*current)) {
848     if (current->HasLayer() &&
849         To<LayoutBoxModelObject>(current)->Layer()->IsSelfPaintingLayer()) {
850       return To<LayoutBoxModelObject>(current)->Layer();
851     } else if (current->IsColumnSpanAll()) {
852       // Column spanners paint through their multicolumn containers which can
853       // be accessed through the associated out-of-flow placeholder's parent.
854       current = current->SpannerPlaceholder();
855     }
856   }
857   // TODO(crbug.com/365897): we should get rid of detached layout subtrees, at
858   // which point this code should not be reached.
859   return nullptr;
860 }
861 
IsFixedPositionObjectInPagedMedia() const862 bool LayoutObject::IsFixedPositionObjectInPagedMedia() const {
863   NOT_DESTROYED();
864   if (StyleRef().GetPosition() != EPosition::kFixed)
865     return false;
866   LayoutView* view = View();
867   return Container() == view && view->PageLogicalHeight() &&
868          // TODO(crbug.com/619094): Figure out the correct behaviour for fixed
869          // position objects in paged media with vertical writing modes.
870          view->IsHorizontalWritingMode();
871 }
872 
ScrollRectToVisible(const PhysicalRect & rect,mojom::blink::ScrollIntoViewParamsPtr params)873 PhysicalRect LayoutObject::ScrollRectToVisible(
874     const PhysicalRect& rect,
875     mojom::blink::ScrollIntoViewParamsPtr params) {
876   NOT_DESTROYED();
877   LayoutBox* enclosing_box = EnclosingBox();
878   if (!enclosing_box)
879     return rect;
880 
881   GetDocument().GetFrame()->GetSmoothScrollSequencer().AbortAnimations();
882   GetDocument().GetFrame()->GetSmoothScrollSequencer().SetScrollType(
883       params->type);
884   params->is_for_scroll_sequence |=
885       params->type == mojom::blink::ScrollType::kProgrammatic;
886   PhysicalRect new_location =
887       enclosing_box->ScrollRectToVisibleRecursive(rect, std::move(params));
888   GetDocument().GetFrame()->GetSmoothScrollSequencer().RunQueuedAnimations();
889 
890   return new_location;
891 }
892 
EnclosingBox() const893 LayoutBox* LayoutObject::EnclosingBox() const {
894   NOT_DESTROYED();
895   LayoutObject* curr = const_cast<LayoutObject*>(this);
896   while (curr) {
897     if (curr->IsBox())
898       return To<LayoutBox>(curr);
899     curr = curr->Parent();
900   }
901 
902   NOTREACHED();
903   return nullptr;
904 }
905 
FragmentItemsContainer() const906 LayoutBlockFlow* LayoutObject::FragmentItemsContainer() const {
907   NOT_DESTROYED();
908   for (LayoutObject* parent = Parent(); parent; parent = parent->Parent()) {
909     if (auto* block_flow = DynamicTo<LayoutBlockFlow>(parent))
910       return block_flow;
911   }
912   return nullptr;
913 }
914 
ContainingNGBlockFlow() const915 LayoutBlockFlow* LayoutObject::ContainingNGBlockFlow() const {
916   NOT_DESTROYED();
917   DCHECK(IsInline());
918   if (!RuntimeEnabledFeatures::LayoutNGEnabled())
919     return nullptr;
920   for (LayoutObject* parent = Parent(); parent; parent = parent->Parent()) {
921     if (auto* block_flow = DynamicTo<LayoutBlockFlow>(parent)) {
922       // Skip |LayoutFlowThread| because it is skipped when finding the first
923       // child in |GetLayoutObjectForFirstChildNode|.
924       if (UNLIKELY(block_flow->IsLayoutFlowThread()))
925         block_flow = DynamicTo<LayoutBlockFlow>(block_flow->Parent());
926       if (!NGBlockNode::CanUseNewLayout(*block_flow))
927         return nullptr;
928       return block_flow;
929     }
930   }
931   return nullptr;
932 }
933 
ContainingBlockFlowFragment() const934 const NGPhysicalBoxFragment* LayoutObject::ContainingBlockFlowFragment() const {
935   NOT_DESTROYED();
936   DCHECK(IsInline() || IsText());
937   LayoutBlockFlow* const block_flow = ContainingNGBlockFlow();
938   if (!block_flow || !block_flow->ChildrenInline())
939     return nullptr;
940   // TODO(kojii): CurrentFragment isn't always available after layout clean.
941   // Investigate why.
942   return block_flow->CurrentFragment();
943 }
944 
IsFirstInlineFragmentSafe() const945 bool LayoutObject::IsFirstInlineFragmentSafe() const {
946   NOT_DESTROYED();
947   DCHECK(IsInline());
948   LayoutBlockFlow* block_flow = ContainingNGBlockFlow();
949   return block_flow && !block_flow->NeedsLayout();
950 }
951 
EnclosingScrollableBox() const952 LayoutBox* LayoutObject::EnclosingScrollableBox() const {
953   NOT_DESTROYED();
954   for (LayoutObject* ancestor = Parent(); ancestor;
955        ancestor = ancestor->Parent()) {
956     if (!ancestor->IsBox())
957       continue;
958 
959     auto* ancestor_box = To<LayoutBox>(ancestor);
960     if (ancestor_box->CanBeScrolledAndHasScrollableArea())
961       return ancestor_box;
962   }
963 
964   return nullptr;
965 }
966 
LocateFlowThreadContainingBlock() const967 LayoutFlowThread* LayoutObject::LocateFlowThreadContainingBlock() const {
968   NOT_DESTROYED();
969   DCHECK(IsInsideFlowThread());
970 
971   // See if we have the thread cached because we're in the middle of layout.
972   if (LayoutView* view = View()) {
973     if (LayoutState* layout_state = view->GetLayoutState()) {
974       // TODO(mstensho): We should really just return whatever
975       // layoutState->flowThread() returns here, also if the value is nullptr.
976       if (LayoutFlowThread* flow_thread = layout_state->FlowThread())
977         return flow_thread;
978     }
979   }
980 
981   // Not in the middle of layout so have to find the thread the slow way.
982   return LayoutFlowThread::LocateFlowThreadContainingBlockOf(
983       *this, LayoutFlowThread::kAnyAncestor);
984 }
985 
ObjectIsRelayoutBoundary(const LayoutObject * object)986 static inline bool ObjectIsRelayoutBoundary(const LayoutObject* object) {
987   // FIXME: In future it may be possible to broaden these conditions in order to
988   // improve performance.
989 
990   // Positioned objects always have self-painting layers and are safe to use as
991   // relayout boundaries.
992   bool is_svg_root = object->IsSVGRoot();
993   bool has_self_painting_layer =
994       object->HasLayer() &&
995       To<LayoutBoxModelObject>(object)->HasSelfPaintingLayer();
996   if (!has_self_painting_layer && !is_svg_root)
997     return false;
998 
999   // LayoutInline can't be relayout roots since LayoutBlockFlow is responsible
1000   // for layouting them.
1001   if (object->IsLayoutInline())
1002     return false;
1003 
1004   // Table parts can't be relayout roots since the table is responsible for
1005   // layouting all the parts.
1006   if (object->IsTablePart())
1007     return false;
1008 
1009   // OOF-positioned objects which rely on their static-position for placement
1010   // cannot be relayout boundaries (their final position would be incorrect).
1011   const ComputedStyle* style = object->Style();
1012   if (object->IsOutOfFlowPositioned() &&
1013       (style->HasAutoLeftAndRight() || style->HasAutoTopAndBottom()))
1014     return false;
1015 
1016   if (UNLIKELY(RuntimeEnabledFeatures::LayoutNGFragmentTraversalEnabled() &&
1017                object->IsLayoutNGObject())) {
1018     // We need to rebuild the entire NG fragment spine all the way from the root
1019     // (or at least the nearest self-painting paint layer), since we traverse
1020     // the fragments, and not objects. Fragment painting is initiated at
1021     // self-painting layers, but we cannot check if it's a self-painting layer
1022     // now, because it may cease to be one during layout (an object with clipped
1023     // overflow that no longer has content that requires it to clip).
1024     return false;
1025   }
1026 
1027   if (const auto* layout_box = DynamicTo<LayoutBox>(object)) {
1028     // In general we can't relayout a flex item independently of its container;
1029     // not only is the result incorrect due to the override size that's set, it
1030     // also messes with the cached main size on the flexbox.
1031     if (layout_box->IsFlexItemIncludingNG())
1032       return false;
1033 
1034     // In LayoutNG, if box has any OOF descendants, they are propagated to
1035     // parent. Therefore, we must mark parent chain for layout.
1036     if (const NGLayoutResult* layouot_result =
1037             layout_box->GetCachedLayoutResult()) {
1038       if (layouot_result->PhysicalFragment()
1039               .HasOutOfFlowPositionedDescendants())
1040         return false;
1041     }
1042   }
1043 
1044   if (object->ShouldApplyLayoutContainment() &&
1045       object->ShouldApplySizeContainment()) {
1046     return true;
1047   }
1048 
1049   // SVG roots are sufficiently self-contained to be a relayout boundary, even
1050   // if their size is non-fixed.
1051   if (is_svg_root)
1052     return true;
1053 
1054   // If either dimension is percent-based, intrinsic, or anything but fixed,
1055   // this object cannot form a re-layout boundary. A non-fixed computed logical
1056   // height will allow the object to grow and shrink based on the content
1057   // inside. The same goes for for logical width, if this objects is inside a
1058   // shrink-to-fit container, for instance.
1059   if (!style->Width().IsFixed() || !style->Height().IsFixed())
1060     return false;
1061 
1062   if (object->IsTextControlIncludingNG())
1063     return true;
1064 
1065   if (!object->HasNonVisibleOverflow())
1066     return false;
1067 
1068   // Scrollbar parts can be removed during layout. Avoid the complexity of
1069   // having to deal with that.
1070   if (object->IsLayoutCustomScrollbarPart())
1071     return false;
1072 
1073   // Inside multicol it's generally problematic to allow relayout roots. The
1074   // multicol container itself may be scheduled for relayout as well (due to
1075   // other changes that may have happened since the previous layout pass),
1076   // which might affect the column heights, which may affect how this object
1077   // breaks across columns). Spanners may also have been added or removed since
1078   // the previous layout pass, which is just another way of affecting the column
1079   // heights (and the number of rows). Instead of identifying cases where it's
1080   // safe to allow relayout roots, just disallow them inside multicol.
1081   if (object->IsInsideFlowThread())
1082     return false;
1083 
1084   return true;
1085 }
1086 
1087 // Mark this object needing to re-run |CollectInlines()|.
1088 //
1089 // The flag is propagated to its container so that NGInlineNode that contains
1090 // |this| is marked too. When |this| is a container, the propagation stops at
1091 // |this|. When invalidating on inline blocks, floats, or OOF, caller need to
1092 // pay attention whether it should mark its inner context or outer.
SetNeedsCollectInlines()1093 void LayoutObject::SetNeedsCollectInlines() {
1094   NOT_DESTROYED();
1095   if (!RuntimeEnabledFeatures::LayoutNGEnabled())
1096     return;
1097 
1098   if (NeedsCollectInlines())
1099     return;
1100 
1101   if (UNLIKELY(IsSVGChild()))
1102     return;
1103 
1104   // Don't mark |LayoutFlowThread| because |CollectInlines()| skips them.
1105   if (!IsLayoutFlowThread())
1106     SetNeedsCollectInlines(true);
1107 
1108   if (LayoutObject* parent = Parent())
1109     parent->SetChildNeedsCollectInlines();
1110 }
1111 
SetChildNeedsCollectInlines()1112 void LayoutObject::SetChildNeedsCollectInlines() {
1113   NOT_DESTROYED();
1114   if (!RuntimeEnabledFeatures::LayoutNGEnabled())
1115     return;
1116 
1117   LayoutObject* object = this;
1118   do {
1119     // Should not stop at |LayoutFlowThread| as |CollectInlines()| skips them.
1120     if (UNLIKELY(object->IsLayoutFlowThread())) {
1121       object = object->Parent();
1122       continue;
1123     }
1124     if (object->NeedsCollectInlines())
1125       break;
1126     object->SetNeedsCollectInlines(true);
1127 
1128     // Stop marking at the inline formatting context root. This is usually a
1129     // |LayoutBlockFlow|, but some other classes can have children; e.g.,
1130     // |LayoutButton| or |LayoutSVGRoot|. |LayoutInline| is the only class we
1131     // collect recursively (see |CollectInlines|). Use the same condition here.
1132     if (!object->IsLayoutInline())
1133       break;
1134 
1135     object = object->Parent();
1136   } while (object);
1137 }
1138 
MarkContainerChainForLayout(bool schedule_relayout,SubtreeLayoutScope * layouter)1139 void LayoutObject::MarkContainerChainForLayout(bool schedule_relayout,
1140                                                SubtreeLayoutScope* layouter) {
1141   NOT_DESTROYED();
1142 #if DCHECK_IS_ON()
1143   DCHECK(!IsSetNeedsLayoutForbidden());
1144 #endif
1145   DCHECK(!layouter || this != layouter->Root());
1146   // When we're in layout, we're marking a descendant as needing layout with
1147   // the intention of visiting it during this layout. We shouldn't be
1148   // scheduling it to be laid out later. Also, scheduleRelayout() must not be
1149   // called while iterating LocalFrameView::layout_subtree_root_list_.
1150   schedule_relayout &= !GetFrameView()->IsInPerformLayout();
1151 
1152   LayoutObject* object = Container();
1153   LayoutObject* last = this;
1154 
1155   bool simplified_normal_flow_layout = NeedsSimplifiedNormalFlowLayout() &&
1156                                        !SelfNeedsLayout() &&
1157                                        !NormalChildNeedsLayout();
1158 
1159   while (object) {
1160     if (object->SelfNeedsLayout())
1161       return;
1162 
1163     // Note that if the last element we processed was blocked by a display lock,
1164     // and the reason we're propagating a change is that a subtree needed layout
1165     // (ie self doesn't need layout), then we can return and stop the dirty bit
1166     // propagation. Note that it's not enough to check |object|, since the
1167     // element that is actually locked needs its child bits set properly, we
1168     // need to go one more iteration after that.
1169     if (!last->SelfNeedsLayout() && last->ChildLayoutBlockedByDisplayLock()) {
1170       return;
1171     }
1172 
1173     // Don't mark the outermost object of an unrooted subtree. That object will
1174     // be marked when the subtree is added to the document.
1175     LayoutObject* container = object->Container();
1176     if (!container && !IsA<LayoutView>(object))
1177       return;
1178     if (!last->IsTextOrSVGChild() && last->StyleRef().HasOutOfFlowPosition()) {
1179       object = last->ContainingBlock();
1180       if (object->PosChildNeedsLayout())
1181         return;
1182       container = object->Container();
1183       object->SetPosChildNeedsLayout(true);
1184       simplified_normal_flow_layout = true;
1185     } else if (simplified_normal_flow_layout) {
1186       if (object->NeedsSimplifiedNormalFlowLayout())
1187         return;
1188       object->SetNeedsSimplifiedNormalFlowLayout(true);
1189     } else {
1190       if (object->NormalChildNeedsLayout())
1191         return;
1192       object->SetNormalChildNeedsLayout(true);
1193     }
1194 #if DCHECK_IS_ON()
1195     DCHECK(!object->IsSetNeedsLayoutForbidden());
1196 #endif
1197 
1198     object->MarkSelfPaintingLayerForVisualOverflowRecalc();
1199 
1200     if (layouter) {
1201       layouter->RecordObjectMarkedForLayout(object);
1202 
1203       if (object == layouter->Root()) {
1204         if (auto* painting_layer = PaintingLayer())
1205           painting_layer->SetNeedsVisualOverflowRecalc();
1206         return;
1207       }
1208     }
1209 
1210     last = object;
1211     if (schedule_relayout && ObjectIsRelayoutBoundary(last))
1212       break;
1213     object = container;
1214   }
1215 
1216   if (schedule_relayout)
1217     last->ScheduleRelayout();
1218 }
1219 
1220 // LayoutNG has different OOF-positioned handling compared to the existing
1221 // layout system. To correctly determine the static-position of the object,
1222 // LayoutNG "bubbles" up the static-position inside the NGLayoutResult.
1223 // See: |NGLayoutResult::OutOfFlowPositionedDescendants()|.
1224 //
1225 // Whenever an OOF-positioned object is added/removed we need to invalidate
1226 // layout for all the layout objects which may have stored a NGLayoutResult
1227 // with this object contained in that list.
1228 //
1229 // In the future it may be possible to optimize this, e.g.
1230 //  - For the removal case, add a pass which modifies the layout result to
1231 //    remove the OOF-positioned descendant.
1232 //  - For the adding case, if the OOF-positioned doesn't require a
1233 //    static-position, simply insert the object up the NGLayoutResult chain with
1234 //    an invalid static-position.
MarkParentForOutOfFlowPositionedChange()1235 void LayoutObject::MarkParentForOutOfFlowPositionedChange() {
1236   NOT_DESTROYED();
1237 #if DCHECK_IS_ON()
1238   DCHECK(!IsSetNeedsLayoutForbidden());
1239 #endif
1240 
1241   LayoutObject* object = Parent();
1242   if (!object)
1243     return;
1244 
1245   // As OOF-positioned objects are represented as an object replacement
1246   // character in the inline items list. We need to ensure we collect the
1247   // inline items again to either collect or drop the OOF-positioned object.
1248   object->SetNeedsCollectInlines();
1249 
1250   const LayoutBlock* containing_block = ContainingBlock();
1251   while (object != containing_block) {
1252     object->SetChildNeedsLayout(kMarkOnlyThis);
1253     object = object->Parent();
1254   }
1255   // Finally mark the parent block for layout. This will mark everything which
1256   // has an OOF-positioned object in a NGLayoutResult as needing layout.
1257   if (object)
1258     object->SetChildNeedsLayout();
1259 }
1260 
1261 #if DCHECK_IS_ON()
CheckBlockPositionedObjectsNeedLayout()1262 void LayoutObject::CheckBlockPositionedObjectsNeedLayout() {
1263   NOT_DESTROYED();
1264   if (ChildLayoutBlockedByDisplayLock())
1265     return;
1266   DCHECK(!NeedsLayout());
1267 
1268   auto* layout_block = DynamicTo<LayoutBlock>(this);
1269   if (layout_block)
1270     layout_block->CheckPositionedObjectsNeedLayout();
1271 }
1272 #endif
1273 
SetIntrinsicLogicalWidthsDirty(MarkingBehavior mark_parents)1274 void LayoutObject::SetIntrinsicLogicalWidthsDirty(
1275     MarkingBehavior mark_parents) {
1276   NOT_DESTROYED();
1277   bitfields_.SetIntrinsicLogicalWidthsDirty(true);
1278   bitfields_.SetIntrinsicLogicalWidthsDependsOnPercentageBlockSize(true);
1279   bitfields_.SetIntrinsicLogicalWidthsChildDependsOnPercentageBlockSize(true);
1280   if (mark_parents == kMarkContainerChain &&
1281       (IsText() || !StyleRef().HasOutOfFlowPosition()))
1282     InvalidateContainerIntrinsicLogicalWidths();
1283 }
1284 
ClearIntrinsicLogicalWidthsDirty()1285 void LayoutObject::ClearIntrinsicLogicalWidthsDirty() {
1286   NOT_DESTROYED();
1287   bitfields_.SetIntrinsicLogicalWidthsDirty(false);
1288 }
1289 
IsFontFallbackValid() const1290 bool LayoutObject::IsFontFallbackValid() const {
1291   NOT_DESTROYED();
1292   return StyleRef().GetFont().IsFallbackValid() &&
1293          FirstLineStyle()->GetFont().IsFallbackValid();
1294 }
1295 
InvalidateSubtreeLayoutForFontUpdates()1296 void LayoutObject::InvalidateSubtreeLayoutForFontUpdates() {
1297   NOT_DESTROYED();
1298   if (!RuntimeEnabledFeatures::
1299           CSSReducedFontLoadingLayoutInvalidationsEnabled() ||
1300       !IsFontFallbackValid()) {
1301     SetNeedsLayoutAndIntrinsicWidthsRecalcAndFullPaintInvalidation(
1302         layout_invalidation_reason::kFontsChanged);
1303   }
1304   for (LayoutObject* child = SlowFirstChild(); child;
1305        child = child->NextSibling()) {
1306     child->InvalidateSubtreeLayoutForFontUpdates();
1307   }
1308 }
1309 
InvalidateIntersectionObserverCachedRects()1310 void LayoutObject::InvalidateIntersectionObserverCachedRects() {
1311   NOT_DESTROYED();
1312   if (GetNode() && GetNode()->IsElementNode()) {
1313     if (auto* data = To<Element>(GetNode())->IntersectionObserverData()) {
1314       data->InvalidateCachedRects();
1315     }
1316   }
1317 }
1318 
NGKeepInvalidatingBeyond(LayoutObject * o)1319 static inline bool NGKeepInvalidatingBeyond(LayoutObject* o) {
1320   // Because LayoutNG does not work on individual inline objects, we can't
1321   // use a dirty width on an inline as a signal that it is safe to stop --
1322   // inlines never get marked as clean. Instead, we need to keep going to the
1323   // next block container.
1324   // Atomic inlines do not have this problem as they are treated like blocks
1325   // in this context.
1326   // There's a similar issue for flow thread objects, as they are invisible to
1327   // LayoutNG.
1328   if (!RuntimeEnabledFeatures::LayoutNGEnabled())
1329     return false;
1330   if (o->IsLayoutInline() || o->IsText() || o->IsLayoutFlowThread())
1331     return true;
1332   return false;
1333 }
1334 
InvalidateContainerIntrinsicLogicalWidths()1335 inline void LayoutObject::InvalidateContainerIntrinsicLogicalWidths() {
1336   NOT_DESTROYED();
1337   // In order to avoid pathological behavior when inlines are deeply nested, we
1338   // do include them in the chain that we mark dirty (even though they're kind
1339   // of irrelevant).
1340   LayoutObject* o = IsTableCell() ? ContainingBlock() : Container();
1341   while (o &&
1342          (!o->IntrinsicLogicalWidthsDirty() || NGKeepInvalidatingBeyond(o))) {
1343     // Don't invalidate the outermost object of an unrooted subtree. That object
1344     // will be invalidated when the subtree is added to the document.
1345     LayoutObject* container =
1346         o->IsTableCell() ? o->ContainingBlock() : o->Container();
1347     if (!container && !IsA<LayoutView>(o))
1348       break;
1349 
1350     o->bitfields_.SetIntrinsicLogicalWidthsDirty(true);
1351     // A positioned object has no effect on the min/max width of its containing
1352     // block ever. We can optimize this case and not go up any further.
1353     if (o->StyleRef().HasOutOfFlowPosition())
1354       break;
1355     o = container;
1356   }
1357 }
1358 
ContainerForAbsolutePosition(AncestorSkipInfo * skip_info) const1359 LayoutObject* LayoutObject::ContainerForAbsolutePosition(
1360     AncestorSkipInfo* skip_info) const {
1361   NOT_DESTROYED();
1362   return FindAncestorByPredicate(this, skip_info, [](LayoutObject* candidate) {
1363     return candidate->CanContainAbsolutePositionObjects();
1364   });
1365 }
1366 
ContainerForFixedPosition(AncestorSkipInfo * skip_info) const1367 LayoutObject* LayoutObject::ContainerForFixedPosition(
1368     AncestorSkipInfo* skip_info) const {
1369   NOT_DESTROYED();
1370   DCHECK(!IsText());
1371   return FindAncestorByPredicate(this, skip_info, [](LayoutObject* candidate) {
1372     return candidate->CanContainFixedPositionObjects();
1373   });
1374 }
1375 
ContainingBlockForAbsolutePosition(AncestorSkipInfo * skip_info) const1376 LayoutBlock* LayoutObject::ContainingBlockForAbsolutePosition(
1377     AncestorSkipInfo* skip_info) const {
1378   NOT_DESTROYED();
1379   auto* container = ContainerForAbsolutePosition(skip_info);
1380   return FindNonAnonymousContainingBlock(container, skip_info);
1381 }
1382 
ContainingBlockForFixedPosition(AncestorSkipInfo * skip_info) const1383 LayoutBlock* LayoutObject::ContainingBlockForFixedPosition(
1384     AncestorSkipInfo* skip_info) const {
1385   NOT_DESTROYED();
1386   auto* container = ContainerForFixedPosition(skip_info);
1387   return FindNonAnonymousContainingBlock(container, skip_info);
1388 }
1389 
InclusiveContainingBlock() const1390 const LayoutBlock* LayoutObject::InclusiveContainingBlock() const {
1391   NOT_DESTROYED();
1392   auto* layout_block = DynamicTo<LayoutBlock>(this);
1393   return layout_block ? layout_block : ContainingBlock();
1394 }
1395 
ContainingBlock(AncestorSkipInfo * skip_info) const1396 LayoutBlock* LayoutObject::ContainingBlock(AncestorSkipInfo* skip_info) const {
1397   NOT_DESTROYED();
1398   if (!IsTextOrSVGChild()) {
1399     if (style_->GetPosition() == EPosition::kFixed)
1400       return ContainingBlockForFixedPosition(skip_info);
1401     if (style_->GetPosition() == EPosition::kAbsolute)
1402       return ContainingBlockForAbsolutePosition(skip_info);
1403   }
1404   LayoutObject* object;
1405   if (IsColumnSpanAll()) {
1406     object = SpannerPlaceholder()->ContainingBlock();
1407   } else if (IsRenderedLegend()) {
1408     return LayoutFieldset::FindLegendContainingBlock(To<LayoutBox>(*this),
1409                                                      skip_info);
1410   } else {
1411     object = Parent();
1412     if (!object && IsLayoutCustomScrollbarPart()) {
1413       object = To<LayoutCustomScrollbarPart>(this)
1414                    ->GetScrollableArea()
1415                    ->GetLayoutBox();
1416     }
1417     while (object && ((object->IsInline() && !object->IsAtomicInlineLevel()) ||
1418                       !object->IsLayoutBlock())) {
1419       if (skip_info)
1420         skip_info->Update(*object);
1421       object = object->Parent();
1422     }
1423   }
1424 
1425   return DynamicTo<LayoutBlock>(object);
1426 }
1427 
NonAnonymousAncestor() const1428 LayoutObject* LayoutObject::NonAnonymousAncestor() const {
1429   NOT_DESTROYED();
1430   LayoutObject* ancestor = Parent();
1431   while (ancestor && ancestor->IsAnonymous())
1432     ancestor = ancestor->Parent();
1433   return ancestor;
1434 }
1435 
FindNonAnonymousContainingBlock(LayoutObject * container,AncestorSkipInfo * skip_info)1436 LayoutBlock* LayoutObject::FindNonAnonymousContainingBlock(
1437     LayoutObject* container,
1438     AncestorSkipInfo* skip_info) {
1439   // For inlines, we return the nearest non-anonymous enclosing
1440   // block. We don't try to return the inline itself. This allows us to avoid
1441   // having a positioned objects list in all LayoutInlines and lets us return a
1442   // strongly-typed LayoutBlock* result from this method. The
1443   // LayoutObject::Container() method can actually be used to obtain the inline
1444   // directly.
1445   if (container && !container->IsLayoutBlock())
1446     container = container->ContainingBlock(skip_info);
1447 
1448   while (container && container->IsAnonymousBlock())
1449     container = container->ContainingBlock(skip_info);
1450 
1451   return DynamicTo<LayoutBlock>(container);
1452 }
1453 
ComputeIsFixedContainer(const ComputedStyle * style) const1454 bool LayoutObject::ComputeIsFixedContainer(const ComputedStyle* style) const {
1455   NOT_DESTROYED();
1456   if (!style)
1457     return false;
1458   bool is_document_element = IsDocumentElement();
1459   // https://www.w3.org/TR/filter-effects-1/#FilterProperty
1460   if (!is_document_element && style->HasNonInitialFilter())
1461     return true;
1462   // Backdrop-filter creates a containing block for fixed and absolute
1463   // positioned elements:
1464   // https://drafts.fxtf.org/filter-effects-2/#backdrop-filter-operation
1465   if (!is_document_element && style->HasNonInitialBackdropFilter())
1466     return true;
1467   // The LayoutView is always a container of fixed positioned descendants. In
1468   // addition, SVG foreignObjects become such containers, so that descendants
1469   // of a foreignObject cannot escape it. Similarly, text controls let authors
1470   // select elements inside that are created by user agent shadow DOM, and we
1471   // have (C++) code that assumes that the elements are indeed contained by the
1472   // text control. So just make sure this is the case.
1473   if (IsA<LayoutView>(this) || IsSVGForeignObject() ||
1474       IsTextControlIncludingNG())
1475     return true;
1476   // https://www.w3.org/TR/css-transforms-1/#containing-block-for-all-descendants
1477 
1478   if (RuntimeEnabledFeatures::TransformInteropEnabled() &&
1479       style->TransformStyle3D() == ETransformStyle3D::kPreserve3d)
1480     return true;
1481 
1482   if (style->HasTransformRelatedProperty()) {
1483     if (!IsInline() || IsAtomicInlineLevel())
1484       return true;
1485   }
1486   // https://www.w3.org/TR/css-contain-1/#containment-layout
1487   if (ShouldApplyPaintContainment(*style) ||
1488       ShouldApplyLayoutContainment(*style))
1489     return true;
1490 
1491   // We intend to change behavior to set containing block based on computed
1492   // rather than used style of transform-style. HasTransformRelatedProperty
1493   // above will return true if the *used* value of transform-style is
1494   // preserve-3d, so to estimate compat we need to count if the line below is
1495   // reached.
1496   if (style->TransformStyle3D() == ETransformStyle3D::kPreserve3d) {
1497     UseCounter::Count(
1498         GetDocument(),
1499         WebFeature::kTransformStyleContainingBlockComputedUsedMismatch);
1500   }
1501 
1502   return false;
1503 }
1504 
ComputeIsAbsoluteContainer(const ComputedStyle * style) const1505 bool LayoutObject::ComputeIsAbsoluteContainer(
1506     const ComputedStyle* style) const {
1507   NOT_DESTROYED();
1508   if (!style)
1509     return false;
1510   return style->CanContainAbsolutePositionObjects() ||
1511          ComputeIsFixedContainer(style);
1512 }
1513 
AbsoluteBoundingBoxFloatRect(MapCoordinatesFlags flags) const1514 FloatRect LayoutObject::AbsoluteBoundingBoxFloatRect(
1515     MapCoordinatesFlags flags) const {
1516   NOT_DESTROYED();
1517   DCHECK(!(flags & kIgnoreTransforms));
1518   Vector<FloatQuad> quads;
1519   AbsoluteQuads(quads, flags);
1520 
1521   wtf_size_t n = quads.size();
1522   if (n == 0)
1523     return FloatRect();
1524 
1525   FloatRect result = quads[0].BoundingBox();
1526   for (wtf_size_t i = 1; i < n; ++i)
1527     result.Unite(quads[i].BoundingBox());
1528   return result;
1529 }
1530 
AbsoluteBoundingBoxRect(MapCoordinatesFlags flags) const1531 IntRect LayoutObject::AbsoluteBoundingBoxRect(MapCoordinatesFlags flags) const {
1532   NOT_DESTROYED();
1533   DCHECK(!(flags & kIgnoreTransforms));
1534   Vector<FloatQuad> quads;
1535   AbsoluteQuads(quads, flags);
1536 
1537   wtf_size_t n = quads.size();
1538   if (!n)
1539     return IntRect();
1540 
1541   IntRect result = quads[0].EnclosingBoundingBox();
1542   for (wtf_size_t i = 1; i < n; ++i)
1543     result.Unite(quads[i].EnclosingBoundingBox());
1544   return result;
1545 }
1546 
AbsoluteBoundingBoxRectHandlingEmptyInline() const1547 PhysicalRect LayoutObject::AbsoluteBoundingBoxRectHandlingEmptyInline() const {
1548   NOT_DESTROYED();
1549   return PhysicalRect::EnclosingRect(AbsoluteBoundingBoxFloatRect());
1550 }
1551 
AbsoluteBoundingBoxRectForScrollIntoView() const1552 PhysicalRect LayoutObject::AbsoluteBoundingBoxRectForScrollIntoView() const {
1553   NOT_DESTROYED();
1554   PhysicalRect rect = AbsoluteBoundingBoxRectHandlingEmptyInline();
1555   const auto& style = StyleRef();
1556   rect.ExpandEdges(LayoutUnit(style.ScrollMarginTop()),
1557                    LayoutUnit(style.ScrollMarginRight()),
1558                    LayoutUnit(style.ScrollMarginBottom()),
1559                    LayoutUnit(style.ScrollMarginLeft()));
1560   return rect;
1561 }
1562 
AddAbsoluteRectForLayer(IntRect & result)1563 void LayoutObject::AddAbsoluteRectForLayer(IntRect& result) {
1564   NOT_DESTROYED();
1565   if (HasLayer())
1566     result.Unite(AbsoluteBoundingBoxRect());
1567   for (LayoutObject* current = SlowFirstChild(); current;
1568        current = current->NextSibling())
1569     current->AddAbsoluteRectForLayer(result);
1570 }
1571 
AbsoluteBoundingBoxRectIncludingDescendants() const1572 IntRect LayoutObject::AbsoluteBoundingBoxRectIncludingDescendants() const {
1573   NOT_DESTROYED();
1574   IntRect result = AbsoluteBoundingBoxRect();
1575   for (LayoutObject* current = SlowFirstChild(); current;
1576        current = current->NextSibling())
1577     current->AddAbsoluteRectForLayer(result);
1578   return result;
1579 }
1580 
Paint(const PaintInfo &) const1581 void LayoutObject::Paint(const PaintInfo&) const {
1582   NOT_DESTROYED();
1583 }
1584 
DirectlyCompositableContainer() const1585 const LayoutBoxModelObject& LayoutObject::DirectlyCompositableContainer()
1586     const {
1587   NOT_DESTROYED();
1588   CHECK(IsRooted());
1589 
1590   if (const LayoutBoxModelObject* container =
1591           EnclosingDirectlyCompositableContainer())
1592     return *container;
1593 
1594   // If the current frame is not composited, we send just return the main
1595   // frame's LayoutView so that we generate invalidations on the window.
1596   const LayoutView* layout_view = View();
1597   while (const LayoutObject* owner_object =
1598              layout_view->GetFrame()->OwnerLayoutObject())
1599     layout_view = owner_object->View();
1600 
1601   DCHECK(layout_view);
1602   return *layout_view;
1603 }
1604 
1605 const LayoutBoxModelObject*
EnclosingDirectlyCompositableContainer() const1606 LayoutObject::EnclosingDirectlyCompositableContainer() const {
1607   NOT_DESTROYED();
1608   DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
1609   LayoutBoxModelObject* container = nullptr;
1610   // FIXME: CompositingState is not necessarily up to date for many callers of
1611   // this function.
1612   DisableCompositingQueryAsserts disabler;
1613 
1614   if (PaintLayer* painting_layer = PaintingLayer()) {
1615     if (PaintLayer* compositing_layer =
1616             painting_layer
1617                 ->EnclosingDirectlyCompositableLayerCrossingFrameBoundaries())
1618       container = &compositing_layer->GetLayoutObject();
1619   }
1620   return container;
1621 }
1622 
RecalcLayoutOverflow()1623 RecalcLayoutOverflowResult LayoutObject::RecalcLayoutOverflow() {
1624   NOT_DESTROYED();
1625   if (!ChildNeedsLayoutOverflowRecalc())
1626     return RecalcLayoutOverflowResult();
1627 
1628   ClearChildNeedsLayoutOverflowRecalc();
1629   bool children_layout_overflow_changed = false;
1630   for (LayoutObject* current = SlowFirstChild(); current;
1631        current = current->NextSibling()) {
1632     children_layout_overflow_changed |=
1633         current->RecalcLayoutOverflow().layout_overflow_changed;
1634   }
1635   return {children_layout_overflow_changed, /* rebuild_fragment_tree */ false};
1636 }
1637 
RecalcVisualOverflow()1638 void LayoutObject::RecalcVisualOverflow() {
1639   NOT_DESTROYED();
1640   for (LayoutObject* current = SlowFirstChild(); current;
1641        current = current->NextSibling()) {
1642     if (current->HasLayer() &&
1643         To<LayoutBoxModelObject>(current)->HasSelfPaintingLayer())
1644       continue;
1645     current->RecalcVisualOverflow();
1646   }
1647 }
1648 
RecalcNormalFlowChildVisualOverflowIfNeeded()1649 void LayoutObject::RecalcNormalFlowChildVisualOverflowIfNeeded() {
1650   NOT_DESTROYED();
1651   if (IsOutOfFlowPositioned() ||
1652       (HasLayer() && To<LayoutBoxModelObject>(this)->HasSelfPaintingLayer()))
1653     return;
1654   RecalcVisualOverflow();
1655 }
1656 
HasDistortingVisualEffects() const1657 bool LayoutObject::HasDistortingVisualEffects() const {
1658   NOT_DESTROYED();
1659   // TODO(szager): Check occlusion information propagated from out-of-process
1660   // parent frame.
1661 
1662   auto& first_fragment = EnclosingLayer()->GetLayoutObject().FirstFragment();
1663   // This can happen for an iframe element which is outside the viewport and has
1664   // therefore never been painted. In that case, we do the safe thing -- report
1665   // it as having distorting visual effects.
1666   if (!first_fragment.HasLocalBorderBoxProperties())
1667     return true;
1668   auto paint_properties = first_fragment.LocalBorderBoxProperties();
1669 
1670   // No filters, no blends, no opacity < 100%.
1671   for (const auto* effect = &paint_properties.Effect().Unalias(); effect;
1672        effect = effect->UnaliasedParent()) {
1673     if (!effect->Filter().IsEmpty() || !effect->BackdropFilter().IsEmpty() ||
1674         effect->GetColorFilter() != kColorFilterNone ||
1675         effect->BlendMode() != SkBlendMode::kSrcOver ||
1676         effect->Opacity() != 1.0) {
1677       return true;
1678     }
1679   }
1680 
1681   auto& local_frame_root = GetDocument().GetFrame()->LocalFrameRoot();
1682   auto& root_fragment = local_frame_root.ContentLayoutObject()->FirstFragment();
1683   CHECK(root_fragment.HasLocalBorderBoxProperties());
1684   const auto& root_properties = root_fragment.LocalBorderBoxProperties();
1685 
1686   // The only allowed transforms are 2D translation and proportional up-scaling.
1687   const auto& translation_2d_or_matrix =
1688       GeometryMapper::SourceToDestinationProjection(
1689           paint_properties.Transform(), root_properties.Transform());
1690   if (!translation_2d_or_matrix.IsIdentityOr2DTranslation() &&
1691       !translation_2d_or_matrix.Matrix()
1692            .Is2DProportionalUpscaleAndOr2DTranslation())
1693     return true;
1694 
1695   return false;
1696 }
1697 
HasNonZeroEffectiveOpacity() const1698 bool LayoutObject::HasNonZeroEffectiveOpacity() const {
1699   NOT_DESTROYED();
1700   const FragmentData& fragment =
1701       EnclosingLayer()->GetLayoutObject().FirstFragment();
1702 
1703   // This can happen for an iframe element which is outside the viewport and has
1704   // therefore never been painted. In that case, we do the safe thing -- report
1705   // it as having non-zero opacity -- since this method is used by
1706   // IntersectionObserver to detect occlusion.
1707   if (!fragment.HasLocalBorderBoxProperties())
1708     return true;
1709 
1710   const auto& paint_properties = fragment.LocalBorderBoxProperties();
1711 
1712   for (const auto* effect = &paint_properties.Effect().Unalias(); effect;
1713        effect = effect->UnaliasedParent()) {
1714     if (effect->Opacity() == 0.0)
1715       return false;
1716   }
1717   return true;
1718 }
1719 
DecoratedName() const1720 String LayoutObject::DecoratedName() const {
1721   NOT_DESTROYED();
1722   StringBuilder name;
1723   name.Append(GetName());
1724 
1725   if (IsAnonymous())
1726     name.Append(" (anonymous)");
1727   // FIXME: Remove the special case for LayoutView here (requires rebaseline of
1728   // all tests).
1729   if (IsOutOfFlowPositioned() && !IsA<LayoutView>(this))
1730     name.Append(" (positioned)");
1731   if (IsRelPositioned())
1732     name.Append(" (relative positioned)");
1733   if (IsStickyPositioned())
1734     name.Append(" (sticky positioned)");
1735   if (IsFloating())
1736     name.Append(" (floating)");
1737   if (SpannerPlaceholder())
1738     name.Append(" (column spanner)");
1739 
1740   return name.ToString();
1741 }
1742 
DebugName() const1743 String LayoutObject::DebugName() const {
1744   NOT_DESTROYED();
1745   StringBuilder name;
1746   name.Append(DecoratedName());
1747 
1748   if (const Node* node = GetNode()) {
1749     name.Append(' ');
1750     name.Append(node->DebugName());
1751   }
1752   return name.ToString();
1753 }
1754 
OwnerNodeId() const1755 DOMNodeId LayoutObject::OwnerNodeId() const {
1756   NOT_DESTROYED();
1757   return GetNode() ? DOMNodeIds::IdForNode(GetNode()) : kInvalidDOMNodeId;
1758 }
1759 
IsPaintInvalidationContainer() const1760 bool LayoutObject::IsPaintInvalidationContainer() const {
1761   NOT_DESTROYED();
1762   return HasLayer() && To<LayoutBoxModelObject>(this)
1763                            ->Layer()
1764                            ->IsPaintInvalidationContainer();
1765 }
1766 
CanBeCompositedForDirectReasons() const1767 bool LayoutObject::CanBeCompositedForDirectReasons() const {
1768   NOT_DESTROYED();
1769   return HasLayer() && To<LayoutBoxModelObject>(this)
1770                            ->Layer()
1771                            ->CanBeCompositedForDirectReasons();
1772 }
1773 
InvalidateDisplayItemClients(PaintInvalidationReason reason) const1774 void LayoutObject::InvalidateDisplayItemClients(
1775     PaintInvalidationReason reason) const {
1776   NOT_DESTROYED();
1777   // This default implementation invalidates only the object itself as a
1778   // DisplayItemClient.
1779   DCHECK(!GetSelectionDisplayItemClient());
1780   ObjectPaintInvalidator(*this).InvalidateDisplayItemClient(*this, reason);
1781 }
1782 
CompositedScrollsWithRespectTo(const LayoutBoxModelObject & paint_invalidation_container) const1783 bool LayoutObject::CompositedScrollsWithRespectTo(
1784     const LayoutBoxModelObject& paint_invalidation_container) const {
1785   NOT_DESTROYED();
1786   return paint_invalidation_container.UsesCompositedScrolling() &&
1787          this != &paint_invalidation_container;
1788 }
1789 
AbsoluteSelectionRect() const1790 PhysicalRect LayoutObject::AbsoluteSelectionRect() const {
1791   NOT_DESTROYED();
1792   PhysicalRect selection_rect = LocalSelectionVisualRect();
1793   if (!selection_rect.IsEmpty())
1794     MapToVisualRectInAncestorSpace(View(), selection_rect);
1795 
1796   if (LocalFrameView* frame_view = GetFrameView())
1797     return frame_view->DocumentToFrame(selection_rect);
1798 
1799   return selection_rect;
1800 }
1801 
1802 DISABLE_CFI_PERF
InvalidatePaint(const PaintInvalidatorContext & context) const1803 void LayoutObject::InvalidatePaint(
1804     const PaintInvalidatorContext& context) const {
1805   NOT_DESTROYED();
1806   ObjectPaintInvalidatorWithContext(*this, context).InvalidatePaint();
1807 }
1808 
VisualRectInDocument(VisualRectFlags flags) const1809 PhysicalRect LayoutObject::VisualRectInDocument(VisualRectFlags flags) const {
1810   NOT_DESTROYED();
1811   PhysicalRect rect = LocalVisualRect();
1812   MapToVisualRectInAncestorSpace(View(), rect, flags);
1813   return rect;
1814 }
1815 
LocalVisualRectIgnoringVisibility() const1816 PhysicalRect LayoutObject::LocalVisualRectIgnoringVisibility() const {
1817   NOT_DESTROYED();
1818   NOTREACHED();
1819   return PhysicalRect();
1820 }
1821 
MapToVisualRectInAncestorSpaceInternalFastPath(const LayoutBoxModelObject * ancestor,PhysicalRect & rect,VisualRectFlags visual_rect_flags,bool & intersects) const1822 bool LayoutObject::MapToVisualRectInAncestorSpaceInternalFastPath(
1823     const LayoutBoxModelObject* ancestor,
1824     PhysicalRect& rect,
1825     VisualRectFlags visual_rect_flags,
1826     bool& intersects) const {
1827   NOT_DESTROYED();
1828   intersects = true;
1829   if (!(visual_rect_flags & kUseGeometryMapper) || !ancestor ||
1830       !ancestor->FirstFragment().HasLocalBorderBoxProperties())
1831     return false;
1832 
1833   if (ancestor == this)
1834     return true;
1835 
1836   AncestorSkipInfo skip_info(ancestor);
1837   PropertyTreeState container_properties = PropertyTreeState::Uninitialized();
1838   const LayoutObject* property_container =
1839       GetPropertyContainer(&skip_info, &container_properties);
1840   if (!property_container)
1841     return false;
1842 
1843   // This works because it's not possible to have any intervening clips,
1844   // effects, transforms between |this| and |property_container|, and therefore
1845   // FirstFragment().PaintOffset() is relative to the transform space defined by
1846   // FirstFragment().LocalBorderBoxProperties() (if this == property_container)
1847   // or property_container->FirstFragment().ContentsProperties().
1848   rect.Move(FirstFragment().PaintOffset());
1849   if (property_container != ancestor) {
1850     FloatClipRect clip_rect((FloatRect(rect)));
1851     intersects = GeometryMapper::LocalToAncestorVisualRect(
1852         container_properties, ancestor->FirstFragment().ContentsProperties(),
1853         clip_rect, kIgnoreOverlayScrollbarSize,
1854         (visual_rect_flags & kEdgeInclusive) ? kInclusiveIntersect
1855                                              : kNonInclusiveIntersect);
1856     rect = PhysicalRect::EnclosingRect(clip_rect.Rect());
1857   }
1858   rect.offset -= ancestor->FirstFragment().PaintOffset();
1859 
1860   return true;
1861 }
1862 
MapToVisualRectInAncestorSpace(const LayoutBoxModelObject * ancestor,PhysicalRect & rect,VisualRectFlags visual_rect_flags) const1863 bool LayoutObject::MapToVisualRectInAncestorSpace(
1864     const LayoutBoxModelObject* ancestor,
1865     PhysicalRect& rect,
1866     VisualRectFlags visual_rect_flags) const {
1867   NOT_DESTROYED();
1868   bool intersects = true;
1869   if (MapToVisualRectInAncestorSpaceInternalFastPath(
1870           ancestor, rect, visual_rect_flags, intersects))
1871     return intersects;
1872 
1873   TransformState transform_state(TransformState::kApplyTransformDirection,
1874                                  FloatQuad(FloatRect(rect)));
1875   intersects = MapToVisualRectInAncestorSpaceInternal(ancestor, transform_state,
1876                                                       visual_rect_flags);
1877   transform_state.Flatten();
1878   rect = PhysicalRect::EnclosingRect(
1879       transform_state.LastPlanarQuad().BoundingBox());
1880   return intersects;
1881 }
1882 
MapToVisualRectInAncestorSpaceInternal(const LayoutBoxModelObject * ancestor,TransformState & transform_state,VisualRectFlags visual_rect_flags) const1883 bool LayoutObject::MapToVisualRectInAncestorSpaceInternal(
1884     const LayoutBoxModelObject* ancestor,
1885     TransformState& transform_state,
1886     VisualRectFlags visual_rect_flags) const {
1887   NOT_DESTROYED();
1888   // For any layout object that doesn't override this method (the main example
1889   // is LayoutText), the rect is assumed to be in the parent's coordinate space,
1890   // except for container flip.
1891 
1892   if (ancestor == this)
1893     return true;
1894 
1895   if (LayoutObject* parent = Parent()) {
1896     if (parent->IsBox()) {
1897       bool preserve3d = parent->StyleRef().Preserves3D() && !parent->IsText();
1898       TransformState::TransformAccumulation accumulation =
1899           preserve3d ? TransformState::kAccumulateTransform
1900                      : TransformState::kFlattenTransform;
1901 
1902       if (parent != ancestor &&
1903           !To<LayoutBox>(parent)->MapContentsRectToBoxSpace(
1904               transform_state, accumulation, *this, visual_rect_flags))
1905         return false;
1906     }
1907     return parent->MapToVisualRectInAncestorSpaceInternal(
1908         ancestor, transform_state, visual_rect_flags);
1909   }
1910   return true;
1911 }
1912 
GetPropertyContainer(AncestorSkipInfo * skip_info,PropertyTreeStateOrAlias * container_properties) const1913 const LayoutObject* LayoutObject::GetPropertyContainer(
1914     AncestorSkipInfo* skip_info,
1915     PropertyTreeStateOrAlias* container_properties) const {
1916   NOT_DESTROYED();
1917   const LayoutObject* property_container = this;
1918   while (!property_container->FirstFragment().HasLocalBorderBoxProperties()) {
1919     property_container = property_container->Container(skip_info);
1920     if (!property_container || (skip_info && skip_info->AncestorSkipped()) ||
1921         property_container->FirstFragment().NextFragment())
1922       return nullptr;
1923   }
1924   if (container_properties) {
1925     if (property_container == this) {
1926       *container_properties = FirstFragment().LocalBorderBoxProperties();
1927     } else {
1928       *container_properties =
1929           property_container->FirstFragment().ContentsProperties();
1930     }
1931   }
1932   return property_container;
1933 }
1934 
HitTestForOcclusion(const PhysicalRect & hit_rect) const1935 HitTestResult LayoutObject::HitTestForOcclusion(
1936     const PhysicalRect& hit_rect) const {
1937   NOT_DESTROYED();
1938   LocalFrame* frame = GetDocument().GetFrame();
1939   DCHECK(!frame->View()->NeedsLayout());
1940   HitTestRequest::HitTestRequestType hit_type =
1941       HitTestRequest::kIgnorePointerEventsNone | HitTestRequest::kReadOnly |
1942       HitTestRequest::kIgnoreClipping |
1943       HitTestRequest::kIgnoreZeroOpacityObjects |
1944       HitTestRequest::kHitTestVisualOverflow;
1945   HitTestLocation location(hit_rect);
1946   return frame->GetEventHandler().HitTestResultAtLocation(location, hit_type,
1947                                                           this, true);
1948 }
1949 
DirtyLinesFromChangedChild(LayoutObject *,MarkingBehavior)1950 void LayoutObject::DirtyLinesFromChangedChild(LayoutObject*, MarkingBehavior) {
1951   NOT_DESTROYED();
1952 }
1953 
operator <<(std::ostream & out,const LayoutObject & object)1954 std::ostream& operator<<(std::ostream& out, const LayoutObject& object) {
1955   String info;
1956 #if DCHECK_IS_ON()
1957   StringBuilder string_builder;
1958   object.DumpLayoutObject(string_builder, false, 0);
1959   info = string_builder.ToString();
1960 #else
1961   info = object.DebugName();
1962 #endif
1963   return out << static_cast<const void*>(&object) << ":" << info.Utf8();
1964 }
1965 
operator <<(std::ostream & out,const LayoutObject * object)1966 std::ostream& operator<<(std::ostream& out, const LayoutObject* object) {
1967   if (!object)
1968     return out << "<null>";
1969   return out << *object;
1970 }
1971 
1972 #if DCHECK_IS_ON()
1973 
ShowTreeForThis() const1974 void LayoutObject::ShowTreeForThis() const {
1975   NOT_DESTROYED();
1976   if (GetNode())
1977     ::showTree(GetNode());
1978 }
1979 
ShowLayoutTreeForThis() const1980 void LayoutObject::ShowLayoutTreeForThis() const {
1981   NOT_DESTROYED();
1982   showLayoutTree(this, nullptr);
1983 }
1984 
ShowLineTreeForThis() const1985 void LayoutObject::ShowLineTreeForThis() const {
1986   NOT_DESTROYED();
1987   if (const LayoutBlock* cb = InclusiveContainingBlock()) {
1988     auto* child_block_flow = DynamicTo<LayoutBlockFlow>(cb);
1989     if (child_block_flow) {
1990       child_block_flow->ShowLineTreeAndMark(nullptr, nullptr, nullptr, nullptr,
1991                                             this);
1992     }
1993   }
1994 }
1995 
ShowLayoutObject() const1996 void LayoutObject::ShowLayoutObject() const {
1997   NOT_DESTROYED();
1998   StringBuilder string_builder;
1999   DumpLayoutObject(string_builder, true, kShowTreeCharacterOffset);
2000   DLOG(INFO) << "\n" << string_builder.ToString().Utf8();
2001 }
2002 
DumpLayoutObject(StringBuilder & string_builder,bool dump_address,unsigned show_tree_character_offset) const2003 void LayoutObject::DumpLayoutObject(StringBuilder& string_builder,
2004                                     bool dump_address,
2005                                     unsigned show_tree_character_offset) const {
2006   NOT_DESTROYED();
2007   string_builder.Append(DecoratedName());
2008 
2009   if (dump_address)
2010     string_builder.AppendFormat(" %p", this);
2011 
2012   if (IsText() && To<LayoutText>(this)->IsTextFragment()) {
2013     string_builder.AppendFormat(
2014         " \"%s\" ", To<LayoutText>(this)->GetText().Ascii().c_str());
2015   }
2016 
2017   if (VirtualContinuation())
2018     string_builder.AppendFormat(" continuation=%p", VirtualContinuation());
2019 
2020   if (GetNode()) {
2021     while (string_builder.length() < show_tree_character_offset)
2022       string_builder.Append(' ');
2023     string_builder.Append('\t');
2024     string_builder.Append(GetNode()->ToString());
2025   }
2026   if (ChildLayoutBlockedByDisplayLock())
2027     string_builder.Append(" (display-locked)");
2028 }
2029 
DumpLayoutTreeAndMark(StringBuilder & string_builder,const LayoutObject * marked_object1,const char * marked_label1,const LayoutObject * marked_object2,const char * marked_label2,unsigned depth) const2030 void LayoutObject::DumpLayoutTreeAndMark(StringBuilder& string_builder,
2031                                          const LayoutObject* marked_object1,
2032                                          const char* marked_label1,
2033                                          const LayoutObject* marked_object2,
2034                                          const char* marked_label2,
2035                                          unsigned depth) const {
2036   NOT_DESTROYED();
2037   StringBuilder object_info;
2038   if (marked_object1 == this && marked_label1)
2039     object_info.Append(marked_label1);
2040   if (marked_object2 == this && marked_label2)
2041     object_info.Append(marked_label2);
2042   while (object_info.length() < depth * 2)
2043     object_info.Append(' ');
2044 
2045   DumpLayoutObject(object_info, true, kShowTreeCharacterOffset);
2046   string_builder.Append(object_info);
2047 
2048   if (!ChildLayoutBlockedByDisplayLock()) {
2049     for (const LayoutObject* child = SlowFirstChild(); child;
2050          child = child->NextSibling()) {
2051       string_builder.Append('\n');
2052       child->DumpLayoutTreeAndMark(string_builder, marked_object1,
2053                                    marked_label1, marked_object2, marked_label2,
2054                                    depth + 1);
2055     }
2056   }
2057 }
2058 
2059 #endif  // DCHECK_IS_ON()
2060 
IsSelected() const2061 bool LayoutObject::IsSelected() const {
2062   NOT_DESTROYED();
2063   // Keep this fast and small, used in very hot functions to skip computing
2064   // selection when this is not selected. This function may be inlined in
2065   // link-optimized builds, but keeping fast and small helps running perf
2066   // tests.
2067   return GetSelectionState() != SelectionState::kNone ||
2068          // TODO(kojii): Can't we set SelectionState() properly to
2069          // LayoutTextFragment too?
2070          (IsA<LayoutTextFragment>(*this) && LayoutSelection::IsSelected(*this));
2071 }
2072 
IsSelectable() const2073 bool LayoutObject::IsSelectable() const {
2074   NOT_DESTROYED();
2075   return !IsInert() && !(StyleRef().UserSelect() == EUserSelect::kNone &&
2076                          StyleRef().UserModify() == EUserModify::kReadOnly);
2077 }
2078 
SlowEffectiveStyle(NGStyleVariant style_variant) const2079 const ComputedStyle& LayoutObject::SlowEffectiveStyle(
2080     NGStyleVariant style_variant) const {
2081   NOT_DESTROYED();
2082   switch (style_variant) {
2083     case NGStyleVariant::kStandard:
2084       return StyleRef();
2085     case NGStyleVariant::kFirstLine:
2086       return FirstLineStyleRef();
2087     case NGStyleVariant::kEllipsis:
2088       // The ellipsis is styled according to the line style.
2089       // https://www.w3.org/TR/css-overflow-3/#ellipsing-details
2090       // Use first-line style if exists since most cases it is the first line.
2091       DCHECK(IsInline());
2092       if (LayoutObject* block = ContainingBlock())
2093         return block->FirstLineStyleRef();
2094       return FirstLineStyleRef();
2095   }
2096   NOTREACHED();
2097   return StyleRef();
2098 }
2099 
2100 // Called when an object that was floating or positioned becomes a normal flow
2101 // object again. We have to make sure the layout tree updates as needed to
2102 // accommodate the new normal flow object.
HandleDynamicFloatPositionChange(LayoutObject * object)2103 static inline void HandleDynamicFloatPositionChange(LayoutObject* object) {
2104   // We have gone from not affecting the inline status of the parent flow to
2105   // suddenly having an impact.  See if there is a mismatch between the parent
2106   // flow's childrenInline() state and our state.
2107   object->SetInline(object->StyleRef().IsDisplayInlineType());
2108   if (object->IsInline() != object->Parent()->ChildrenInline()) {
2109     if (!object->IsInline()) {
2110       To<LayoutBoxModelObject>(object->Parent())->ChildBecameNonInline(object);
2111     } else {
2112       // An anonymous block must be made to wrap this inline.
2113       LayoutBlock* block =
2114           To<LayoutBlock>(object->Parent())->CreateAnonymousBlock();
2115       LayoutObjectChildList* childlist = object->Parent()->VirtualChildren();
2116       childlist->InsertChildNode(object->Parent(), block, object);
2117       block->Children()->AppendChildNode(
2118           block, childlist->RemoveChildNode(object->Parent(), object));
2119     }
2120   }
2121 }
2122 
AdjustStyleDifference(StyleDifference diff) const2123 StyleDifference LayoutObject::AdjustStyleDifference(
2124     StyleDifference diff) const {
2125   NOT_DESTROYED();
2126   if (diff.TransformChanged() && IsSVG()) {
2127     // Skip a full layout for transforms at the html/svg boundary which do not
2128     // affect sizes inside SVG.
2129     if (!IsSVGRoot())
2130       diff.SetNeedsFullLayout();
2131   }
2132 
2133   // Optimization: for decoration/color property changes, invalidation is only
2134   // needed if we have style or text affected by these properties.
2135   if (diff.TextDecorationOrColorChanged() && !diff.NeedsPaintInvalidation()) {
2136     if (StyleRef().HasBorderColorReferencingCurrentColor() ||
2137         StyleRef().HasOutlineWithCurrentColor() ||
2138         StyleRef().HasBackgroundRelatedColorReferencingCurrentColor() ||
2139         // Skip any text nodes that do not contain text boxes. Whitespace cannot
2140         // be skipped or we will miss invalidating decorations (e.g.,
2141         // underlines). MathML elements are not skipped either as some of them
2142         // do special painting (e.g. fraction bar).
2143         (IsText() && !IsBR() && To<LayoutText>(this)->HasInlineFragments()) ||
2144         (IsSVG() && StyleRef().SvgStyle().IsFillColorCurrentColor()) ||
2145         (IsSVG() && StyleRef().SvgStyle().IsStrokeColorCurrentColor()) ||
2146         IsListMarkerForNormalContent() || IsDetailsMarker() || IsMathML())
2147       diff.SetNeedsPaintInvalidation();
2148   }
2149 
2150   // TODO(1088373): Pixel_WebGLHighToLowPower fails without this. This isn't the
2151   // right way to ensure GPU switching. Investigate and do it in the right way.
2152   if (!diff.NeedsPaintInvalidation() && IsLayoutView() && Style() &&
2153       !Style()->GetFont().IsFallbackValid()) {
2154     diff.SetNeedsPaintInvalidation();
2155   }
2156 
2157   // The answer to layerTypeRequired() for plugins, iframes, and canvas can
2158   // change without the actual style changing, since it depends on whether we
2159   // decide to composite these elements. When the/ layer status of one of these
2160   // elements changes, we need to force a layout.
2161   if (!diff.NeedsFullLayout() && Style() && IsBoxModelObject()) {
2162     bool requires_layer =
2163         To<LayoutBoxModelObject>(this)->LayerTypeRequired() != kNoPaintLayer;
2164     if (HasLayer() != requires_layer)
2165       diff.SetNeedsFullLayout();
2166   }
2167 
2168   return diff;
2169 }
2170 
SetPseudoElementStyle(scoped_refptr<const ComputedStyle> pseudo_style)2171 void LayoutObject::SetPseudoElementStyle(
2172     scoped_refptr<const ComputedStyle> pseudo_style) {
2173   NOT_DESTROYED();
2174   DCHECK(pseudo_style->StyleType() == kPseudoIdBefore ||
2175          pseudo_style->StyleType() == kPseudoIdAfter ||
2176          pseudo_style->StyleType() == kPseudoIdMarker ||
2177          pseudo_style->StyleType() == kPseudoIdFirstLetter);
2178 
2179   // FIXME: We should consider just making all pseudo items use an inherited
2180   // style.
2181 
2182   // Images are special and must inherit the pseudoStyle so the width and height
2183   // of the pseudo element doesn't change the size of the image. In all other
2184   // cases we can just share the style.
2185   //
2186   // Quotes are also LayoutInline, so we need to create an inherited style to
2187   // avoid getting an inline with positioning or an invalid display.
2188   //
2189   if (IsImage() || IsQuote()) {
2190     scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
2191     style->InheritFrom(*pseudo_style);
2192     SetStyle(std::move(style));
2193     return;
2194   }
2195 
2196   SetStyle(std::move(pseudo_style));
2197 }
2198 
MarkContainerChainForOverflowRecalcIfNeeded(bool mark_container_chain_layout_overflow_recalc)2199 void LayoutObject::MarkContainerChainForOverflowRecalcIfNeeded(
2200     bool mark_container_chain_layout_overflow_recalc) {
2201   NOT_DESTROYED();
2202   LayoutObject* object = this;
2203   do {
2204     // Cell and row need to propagate the flag to their containing section and
2205     // row as their containing block is the table wrapper.
2206     // This enables us to only recompute overflow the modified sections / rows.
2207     object = object->IsTableCell() || object->IsTableRow()
2208                  ? object->Parent()
2209                  : object->Container();
2210     if (object) {
2211       bool already_needs_layout_overflow_recalc = false;
2212       if (mark_container_chain_layout_overflow_recalc) {
2213         already_needs_layout_overflow_recalc =
2214             object->ChildNeedsLayoutOverflowRecalc();
2215         if (!already_needs_layout_overflow_recalc)
2216           object->SetChildNeedsLayoutOverflowRecalc();
2217       }
2218 
2219       if (object->HasLayer()) {
2220         auto* box_model_object = To<LayoutBoxModelObject>(object);
2221         if (box_model_object->HasSelfPaintingLayer()) {
2222           auto* layer = box_model_object->Layer();
2223           if (layer->NeedsVisualOverflowRecalc()) {
2224             if (already_needs_layout_overflow_recalc)
2225               return;
2226           } else {
2227             layer->SetNeedsVisualOverflowRecalc();
2228           }
2229         }
2230       }
2231     }
2232 
2233   } while (object);
2234 }
2235 
SetNeedsOverflowRecalc(OverflowRecalcType overflow_recalc_type)2236 void LayoutObject::SetNeedsOverflowRecalc(
2237     OverflowRecalcType overflow_recalc_type) {
2238   NOT_DESTROYED();
2239   bool mark_container_chain_layout_overflow_recalc =
2240       !SelfNeedsLayoutOverflowRecalc();
2241 
2242   if (overflow_recalc_type ==
2243       OverflowRecalcType::kLayoutAndVisualOverflowRecalc) {
2244     SetSelfNeedsLayoutOverflowRecalc();
2245   }
2246 
2247   DCHECK(overflow_recalc_type ==
2248              OverflowRecalcType::kOnlyVisualOverflowRecalc ||
2249          overflow_recalc_type ==
2250              OverflowRecalcType::kLayoutAndVisualOverflowRecalc);
2251   SetShouldCheckForPaintInvalidation();
2252   MarkSelfPaintingLayerForVisualOverflowRecalc();
2253 
2254   if (mark_container_chain_layout_overflow_recalc) {
2255     MarkContainerChainForOverflowRecalcIfNeeded(
2256         overflow_recalc_type ==
2257         OverflowRecalcType::kLayoutAndVisualOverflowRecalc);
2258   }
2259 }
2260 
2261 DISABLE_CFI_PERF
SetStyle(scoped_refptr<const ComputedStyle> style,ApplyStyleChanges apply_changes)2262 void LayoutObject::SetStyle(scoped_refptr<const ComputedStyle> style,
2263                             ApplyStyleChanges apply_changes) {
2264   NOT_DESTROYED();
2265   if (style_ == style)
2266     return;
2267 
2268   if (apply_changes == ApplyStyleChanges::kNo) {
2269     SetStyleInternal(std::move(style));
2270     return;
2271   }
2272 
2273   DCHECK(style);
2274 
2275   StyleDifference diff;
2276   if (style_) {
2277     diff = style_->VisualInvalidationDiff(GetDocument(), *style);
2278     if (const auto* cached_inherited_first_line_style =
2279             style_->GetCachedPseudoElementStyle(kPseudoIdFirstLineInherited)) {
2280       // Merge the difference to the first line style because even if the new
2281       // style is the same as the old style, the new style may have some higher
2282       // priority properties overriding first line style.
2283       // See external/wpt/css/css-pseudo/first-line-change-inline-color*.html.
2284       diff.Merge(cached_inherited_first_line_style->VisualInvalidationDiff(
2285           GetDocument(), *style));
2286     }
2287   }
2288 
2289   diff = AdjustStyleDifference(diff);
2290 
2291   StyleWillChange(diff, *style);
2292 
2293   scoped_refptr<const ComputedStyle> old_style = std::move(style_);
2294   SetStyleInternal(std::move(style));
2295 
2296   if (!IsText())
2297     UpdateImageObservers(old_style.get(), style_.get());
2298 
2299   CheckCounterChanges(old_style.get(), style_.get());
2300 
2301   bool does_not_need_layout_or_paint_invalidation = !parent_;
2302 
2303   StyleDidChange(diff, old_style.get());
2304 
2305   // FIXME: |this| might be destroyed here. This can currently happen for a
2306   // LayoutTextFragment when its first-letter block gets an update in
2307   // LayoutTextFragment::styleDidChange. For LayoutTextFragment(s),
2308   // we will safely bail out with the doesNotNeedLayoutOrPaintInvalidation flag.
2309   // We might want to broaden this condition in the future as we move
2310   // layoutObject changes out of layout and into style changes.
2311   if (does_not_need_layout_or_paint_invalidation)
2312     return;
2313 
2314   // Now that the layer (if any) has been updated, we need to adjust the diff
2315   // again, check whether we should layout now, and decide if we need to
2316   // invalidate paints.
2317   StyleDifference updated_diff = AdjustStyleDifference(diff);
2318 
2319   if (!diff.NeedsFullLayout()) {
2320     if (updated_diff.NeedsFullLayout()) {
2321       SetNeedsLayoutAndIntrinsicWidthsRecalc(
2322           layout_invalidation_reason::kStyleChange);
2323     } else if (updated_diff.NeedsPositionedMovementLayout()) {
2324       SetNeedsPositionedMovementLayout();
2325     }
2326   }
2327 
2328   // TODO(cbiesinger): Shouldn't this check container->NeedsLayout, since that's
2329   // the one we'll mark for NeedsOverflowRecalc()?
2330   if (diff.TransformChanged() && !NeedsLayout()) {
2331     if (LayoutBlock* container = ContainingBlock())
2332       container->SetNeedsOverflowRecalc();
2333   }
2334 
2335   if (diff.NeedsRecomputeVisualOverflow()) {
2336     if (!(IsInLayoutNGInlineFormattingContext() &&
2337           RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) &&
2338         !IsLayoutNGObject() && !IsLayoutBlock() && !NeedsLayout()) {
2339       // TODO(crbug.com/1128199): This is still needed because
2340       // RecalcVisualOverflow() does not actually compute the visual overflow
2341       // for inline elements (legacy layout). However in LayoutNG
2342       // RecalcInlineChildrenInkOverflow() is called and visual overflow is
2343       // recomputed properly so we don't need this (see crbug.com/1043927).
2344       SetNeedsLayoutAndIntrinsicWidthsRecalc(
2345           layout_invalidation_reason::kStyleChange);
2346     } else {
2347       if (IsInLayoutNGInlineFormattingContext() && !NeedsLayout() &&
2348           RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
2349         if (auto* text = DynamicTo<LayoutText>(this))
2350           text->InvalidateVisualOverflow();
2351       }
2352       PaintingLayer()->SetNeedsVisualOverflowRecalc();
2353       SetShouldCheckForPaintInvalidation();
2354     }
2355   }
2356 
2357   if (diff.NeedsPaintInvalidation() || updated_diff.NeedsPaintInvalidation()) {
2358     if (IsSVGRoot()) {
2359       // LayoutSVGRoot::LocalVisualRect() depends on some styles.
2360       SetShouldDoFullPaintInvalidation();
2361     } else {
2362       // We'll set needing geometry change later if the style change does cause
2363       // possible layout change or visual overflow change.
2364       SetShouldDoFullPaintInvalidationWithoutGeometryChange();
2365     }
2366   }
2367 
2368   if (diff.NeedsPaintInvalidation() && old_style &&
2369       !old_style->ClipPathDataEquivalent(*style_)) {
2370     InvalidateClipPathCache();
2371     PaintingLayer()->SetNeedsCompositingInputsUpdate();
2372   }
2373 
2374   if (diff.NeedsVisualRectUpdate())
2375     SetShouldCheckForPaintInvalidation();
2376 
2377   // Text nodes share style with their parents but the paint properties don't
2378   // apply to them, hence the !isText() check. If property nodes are added or
2379   // removed as a result of these style changes, PaintPropertyTreeBuilder will
2380   // call SetNeedsRepaint to cause re-generation of PaintChunks.
2381   // This is skipped if no layer is present because |PaintLayer::StyleDidChange|
2382   // will handle this invalidation.
2383   if (!IsText() && !HasLayer() &&
2384       (diff.TransformChanged() || diff.OpacityChanged() ||
2385        diff.ZIndexChanged() || diff.FilterChanged() || diff.CssClipChanged() ||
2386        diff.BlendModeChanged() || diff.MaskChanged() ||
2387        diff.CompositingReasonsChanged())) {
2388     SetNeedsPaintPropertyUpdate();
2389   }
2390 }
2391 
UpdateImageObservers(const ComputedStyle * old_style,const ComputedStyle * new_style)2392 void LayoutObject::UpdateImageObservers(const ComputedStyle* old_style,
2393                                         const ComputedStyle* new_style) {
2394   NOT_DESTROYED();
2395   DCHECK(old_style || new_style);
2396   DCHECK(!IsText());
2397 
2398   UpdateFillImages(old_style ? &old_style->BackgroundLayers() : nullptr,
2399                    new_style ? &new_style->BackgroundLayers() : nullptr);
2400   UpdateFillImages(old_style ? &old_style->MaskLayers() : nullptr,
2401                    new_style ? &new_style->MaskLayers() : nullptr);
2402 
2403   UpdateImage(old_style ? old_style->BorderImage().GetImage() : nullptr,
2404               new_style ? new_style->BorderImage().GetImage() : nullptr);
2405   UpdateImage(old_style ? old_style->MaskBoxImage().GetImage() : nullptr,
2406               new_style ? new_style->MaskBoxImage().GetImage() : nullptr);
2407 
2408   StyleImage* old_content_image =
2409       old_style && old_style->GetContentData() &&
2410               old_style->GetContentData()->IsImage()
2411           ? To<ImageContentData>(old_style->GetContentData())->GetImage()
2412           : nullptr;
2413   StyleImage* new_content_image =
2414       new_style && new_style->GetContentData() &&
2415               new_style->GetContentData()->IsImage()
2416           ? To<ImageContentData>(new_style->GetContentData())->GetImage()
2417           : nullptr;
2418   UpdateImage(old_content_image, new_content_image);
2419 
2420   StyleImage* old_box_reflect_mask_image =
2421       old_style && old_style->BoxReflect()
2422           ? old_style->BoxReflect()->Mask().GetImage()
2423           : nullptr;
2424   StyleImage* new_box_reflect_mask_image =
2425       new_style && new_style->BoxReflect()
2426           ? new_style->BoxReflect()->Mask().GetImage()
2427           : nullptr;
2428   UpdateImage(old_box_reflect_mask_image, new_box_reflect_mask_image);
2429 
2430   UpdateShapeImage(old_style ? old_style->ShapeOutside() : nullptr,
2431                    new_style ? new_style->ShapeOutside() : nullptr);
2432   UpdateCursorImages(old_style ? old_style->Cursors() : nullptr,
2433                      new_style ? new_style->Cursors() : nullptr);
2434 
2435   UpdateFirstLineImageObservers(new_style);
2436 }
2437 
UpdateFirstLineImageObservers(const ComputedStyle * new_style)2438 void LayoutObject::UpdateFirstLineImageObservers(
2439     const ComputedStyle* new_style) {
2440   NOT_DESTROYED();
2441   bool has_new_first_line_style =
2442       new_style && new_style->HasPseudoElementStyle(kPseudoIdFirstLine) &&
2443       BehavesLikeBlockContainer();
2444   DCHECK(!has_new_first_line_style || new_style == Style());
2445 
2446   if (!bitfields_.RegisteredAsFirstLineImageObserver() &&
2447       !has_new_first_line_style)
2448     return;
2449 
2450   using FirstLineStyleMap =
2451       HashMap<const LayoutObject*, scoped_refptr<const ComputedStyle>>;
2452   DEFINE_STATIC_LOCAL(FirstLineStyleMap, first_line_style_map, ());
2453   DCHECK_EQ(bitfields_.RegisteredAsFirstLineImageObserver(),
2454             first_line_style_map.Contains(this));
2455   const auto* old_first_line_style =
2456       bitfields_.RegisteredAsFirstLineImageObserver()
2457           ? first_line_style_map.at(this)
2458           : nullptr;
2459 
2460   // UpdateFillImages() may indirectly call LayoutBlock::ImageChanged() which
2461   // will invalidate the first line style cache and remove a reference to
2462   // new_first_line_style, so hold a reference here.
2463   scoped_refptr<const ComputedStyle> new_first_line_style =
2464       has_new_first_line_style ? FirstLineStyleWithoutFallback() : nullptr;
2465 
2466   if (new_first_line_style && !new_first_line_style->HasBackgroundImage())
2467     new_first_line_style = nullptr;
2468 
2469   if (old_first_line_style || new_first_line_style) {
2470     UpdateFillImages(
2471         old_first_line_style ? &old_first_line_style->BackgroundLayers()
2472                              : nullptr,
2473         new_first_line_style ? &new_first_line_style->BackgroundLayers()
2474                              : nullptr);
2475     if (new_first_line_style) {
2476       // The cached first line style may have been invalidated during
2477       // UpdateFillImages, so get it again. However, the new cached first line
2478       // style should be the same as the previous new_first_line_style.
2479       DCHECK(FillLayer::ImagesIdentical(
2480           &new_first_line_style->BackgroundLayers(),
2481           &FirstLineStyleWithoutFallback()->BackgroundLayers()));
2482       new_first_line_style = FirstLineStyleWithoutFallback();
2483       bitfields_.SetRegisteredAsFirstLineImageObserver(true);
2484       first_line_style_map.Set(this, std::move(new_first_line_style));
2485     } else {
2486       bitfields_.SetRegisteredAsFirstLineImageObserver(false);
2487       first_line_style_map.erase(this);
2488     }
2489     DCHECK_EQ(bitfields_.RegisteredAsFirstLineImageObserver(),
2490               first_line_style_map.Contains(this));
2491   }
2492 }
2493 
StyleWillChange(StyleDifference diff,const ComputedStyle & new_style)2494 void LayoutObject::StyleWillChange(StyleDifference diff,
2495                                    const ComputedStyle& new_style) {
2496   NOT_DESTROYED();
2497   if (style_) {
2498     bool visibility_changed = style_->Visibility() != new_style.Visibility();
2499     // If our z-index changes value or our visibility changes,
2500     // we need to dirty our stacking context's z-order list.
2501     if (visibility_changed ||
2502         style_->EffectiveZIndex() != new_style.EffectiveZIndex() ||
2503         IsStackingContext(*style_) != IsStackingContext(new_style)) {
2504       GetDocument().SetAnnotatedRegionsDirty(true);
2505       if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache()) {
2506         if (GetNode())
2507           cache->ChildrenChanged(GetNode()->parentNode());
2508         else
2509           cache->ChildrenChanged(Parent());
2510       }
2511     }
2512 
2513     bool background_color_changed =
2514         ResolveColor(GetCSSPropertyBackgroundColor()) !=
2515         ResolveColor(new_style, GetCSSPropertyBackgroundColor());
2516 
2517     if (diff.TextDecorationOrColorChanged() || background_color_changed ||
2518         style_->GetFontDescription() != new_style.GetFontDescription() ||
2519         style_->GetWritingDirection() != new_style.GetWritingDirection() ||
2520         style_->InsideLink() != new_style.InsideLink() ||
2521         style_->VerticalAlign() != new_style.VerticalAlign() ||
2522         style_->GetTextAlign() != new_style.GetTextAlign() ||
2523         style_->TextIndent() != new_style.TextIndent()) {
2524       if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache())
2525         cache->StyleChanged(this);
2526     }
2527 
2528     if (diff.TransformChanged()) {
2529       if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache())
2530         cache->LocationChanged(this);
2531     }
2532 
2533     // Keep layer hierarchy visibility bits up to date if visibility changes.
2534     if (visibility_changed) {
2535       // We might not have an enclosing layer yet because we might not be in the
2536       // tree.
2537       if (PaintLayer* layer = EnclosingLayer())
2538         layer->DirtyVisibleContentStatus();
2539     }
2540 
2541     if (IsFloating() &&
2542         (style_->UnresolvedFloating() != new_style.UnresolvedFloating())) {
2543       // For changes in float styles, we need to conceivably remove ourselves
2544       // from the floating objects list.
2545       To<LayoutBox>(this)->RemoveFloatingOrPositionedChildFromBlockLists();
2546     } else if (IsOutOfFlowPositioned() &&
2547                (style_->GetPosition() != new_style.GetPosition())) {
2548       // For changes in positioning styles, we need to conceivably remove
2549       // ourselves from the positioned objects list.
2550       To<LayoutBox>(this)->RemoveFloatingOrPositionedChildFromBlockLists();
2551     }
2552 
2553     affects_parent_block_ =
2554         IsFloatingOrOutOfFlowPositioned() &&
2555         ((!new_style.IsFloating() || new_style.IsFlexOrGridItem()) &&
2556          !new_style.HasOutOfFlowPosition()) &&
2557         Parent() &&
2558         (Parent()->IsLayoutBlockFlow() || Parent()->IsLayoutInline());
2559 
2560     // Clearing these bits is required to avoid leaving stale layoutObjects.
2561     // FIXME: We shouldn't need that hack if our logic was totally correct.
2562     if (diff.NeedsLayout()) {
2563       SetFloating(false);
2564       ClearPositionedState();
2565     }
2566   } else {
2567     affects_parent_block_ = false;
2568   }
2569 
2570   // Elements with non-auto touch-action will send a SetTouchAction message
2571   // on touchstart in EventHandler::handleTouchEvent, and so effectively have
2572   // a touchstart handler that must be reported.
2573   //
2574   // Since a CSS property cannot be applied directly to a text node, a
2575   // handler will have already been added for its parent so ignore it.
2576   //
2577   // Elements may inherit touch action from parent frame, so we need to report
2578   // touchstart handler if the root layout object has non-auto effective touch
2579   // action.
2580   TouchAction old_touch_action = TouchAction::kAuto;
2581   bool is_document_element = GetNode() && IsDocumentElement();
2582   if (style_) {
2583     old_touch_action = style_->GetEffectiveTouchAction();
2584   }
2585   TouchAction new_touch_action = new_style.GetEffectiveTouchAction();
2586   if (GetNode() && !GetNode()->IsTextNode() &&
2587       (old_touch_action == TouchAction::kAuto) !=
2588           (new_touch_action == TouchAction::kAuto)) {
2589     EventHandlerRegistry& registry =
2590         GetDocument().GetFrame()->GetEventHandlerRegistry();
2591     if (new_touch_action != TouchAction::kAuto) {
2592       registry.DidAddEventHandler(*GetNode(),
2593                                   EventHandlerRegistry::kTouchAction);
2594     } else {
2595       registry.DidRemoveEventHandler(*GetNode(),
2596                                      EventHandlerRegistry::kTouchAction);
2597     }
2598     MarkEffectiveAllowedTouchActionChanged();
2599   }
2600   if (is_document_element && style_ && style_->Opacity() == 0.0f &&
2601       new_style.Opacity() != 0.0f) {
2602     if (LocalFrameView* frame_view = GetFrameView())
2603       frame_view->GetPaintTimingDetector().ReportIgnoredContent();
2604   }
2605 }
2606 
ClearBaseComputedStyle()2607 void LayoutObject::ClearBaseComputedStyle() {
2608   NOT_DESTROYED();
2609   auto* element = DynamicTo<Element>(GetNode());
2610   if (!element)
2611     return;
2612 
2613   if (ElementAnimations* animations = element->GetElementAnimations())
2614     animations->ClearBaseComputedStyle();
2615 }
2616 
AreNonIdenticalCursorListsEqual(const ComputedStyle * a,const ComputedStyle * b)2617 static bool AreNonIdenticalCursorListsEqual(const ComputedStyle* a,
2618                                             const ComputedStyle* b) {
2619   DCHECK_NE(a->Cursors(), b->Cursors());
2620   return a->Cursors() && b->Cursors() && *a->Cursors() == *b->Cursors();
2621 }
2622 
AreCursorsEqual(const ComputedStyle * a,const ComputedStyle * b)2623 static inline bool AreCursorsEqual(const ComputedStyle* a,
2624                                    const ComputedStyle* b) {
2625   return a->Cursor() == b->Cursor() && (a->Cursors() == b->Cursors() ||
2626                                         AreNonIdenticalCursorListsEqual(a, b));
2627 }
2628 
SetScrollAnchorDisablingStyleChangedOnAncestor()2629 void LayoutObject::SetScrollAnchorDisablingStyleChangedOnAncestor() {
2630   NOT_DESTROYED();
2631   // Walk up the parent chain and find the first scrolling block to disable
2632   // scroll anchoring on.
2633   LayoutObject* object = Parent();
2634   Element* viewport_defining_element = GetDocument().ViewportDefiningElement();
2635   while (object) {
2636     auto* block = DynamicTo<LayoutBlock>(object);
2637     if (block && (block->HasNonVisibleOverflow() ||
2638                   block->GetNode() == viewport_defining_element)) {
2639       block->SetScrollAnchorDisablingStyleChanged(true);
2640       return;
2641     }
2642     object = object->Parent();
2643   }
2644 }
2645 
ClearAncestorScrollAnchors(LayoutObject * layout_object)2646 static void ClearAncestorScrollAnchors(LayoutObject* layout_object) {
2647   PaintLayer* layer = nullptr;
2648   if (LayoutObject* parent = layout_object->Parent())
2649     layer = parent->EnclosingLayer();
2650 
2651   while (layer) {
2652     if (PaintLayerScrollableArea* scrollable_area =
2653             layer->GetScrollableArea()) {
2654       ScrollAnchor* anchor = scrollable_area->GetScrollAnchor();
2655       DCHECK(anchor);
2656       anchor->Clear();
2657     }
2658     layer = layer->Parent();
2659   }
2660 }
2661 
StyleDidChange(StyleDifference diff,const ComputedStyle * old_style)2662 void LayoutObject::StyleDidChange(StyleDifference diff,
2663                                   const ComputedStyle* old_style) {
2664   NOT_DESTROYED();
2665   if (HasHiddenBackface()) {
2666     bool preserve_3d =
2667         (Parent() && Parent()->StyleRef().UsedTransformStyle3D() ==
2668                          ETransformStyle3D::kPreserve3d);
2669     if (style_->HasTransform() || preserve_3d) {
2670       UseCounter::Count(GetDocument(),
2671                         WebFeature::kHiddenBackfaceWithPossible3D);
2672     }
2673     if (preserve_3d) {
2674       UseCounter::Count(GetDocument(),
2675                         WebFeature::kHiddenBackfaceWithPreserve3D);
2676     }
2677   }
2678 
2679   if (ShouldApplyStrictContainment() &&
2680       (style_->ContentVisibility() == EContentVisibility::kVisible)) {
2681     if (ShouldApplyStyleContainment()) {
2682       UseCounter::Count(GetDocument(),
2683                         WebFeature::kCSSContainAllWithoutContentVisibility);
2684     }
2685     UseCounter::Count(GetDocument(),
2686                       WebFeature::kCSSContainStrictWithoutContentVisibility);
2687   }
2688 
2689   // First assume the outline will be affected. It may be updated when we know
2690   // it's not affected.
2691   SetOutlineMayBeAffectedByDescendants(style_->HasOutline());
2692 
2693   if (affects_parent_block_)
2694     HandleDynamicFloatPositionChange(this);
2695 
2696   if (diff.NeedsFullLayout()) {
2697     // If the in-flow state of an element is changed, disable scroll
2698     // anchoring on the containing scroller.
2699     if (old_style->HasOutOfFlowPosition() != style_->HasOutOfFlowPosition()) {
2700       SetScrollAnchorDisablingStyleChangedOnAncestor();
2701       if (RuntimeEnabledFeatures::LayoutNGEnabled())
2702         MarkParentForOutOfFlowPositionedChange();
2703     }
2704 
2705     // If the object already needs layout, then setNeedsLayout won't do
2706     // any work. But if the containing block has changed, then we may need
2707     // to mark the new containing blocks for layout. The change that can
2708     // directly affect the containing block of this object is a change to
2709     // the position style.
2710     if (NeedsLayout() && old_style->GetPosition() != style_->GetPosition()) {
2711       MarkContainerChainForLayout();
2712     }
2713 
2714     SetNeedsLayoutAndIntrinsicWidthsRecalc(
2715         layout_invalidation_reason::kStyleChange);
2716   } else if (diff.NeedsPositionedMovementLayout()) {
2717     SetNeedsPositionedMovementLayout();
2718   }
2719 
2720   if (diff.ScrollAnchorDisablingPropertyChanged())
2721     SetScrollAnchorDisablingStyleChanged(true);
2722 
2723   // Don't check for paint invalidation here; we need to wait until the layer
2724   // has been updated by subclasses before we know if we have to invalidate
2725   // paints (in setStyle()).
2726 
2727   if (old_style && !AreCursorsEqual(old_style, Style())) {
2728     if (LocalFrame* frame = GetFrame()) {
2729       // Cursor update scheduling is done by the local root, which is the main
2730       // frame if there are no RemoteFrame ancestors in the frame tree. Use of
2731       // localFrameRoot() is discouraged but will change when cursor update
2732       // scheduling is moved from EventHandler to PageEventHandler.
2733       frame->LocalFrameRoot().GetEventHandler().ScheduleCursorUpdate();
2734     }
2735   }
2736 
2737   if (diff.NeedsPaintInvalidation() && old_style) {
2738     if (ResolveColor(*old_style, GetCSSPropertyBackgroundColor()) !=
2739             ResolveColor(GetCSSPropertyBackgroundColor()) ||
2740         old_style->BackgroundLayers() != StyleRef().BackgroundLayers())
2741       SetBackgroundNeedsFullPaintInvalidation();
2742   }
2743 
2744   ApplyPseudoElementStyleChanges(old_style);
2745 
2746   if (old_style &&
2747       old_style->UsedTransformStyle3D() != StyleRef().UsedTransformStyle3D()) {
2748     // Change of transform-style may affect descendant transform property nodes.
2749     AddSubtreePaintPropertyUpdateReason(
2750         SubtreePaintPropertyUpdateReason::kTransformStyleChanged);
2751   }
2752 
2753   if (old_style && old_style->OverflowAnchor() != StyleRef().OverflowAnchor()) {
2754     ClearAncestorScrollAnchors(this);
2755   }
2756 }
2757 
ApplyPseudoElementStyleChanges(const ComputedStyle * old_style)2758 void LayoutObject::ApplyPseudoElementStyleChanges(
2759     const ComputedStyle* old_style) {
2760   NOT_DESTROYED();
2761   ApplyFirstLineChanges(old_style);
2762 
2763   if ((old_style && old_style->HasPseudoElementStyle(kPseudoIdSelection)) ||
2764       StyleRef().HasPseudoElementStyle(kPseudoIdSelection))
2765     InvalidateSelectedChildrenOnStyleChange();
2766 }
2767 
ApplyFirstLineChanges(const ComputedStyle * old_style)2768 void LayoutObject::ApplyFirstLineChanges(const ComputedStyle* old_style) {
2769   NOT_DESTROYED();
2770   bool has_old_first_line_style =
2771       old_style && old_style->HasPseudoElementStyle(kPseudoIdFirstLine);
2772   bool has_new_first_line_style =
2773       StyleRef().HasPseudoElementStyle(kPseudoIdFirstLine);
2774   if (!has_old_first_line_style && !has_new_first_line_style)
2775     return;
2776 
2777   StyleDifference diff;
2778   bool has_diff = false;
2779   if (Parent() && has_old_first_line_style && has_new_first_line_style) {
2780     if (const auto* old_first_line_style =
2781             old_style->GetCachedPseudoElementStyle(kPseudoIdFirstLine)) {
2782       if (const auto* new_first_line_style = FirstLineStyleWithoutFallback()) {
2783         diff = old_first_line_style->VisualInvalidationDiff(
2784             GetDocument(), *new_first_line_style);
2785         has_diff = true;
2786       }
2787     }
2788   }
2789   if (!has_diff) {
2790     diff.SetNeedsPaintInvalidation();
2791     diff.SetNeedsFullLayout();
2792   }
2793 
2794   if (BehavesLikeBlockContainer() &&
2795       (diff.NeedsPaintInvalidation() || diff.TextDecorationOrColorChanged())) {
2796     if (auto* first_line_container =
2797             To<LayoutBlock>(this)->NearestInnerBlockWithFirstLine())
2798       first_line_container->SetShouldDoFullPaintInvalidationForFirstLine();
2799   }
2800 
2801   if (diff.NeedsLayout()) {
2802     if (diff.NeedsFullLayout())
2803       SetNeedsCollectInlines();
2804     SetNeedsLayoutAndIntrinsicWidthsRecalc(
2805         layout_invalidation_reason::kStyleChange);
2806   }
2807 }
2808 
PropagateStyleToAnonymousChildren()2809 void LayoutObject::PropagateStyleToAnonymousChildren() {
2810   NOT_DESTROYED();
2811   // FIXME: We could save this call when the change only affected non-inherited
2812   // properties.
2813   for (LayoutObject* child = SlowFirstChild(); child;
2814        child = child->NextSibling()) {
2815     if (!child->IsAnonymous() || child->StyleRef().StyleType() != kPseudoIdNone)
2816       continue;
2817     if (child->AnonymousHasStylePropagationOverride())
2818       continue;
2819 
2820     scoped_refptr<ComputedStyle> new_style =
2821         ComputedStyle::CreateAnonymousStyleWithDisplay(
2822             StyleRef(), child->StyleRef().Display());
2823 
2824     // Preserve the position style of anonymous block continuations as they can
2825     // have relative position when they contain block descendants of relative
2826     // positioned inlines.
2827     auto* child_block_flow = DynamicTo<LayoutBlockFlow>(child);
2828     if (child->IsInFlowPositioned() && child_block_flow &&
2829         child_block_flow->IsAnonymousBlockContinuation())
2830       new_style->SetPosition(child->StyleRef().GetPosition());
2831 
2832     UpdateAnonymousChildStyle(child, *new_style);
2833 
2834     child->SetStyle(std::move(new_style));
2835   }
2836 
2837   PseudoId pseudo_id = StyleRef().StyleType();
2838   if (pseudo_id == kPseudoIdNone)
2839     return;
2840 
2841   // Don't propagate style from markers with 'content: normal' because it's not
2842   // needed and it would be slow.
2843   if (pseudo_id == kPseudoIdMarker && StyleRef().ContentBehavesAsNormal())
2844     return;
2845 
2846   // Propagate style from pseudo elements to generated content. We skip children
2847   // with pseudo element StyleType() in the for-loop above and skip over
2848   // descendants which are not generated content in this subtree traversal.
2849   //
2850   // TODO(futhark): It's possible we could propagate anonymous style from pseudo
2851   // elements through anonymous table layout objects in the recursive
2852   // implementation above, but it would require propagating the StyleType()
2853   // somehow because there is code relying on generated content having a certain
2854   // StyleType().
2855   LayoutObject* child = NextInPreOrder(this);
2856   while (child) {
2857     if (!child->IsAnonymous()) {
2858       // Don't propagate into non-anonymous descendants of pseudo elements. This
2859       // can typically happen for ::first-letter inside ::before. The
2860       // ::first-letter will propagate to its anonymous children separately.
2861       child = child->NextInPreOrderAfterChildren(this);
2862       continue;
2863     }
2864     if (child->IsText() || child->IsQuote() || child->IsImage())
2865       child->SetPseudoElementStyle(Style());
2866     child = child->NextInPreOrder(this);
2867   }
2868 }
2869 
AddAsImageObserver(StyleImage * image)2870 void LayoutObject::AddAsImageObserver(StyleImage* image) {
2871   NOT_DESTROYED();
2872   if (!image)
2873     return;
2874 #if DCHECK_IS_ON()
2875   ++as_image_observer_count_;
2876 #endif
2877   image->AddClient(this);
2878 }
2879 
RemoveAsImageObserver(StyleImage * image)2880 void LayoutObject::RemoveAsImageObserver(StyleImage* image) {
2881   NOT_DESTROYED();
2882   if (!image)
2883     return;
2884 #if DCHECK_IS_ON()
2885   SECURITY_DCHECK(as_image_observer_count_ > 0u);
2886   --as_image_observer_count_;
2887 #endif
2888   image->RemoveClient(this);
2889 }
2890 
UpdateFillImages(const FillLayer * old_layers,const FillLayer * new_layers)2891 void LayoutObject::UpdateFillImages(const FillLayer* old_layers,
2892                                     const FillLayer* new_layers) {
2893   NOT_DESTROYED();
2894   // Optimize the common case
2895   if (FillLayer::ImagesIdentical(old_layers, new_layers))
2896     return;
2897 
2898   // Go through the new layers and AddAsImageObserver() first, to avoid removing
2899   // all clients of an image.
2900   for (const FillLayer* curr_new = new_layers; curr_new;
2901        curr_new = curr_new->Next())
2902     AddAsImageObserver(curr_new->GetImage());
2903 
2904   for (const FillLayer* curr_old = old_layers; curr_old;
2905        curr_old = curr_old->Next())
2906     RemoveAsImageObserver(curr_old->GetImage());
2907 }
2908 
UpdateCursorImages(const CursorList * old_cursors,const CursorList * new_cursors)2909 void LayoutObject::UpdateCursorImages(const CursorList* old_cursors,
2910                                       const CursorList* new_cursors) {
2911   NOT_DESTROYED();
2912   if (old_cursors && new_cursors && *old_cursors == *new_cursors)
2913     return;
2914 
2915   if (new_cursors) {
2916     for (const auto& cursor : *new_cursors)
2917       AddAsImageObserver(cursor.GetImage());
2918   }
2919   if (old_cursors) {
2920     for (const auto& cursor : *old_cursors)
2921       RemoveAsImageObserver(cursor.GetImage());
2922   }
2923 }
2924 
UpdateImage(StyleImage * old_image,StyleImage * new_image)2925 void LayoutObject::UpdateImage(StyleImage* old_image, StyleImage* new_image) {
2926   NOT_DESTROYED();
2927   if (old_image != new_image) {
2928     // AddAsImageObserver first, to avoid removing all clients of an image.
2929     AddAsImageObserver(new_image);
2930     RemoveAsImageObserver(old_image);
2931   }
2932 }
2933 
UpdateShapeImage(const ShapeValue * old_shape_value,const ShapeValue * new_shape_value)2934 void LayoutObject::UpdateShapeImage(const ShapeValue* old_shape_value,
2935                                     const ShapeValue* new_shape_value) {
2936   NOT_DESTROYED();
2937   if (old_shape_value || new_shape_value) {
2938     UpdateImage(old_shape_value ? old_shape_value->GetImage() : nullptr,
2939                 new_shape_value ? new_shape_value->GetImage() : nullptr);
2940   }
2941 }
2942 
CheckCounterChanges(const ComputedStyle * old_style,const ComputedStyle * new_style)2943 void LayoutObject::CheckCounterChanges(const ComputedStyle* old_style,
2944                                        const ComputedStyle* new_style) {
2945   NOT_DESTROYED();
2946   DCHECK(new_style);
2947   if (old_style) {
2948     if (old_style->CounterDirectivesEqual(*new_style))
2949       return;
2950   } else {
2951     if (!new_style->GetCounterDirectives())
2952       return;
2953   }
2954   LayoutCounter::LayoutObjectStyleChanged(*this, old_style, *new_style);
2955   View()->SetNeedsCounterUpdate();
2956 }
2957 
ViewRect() const2958 PhysicalRect LayoutObject::ViewRect() const {
2959   NOT_DESTROYED();
2960   return View()->ViewRect();
2961 }
2962 
AncestorToLocalFloatPoint(const LayoutBoxModelObject * ancestor,const FloatPoint & container_point,MapCoordinatesFlags mode) const2963 FloatPoint LayoutObject::AncestorToLocalFloatPoint(
2964     const LayoutBoxModelObject* ancestor,
2965     const FloatPoint& container_point,
2966     MapCoordinatesFlags mode) const {
2967   NOT_DESTROYED();
2968   TransformState transform_state(
2969       TransformState::kUnapplyInverseTransformDirection, container_point);
2970   MapAncestorToLocal(ancestor, transform_state, mode);
2971   transform_state.Flatten();
2972 
2973   return transform_state.LastPlanarPoint();
2974 }
2975 
AncestorToLocalQuad(const LayoutBoxModelObject * ancestor,const FloatQuad & quad,MapCoordinatesFlags mode) const2976 FloatQuad LayoutObject::AncestorToLocalQuad(
2977     const LayoutBoxModelObject* ancestor,
2978     const FloatQuad& quad,
2979     MapCoordinatesFlags mode) const {
2980   NOT_DESTROYED();
2981   TransformState transform_state(
2982       TransformState::kUnapplyInverseTransformDirection,
2983       quad.BoundingBox().Center(), quad);
2984   MapAncestorToLocal(ancestor, transform_state, mode);
2985   transform_state.Flatten();
2986   return transform_state.LastPlanarQuad();
2987 }
2988 
MapLocalToAncestor(const LayoutBoxModelObject * ancestor,TransformState & transform_state,MapCoordinatesFlags mode) const2989 void LayoutObject::MapLocalToAncestor(const LayoutBoxModelObject* ancestor,
2990                                       TransformState& transform_state,
2991                                       MapCoordinatesFlags mode) const {
2992   NOT_DESTROYED();
2993   if (ancestor == this)
2994     return;
2995 
2996   AncestorSkipInfo skip_info(ancestor);
2997   const LayoutObject* container = Container(&skip_info);
2998   if (!container)
2999     return;
3000 
3001   PhysicalOffset container_offset =
3002       OffsetFromContainer(container, mode & kIgnoreScrollOffset);
3003   // TODO(smcgruer): This is inefficient. Instead we should avoid including
3004   // offsetForInFlowPosition in offsetFromContainer when ignoring sticky.
3005   if (mode & kIgnoreStickyOffset && IsStickyPositioned()) {
3006     container_offset -=
3007         To<LayoutBoxModelObject>(this)->OffsetForInFlowPosition();
3008   }
3009 
3010   if (IsLayoutFlowThread()) {
3011     // So far the point has been in flow thread coordinates (i.e. as if
3012     // everything in the fragmentation context lived in one tall single column).
3013     // Convert it to a visual point now, since we're about to escape the flow
3014     // thread.
3015     container_offset += PhysicalOffsetToBeNoop(
3016         ColumnOffset(transform_state.MappedPoint().ToLayoutPoint()));
3017   }
3018 
3019   // Text objects just copy their parent's computed style, so we need to ignore
3020   // them.
3021   bool use_transforms = !(mode & kIgnoreTransforms);
3022   bool preserve3d =
3023       use_transforms &&
3024       ((container->StyleRef().Preserves3D() && !container->IsText()) ||
3025        (StyleRef().Preserves3D() && !IsText()));
3026   if (use_transforms && ShouldUseTransformFromContainer(container)) {
3027     TransformationMatrix t;
3028     GetTransformFromContainer(container, container_offset, t);
3029     transform_state.ApplyTransform(t, preserve3d
3030                                           ? TransformState::kAccumulateTransform
3031                                           : TransformState::kFlattenTransform);
3032   } else {
3033     transform_state.Move(container_offset,
3034                          preserve3d ? TransformState::kAccumulateTransform
3035                                     : TransformState::kFlattenTransform);
3036   }
3037 
3038   if (skip_info.AncestorSkipped()) {
3039     // There can't be a transform between |ancestor| and |o|, because transforms
3040     // create containers, so it should be safe to just subtract the delta
3041     // between the ancestor and |o|.
3042     transform_state.Move(-ancestor->OffsetFromAncestor(container),
3043                          preserve3d ? TransformState::kAccumulateTransform
3044                                     : TransformState::kFlattenTransform);
3045     // If the ancestor is fixed, then the rect is already in its coordinates so
3046     // doesn't need viewport-adjusting.
3047     auto* layout_view = DynamicTo<LayoutView>(container);
3048     if (ancestor->StyleRef().GetPosition() != EPosition::kFixed &&
3049         layout_view && StyleRef().GetPosition() == EPosition::kFixed) {
3050       transform_state.Move(layout_view->OffsetForFixedPosition());
3051     }
3052     return;
3053   }
3054 
3055   container->MapLocalToAncestor(ancestor, transform_state, mode);
3056 }
3057 
PushMappingToContainer(const LayoutBoxModelObject * ancestor_to_stop_at,LayoutGeometryMap & geometry_map) const3058 const LayoutObject* LayoutObject::PushMappingToContainer(
3059     const LayoutBoxModelObject* ancestor_to_stop_at,
3060     LayoutGeometryMap& geometry_map) const {
3061   NOT_DESTROYED();
3062   NOTREACHED();
3063   return nullptr;
3064 }
3065 
MapAncestorToLocal(const LayoutBoxModelObject * ancestor,TransformState & transform_state,MapCoordinatesFlags mode) const3066 void LayoutObject::MapAncestorToLocal(const LayoutBoxModelObject* ancestor,
3067                                       TransformState& transform_state,
3068                                       MapCoordinatesFlags mode) const {
3069   NOT_DESTROYED();
3070   if (this == ancestor)
3071     return;
3072 
3073   AncestorSkipInfo skip_info(ancestor);
3074   LayoutObject* container = Container(&skip_info);
3075   if (!container)
3076     return;
3077 
3078   if (!skip_info.AncestorSkipped())
3079     container->MapAncestorToLocal(ancestor, transform_state, mode);
3080 
3081   PhysicalOffset container_offset = OffsetFromContainer(container);
3082   bool use_transforms = !(mode & kIgnoreTransforms);
3083   bool preserve3d = use_transforms && (container->StyleRef().Preserves3D() ||
3084                                        StyleRef().Preserves3D());
3085   if (use_transforms && ShouldUseTransformFromContainer(container)) {
3086     TransformationMatrix t;
3087     GetTransformFromContainer(container, container_offset, t);
3088     transform_state.ApplyTransform(t, preserve3d
3089                                           ? TransformState::kAccumulateTransform
3090                                           : TransformState::kFlattenTransform);
3091   } else {
3092     transform_state.Move(container_offset,
3093                          preserve3d ? TransformState::kAccumulateTransform
3094                                     : TransformState::kFlattenTransform);
3095   }
3096 
3097   if (IsLayoutFlowThread()) {
3098     // Descending into a flow thread. Convert to the local coordinate space,
3099     // i.e. flow thread coordinates.
3100     PhysicalOffset visual_point = transform_state.MappedPoint();
3101     transform_state.Move(
3102         visual_point -
3103         PhysicalOffsetToBeNoop(
3104             To<LayoutFlowThread>(this)->VisualPointToFlowThreadPoint(
3105                 visual_point.ToLayoutPoint())));
3106   }
3107 
3108   if (skip_info.AncestorSkipped()) {
3109     container_offset = ancestor->OffsetFromAncestor(container);
3110     transform_state.Move(-container_offset);
3111     // If the ancestor is fixed, then the rect is already in its coordinates so
3112     // doesn't need viewport-adjusting.
3113     auto* layout_view = DynamicTo<LayoutView>(container);
3114     if (ancestor->StyleRef().GetPosition() != EPosition::kFixed &&
3115         layout_view && StyleRef().GetPosition() == EPosition::kFixed) {
3116       transform_state.Move(layout_view->OffsetForFixedPosition());
3117     }
3118   }
3119 }
3120 
ShouldUseTransformFromContainer(const LayoutObject * container_object) const3121 bool LayoutObject::ShouldUseTransformFromContainer(
3122     const LayoutObject* container_object) const {
3123   NOT_DESTROYED();
3124   // hasTransform() indicates whether the object has transform, transform-style
3125   // or perspective. We just care about transform, so check the layer's
3126   // transform directly.
3127   return (HasLayer() && To<LayoutBoxModelObject>(this)->Layer()->Transform()) ||
3128          (container_object && container_object->StyleRef().HasPerspective());
3129 }
3130 
GetTransformFromContainer(const LayoutObject * container_object,const PhysicalOffset & offset_in_container,TransformationMatrix & transform,const PhysicalSize * size) const3131 void LayoutObject::GetTransformFromContainer(
3132     const LayoutObject* container_object,
3133     const PhysicalOffset& offset_in_container,
3134     TransformationMatrix& transform,
3135     const PhysicalSize* size) const {
3136   NOT_DESTROYED();
3137   transform.MakeIdentity();
3138   PaintLayer* layer =
3139       HasLayer() ? To<LayoutBoxModelObject>(this)->Layer() : nullptr;
3140   if (layer && layer->Transform())
3141     transform.Multiply(layer->CurrentTransform());
3142 
3143   transform.PostTranslate(offset_in_container.left.ToFloat(),
3144                           offset_in_container.top.ToFloat());
3145 
3146   bool has_perspective = container_object && container_object->HasLayer() &&
3147                          container_object->StyleRef().HasPerspective();
3148   if (has_perspective && RuntimeEnabledFeatures::TransformInteropEnabled() &&
3149       container_object != NonAnonymousAncestor())
3150     has_perspective = false;
3151 
3152   if (has_perspective) {
3153     // Perspective on the container affects us, so we have to factor it in here.
3154     DCHECK(container_object->HasLayer());
3155     FloatPoint perspective_origin;
3156     if (const auto* container_box = DynamicTo<LayoutBox>(container_object))
3157       perspective_origin = container_box->PerspectiveOrigin(size);
3158 
3159     TransformationMatrix perspective_matrix;
3160     perspective_matrix.ApplyPerspective(
3161         container_object->StyleRef().Perspective());
3162     perspective_matrix.ApplyTransformOrigin(perspective_origin.X(),
3163                                             perspective_origin.Y(), 0);
3164 
3165     transform = perspective_matrix * transform;
3166   }
3167 }
3168 
LocalToAncestorFloatPoint(const FloatPoint & local_point,const LayoutBoxModelObject * ancestor,MapCoordinatesFlags mode) const3169 FloatPoint LayoutObject::LocalToAncestorFloatPoint(
3170     const FloatPoint& local_point,
3171     const LayoutBoxModelObject* ancestor,
3172     MapCoordinatesFlags mode) const {
3173   NOT_DESTROYED();
3174   TransformState transform_state(TransformState::kApplyTransformDirection,
3175                                  local_point);
3176   MapLocalToAncestor(ancestor, transform_state, mode);
3177   transform_state.Flatten();
3178 
3179   return transform_state.LastPlanarPoint();
3180 }
3181 
LocalToAncestorRectFastPath(const PhysicalRect & rect,const LayoutBoxModelObject * ancestor,MapCoordinatesFlags mode,PhysicalRect & result) const3182 bool LayoutObject::LocalToAncestorRectFastPath(
3183     const PhysicalRect& rect,
3184     const LayoutBoxModelObject* ancestor,
3185     MapCoordinatesFlags mode,
3186     PhysicalRect& result) const {
3187   NOT_DESTROYED();
3188   if (!(mode & kUseGeometryMapperMode))
3189     return false;
3190   // No other modes are supported.
3191   if (mode & (~kUseGeometryMapperMode))
3192     return false;
3193 
3194   if (!ancestor)
3195     ancestor = View();
3196 
3197   if (ancestor == this)
3198     return true;
3199 
3200   AncestorSkipInfo skip_info(ancestor);
3201   PropertyTreeStateOrAlias container_properties =
3202       PropertyTreeState::Uninitialized();
3203   const LayoutObject* property_container =
3204       GetPropertyContainer(&skip_info, &container_properties);
3205   if (!property_container)
3206     return false;
3207 
3208   FloatRect mapping_rect(rect);
3209 
3210   // This works because it's not possible to have any intervening clips,
3211   // effects, transforms between |this| and |property_container|, and therefore
3212   // FirstFragment().PaintOffset() is relative to the transform space defined by
3213   // FirstFragment().LocalBorderBoxProperties() (if this == property_container)
3214   // or property_container->FirstFragment().ContentsProperties().
3215   mapping_rect.Move(FloatSize(FirstFragment().PaintOffset()));
3216 
3217   if (property_container != ancestor) {
3218     GeometryMapper::SourceToDestinationRect(
3219         container_properties.Transform(),
3220         ancestor->FirstFragment().LocalBorderBoxProperties().Transform(),
3221         mapping_rect);
3222   }
3223   mapping_rect.Move(-FloatSize(ancestor->FirstFragment().PaintOffset()));
3224 
3225   result = PhysicalRect::EnclosingRect(mapping_rect);
3226   return true;
3227 }
3228 
LocalToAncestorRect(const PhysicalRect & rect,const LayoutBoxModelObject * ancestor,MapCoordinatesFlags mode) const3229 PhysicalRect LayoutObject::LocalToAncestorRect(
3230     const PhysicalRect& rect,
3231     const LayoutBoxModelObject* ancestor,
3232     MapCoordinatesFlags mode) const {
3233   NOT_DESTROYED();
3234   PhysicalRect result;
3235   if (LocalToAncestorRectFastPath(rect, ancestor, mode, result))
3236     return result;
3237 
3238   return PhysicalRect::EnclosingRect(
3239       LocalToAncestorQuad(FloatRect(rect), ancestor, mode).BoundingBox());
3240 }
3241 
LocalToAncestorQuad(const FloatQuad & local_quad,const LayoutBoxModelObject * ancestor,MapCoordinatesFlags mode) const3242 FloatQuad LayoutObject::LocalToAncestorQuad(
3243     const FloatQuad& local_quad,
3244     const LayoutBoxModelObject* ancestor,
3245     MapCoordinatesFlags mode) const {
3246   NOT_DESTROYED();
3247   // Track the point at the center of the quad's bounding box. As
3248   // MapLocalToAncestor() calls OffsetFromContainer(), it will use that point
3249   // as the reference point to decide which column's transform to apply in
3250   // multiple-column blocks.
3251   TransformState transform_state(TransformState::kApplyTransformDirection,
3252                                  local_quad.BoundingBox().Center(), local_quad);
3253   MapLocalToAncestor(ancestor, transform_state, mode);
3254   transform_state.Flatten();
3255 
3256   return transform_state.LastPlanarQuad();
3257 }
3258 
LocalToAncestorRects(Vector<PhysicalRect> & rects,const LayoutBoxModelObject * ancestor,const PhysicalOffset & pre_offset,const PhysicalOffset & post_offset) const3259 void LayoutObject::LocalToAncestorRects(
3260     Vector<PhysicalRect>& rects,
3261     const LayoutBoxModelObject* ancestor,
3262     const PhysicalOffset& pre_offset,
3263     const PhysicalOffset& post_offset) const {
3264   NOT_DESTROYED();
3265   for (wtf_size_t i = 0; i < rects.size(); ++i) {
3266     PhysicalRect& rect = rects[i];
3267     rect.Move(pre_offset);
3268     FloatQuad container_quad =
3269         LocalToAncestorQuad(FloatQuad(FloatRect(rect)), ancestor);
3270     PhysicalRect container_rect =
3271         PhysicalRect::EnclosingRect(container_quad.BoundingBox());
3272     if (container_rect.IsEmpty()) {
3273       rects.EraseAt(i--);
3274       continue;
3275     }
3276     container_rect.Move(post_offset);
3277     rects[i] = container_rect;
3278   }
3279 }
3280 
LocalToAncestorTransform(const LayoutBoxModelObject * ancestor,MapCoordinatesFlags mode) const3281 TransformationMatrix LayoutObject::LocalToAncestorTransform(
3282     const LayoutBoxModelObject* ancestor,
3283     MapCoordinatesFlags mode) const {
3284   NOT_DESTROYED();
3285   DCHECK(!(mode & kIgnoreTransforms));
3286   TransformState transform_state(TransformState::kApplyTransformDirection);
3287   MapLocalToAncestor(ancestor, transform_state, mode);
3288   return transform_state.AccumulatedTransform();
3289 }
3290 
OffsetFromContainer(const LayoutObject * o,bool ignore_scroll_offset) const3291 PhysicalOffset LayoutObject::OffsetFromContainer(
3292     const LayoutObject* o,
3293     bool ignore_scroll_offset) const {
3294   NOT_DESTROYED();
3295   return OffsetFromContainerInternal(o, ignore_scroll_offset);
3296 }
3297 
OffsetFromContainerInternal(const LayoutObject * o,bool ignore_scroll_offset) const3298 PhysicalOffset LayoutObject::OffsetFromContainerInternal(
3299     const LayoutObject* o,
3300     bool ignore_scroll_offset) const {
3301   NOT_DESTROYED();
3302   DCHECK_EQ(o, Container());
3303   return o->IsScrollContainer()
3304              ? OffsetFromScrollableContainer(o, ignore_scroll_offset)
3305              : PhysicalOffset();
3306 }
3307 
OffsetFromScrollableContainer(const LayoutObject * container,bool ignore_scroll_offset) const3308 PhysicalOffset LayoutObject::OffsetFromScrollableContainer(
3309     const LayoutObject* container,
3310     bool ignore_scroll_offset) const {
3311   NOT_DESTROYED();
3312   DCHECK(container->IsScrollContainer());
3313   const auto* box = To<LayoutBox>(container);
3314   if (!ignore_scroll_offset)
3315     return -PhysicalOffset(box->ScrolledContentOffset());
3316 
3317   // ScrollOrigin accounts for other writing modes whose content's origin is not
3318   // at the top-left.
3319   return PhysicalOffset(box->GetScrollableArea()->ScrollOrigin());
3320 }
3321 
OffsetFromAncestor(const LayoutObject * ancestor_container) const3322 PhysicalOffset LayoutObject::OffsetFromAncestor(
3323     const LayoutObject* ancestor_container) const {
3324   NOT_DESTROYED();
3325   if (ancestor_container == this)
3326     return PhysicalOffset();
3327 
3328   PhysicalOffset offset;
3329   PhysicalOffset reference_point;
3330   const LayoutObject* curr_container = this;
3331   AncestorSkipInfo skip_info(ancestor_container);
3332   do {
3333     const LayoutObject* next_container = curr_container->Container(&skip_info);
3334 
3335     // This means we reached the top without finding container.
3336     CHECK(next_container);
3337     if (!next_container)
3338       break;
3339     DCHECK(!curr_container->HasTransformRelatedProperty());
3340     PhysicalOffset current_offset =
3341         curr_container->OffsetFromContainer(next_container);
3342     offset += current_offset;
3343     reference_point += current_offset;
3344     curr_container = next_container;
3345   } while (curr_container != ancestor_container &&
3346            !skip_info.AncestorSkipped());
3347   if (skip_info.AncestorSkipped()) {
3348     DCHECK(curr_container);
3349     offset -= ancestor_container->OffsetFromAncestor(curr_container);
3350   }
3351 
3352   return offset;
3353 }
3354 
LocalCaretRect(const InlineBox *,int,LayoutUnit * extra_width_to_end_of_line) const3355 LayoutRect LayoutObject::LocalCaretRect(
3356     const InlineBox*,
3357     int,
3358     LayoutUnit* extra_width_to_end_of_line) const {
3359   NOT_DESTROYED();
3360   if (extra_width_to_end_of_line)
3361     *extra_width_to_end_of_line = LayoutUnit();
3362 
3363   return LayoutRect();
3364 }
3365 
IsRooted() const3366 bool LayoutObject::IsRooted() const {
3367   NOT_DESTROYED();
3368   const LayoutObject* object = this;
3369   while (object->Parent() && !object->HasLayer())
3370     object = object->Parent();
3371   if (object->HasLayer())
3372     return To<LayoutBoxModelObject>(object)->Layer()->Root()->IsRootLayer();
3373   return false;
3374 }
3375 
ShouldRespectImageOrientation(const LayoutObject * layout_object)3376 RespectImageOrientationEnum LayoutObject::ShouldRespectImageOrientation(
3377     const LayoutObject* layout_object) {
3378   if (layout_object && layout_object->Style() &&
3379       layout_object->StyleRef().RespectImageOrientation() !=
3380           kRespectImageOrientation)
3381     return kDoNotRespectImageOrientation;
3382 
3383   return kRespectImageOrientation;
3384 }
3385 
Container(AncestorSkipInfo * skip_info) const3386 LayoutObject* LayoutObject::Container(AncestorSkipInfo* skip_info) const {
3387   NOT_DESTROYED();
3388   // TODO(mstensho): Get rid of this. Nobody should call this method with those
3389   // flags already set.
3390   if (skip_info)
3391     skip_info->ResetOutput();
3392 
3393   if (IsTextOrSVGChild())
3394     return Parent();
3395 
3396   EPosition pos = style_->GetPosition();
3397   if (pos == EPosition::kFixed)
3398     return ContainerForFixedPosition(skip_info);
3399 
3400   if (pos == EPosition::kAbsolute) {
3401     return ContainerForAbsolutePosition(skip_info);
3402   }
3403 
3404   if (IsColumnSpanAll()) {
3405     LayoutObject* multicol_container = SpannerPlaceholder()->Container();
3406     if (skip_info) {
3407       // We jumped directly from the spanner to the multicol container. Need to
3408       // check if we skipped |ancestor| or filter/reflection on the way.
3409       for (LayoutObject* walker = Parent();
3410            walker && walker != multicol_container; walker = walker->Parent())
3411         skip_info->Update(*walker);
3412     }
3413     return multicol_container;
3414   }
3415 
3416   if ((IsFloating() && !IsInLayoutNGInlineFormattingContext()) ||
3417       IsRenderedLegend())
3418     return ContainingBlock(skip_info);
3419 
3420   return Parent();
3421 }
3422 
ParentCrossingFrames() const3423 inline LayoutObject* LayoutObject::ParentCrossingFrames() const {
3424   NOT_DESTROYED();
3425   if (IsA<LayoutView>(this))
3426     return GetFrame()->OwnerLayoutObject();
3427   return Parent();
3428 }
3429 
ClearLayoutRootIfNeeded() const3430 inline void LayoutObject::ClearLayoutRootIfNeeded() const {
3431   NOT_DESTROYED();
3432   if (LocalFrameView* view = GetFrameView()) {
3433     if (!DocumentBeingDestroyed())
3434       view->ClearLayoutSubtreeRoot(*this);
3435   }
3436 }
3437 
WillBeDestroyed()3438 void LayoutObject::WillBeDestroyed() {
3439   NOT_DESTROYED();
3440   // Destroy any leftover anonymous children.
3441   LayoutObjectChildList* children = VirtualChildren();
3442   if (children)
3443     children->DestroyLeftoverChildren();
3444 
3445   if (LocalFrame* frame = GetFrame()) {
3446     // If this layoutObject is being autoscrolled, stop the autoscrolling.
3447     if (frame->GetPage())
3448       frame->GetPage()->GetAutoscrollController().StopAutoscrollIfNeeded(this);
3449   }
3450 
3451   // For accessibility management, notify the parent of the imminent change to
3452   // its child set.
3453   // We do it now, before remove(), while the parent pointer is still available.
3454   if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache())
3455     cache->ChildrenChanged(Parent());
3456 
3457   Remove();
3458 
3459   // The remove() call above may invoke axObjectCache()->childrenChanged() on
3460   // the parent, which may require the AX layout object for this layoutObject.
3461   // So we remove the AX layout object now, after the layoutObject is removed.
3462   if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache())
3463     cache->Remove(this);
3464 
3465   // If this layoutObject had a parent, remove should have destroyed any
3466   // counters attached to this layoutObject and marked the affected other
3467   // counters for reevaluation. This apparently redundant check is here for the
3468   // case when this layoutObject had no parent at the time remove() was called.
3469 
3470   if (HasCounterNodeMap())
3471     LayoutCounter::DestroyCounterNodes(*this);
3472 
3473   // Remove the handler if node had touch-action set. Handlers are not added
3474   // for text nodes so don't try removing for one too. Need to check if
3475   // m_style is null in cases of partial construction. Any handler we added
3476   // previously may have already been removed by the Document independently.
3477   if (GetNode() && !GetNode()->IsTextNode() && style_ &&
3478       style_->GetTouchAction() != TouchAction::kAuto) {
3479     EventHandlerRegistry& registry =
3480         GetDocument().GetFrame()->GetEventHandlerRegistry();
3481     if (registry.EventHandlerTargets(EventHandlerRegistry::kTouchAction)
3482             ->Contains(GetNode())) {
3483       registry.DidRemoveEventHandler(*GetNode(),
3484                                      EventHandlerRegistry::kTouchAction);
3485     }
3486   }
3487 
3488   SetAncestorLineBoxDirty(false);
3489 
3490   ClearLayoutRootIfNeeded();
3491 
3492   // Remove this object as ImageResourceObserver.
3493   if (style_ && !IsText())
3494     UpdateImageObservers(style_.get(), nullptr);
3495 
3496   // We must have removed all image observers.
3497   SECURITY_CHECK(!bitfields_.RegisteredAsFirstLineImageObserver());
3498 #if DCHECK_IS_ON()
3499   SECURITY_DCHECK(as_image_observer_count_ == 0u);
3500 #endif
3501 
3502   if (GetFrameView())
3503     SetIsBackgroundAttachmentFixedObject(false);
3504 }
3505 
3506 DISABLE_CFI_PERF
InsertedIntoTree()3507 void LayoutObject::InsertedIntoTree() {
3508   NOT_DESTROYED();
3509   // FIXME: We should DCHECK(isRooted()) here but generated content makes some
3510   // out-of-order insertion.
3511 
3512   // Keep our layer hierarchy updated. Optimize for the common case where we
3513   // don't have any children and don't have a layer attached to ourselves.
3514   PaintLayer* layer = nullptr;
3515   if (SlowFirstChild() || HasLayer()) {
3516     layer = Parent()->EnclosingLayer();
3517     AddLayers(layer);
3518   }
3519 
3520   // If |this| is visible but this object was not, tell the layer it has some
3521   // visible content that needs to be drawn and layer visibility optimization
3522   // can't be used
3523   if (Parent()->StyleRef().Visibility() != EVisibility::kVisible &&
3524       StyleRef().Visibility() == EVisibility::kVisible && !HasLayer()) {
3525     if (!layer)
3526       layer = Parent()->EnclosingLayer();
3527     if (layer)
3528       layer->DirtyVisibleContentStatus();
3529   }
3530 
3531   // |FirstInlineFragment()| should be cleared. |LayoutObjectChildList| does
3532   // this, just check here for all new objects in the tree.
3533   DCHECK_EQ(FirstInlineFragment(), nullptr);
3534 
3535   if (Parent()->ChildrenInline())
3536     Parent()->DirtyLinesFromChangedChild(this);
3537 
3538   if (LayoutFlowThread* flow_thread = FlowThreadContainingBlock())
3539     flow_thread->FlowThreadDescendantWasInserted(this);
3540 }
3541 
3542 enum FindReferencingScrollAnchorsBehavior { kDontClear, kClear };
3543 
FindReferencingScrollAnchors(LayoutObject * layout_object,FindReferencingScrollAnchorsBehavior behavior)3544 static bool FindReferencingScrollAnchors(
3545     LayoutObject* layout_object,
3546     FindReferencingScrollAnchorsBehavior behavior) {
3547   PaintLayer* layer = nullptr;
3548   if (LayoutObject* parent = layout_object->Parent())
3549     layer = parent->EnclosingLayer();
3550   bool found = false;
3551 
3552   // Walk up the layer tree to clear any scroll anchors that reference us.
3553   while (layer) {
3554     if (PaintLayerScrollableArea* scrollable_area =
3555             layer->GetScrollableArea()) {
3556       ScrollAnchor* anchor = scrollable_area->GetScrollAnchor();
3557       DCHECK(anchor);
3558       if (anchor->RefersTo(layout_object)) {
3559         found = true;
3560         if (behavior == kClear)
3561           anchor->NotifyRemoved(layout_object);
3562         else
3563           return true;
3564       }
3565     }
3566     layer = layer->Parent();
3567   }
3568   return found;
3569 }
3570 
WillBeRemovedFromTree()3571 void LayoutObject::WillBeRemovedFromTree() {
3572   NOT_DESTROYED();
3573   // FIXME: We should DCHECK(isRooted()) but we have some out-of-order removals
3574   // which would need to be fixed first.
3575 
3576   // If we remove a visible child from an invisible parent, we don't know the
3577   // layer visibility any more.
3578   PaintLayer* layer = nullptr;
3579   if (Parent()->StyleRef().Visibility() != EVisibility::kVisible &&
3580       StyleRef().Visibility() == EVisibility::kVisible && !HasLayer()) {
3581     layer = Parent()->EnclosingLayer();
3582     if (layer)
3583       layer->DirtyVisibleContentStatus();
3584   }
3585 
3586   // Keep our layer hierarchy updated.
3587   if (SlowFirstChild() || HasLayer()) {
3588     if (!layer)
3589       layer = Parent()->EnclosingLayer();
3590     RemoveLayers(layer);
3591   }
3592 
3593   if (IsOutOfFlowPositioned() && Parent()->ChildrenInline())
3594     Parent()->DirtyLinesFromChangedChild(this);
3595 
3596   RemoveFromLayoutFlowThread();
3597 
3598   // Update cached boundaries in SVG layoutObjects if a child is removed.
3599   if (Parent()->IsSVG())
3600     Parent()->SetNeedsBoundariesUpdate();
3601 
3602   if (bitfields_.IsScrollAnchorObject()) {
3603     // Clear the bit first so that anchor.clear() doesn't recurse into
3604     // findReferencingScrollAnchors.
3605     bitfields_.SetIsScrollAnchorObject(false);
3606     FindReferencingScrollAnchors(this, kClear);
3607   }
3608 
3609   if (LocalFrameView* frame_view = GetFrameView())
3610     frame_view->GetPaintTimingDetector().LayoutObjectWillBeDestroyed(*this);
3611 }
3612 
SetNeedsPaintPropertyUpdate()3613 void LayoutObject::SetNeedsPaintPropertyUpdate() {
3614   NOT_DESTROYED();
3615   SetNeedsPaintPropertyUpdatePreservingCachedRects();
3616   InvalidateIntersectionObserverCachedRects();
3617 }
3618 
SetNeedsPaintPropertyUpdatePreservingCachedRects()3619 void LayoutObject::SetNeedsPaintPropertyUpdatePreservingCachedRects() {
3620   NOT_DESTROYED();
3621   if (bitfields_.NeedsPaintPropertyUpdate())
3622     return;
3623 
3624   // Anytime a layout object needs a paint property update, we should also do
3625   // intersection observation.
3626   // TODO(vmpstr): Figure out if there's a cleaner way to do this outside of
3627   // this function, since this is potentially called many times for a single
3628   // frame view subtree.
3629   GetFrameView()->SetIntersectionObservationState(LocalFrameView::kDesired);
3630 
3631   bitfields_.SetNeedsPaintPropertyUpdate(true);
3632   for (auto* ancestor = ParentCrossingFrames();
3633        ancestor && !ancestor->DescendantNeedsPaintPropertyUpdate();
3634        ancestor = ancestor->ParentCrossingFrames()) {
3635     ancestor->bitfields_.SetDescendantNeedsPaintPropertyUpdate(true);
3636   }
3637 }
3638 
SetAncestorsNeedPaintPropertyUpdateForMainThreadScrolling()3639 void LayoutObject::SetAncestorsNeedPaintPropertyUpdateForMainThreadScrolling() {
3640   NOT_DESTROYED();
3641   LayoutObject* ancestor = ParentCrossingFrames();
3642   while (ancestor) {
3643     ancestor->SetNeedsPaintPropertyUpdate();
3644     ancestor = ancestor->ParentCrossingFrames();
3645   }
3646 }
3647 
MaybeClearIsScrollAnchorObject()3648 void LayoutObject::MaybeClearIsScrollAnchorObject() {
3649   NOT_DESTROYED();
3650   if (!bitfields_.IsScrollAnchorObject())
3651     return;
3652   bitfields_.SetIsScrollAnchorObject(
3653       FindReferencingScrollAnchors(this, kDontClear));
3654 }
3655 
RemoveFromLayoutFlowThread()3656 void LayoutObject::RemoveFromLayoutFlowThread() {
3657   NOT_DESTROYED();
3658   if (!IsInsideFlowThread())
3659     return;
3660 
3661   // Sometimes we remove the element from the flow, but it's not destroyed at
3662   // that time.
3663   // It's only until later when we actually destroy it and remove all the
3664   // children from it.
3665   // Currently, that happens for firstLetter elements and list markers.
3666   // Pass in the flow thread so that we don't have to look it up for all the
3667   // children.
3668   // If we're a column spanner, we need to use our parent to find the flow
3669   // thread, since a spanner doesn't have the flow thread in its containing
3670   // block chain. We still need to notify the flow thread when the layoutObject
3671   // removed happens to be a spanner, so that we get rid of the spanner
3672   // placeholder, and column sets around the placeholder get merged.
3673   LayoutFlowThread* flow_thread = IsColumnSpanAll()
3674                                       ? Parent()->FlowThreadContainingBlock()
3675                                       : FlowThreadContainingBlock();
3676   RemoveFromLayoutFlowThreadRecursive(flow_thread);
3677 }
3678 
RemoveFromLayoutFlowThreadRecursive(LayoutFlowThread * layout_flow_thread)3679 void LayoutObject::RemoveFromLayoutFlowThreadRecursive(
3680     LayoutFlowThread* layout_flow_thread) {
3681   NOT_DESTROYED();
3682   if (const LayoutObjectChildList* children = VirtualChildren()) {
3683     for (LayoutObject* child = children->FirstChild(); child;
3684          child = child->NextSibling()) {
3685       if (child->IsLayoutFlowThread())
3686         continue;  // Don't descend into inner fragmentation contexts.
3687       child->RemoveFromLayoutFlowThreadRecursive(
3688           child->IsLayoutFlowThread() ? To<LayoutFlowThread>(child)
3689                                       : layout_flow_thread);
3690     }
3691   }
3692 
3693   if (layout_flow_thread && layout_flow_thread != this)
3694     layout_flow_thread->FlowThreadDescendantWillBeRemoved(this);
3695   SetIsInsideFlowThread(false);
3696   CHECK(!SpannerPlaceholder());
3697 }
3698 
DestroyAndCleanupAnonymousWrappers()3699 void LayoutObject::DestroyAndCleanupAnonymousWrappers() {
3700   NOT_DESTROYED();
3701   // If the tree is destroyed, there is no need for a clean-up phase.
3702   if (DocumentBeingDestroyed()) {
3703     Destroy();
3704     return;
3705   }
3706 
3707   LayoutObject* destroy_root = this;
3708   for (LayoutObject *destroy_root_parent = destroy_root->Parent();
3709        destroy_root_parent && destroy_root_parent->IsAnonymous();
3710        destroy_root = destroy_root_parent,
3711                     destroy_root_parent = destroy_root_parent->Parent()) {
3712     // Anonymous block continuations are tracked and destroyed elsewhere (see
3713     // the bottom of LayoutBlockFlow::RemoveChild)
3714     auto* destroy_root_parent_block =
3715         DynamicTo<LayoutBlockFlow>(destroy_root_parent);
3716     if (destroy_root_parent_block &&
3717         destroy_root_parent_block->IsAnonymousBlockContinuation())
3718       break;
3719     // A flow thread is tracked by its containing block. Whether its children
3720     // are removed or not is irrelevant.
3721     if (destroy_root_parent->IsLayoutFlowThread())
3722       break;
3723 
3724     // We need to keep the anonymous parent, if it won't become empty by the
3725     // removal of this LayoutObject.
3726     if (destroy_root->PreviousSibling())
3727       break;
3728     if (const LayoutObject* sibling = destroy_root->NextSibling()) {
3729       if (destroy_root->GetNode()) {
3730         // When there are inline continuations, there may be multiple layout
3731         // objects generated from the same node, and those are special. They
3732         // will be removed as part of destroying |this|, in
3733         // LayoutInline::WillBeDestroyed(). So if that's all we have left, we
3734         // need to realize now that the anonymous containing block will become
3735         // empty. So we have to destroy it.
3736         while (sibling && sibling->GetNode() == destroy_root->GetNode())
3737           sibling = sibling->NextSibling();
3738       }
3739       if (sibling)
3740         break;
3741       DCHECK(destroy_root->IsLayoutInline());
3742       DCHECK(To<LayoutInline>(destroy_root)->Continuation());
3743     }
3744   }
3745 
3746   destroy_root->Destroy();
3747 
3748   // WARNING: |this| is deleted here.
3749 }
3750 
Destroy()3751 void LayoutObject::Destroy() {
3752   NOT_DESTROYED();
3753   CHECK(g_allow_destroying_layout_object_in_finalizer ||
3754         !ThreadState::Current()->InAtomicSweepingPause());
3755 
3756   // Mark as being destroyed to avoid trouble with merges in |RemoveChild()| and
3757   // other house keepings.
3758   bitfields_.SetBeingDestroyed(true);
3759   WillBeDestroyed();
3760   DeleteThis();
3761 }
3762 
DeleteThis()3763 void LayoutObject::DeleteThis() {
3764   NOT_DESTROYED();
3765   delete this;
3766 }
3767 
PositionForPoint(const PhysicalOffset &) const3768 PositionWithAffinity LayoutObject::PositionForPoint(
3769     const PhysicalOffset&) const {
3770   NOT_DESTROYED();
3771   return CreatePositionWithAffinity(CaretMinOffset());
3772 }
3773 
GetCompositingState() const3774 CompositingState LayoutObject::GetCompositingState() const {
3775   NOT_DESTROYED();
3776   return HasLayer()
3777              ? To<LayoutBoxModelObject>(this)->Layer()->GetCompositingState()
3778              : kNotComposited;
3779 }
3780 
CanHaveAdditionalCompositingReasons() const3781 bool LayoutObject::CanHaveAdditionalCompositingReasons() const {
3782   NOT_DESTROYED();
3783   return false;
3784 }
3785 
AdditionalCompositingReasons() const3786 CompositingReasons LayoutObject::AdditionalCompositingReasons() const {
3787   NOT_DESTROYED();
3788   return CompositingReason::kNone;
3789 }
3790 
HitTestAllPhases(HitTestResult & result,const HitTestLocation & hit_test_location,const PhysicalOffset & accumulated_offset,HitTestFilter hit_test_filter)3791 bool LayoutObject::HitTestAllPhases(HitTestResult& result,
3792                                     const HitTestLocation& hit_test_location,
3793                                     const PhysicalOffset& accumulated_offset,
3794                                     HitTestFilter hit_test_filter) {
3795   NOT_DESTROYED();
3796   bool inside = false;
3797   if (hit_test_filter != kHitTestSelf) {
3798     // First test the foreground layer (lines and inlines).
3799     inside = NodeAtPoint(result, hit_test_location, accumulated_offset,
3800                          kHitTestForeground);
3801 
3802     // Test floats next.
3803     if (!inside)
3804       inside = NodeAtPoint(result, hit_test_location, accumulated_offset,
3805                            kHitTestFloat);
3806 
3807     // Finally test to see if the mouse is in the background (within a child
3808     // block's background).
3809     if (!inside)
3810       inside = NodeAtPoint(result, hit_test_location, accumulated_offset,
3811                            kHitTestChildBlockBackgrounds);
3812   }
3813 
3814   // See if the mouse is inside us but not any of our descendants
3815   if (hit_test_filter != kHitTestDescendants && !inside)
3816     inside = NodeAtPoint(result, hit_test_location, accumulated_offset,
3817                          kHitTestBlockBackground);
3818 
3819   return inside;
3820 }
3821 
NodeForHitTest() const3822 Node* LayoutObject::NodeForHitTest() const {
3823   NOT_DESTROYED();
3824   if (Node* node = GetNode())
3825     return node;
3826 
3827   // If we hit the anonymous layoutObjects inside generated content we should
3828   // actually hit the generated content so walk up to the PseudoElement.
3829   if (const LayoutObject* parent = Parent()) {
3830     if (parent->IsBeforeOrAfterContent() || parent->IsMarkerContent() ||
3831         parent->StyleRef().StyleType() == kPseudoIdFirstLetter) {
3832       for (; parent; parent = parent->Parent()) {
3833         if (Node* node = parent->GetNode())
3834           return node;
3835       }
3836     }
3837   }
3838 
3839   return nullptr;
3840 }
3841 
UpdateHitTestResult(HitTestResult & result,const PhysicalOffset & point) const3842 void LayoutObject::UpdateHitTestResult(HitTestResult& result,
3843                                        const PhysicalOffset& point) const {
3844   NOT_DESTROYED();
3845   if (result.InnerNode())
3846     return;
3847 
3848   if (Node* n = NodeForHitTest())
3849     result.SetNodeAndPosition(n, point);
3850 }
3851 
NodeAtPoint(HitTestResult &,const HitTestLocation &,const PhysicalOffset &,HitTestAction)3852 bool LayoutObject::NodeAtPoint(HitTestResult&,
3853                                const HitTestLocation&,
3854                                const PhysicalOffset&,
3855                                HitTestAction) {
3856   NOT_DESTROYED();
3857   return false;
3858 }
3859 
ScheduleRelayout()3860 void LayoutObject::ScheduleRelayout() {
3861   NOT_DESTROYED();
3862   if (auto* layout_view = DynamicTo<LayoutView>(this)) {
3863     if (LocalFrameView* view = layout_view->GetFrameView())
3864       view->ScheduleRelayout();
3865   } else {
3866     if (IsRooted()) {
3867       layout_view = View();
3868       if (layout_view) {
3869         if (LocalFrameView* frame_view = layout_view->GetFrameView())
3870           frame_view->ScheduleRelayoutOfSubtree(this);
3871       }
3872     }
3873   }
3874 }
3875 
ForceLayout()3876 void LayoutObject::ForceLayout() {
3877   NOT_DESTROYED();
3878   SetSelfNeedsLayoutForAvailableSpace(true);
3879   UpdateLayout();
3880 }
3881 
FirstLineStyleWithoutFallback() const3882 const ComputedStyle* LayoutObject::FirstLineStyleWithoutFallback() const {
3883   NOT_DESTROYED();
3884   DCHECK(GetDocument().GetStyleEngine().UsesFirstLineRules());
3885 
3886   // Normal markers don't use ::first-line styles in Chromium, so be consistent
3887   // and return null for content markers. This may need to change depending on
3888   // https://github.com/w3c/csswg-drafts/issues/4506
3889   if (IsMarkerContent())
3890     return nullptr;
3891   if (IsBeforeOrAfterContent() || IsText()) {
3892     if (!Parent())
3893       return nullptr;
3894     return Parent()->FirstLineStyleWithoutFallback();
3895   }
3896 
3897   if (BehavesLikeBlockContainer()) {
3898     if (const ComputedStyle* cached =
3899             StyleRef().GetCachedPseudoElementStyle(kPseudoIdFirstLine))
3900       return cached;
3901 
3902     if (const LayoutBlock* first_line_block =
3903             To<LayoutBlock>(this)->EnclosingFirstLineStyleBlock()) {
3904       if (first_line_block->Style() == Style()) {
3905         return first_line_block->GetCachedPseudoElementStyle(
3906             kPseudoIdFirstLine);
3907       }
3908 
3909       // We can't use first_line_block->GetCachedPseudoElementStyle() because
3910       // it's based on first_line_block's style. We need to get the uncached
3911       // first line style based on this object's style and cache the result in
3912       // it.
3913       if (scoped_refptr<ComputedStyle> first_line_style =
3914               first_line_block->GetUncachedPseudoElementStyle(
3915                   PseudoElementStyleRequest(kPseudoIdFirstLine), Style())) {
3916         return StyleRef().AddCachedPseudoElementStyle(
3917             std::move(first_line_style));
3918       }
3919     }
3920   } else if (!IsAnonymous() && IsLayoutInline() &&
3921              !GetNode()->IsFirstLetterPseudoElement()) {
3922     if (const ComputedStyle* cached =
3923             StyleRef().GetCachedPseudoElementStyle(kPseudoIdFirstLineInherited))
3924       return cached;
3925 
3926     if (const ComputedStyle* parent_first_line_style =
3927             Parent()->FirstLineStyleWithoutFallback()) {
3928       // A first-line style is in effect. Get uncached first line style based on
3929       // parent_first_line_style and cache the result in this object's style.
3930       if (scoped_refptr<ComputedStyle> first_line_style =
3931               GetUncachedPseudoElementStyle(kPseudoIdFirstLineInherited,
3932                                             parent_first_line_style)) {
3933         return StyleRef().AddCachedPseudoElementStyle(
3934             std::move(first_line_style));
3935       }
3936     }
3937   }
3938   return nullptr;
3939 }
3940 
GetCachedPseudoElementStyle(PseudoId pseudo) const3941 const ComputedStyle* LayoutObject::GetCachedPseudoElementStyle(
3942     PseudoId pseudo) const {
3943   NOT_DESTROYED();
3944   DCHECK_NE(pseudo, kPseudoIdBefore);
3945   DCHECK_NE(pseudo, kPseudoIdAfter);
3946   if (!GetNode())
3947     return nullptr;
3948 
3949   Element* element = Traversal<Element>::FirstAncestorOrSelf(*GetNode());
3950   if (!element)
3951     return nullptr;
3952 
3953   return element->CachedStyleForPseudoElement(
3954       PseudoElementStyleRequest(pseudo));
3955 }
3956 
GetUncachedPseudoElementStyle(const PseudoElementStyleRequest & request,const ComputedStyle * parent_style) const3957 scoped_refptr<ComputedStyle> LayoutObject::GetUncachedPseudoElementStyle(
3958     const PseudoElementStyleRequest& request,
3959     const ComputedStyle* parent_style) const {
3960   NOT_DESTROYED();
3961   DCHECK_NE(request.pseudo_id, kPseudoIdBefore);
3962   DCHECK_NE(request.pseudo_id, kPseudoIdAfter);
3963   if (!GetNode())
3964     return nullptr;
3965 
3966   Element* element = Traversal<Element>::FirstAncestorOrSelf(*GetNode());
3967   if (!element)
3968     return nullptr;
3969   if (element->IsPseudoElement())
3970     return nullptr;
3971 
3972   return element->StyleForPseudoElement(request, parent_style);
3973 }
3974 
AddAnnotatedRegions(Vector<AnnotatedRegionValue> & regions)3975 void LayoutObject::AddAnnotatedRegions(Vector<AnnotatedRegionValue>& regions) {
3976   NOT_DESTROYED();
3977   // Convert the style regions to absolute coordinates.
3978   if (StyleRef().Visibility() != EVisibility::kVisible || !IsBox())
3979     return;
3980 
3981   if (StyleRef().DraggableRegionMode() == EDraggableRegionMode::kNone)
3982     return;
3983 
3984   auto* box = To<LayoutBox>(this);
3985   PhysicalRect local_bounds = box->PhysicalBorderBoxRect();
3986   PhysicalRect abs_bounds = LocalToAbsoluteRect(local_bounds);
3987 
3988   AnnotatedRegionValue region;
3989   region.draggable =
3990       StyleRef().DraggableRegionMode() == EDraggableRegionMode::kDrag;
3991   region.bounds = abs_bounds;
3992   regions.push_back(region);
3993 }
3994 
WillRenderImage()3995 bool LayoutObject::WillRenderImage() {
3996   NOT_DESTROYED();
3997   // Without visibility we won't render (and therefore don't care about
3998   // animation).
3999   if (StyleRef().Visibility() != EVisibility::kVisible)
4000     return false;
4001 
4002   // We will not render a new image when ExecutionContext is paused
4003   if (GetDocument().GetExecutionContext()->IsContextPaused())
4004     return false;
4005 
4006   // Suspend animations when the page is not visible.
4007   if (GetDocument().hidden())
4008     return false;
4009 
4010   // If we're not in a window (i.e., we're dormant from being in a background
4011   // tab) then we don't want to render either.
4012   return GetDocument().View()->IsVisible();
4013 }
4014 
GetImageAnimationPolicy(mojom::blink::ImageAnimationPolicy & policy)4015 bool LayoutObject::GetImageAnimationPolicy(
4016     mojom::blink::ImageAnimationPolicy& policy) {
4017   NOT_DESTROYED();
4018   if (!GetDocument().GetSettings())
4019     return false;
4020   policy = GetDocument().GetSettings()->GetImageAnimationPolicy();
4021   return true;
4022 }
4023 
IsInsideListMarker() const4024 bool LayoutObject::IsInsideListMarker() const {
4025   NOT_DESTROYED();
4026   return (IsListMarkerForNormalContent() &&
4027           To<LayoutListMarker>(this)->IsInside()) ||
4028          IsInsideListMarkerForCustomContent();
4029 }
4030 
IsOutsideListMarker() const4031 bool LayoutObject::IsOutsideListMarker() const {
4032   NOT_DESTROYED();
4033   return (IsListMarkerForNormalContent() &&
4034           !To<LayoutListMarker>(this)->IsInside()) ||
4035          IsOutsideListMarkerForCustomContent();
4036 }
4037 
CaretMinOffset() const4038 int LayoutObject::CaretMinOffset() const {
4039   NOT_DESTROYED();
4040   return 0;
4041 }
4042 
CaretMaxOffset() const4043 int LayoutObject::CaretMaxOffset() const {
4044   NOT_DESTROYED();
4045   if (IsAtomicInlineLevel())
4046     return GetNode() ? std::max(1U, GetNode()->CountChildren()) : 1;
4047   if (IsHR())
4048     return 1;
4049   return 0;
4050 }
4051 
IsInert() const4052 bool LayoutObject::IsInert() const {
4053   NOT_DESTROYED();
4054   const LayoutObject* layout_object = this;
4055   while (!layout_object->GetNode())
4056     layout_object = layout_object->Parent();
4057   return layout_object->GetNode()->IsInert();
4058 }
4059 
ImageChanged(ImageResourceContent * image,CanDeferInvalidation defer)4060 void LayoutObject::ImageChanged(ImageResourceContent* image,
4061                                 CanDeferInvalidation defer) {
4062   NOT_DESTROYED();
4063   DCHECK(node_);
4064 
4065   // Image change notifications should not be received during paint because
4066   // the resulting invalidations will be cleared following paint. This can also
4067   // lead to modifying the tree out from under paint(), see: crbug.com/616700.
4068   DCHECK_NE(GetDocument().Lifecycle().GetState(),
4069             DocumentLifecycle::LifecycleState::kInPaint);
4070 
4071   ImageChanged(static_cast<WrappedImagePtr>(image), defer);
4072 }
4073 
ImageNotifyFinished(ImageResourceContent * image)4074 void LayoutObject::ImageNotifyFinished(ImageResourceContent* image) {
4075   NOT_DESTROYED();
4076   if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache())
4077     cache->ImageLoaded(this);
4078 
4079   if (LocalDOMWindow* window = GetDocument().domWindow())
4080     ImageElementTiming::From(*window).NotifyImageFinished(*this, image);
4081   if (LocalFrameView* frame_view = GetFrameView())
4082     frame_view->GetPaintTimingDetector().NotifyImageFinished(*this, image);
4083 }
4084 
OffsetParent(const Element * base) const4085 Element* LayoutObject::OffsetParent(const Element* base) const {
4086   NOT_DESTROYED();
4087   if (IsDocumentElement() || IsBody())
4088     return nullptr;
4089 
4090   if (IsFixedPositioned())
4091     return nullptr;
4092 
4093   float effective_zoom = StyleRef().EffectiveZoom();
4094   Node* node = nullptr;
4095   for (LayoutObject* ancestor = Parent(); ancestor;
4096        ancestor = ancestor->Parent()) {
4097     // Spec: http://www.w3.org/TR/cssom-view/#offset-attributes
4098 
4099     node = ancestor->GetNode();
4100 
4101     if (!node)
4102       continue;
4103 
4104     // TODO(kochi): If |base| or |node| is nested deep in shadow roots, this
4105     // loop may get expensive, as isUnclosedNodeOf() can take up to O(N+M) time
4106     // (N and M are depths).
4107     if (base && (node->IsClosedShadowHiddenFrom(*base) ||
4108                  (node->IsInShadowTree() &&
4109                   node->ContainingShadowRoot()->IsUserAgent()))) {
4110       // If 'position: fixed' node is found while traversing up, terminate the
4111       // loop and return null.
4112       if (ancestor->IsFixedPositioned())
4113         return nullptr;
4114       continue;
4115     }
4116 
4117     if (ancestor->CanContainAbsolutePositionObjects())
4118       break;
4119 
4120     if (IsA<HTMLBodyElement>(*node))
4121       break;
4122 
4123     if (!IsPositioned() &&
4124         (IsA<HTMLTableElement>(*node) || IsA<HTMLTableCellElement>(*node)))
4125       break;
4126 
4127     // Webkit specific extension where offsetParent stops at zoom level changes.
4128     if (effective_zoom != ancestor->StyleRef().EffectiveZoom())
4129       break;
4130   }
4131 
4132   return DynamicTo<Element>(node);
4133 }
4134 
NotifyImageFullyRemoved(ImageResourceContent * image)4135 void LayoutObject::NotifyImageFullyRemoved(ImageResourceContent* image) {
4136   NOT_DESTROYED();
4137   if (LocalDOMWindow* window = GetDocument().domWindow())
4138     ImageElementTiming::From(*window).NotifyImageRemoved(this, image);
4139   if (LocalFrameView* frame_view = GetFrameView())
4140     frame_view->GetPaintTimingDetector().NotifyImageRemoved(*this, image);
4141 }
4142 
CreatePositionWithAffinity(int offset,TextAffinity affinity) const4143 PositionWithAffinity LayoutObject::CreatePositionWithAffinity(
4144     int offset,
4145     TextAffinity affinity) const {
4146   NOT_DESTROYED();
4147   // If this is a non-anonymous layoutObject in an editable area, then it's
4148   // simple.
4149   if (Node* node = NonPseudoNode()) {
4150     if (!HasEditableStyle(*node)) {
4151       // If it can be found, we prefer a visually equivalent position that is
4152       // editable.
4153       // TODO(layout-dev): Once we fix callers of |CreatePositionWithAffinity()|
4154       // we should use |Position| constructor. See http://crbug.com/827923
4155       const Position position =
4156           Position::CreateWithoutValidationDeprecated(*node, offset);
4157       Position candidate =
4158           MostForwardCaretPosition(position, kCanCrossEditingBoundary);
4159       if (HasEditableStyle(*candidate.AnchorNode()))
4160         return PositionWithAffinity(candidate, affinity);
4161       candidate = MostBackwardCaretPosition(position, kCanCrossEditingBoundary);
4162       if (HasEditableStyle(*candidate.AnchorNode()))
4163         return PositionWithAffinity(candidate, affinity);
4164     }
4165     // FIXME: Eliminate legacy editing positions
4166     return PositionWithAffinity(Position::EditingPositionOf(node, offset),
4167                                 affinity);
4168   }
4169 
4170   // We don't want to cross the boundary between editable and non-editable
4171   // regions of the document, but that is either impossible or at least
4172   // extremely unlikely in any normal case because we stop as soon as we
4173   // find a single non-anonymous layoutObject.
4174 
4175   // Find a nearby non-anonymous layoutObject.
4176   const LayoutObject* child = this;
4177   while (const LayoutObject* parent = child->Parent()) {
4178     // Find non-anonymous content after.
4179     for (const LayoutObject* layout_object = child->NextInPreOrder(parent);
4180          layout_object; layout_object = layout_object->NextInPreOrder(parent)) {
4181       if (const Node* node = layout_object->NonPseudoNode()) {
4182         return PositionWithAffinity(FirstPositionInOrBeforeNode(*node));
4183       }
4184     }
4185 
4186     // Find non-anonymous content before.
4187     for (const LayoutObject* layout_object = child->PreviousInPreOrder();
4188          layout_object; layout_object = layout_object->PreviousInPreOrder()) {
4189       if (layout_object == parent)
4190         break;
4191       if (const Node* node = layout_object->NonPseudoNode())
4192         return PositionWithAffinity(LastPositionInOrAfterNode(*node));
4193     }
4194 
4195     // Use the parent itself unless it too is anonymous.
4196     if (const Node* node = parent->NonPseudoNode())
4197       return PositionWithAffinity(FirstPositionInOrBeforeNode(*node));
4198 
4199     // Repeat at the next level up.
4200     child = parent;
4201   }
4202 
4203   // Everything was anonymous. Give up.
4204   return PositionWithAffinity();
4205 }
4206 
CreatePositionWithAffinity(int offset) const4207 PositionWithAffinity LayoutObject::CreatePositionWithAffinity(
4208     int offset) const {
4209   NOT_DESTROYED();
4210   return CreatePositionWithAffinity(offset, TextAffinity::kDownstream);
4211 }
4212 
CreatePositionWithAffinity(const Position & position) const4213 PositionWithAffinity LayoutObject::CreatePositionWithAffinity(
4214     const Position& position) const {
4215   NOT_DESTROYED();
4216   if (position.IsNotNull())
4217     return PositionWithAffinity(position);
4218 
4219   DCHECK(!NonPseudoNode());
4220   return CreatePositionWithAffinity(0);
4221 }
4222 
GetCursor(const PhysicalOffset &,ui::Cursor &) const4223 CursorDirective LayoutObject::GetCursor(const PhysicalOffset&,
4224                                         ui::Cursor&) const {
4225   NOT_DESTROYED();
4226   return kSetCursorBasedOnStyle;
4227 }
4228 
CanUpdateSelectionOnRootLineBoxes() const4229 bool LayoutObject::CanUpdateSelectionOnRootLineBoxes() const {
4230   NOT_DESTROYED();
4231   if (NeedsLayout())
4232     return false;
4233 
4234   const LayoutBlock* containing_block = ContainingBlock();
4235   return containing_block ? !containing_block->NeedsLayout() : false;
4236 }
4237 
SetNeedsBoundariesUpdate()4238 void LayoutObject::SetNeedsBoundariesUpdate() {
4239   NOT_DESTROYED();
4240   if (IsSVGChild()) {
4241     // The boundaries affect mask clip.
4242     auto* resources = SVGResourcesCache::CachedResourcesForLayoutObject(*this);
4243     if (resources && resources->Masker())
4244       SetNeedsPaintPropertyUpdate();
4245     if (resources && resources->Clipper())
4246       InvalidateClipPathCache();
4247   }
4248   if (LayoutObject* layout_object = Parent())
4249     layout_object->SetNeedsBoundariesUpdate();
4250 }
4251 
ObjectBoundingBox() const4252 FloatRect LayoutObject::ObjectBoundingBox() const {
4253   NOT_DESTROYED();
4254   NOTREACHED();
4255   return FloatRect();
4256 }
4257 
StrokeBoundingBox() const4258 FloatRect LayoutObject::StrokeBoundingBox() const {
4259   NOT_DESTROYED();
4260   NOTREACHED();
4261   return FloatRect();
4262 }
4263 
VisualRectInLocalSVGCoordinates() const4264 FloatRect LayoutObject::VisualRectInLocalSVGCoordinates() const {
4265   NOT_DESTROYED();
4266   NOTREACHED();
4267   return FloatRect();
4268 }
4269 
LocalSVGTransform() const4270 AffineTransform LayoutObject::LocalSVGTransform() const {
4271   NOT_DESTROYED();
4272   return AffineTransform();
4273 }
4274 
IsRelayoutBoundary() const4275 bool LayoutObject::IsRelayoutBoundary() const {
4276   NOT_DESTROYED();
4277   return ObjectIsRelayoutBoundary(this);
4278 }
4279 
SetShouldCheckGeometryForPaintInvalidation()4280 inline void LayoutObject::SetShouldCheckGeometryForPaintInvalidation() {
4281   NOT_DESTROYED();
4282   DCHECK(ShouldCheckForPaintInvalidation());
4283   bitfields_.SetShouldCheckGeometryForPaintInvalidation(true);
4284   for (auto* ancestor = ParentCrossingFrames();
4285        ancestor &&
4286        !ancestor->DescendantShouldCheckGeometryForPaintInvalidation();
4287        ancestor = ancestor->ParentCrossingFrames()) {
4288     ancestor->bitfields_.SetDescendantShouldCheckGeometryForPaintInvalidation(
4289         true);
4290   }
4291 }
4292 
SetShouldInvalidateSelection()4293 void LayoutObject::SetShouldInvalidateSelection() {
4294   NOT_DESTROYED();
4295   bitfields_.SetShouldInvalidateSelection(true);
4296   SetShouldCheckForPaintInvalidation();
4297 }
4298 
SetShouldDoFullPaintInvalidation(PaintInvalidationReason reason)4299 void LayoutObject::SetShouldDoFullPaintInvalidation(
4300     PaintInvalidationReason reason) {
4301   NOT_DESTROYED();
4302   SetShouldDoFullPaintInvalidationWithoutGeometryChange(reason);
4303   SetShouldCheckGeometryForPaintInvalidation();
4304 }
4305 
DocumentLifecycleBasedPaintInvalidationReason(const DocumentLifecycle & document_lifecycle)4306 static PaintInvalidationReason DocumentLifecycleBasedPaintInvalidationReason(
4307     const DocumentLifecycle& document_lifecycle) {
4308   switch (document_lifecycle.GetState()) {
4309     case DocumentLifecycle::kInStyleRecalc:
4310       return PaintInvalidationReason::kStyle;
4311     case DocumentLifecycle::kInPreLayout:
4312     case DocumentLifecycle::kInPerformLayout:
4313     case DocumentLifecycle::kAfterPerformLayout:
4314       return PaintInvalidationReason::kGeometry;
4315     case DocumentLifecycle::kInCompositingAssignmentsUpdate:
4316       DCHECK(false);
4317       return PaintInvalidationReason::kFull;
4318     default:
4319       return PaintInvalidationReason::kFull;
4320   }
4321 }
4322 
4323 void LayoutObject::
SetShouldDoFullPaintInvalidationWithoutGeometryChangeInternal(PaintInvalidationReason reason)4324     SetShouldDoFullPaintInvalidationWithoutGeometryChangeInternal(
4325         PaintInvalidationReason reason) {
4326   NOT_DESTROYED();
4327   // Only full invalidation reasons are allowed.
4328   DCHECK(IsFullPaintInvalidationReason(reason));
4329   if (ShouldDoFullPaintInvalidation())
4330     return;
4331 
4332   SetShouldCheckForPaintInvalidationWithoutGeometryChange();
4333   if (reason == PaintInvalidationReason::kFull) {
4334     reason = DocumentLifecycleBasedPaintInvalidationReason(
4335         GetDocument().Lifecycle());
4336   }
4337   full_paint_invalidation_reason_ = reason;
4338   bitfields_.SetShouldDelayFullPaintInvalidation(false);
4339 }
4340 
SetShouldCheckForPaintInvalidation()4341 void LayoutObject::SetShouldCheckForPaintInvalidation() {
4342   NOT_DESTROYED();
4343   SetShouldCheckForPaintInvalidationWithoutGeometryChange();
4344   SetShouldCheckGeometryForPaintInvalidation();
4345 }
4346 
SetShouldCheckForPaintInvalidationWithoutGeometryChange()4347 void LayoutObject::SetShouldCheckForPaintInvalidationWithoutGeometryChange() {
4348   NOT_DESTROYED();
4349   if (ShouldCheckForPaintInvalidation())
4350     return;
4351   GetFrameView()->ScheduleVisualUpdateForPaintInvalidationIfNeeded();
4352 
4353   bitfields_.SetShouldCheckForPaintInvalidation(true);
4354   for (LayoutObject* parent = ParentCrossingFrames();
4355        parent && !parent->ShouldCheckForPaintInvalidation();
4356        parent = parent->ParentCrossingFrames()) {
4357     parent->bitfields_.SetShouldCheckForPaintInvalidation(true);
4358   }
4359 }
4360 
SetSubtreeShouldCheckForPaintInvalidation()4361 void LayoutObject::SetSubtreeShouldCheckForPaintInvalidation() {
4362   NOT_DESTROYED();
4363   if (SubtreeShouldCheckForPaintInvalidation()) {
4364     DCHECK(ShouldCheckForPaintInvalidation());
4365     return;
4366   }
4367   SetShouldCheckForPaintInvalidation();
4368   bitfields_.SetSubtreeShouldCheckForPaintInvalidation(true);
4369 }
4370 
SetMayNeedPaintInvalidationAnimatedBackgroundImage()4371 void LayoutObject::SetMayNeedPaintInvalidationAnimatedBackgroundImage() {
4372   NOT_DESTROYED();
4373   if (MayNeedPaintInvalidationAnimatedBackgroundImage())
4374     return;
4375   bitfields_.SetMayNeedPaintInvalidationAnimatedBackgroundImage(true);
4376   SetShouldCheckForPaintInvalidationWithoutGeometryChange();
4377 }
4378 
SetShouldDelayFullPaintInvalidation()4379 void LayoutObject::SetShouldDelayFullPaintInvalidation() {
4380   NOT_DESTROYED();
4381   // Should have already set a full paint invalidation reason.
4382   DCHECK(IsFullPaintInvalidationReason(full_paint_invalidation_reason_));
4383 
4384   bitfields_.SetShouldDelayFullPaintInvalidation(true);
4385   if (!ShouldCheckForPaintInvalidation()) {
4386     // This will also schedule a visual update.
4387     SetShouldCheckForPaintInvalidationWithoutGeometryChange();
4388   } else {
4389     // Schedule visual update for the next document cycle in which we will
4390     // check if the delayed invalidation should be promoted to a real
4391     // invalidation.
4392     GetFrameView()->ScheduleVisualUpdateForPaintInvalidationIfNeeded();
4393   }
4394 }
4395 
ClearShouldDelayFullPaintInvalidation()4396 void LayoutObject::ClearShouldDelayFullPaintInvalidation() {
4397   // This will clear ShouldDelayFullPaintInvalidation() flag and enable previous
4398   // BackgroundNeedsFullPaintInvalidaiton() if it's set.
4399   SetShouldDoFullPaintInvalidationWithoutGeometryChangeInternal(
4400       FullPaintInvalidationReason());
4401 }
4402 
ClearPaintInvalidationFlags()4403 void LayoutObject::ClearPaintInvalidationFlags() {
4404   NOT_DESTROYED();
4405 // PaintInvalidationStateIsDirty should be kept in sync with the
4406 // booleans that are cleared below.
4407 #if DCHECK_IS_ON()
4408   DCHECK(!ShouldCheckForPaintInvalidation() || PaintInvalidationStateIsDirty());
4409 #endif
4410   fragment_.SetPartialInvalidationLocalRect(PhysicalRect());
4411   if (!ShouldDelayFullPaintInvalidation()) {
4412     full_paint_invalidation_reason_ = PaintInvalidationReason::kNone;
4413     bitfields_.SetBackgroundNeedsFullPaintInvalidation(false);
4414   }
4415   bitfields_.SetShouldCheckForPaintInvalidation(false);
4416   bitfields_.SetSubtreeShouldCheckForPaintInvalidation(false);
4417   bitfields_.SetSubtreeShouldDoFullPaintInvalidation(false);
4418   bitfields_.SetMayNeedPaintInvalidationAnimatedBackgroundImage(false);
4419   bitfields_.SetShouldCheckGeometryForPaintInvalidation(false);
4420   bitfields_.SetDescendantShouldCheckGeometryForPaintInvalidation(false);
4421   bitfields_.SetShouldInvalidateSelection(false);
4422 }
4423 
4424 #if DCHECK_IS_ON()
PaintInvalidationStateIsDirty() const4425 bool LayoutObject::PaintInvalidationStateIsDirty() const {
4426   NOT_DESTROYED();
4427   return BackgroundNeedsFullPaintInvalidation() ||
4428          ShouldCheckForPaintInvalidation() || ShouldInvalidateSelection() ||
4429          ShouldCheckGeometryForPaintInvalidation() ||
4430          DescendantShouldCheckGeometryForPaintInvalidation() ||
4431          ShouldDoFullPaintInvalidation() ||
4432          SubtreeShouldDoFullPaintInvalidation() ||
4433          MayNeedPaintInvalidationAnimatedBackgroundImage() ||
4434          !fragment_.PartialInvalidationLocalRect().IsEmpty();
4435 }
4436 #endif
4437 
EnsureIsReadyForPaintInvalidation()4438 void LayoutObject::EnsureIsReadyForPaintInvalidation() {
4439   NOT_DESTROYED();
4440   DCHECK(!NeedsLayout() || ChildLayoutBlockedByDisplayLock());
4441 
4442   // Force full paint invalidation if the outline may be affected by descendants
4443   // and this object is marked for checking paint invalidation for any reason.
4444   if (bitfields_.OutlineMayBeAffectedByDescendants() ||
4445       bitfields_.PreviousOutlineMayBeAffectedByDescendants()) {
4446     SetShouldDoFullPaintInvalidationWithoutGeometryChange(
4447         PaintInvalidationReason::kOutline);
4448   }
4449   bitfields_.SetPreviousOutlineMayBeAffectedByDescendants(
4450       bitfields_.OutlineMayBeAffectedByDescendants());
4451 }
4452 
ClearPaintFlags()4453 void LayoutObject::ClearPaintFlags() {
4454   NOT_DESTROYED();
4455   DCHECK_EQ(GetDocument().Lifecycle().GetState(),
4456             DocumentLifecycle::kInPrePaint);
4457   ClearPaintInvalidationFlags();
4458   bitfields_.SetNeedsPaintPropertyUpdate(false);
4459   bitfields_.SetEffectiveAllowedTouchActionChanged(false);
4460   bitfields_.SetBlockingWheelEventHandlerChanged(false);
4461 
4462   if (!ChildPrePaintBlockedByDisplayLock()) {
4463     bitfields_.SetDescendantNeedsPaintPropertyUpdate(false);
4464     bitfields_.SetDescendantEffectiveAllowedTouchActionChanged(false);
4465     bitfields_.SetDescendantBlockingWheelEventHandlerChanged(false);
4466     bitfields_.ResetSubtreePaintPropertyUpdateReasons();
4467   }
4468 }
4469 
IsAllowedToModifyLayoutTreeStructure(Document & document)4470 bool LayoutObject::IsAllowedToModifyLayoutTreeStructure(Document& document) {
4471   return document.Lifecycle().StateAllowsLayoutTreeMutations();
4472 }
4473 
SetSubtreeShouldDoFullPaintInvalidation(PaintInvalidationReason reason)4474 void LayoutObject::SetSubtreeShouldDoFullPaintInvalidation(
4475     PaintInvalidationReason reason) {
4476   NOT_DESTROYED();
4477   SetShouldDoFullPaintInvalidation(reason);
4478   bitfields_.SetSubtreeShouldDoFullPaintInvalidation(true);
4479 }
4480 
SetIsBackgroundAttachmentFixedObject(bool is_background_attachment_fixed_object)4481 void LayoutObject::SetIsBackgroundAttachmentFixedObject(
4482     bool is_background_attachment_fixed_object) {
4483   NOT_DESTROYED();
4484   DCHECK(GetFrameView());
4485   if (bitfields_.IsBackgroundAttachmentFixedObject() ==
4486       is_background_attachment_fixed_object)
4487     return;
4488   bitfields_.SetIsBackgroundAttachmentFixedObject(
4489       is_background_attachment_fixed_object);
4490   if (is_background_attachment_fixed_object)
4491     GetFrameView()->AddBackgroundAttachmentFixedObject(this);
4492   else
4493     GetFrameView()->RemoveBackgroundAttachmentFixedObject(this);
4494 }
4495 
DebugRect() const4496 PhysicalRect LayoutObject::DebugRect() const {
4497   NOT_DESTROYED();
4498   return PhysicalRect();
4499 }
4500 
InvalidateSelectedChildrenOnStyleChange()4501 void LayoutObject::InvalidateSelectedChildrenOnStyleChange() {
4502   NOT_DESTROYED();
4503   // LayoutSelection::Commit() propagates the state up the containing node
4504   // chain to
4505   // tell if a block contains selected nodes or not. If this layout object is
4506   // not a block, we need to get the selection state from the containing block
4507   // to tell if we have any selected node children.
4508   LayoutBlock* block =
4509       IsLayoutBlock() ? To<LayoutBlock>(this) : ContainingBlock();
4510   if (!block)
4511     return;
4512   if (!block->IsSelected())
4513     return;
4514 
4515   // ::selection style only applies to direct selection leaf children of the
4516   // element on which the ::selection style is set. Thus, we only walk the
4517   // direct children here.
4518   for (LayoutObject* child = SlowFirstChild(); child;
4519        child = child->NextSibling()) {
4520     if (!child->CanBeSelectionLeaf())
4521       continue;
4522     if (!child->IsSelected())
4523       continue;
4524     child->SetShouldInvalidateSelection();
4525   }
4526 }
4527 
MarkEffectiveAllowedTouchActionChanged()4528 void LayoutObject::MarkEffectiveAllowedTouchActionChanged() {
4529   NOT_DESTROYED();
4530   bitfields_.SetEffectiveAllowedTouchActionChanged(true);
4531   // If we're locked, mark our descendants as needing this change. This is used
4532   // a signal to ensure we mark the element as needing effective allowed
4533   // touch action recalculation when the element becomes unlocked.
4534   if (ChildPrePaintBlockedByDisplayLock()) {
4535     bitfields_.SetDescendantEffectiveAllowedTouchActionChanged(true);
4536     return;
4537   }
4538 
4539   LayoutObject* obj = ParentCrossingFrames();
4540   while (obj && !obj->DescendantEffectiveAllowedTouchActionChanged()) {
4541     obj->bitfields_.SetDescendantEffectiveAllowedTouchActionChanged(true);
4542     if (obj->ChildPrePaintBlockedByDisplayLock())
4543       break;
4544 
4545     obj = obj->ParentCrossingFrames();
4546   }
4547 }
4548 
MarkBlockingWheelEventHandlerChanged()4549 void LayoutObject::MarkBlockingWheelEventHandlerChanged() {
4550   DCHECK(base::FeatureList::IsEnabled(::features::kWheelEventRegions));
4551   bitfields_.SetBlockingWheelEventHandlerChanged(true);
4552   // If we're locked, mark our descendants as needing this change. This is used
4553   // as a signal to ensure we mark the element as needing wheel event handler
4554   // recalculation when the element becomes unlocked.
4555   if (ChildPrePaintBlockedByDisplayLock()) {
4556     bitfields_.SetDescendantBlockingWheelEventHandlerChanged(true);
4557     return;
4558   }
4559 
4560   LayoutObject* obj = ParentCrossingFrames();
4561   while (obj && !obj->DescendantBlockingWheelEventHandlerChanged()) {
4562     obj->bitfields_.SetDescendantBlockingWheelEventHandlerChanged(true);
4563     if (obj->ChildPrePaintBlockedByDisplayLock())
4564       break;
4565 
4566     obj = obj->ParentCrossingFrames();
4567   }
4568 }
4569 
4570 // Note about ::first-letter pseudo-element:
4571 //   When an element has ::first-letter pseudo-element, first letter characters
4572 //   are taken from |Text| node and first letter characters are considered
4573 //   as content of <pseudo:first-letter>.
4574 //   For following HTML,
4575 //      <style>div::first-letter {color: red}</style>
4576 //      <div>abc</div>
4577 //   we have following layout tree:
4578 //      LayoutBlockFlow {DIV} at (0,0) size 784x55
4579 //        LayoutInline {<pseudo:first-letter>} at (0,0) size 22x53
4580 //          LayoutTextFragment (anonymous) at (0,1) size 22x53
4581 //            text run at (0,1) width 22: "a"
4582 //        LayoutTextFragment {#text} at (21,30) size 16x17
4583 //          text run at (21,30) width 16: "bc"
4584 //  In this case, |Text::layoutObject()| for "abc" returns |LayoutTextFragment|
4585 //  containing "bc", and it is called remaining part.
4586 //
4587 //  Even if |Text| node contains only first-letter characters, e.g. just "a",
4588 //  remaining part of |LayoutTextFragment|, with |fragmentLength()| == 0, is
4589 //  appeared in layout tree.
4590 //
4591 //  When |Text| node contains only first-letter characters and whitespaces, e.g.
4592 //  "B\n", associated |LayoutTextFragment| is first-letter part instead of
4593 //  remaining part.
4594 //
4595 //  Punctuation characters are considered as first-letter. For "(1)ab",
4596 //  "(1)" are first-letter part and "ab" are remaining part.
AssociatedLayoutObjectOf(const Node & node,int offset_in_node,LayoutObjectSide object_side)4597 const LayoutObject* AssociatedLayoutObjectOf(const Node& node,
4598                                              int offset_in_node,
4599                                              LayoutObjectSide object_side) {
4600   DCHECK_GE(offset_in_node, 0);
4601   LayoutObject* layout_object = node.GetLayoutObject();
4602   if (!node.IsTextNode() || !layout_object ||
4603       !To<LayoutText>(layout_object)->IsTextFragment())
4604     return layout_object;
4605   auto* layout_text_fragment = To<LayoutTextFragment>(layout_object);
4606   if (!layout_text_fragment->IsRemainingTextLayoutObject()) {
4607     DCHECK_LE(
4608         static_cast<unsigned>(offset_in_node),
4609         layout_text_fragment->Start() + layout_text_fragment->FragmentLength());
4610     return layout_text_fragment;
4611   }
4612   if (layout_text_fragment->FragmentLength()) {
4613     const unsigned threshold =
4614         object_side == LayoutObjectSide::kRemainingTextIfOnBoundary
4615             ? layout_text_fragment->Start()
4616             : layout_text_fragment->Start() + 1;
4617     if (static_cast<unsigned>(offset_in_node) >= threshold)
4618       return layout_object;
4619   }
4620   return layout_text_fragment->GetFirstLetterPart();
4621 }
4622 
CanBeSelectionLeaf() const4623 bool LayoutObject::CanBeSelectionLeaf() const {
4624   NOT_DESTROYED();
4625   if (SlowFirstChild() || StyleRef().Visibility() != EVisibility::kVisible ||
4626       DisplayLockUtilities::NearestLockedExclusiveAncestor(*this)) {
4627     return false;
4628   }
4629   return CanBeSelectionLeafInternal();
4630 }
4631 
InvalidateClipPathCache()4632 void LayoutObject::InvalidateClipPathCache() {
4633   NOT_DESTROYED();
4634   SetNeedsPaintPropertyUpdate();
4635   for (auto* fragment = &fragment_; fragment;
4636        fragment = fragment->NextFragment())
4637     fragment->InvalidateClipPathCache();
4638 }
4639 
OutlineRects(const PhysicalOffset & additional_offset,NGOutlineType outline_type) const4640 Vector<PhysicalRect> LayoutObject::OutlineRects(
4641     const PhysicalOffset& additional_offset,
4642     NGOutlineType outline_type) const {
4643   NOT_DESTROYED();
4644   Vector<PhysicalRect> outline_rects;
4645   AddOutlineRects(outline_rects, additional_offset, outline_type);
4646   return outline_rects;
4647 }
4648 
SetModifiedStyleOutsideStyleRecalc(scoped_refptr<const ComputedStyle> style,ApplyStyleChanges apply_changes)4649 void LayoutObject::SetModifiedStyleOutsideStyleRecalc(
4650     scoped_refptr<const ComputedStyle> style,
4651     ApplyStyleChanges apply_changes) {
4652   NOT_DESTROYED();
4653   SetStyle(style, apply_changes);
4654   if (IsAnonymous() || !GetNode() || !GetNode()->IsElementNode())
4655     return;
4656   GetNode()->SetComputedStyle(std::move(style));
4657 }
4658 
FlipForWritingModeInternal(LayoutUnit position,LayoutUnit width,const LayoutBox * box_for_flipping) const4659 LayoutUnit LayoutObject::FlipForWritingModeInternal(
4660     LayoutUnit position,
4661     LayoutUnit width,
4662     const LayoutBox* box_for_flipping) const {
4663   NOT_DESTROYED();
4664   DCHECK(!IsBox());
4665   DCHECK(HasFlippedBlocksWritingMode());
4666   DCHECK(!box_for_flipping || box_for_flipping == ContainingBlock());
4667   // For now, block flipping doesn't apply for non-box SVG objects.
4668   if (IsSVG())
4669     return position;
4670   return (box_for_flipping ? box_for_flipping : ContainingBlock())
4671       ->FlipForWritingMode(position, width);
4672 }
4673 
SelfPaintingLayerNeedsVisualOverflowRecalc() const4674 bool LayoutObject::SelfPaintingLayerNeedsVisualOverflowRecalc() const {
4675   NOT_DESTROYED();
4676   if (HasLayer()) {
4677     auto* box_model_object = To<LayoutBoxModelObject>(this);
4678     if (box_model_object->HasSelfPaintingLayer())
4679       return box_model_object->Layer()->NeedsVisualOverflowRecalc();
4680   }
4681   return false;
4682 }
4683 
MarkSelfPaintingLayerForVisualOverflowRecalc()4684 void LayoutObject::MarkSelfPaintingLayerForVisualOverflowRecalc() {
4685   NOT_DESTROYED();
4686   if (HasLayer()) {
4687     auto* box_model_object = To<LayoutBoxModelObject>(this);
4688     if (box_model_object->HasSelfPaintingLayer())
4689       box_model_object->Layer()->SetNeedsVisualOverflowRecalc();
4690   }
4691 }
4692 
IsMenuList(const LayoutObject * object)4693 bool IsMenuList(const LayoutObject* object) {
4694   if (!object)
4695     return false;
4696   auto* select = DynamicTo<HTMLSelectElement>(object->GetNode());
4697   return select && select->UsesMenuList();
4698 }
4699 
IsListBox(const LayoutObject * object)4700 bool IsListBox(const LayoutObject* object) {
4701   if (!object)
4702     return false;
4703   auto* select = DynamicTo<HTMLSelectElement>(object->GetNode());
4704   return select && !select->UsesMenuList();
4705 }
4706 
4707 }  // namespace blink
4708 
4709 #if DCHECK_IS_ON()
4710 
showTree(const blink::LayoutObject * object)4711 void showTree(const blink::LayoutObject* object) {
4712   if (object)
4713     object->ShowTreeForThis();
4714   else
4715     DLOG(INFO) << "Cannot showTree. Root is (nil)";
4716 }
4717 
showLineTree(const blink::LayoutObject * object)4718 void showLineTree(const blink::LayoutObject* object) {
4719   if (object)
4720     object->ShowLineTreeForThis();
4721   else
4722     DLOG(INFO) << "Cannot showLineTree. Root is (nil)";
4723 }
4724 
showLayoutTree(const blink::LayoutObject * object1)4725 void showLayoutTree(const blink::LayoutObject* object1) {
4726   showLayoutTree(object1, nullptr);
4727 }
4728 
showLayoutTree(const blink::LayoutObject * object1,const blink::LayoutObject * object2)4729 void showLayoutTree(const blink::LayoutObject* object1,
4730                     const blink::LayoutObject* object2) {
4731   if (object1) {
4732     const blink::LayoutObject* root = object1;
4733     while (root->Parent())
4734       root = root->Parent();
4735     if (object1) {
4736       StringBuilder string_builder;
4737       root->DumpLayoutTreeAndMark(string_builder, object1, "*", object2, "-",
4738                                   0);
4739       DLOG(INFO) << "\n" << string_builder.ToString().Utf8();
4740     }
4741   } else {
4742     DLOG(INFO) << "Cannot showLayoutTree. Root is (nil)";
4743   }
4744 }
4745 
4746 #endif  // DCHECK_IS_ON()
4747