1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_PHYSICAL_FRAGMENT_H_
6 #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_PHYSICAL_FRAGMENT_H_
7
8 #include "base/memory/scoped_refptr.h"
9 #include "third_party/blink/renderer/core/core_export.h"
10 #include "third_party/blink/renderer/core/editing/forward.h"
11 #include "third_party/blink/renderer/core/layout/geometry/physical_offset.h"
12 #include "third_party/blink/renderer/core/layout/geometry/physical_rect.h"
13 #include "third_party/blink/renderer/core/layout/geometry/physical_size.h"
14 #include "third_party/blink/renderer/core/layout/layout_box.h"
15 #include "third_party/blink/renderer/core/layout/ng/ng_style_variant.h"
16 #include "third_party/blink/renderer/platform/graphics/touch_action.h"
17 #include "third_party/blink/renderer/platform/wtf/ref_counted.h"
18
19 #include <unicode/ubidi.h>
20
21 namespace blink {
22
23 class ComputedStyle;
24 class FragmentData;
25 class Node;
26 class NGFragmentBuilder;
27 class NGInlineItem;
28 class NGPhysicalFragment;
29 class PaintLayer;
30 struct LogicalRect;
31
32 struct CORE_EXPORT NGPhysicalFragmentTraits {
33 static void Destruct(const NGPhysicalFragment*);
34 };
35
36 // The NGPhysicalFragment contains the output geometry from layout. The
37 // fragment stores all of its information in the physical coordinate system for
38 // use by paint, hit-testing etc.
39 //
40 // The fragment keeps a pointer back to the LayoutObject which generated it.
41 // Once we have transitioned fully to LayoutNG it should be a const pointer
42 // such that paint/hit-testing/etc don't modify it.
43 //
44 // Layout code should only access geometry information through the
45 // NGFragment wrapper classes which transforms information into the logical
46 // coordinate system.
47 class CORE_EXPORT NGPhysicalFragment
48 : public RefCounted<const NGPhysicalFragment, NGPhysicalFragmentTraits> {
49 public:
50 enum NGFragmentType {
51 kFragmentBox = 0,
52 kFragmentText = 1,
53 kFragmentLineBox = 2,
54 // When adding new values, make sure the bit size of |type_| is large
55 // enough to store.
56 };
57 enum NGBoxType {
58 kNormalBox,
59 kInlineBox,
60 // A multi-column container creates column boxes as its children, which
61 // content is flowed into. https://www.w3.org/TR/css-multicol-1/#column-box
62 kColumnBox,
63 kAtomicInline,
64 kFloating,
65 kOutOfFlowPositioned,
66 kBlockFlowRoot,
67 kRenderedLegend,
68 // When adding new values, make sure the bit size of |sub_type_| is large
69 // enough to store.
70
71 // Also, add after kMinimumFormattingContextRoot if the box type is a
72 // formatting context root, or before otherwise. See
73 // IsFormattingContextRoot().
74 kMinimumFormattingContextRoot = kAtomicInline
75 };
76
77 ~NGPhysicalFragment();
78
Type()79 NGFragmentType Type() const { return static_cast<NGFragmentType>(type_); }
IsContainer()80 bool IsContainer() const {
81 return Type() == NGFragmentType::kFragmentBox ||
82 Type() == NGFragmentType::kFragmentLineBox;
83 }
IsBox()84 bool IsBox() const { return Type() == NGFragmentType::kFragmentBox; }
IsText()85 bool IsText() const { return Type() == NGFragmentType::kFragmentText; }
IsLineBox()86 bool IsLineBox() const { return Type() == NGFragmentType::kFragmentLineBox; }
87
88 // Returns the box type of this fragment.
BoxType()89 NGBoxType BoxType() const {
90 DCHECK(IsBox());
91 return static_cast<NGBoxType>(sub_type_);
92 }
93 // True if this is an inline box; e.g., <span>. Atomic inlines such as
94 // replaced elements or inline block are not included.
IsInlineBox()95 bool IsInlineBox() const {
96 return IsBox() && BoxType() == NGBoxType::kInlineBox;
97 }
IsColumnBox()98 bool IsColumnBox() const {
99 return IsBox() && BoxType() == NGBoxType::kColumnBox;
100 }
IsFragmentainerBox()101 bool IsFragmentainerBox() const { return IsColumnBox(); }
IsColumnSpanAll()102 bool IsColumnSpanAll() const {
103 if (const auto* box = DynamicTo<LayoutBox>(GetLayoutObject()))
104 return box->IsColumnSpanAll();
105 return false;
106 }
107 // An atomic inline is represented as a kFragmentBox, such as inline block and
108 // replaced elements.
IsAtomicInline()109 bool IsAtomicInline() const {
110 return IsBox() && BoxType() == NGBoxType::kAtomicInline;
111 }
112 // True if this fragment is in-flow in an inline formatting context.
IsInline()113 bool IsInline() const {
114 return IsText() || IsInlineBox() || IsAtomicInline();
115 }
IsFloating()116 bool IsFloating() const {
117 return IsBox() && BoxType() == NGBoxType::kFloating;
118 }
IsOutOfFlowPositioned()119 bool IsOutOfFlowPositioned() const {
120 return IsBox() && BoxType() == NGBoxType::kOutOfFlowPositioned;
121 }
IsFloatingOrOutOfFlowPositioned()122 bool IsFloatingOrOutOfFlowPositioned() const {
123 return IsFloating() || IsOutOfFlowPositioned();
124 }
125 // Return true if this is the legend child of a fieldset that gets special
126 // treatment (i.e. placed over the block-start border).
IsRenderedLegend()127 bool IsRenderedLegend() const {
128 return IsBox() && BoxType() == NGBoxType::kRenderedLegend;
129 }
IsMathMLFraction()130 bool IsMathMLFraction() const { return IsBox() && is_math_fraction_; }
131
IsMathMLOperator()132 bool IsMathMLOperator() const { return IsBox() && is_math_operator_; }
133
134 // Return true if this fragment corresponds directly to an entry in the CSS
135 // box tree [1]. Note that anonymous blocks also exist in the CSS box
136 // tree. Returns false otherwise, i.e. if the fragment is generated by the
137 // layout engine to contain fragments from CSS boxes (a line or a generated
138 // fragmentainer [2], in other words). The main signification of this is
139 // whether we can use the LayoutObject associated with this fragment for all
140 // purposes.
141 //
142 // [1] https://www.w3.org/TR/css-display-3/#box-tree
143 // [2] https://www.w3.org/TR/css-break-3/#fragmentation-container
IsCSSBox()144 bool IsCSSBox() const { return !IsLineBox() && !IsFragmentainerBox(); }
145
146 bool IsBlockFlow() const;
IsAnonymousBlock()147 bool IsAnonymousBlock() const {
148 return IsCSSBox() && layout_object_->IsAnonymousBlock();
149 }
IsListMarker()150 bool IsListMarker() const {
151 return IsCSSBox() && layout_object_->IsLayoutNGOutsideListMarker();
152 }
IsRubyRun()153 bool IsRubyRun() const { return layout_object_->IsRubyRun(); }
154
155 // Return true if this fragment is for LayoutNGRubyRun, LayoutNGRubyText, or
156 // LayoutNGRubyBase. They are handled specially in scrollable overflow
157 // computation.
IsRubyBox()158 bool IsRubyBox() const {
159 return layout_object_->IsRubyRun() || layout_object_->IsRubyText() ||
160 layout_object_->IsRubyBase();
161 }
162
IsTableNGPart()163 bool IsTableNGPart() const { return is_table_ng_part_; }
164
IsTable()165 bool IsTable() const { return IsBox() && layout_object_->IsTable(); }
166
IsTableNGRow()167 bool IsTableNGRow() const {
168 return IsTableNGPart() && layout_object_->IsTableRow();
169 }
170
IsTableNGSection()171 bool IsTableNGSection() const {
172 return IsTableNGPart() && layout_object_->IsTableSection();
173 }
174
IsTableNGCell()175 bool IsTableNGCell() const {
176 return IsTableNGPart() && layout_object_->IsTableCell() &&
177 !layout_object_->IsTableCellLegacy();
178 }
179
180 bool IsTextControlPlaceholder() const;
181
182 // Return true if this fragment is a container established by a fieldset
183 // element. Such a fragment contains an optional rendered legend fragment and
184 // an optional fieldset contents wrapper fragment (which holds everything
185 // inside the fieldset except the rendered legend).
IsFieldsetContainer()186 bool IsFieldsetContainer() const { return is_fieldset_container_; }
187
188 // Returns whether the fragment is legacy layout root.
IsLegacyLayoutRoot()189 bool IsLegacyLayoutRoot() const { return is_legacy_layout_root_; }
190
191 // Returns whether the fragment should be atomically painted.
IsPaintedAtomically()192 bool IsPaintedAtomically() const { return is_painted_atomically_; }
193
194 // Returns whether the fragment is a table part with collapsed borders.
HasCollapsedBorders()195 bool HasCollapsedBorders() const { return has_collapsed_borders_; }
196
IsFormattingContextRoot()197 bool IsFormattingContextRoot() const {
198 return (IsBox() && BoxType() >= NGBoxType::kMinimumFormattingContextRoot) ||
199 IsLegacyLayoutRoot();
200 }
201
202 // |Offset()| is reliable only when this fragment was placed by LayoutNG
203 // parent. When the parent is not LayoutNG, the parent may move the
204 // |LayoutObject| after this fragment was placed. See comments in
205 // |LayoutNGBlockFlow::UpdateBlockLayout()| and crbug.com/788590
206 bool IsPlacedByLayoutNG() const;
207
208 // The accessors in this class shouldn't be used by layout code directly,
209 // instead should be accessed by the NGFragmentBase classes. These accessors
210 // exist for paint, hit-testing, etc.
211
212 // Returns the border-box size.
Size()213 PhysicalSize Size() const { return size_; }
214
215 // Returns the rect in the local coordinate of this fragment; i.e., offset is
216 // (0, 0).
LocalRect()217 PhysicalRect LocalRect() const { return {{}, size_}; }
218
StyleVariant()219 NGStyleVariant StyleVariant() const {
220 return static_cast<NGStyleVariant>(style_variant_);
221 }
UsesFirstLineStyle()222 bool UsesFirstLineStyle() const {
223 return StyleVariant() == NGStyleVariant::kFirstLine;
224 }
225
226 // Returns the style for this fragment.
227 //
228 // For a line box, this returns the style of the containing block. This mostly
229 // represents the style for the line box, except 1) |style.Direction()| maybe
230 // incorrect, use |BaseDirection()| instead, and 2) margin/border/padding,
231 // background etc. do not apply to the line box.
Style()232 const ComputedStyle& Style() const {
233 return layout_object_->EffectiveStyle(StyleVariant());
234 }
235
GetDocument()236 const Document& GetDocument() const {
237 DCHECK(layout_object_);
238 return layout_object_->GetDocument();
239 }
GetNode()240 Node* GetNode() const {
241 return IsCSSBox() ? layout_object_->GetNode() : nullptr;
242 }
GeneratingNode()243 Node* GeneratingNode() const {
244 return IsCSSBox() ? layout_object_->GeneratingNode() : nullptr;
245 }
246 // The node to return when hit-testing on this fragment. This can be different
247 // from GetNode() when this fragment is content of a pseudo node.
NodeForHitTest()248 Node* NodeForHitTest() const { return layout_object_->NodeForHitTest(); }
249
NonPseudoNode()250 Node* NonPseudoNode() const {
251 return IsCSSBox() ? layout_object_->NonPseudoNode() : nullptr;
252 }
253
IsInSelfHitTestingPhase(HitTestAction action)254 bool IsInSelfHitTestingPhase(HitTestAction action) const {
255 if (const auto* box = DynamicTo<LayoutBox>(GetLayoutObject()))
256 return box->IsInSelfHitTestingPhase(action);
257 if (IsInlineBox())
258 return action == kHitTestForeground;
259 // Assuming this is some sort of container, e.g. a fragmentainer (they don't
260 // have a LayoutObject associated).
261 return action == kHitTestBlockBackground ||
262 action == kHitTestChildBlockBackground;
263 }
264
265 // Whether there is a PaintLayer associated with the fragment.
HasLayer()266 bool HasLayer() const { return IsCSSBox() && layout_object_->HasLayer(); }
267
268 // The PaintLayer associated with the fragment.
Layer()269 PaintLayer* Layer() const {
270 if (!HasLayer())
271 return nullptr;
272 return To<LayoutBoxModelObject>(layout_object_)->Layer();
273 }
274
275 // Whether this object has a self-painting |Layer()|.
HasSelfPaintingLayer()276 bool HasSelfPaintingLayer() const {
277 return HasLayer() &&
278 To<LayoutBoxModelObject>(layout_object_)->HasSelfPaintingLayer();
279 }
280
281 // True if overflow != 'visible', except for certain boxes that do not allow
282 // overflow clip; i.e., AllowOverflowClip() returns false.
HasNonVisibleOverflow()283 bool HasNonVisibleOverflow() const {
284 return IsCSSBox() && layout_object_->HasNonVisibleOverflow();
285 }
286
287 // True if this is considered a scroll-container. See
288 // ComputedStyle::IsScrollContainer() for details.
IsScrollContainer()289 bool IsScrollContainer() const {
290 return IsCSSBox() && layout_object_->IsScrollContainer();
291 }
292
293 // Return true if the given object is the effective root scroller in its
294 // Document. See |effective root scroller| in page/scrolling/README.md.
295 // Note: a root scroller always establishes a PaintLayer.
296 // This bit is updated in
297 // RootScrollerController::RecomputeEffectiveRootScroller in the LayoutClean
298 // document lifecycle phase.
IsEffectiveRootScroller()299 bool IsEffectiveRootScroller() const {
300 return IsCSSBox() && layout_object_->IsEffectiveRootScroller();
301 }
302
ShouldApplyLayoutContainment()303 bool ShouldApplyLayoutContainment() const {
304 return IsCSSBox() && layout_object_->ShouldApplyLayoutContainment();
305 }
306
ShouldClipOverflowAlongEitherAxis()307 bool ShouldClipOverflowAlongEitherAxis() const {
308 return IsCSSBox() && layout_object_->ShouldClipOverflowAlongEitherAxis();
309 }
310
ShouldClipOverflowAlongBothAxis()311 bool ShouldClipOverflowAlongBothAxis() const {
312 return IsCSSBox() && layout_object_->ShouldClipOverflowAlongBothAxis();
313 }
314
IsFragmentationContextRoot()315 bool IsFragmentationContextRoot() const {
316 // We have no bit that tells us whether this is a fragmentation context
317 // root, so some additional checking is necessary here, to make sure that
318 // we're actually establishing one. We check that we're not a custom layout
319 // box, as specifying columns on such a box has no effect. Note that
320 // specifying columns together with a display value of e.g. 'flex', 'grid'
321 // or 'table' also has no effect, but we don't need to check for that here,
322 // since such display types don't create a block flow (block container).
323 return IsCSSBox() && Style().SpecifiesColumns() && IsBlockFlow() &&
324 !layout_object_->IsLayoutNGCustom();
325 }
326
327 // Return whether we can traverse this fragment and its children directly, for
328 // painting, hit-testing and other layout read operations. If false is
329 // returned, we need to traverse the layout object tree instead.
CanTraverse()330 bool CanTraverse() const {
331 return layout_object_->CanTraversePhysicalFragments();
332 }
333
334 // This fragment is hidden for paint purpose, but exists for querying layout
335 // information. Used for `text-overflow: ellipsis`.
IsHiddenForPaint()336 bool IsHiddenForPaint() const { return is_hidden_for_paint_; }
337
338 // Return true if this fragment is monolithic, as far as block fragmentation
339 // is concerned.
IsMonolithic()340 bool IsMonolithic() const {
341 const LayoutObject* layout_object = GetLayoutObject();
342 if (!layout_object || !IsBox() || !layout_object->IsBox())
343 return false;
344 return To<LayoutBox>(layout_object)->GetNGPaginationBreakability() ==
345 LayoutBox::kForbidBreaks;
346 }
347
348 // GetLayoutObject should only be used when necessary for compatibility
349 // with LegacyLayout.
350 //
351 // For a line box, |layout_object_| has its containing block but this function
352 // returns |nullptr| for the historical reasons. TODO(kojii): We may change
353 // this in future. Use |IsLineBox()| instead of testing this is |nullptr|.
GetLayoutObject()354 const LayoutObject* GetLayoutObject() const {
355 return IsCSSBox() ? layout_object_ : nullptr;
356 }
357 // TODO(kojii): We should not have mutable version at all, the use of this
358 // function should be eliminiated over time.
GetMutableLayoutObject()359 LayoutObject* GetMutableLayoutObject() const {
360 return IsCSSBox() ? layout_object_ : nullptr;
361 }
362 // Similar to |GetLayoutObject|, but returns the |LayoutObject| of its
363 // container for |!IsCSSBox()| fragments instead of |nullptr|.
GetSelfOrContainerLayoutObject()364 const LayoutObject* GetSelfOrContainerLayoutObject() const {
365 return layout_object_;
366 }
367
368 const FragmentData* GetFragmentData() const;
369
370 // |NGPhysicalFragment| may live longer than the corresponding |LayoutObject|.
371 // Though |NGPhysicalFragment| is immutable, |layout_object_| is cleared to
372 // |nullptr| when it was destroyed to avoid reading destroyed objects.
IsLayoutObjectDestroyedOrMoved()373 bool IsLayoutObjectDestroyedOrMoved() const { return !layout_object_; }
LayoutObjectWillBeDestroyed()374 void LayoutObjectWillBeDestroyed() const {
375 const_cast<NGPhysicalFragment*>(this)->layout_object_ = nullptr;
376 }
377
378 // Returns the latest generation of the post-layout fragment. Returns
379 // |nullptr| if |this| is the one.
380 //
381 // When subtree relayout occurs at the relayout boundary, its containing block
382 // may keep the reference to old generations of this fragment. Callers can
383 // check if there were newer generations.
384 const NGPhysicalFragment* PostLayout() const;
385
386 // Specifies the type of scrollable overflow computation.
387 enum TextHeightType {
388 // Apply text fragment size as is.
389 kNormalHeight,
390 // Adjust text fragment size for 'em' height, and skip to unite
391 // container's bounding box. This type is useful for ruby annotation.
392 kEmHeight
393 };
394 // Scrollable overflow. including contents, in the local coordinate.
395 PhysicalRect ScrollableOverflow(const NGPhysicalBoxFragment& container,
396 TextHeightType height_type) const;
397
398 // ScrollableOverflow(), with transforms applied wrt container if needed.
399 // This does not include any offsets from the parent (including relpos).
400 PhysicalRect ScrollableOverflowForPropagation(
401 const NGPhysicalBoxFragment& container,
402 TextHeightType height_type) const;
403 void AdjustScrollableOverflowForPropagation(
404 const NGPhysicalBoxFragment& container,
405 TextHeightType height_type,
406 PhysicalRect* overflow) const;
407
408 // The allowed touch action is the union of the effective touch action
409 // (from style) and blocking touch event handlers.
410 TouchAction EffectiveAllowedTouchAction() const;
411
412 // Returns if this fragment is inside a non-passive wheel event handler.
413 bool InsideBlockingWheelEventHandler() const;
414
415 // Returns the bidi level of a text or atomic inline fragment.
416 UBiDiLevel BidiLevel() const;
417
418 // Returns the resolved direction of a text or atomic inline fragment. Not to
419 // be confused with the CSS 'direction' property.
420 TextDirection ResolvedDirection() const;
421
422 // Helper functions to convert between |PhysicalRect| and |LogicalRect| of a
423 // child.
424 LogicalRect ConvertChildToLogical(const PhysicalRect& physical_rect) const;
425 PhysicalRect ConvertChildToPhysical(const LogicalRect& logical_rect) const;
426
427 // Utility functions for caret painting. Note that carets are painted as part
428 // of the containing block's foreground.
429 bool ShouldPaintCursorCaret() const;
430 bool ShouldPaintDragCaret() const;
ShouldPaintCarets()431 bool ShouldPaintCarets() const {
432 return ShouldPaintCursorCaret() || ShouldPaintDragCaret();
433 }
434
435 String ToString() const;
436
437 void CheckType() const;
438 void CheckCanUpdateInkOverflow() const;
439
440 enum DumpFlag {
441 DumpHeaderText = 0x1,
442 DumpSubtree = 0x2,
443 DumpIndentation = 0x4,
444 DumpType = 0x8,
445 DumpOffset = 0x10,
446 DumpSize = 0x20,
447 DumpTextOffsets = 0x40,
448 DumpSelfPainting = 0x80,
449 DumpNodeName = 0x100,
450 DumpItems = 0x200,
451 DumpAll = -1
452 };
453 typedef int DumpFlags;
454
455 String DumpFragmentTree(DumpFlags,
456 base::Optional<PhysicalOffset> = base::nullopt,
457 unsigned indent = 2) const;
458
459 #if DCHECK_IS_ON()
460 void ShowFragmentTree() const;
461 #endif
462
463 protected:
464 NGPhysicalFragment(NGFragmentBuilder*,
465 NGFragmentType type,
466 unsigned sub_type);
467
468 NGPhysicalFragment(LayoutObject* layout_object,
469 NGStyleVariant,
470 PhysicalSize size,
471 NGFragmentType type,
472 unsigned sub_type);
473
474 NGPhysicalFragment(const NGPhysicalFragment& other);
475
476 const ComputedStyle& SlowEffectiveStyle() const;
477
478 const Vector<NGInlineItem>& InlineItemsOfContainingBlock() const;
479
480 // The following bitfields are only to be used by NGPhysicalContainerFragment
481 // (it's defined here to save memory, since that class has no bitfields).
482 unsigned has_floating_descendants_for_paint_ : 1;
483 unsigned has_adjoining_object_descendants_ : 1;
484 unsigned depends_on_percentage_block_size_ : 1;
485
486 // The following bitfields are only to be used by NGPhysicalLineBoxFragment
487 // (it's defined here to save memory, since that class has no bitfields).
488 unsigned has_propagated_descendants_ : 1;
489 unsigned has_hanging_ : 1;
490
491 // The following bitfields are only to be used by NGPhysicalBoxFragment
492 // (it's defined here to save memory, since that class has no bitfields).
493 unsigned is_inline_formatting_context_ : 1;
494 unsigned has_fragment_items_ : 1;
495 unsigned include_border_top_ : 1;
496 unsigned include_border_right_ : 1;
497 unsigned include_border_bottom_ : 1;
498 unsigned include_border_left_ : 1;
499 unsigned has_layout_overflow_ : 1;
500 unsigned has_borders_ : 1;
501 unsigned has_padding_ : 1;
502 unsigned has_inflow_bounds_ : 1;
503 unsigned has_rare_data_ : 1;
504 unsigned is_first_for_node_ : 1;
505
506 LayoutObject* layout_object_;
507 const PhysicalSize size_;
508
509 const unsigned type_ : 2; // NGFragmentType
510 const unsigned sub_type_ : 3; // NGBoxType, NGTextType, or NGLineBoxType
511 const unsigned style_variant_ : 2; // NGStyleVariant
512 const unsigned is_hidden_for_paint_ : 1;
513 unsigned is_math_fraction_ : 1;
514 unsigned is_math_operator_ : 1;
515 // base (line box) or resolve (text) direction
516 unsigned base_or_resolved_direction_ : 1; // TextDirection
517 unsigned may_have_descendant_above_block_start_ : 1;
518
519 // The following are only used by NGPhysicalBoxFragment but are initialized
520 // for all types to allow methods using them to be inlined.
521 unsigned is_fieldset_container_ : 1;
522 unsigned is_table_ng_part_ : 1;
523 unsigned is_legacy_layout_root_ : 1;
524 unsigned is_painted_atomically_ : 1;
525 unsigned has_collapsed_borders_ : 1;
526 unsigned has_baseline_ : 1;
527 unsigned has_last_baseline_ : 1;
528
529 // The following bitfields are only to be used by NGPhysicalTextFragment
530 // (it's defined here to save memory, since that class has no bitfields).
531 mutable unsigned ink_overflow_computed_ : 1;
532
533 // Note: We've used 32-bit bit field. If you need more bits, please think to
534 // share bit fields, or put them before layout_object_ to fill the gap after
535 // RefCounted on 64-bit systems.
536
537 private:
538 friend struct NGPhysicalFragmentTraits;
539 void Destroy() const;
540 };
541
542 // Used for return value of traversing fragment tree.
543 struct CORE_EXPORT NGPhysicalFragmentWithOffset {
544 DISALLOW_NEW();
545
546 scoped_refptr<const NGPhysicalFragment> fragment;
547 PhysicalOffset offset_to_container_box;
548
549 PhysicalRect RectInContainerBox() const;
550 };
551
552 CORE_EXPORT std::ostream& operator<<(std::ostream&, const NGPhysicalFragment*);
553 CORE_EXPORT std::ostream& operator<<(std::ostream&, const NGPhysicalFragment&);
554
555 #if !DCHECK_IS_ON()
CheckType()556 inline void NGPhysicalFragment::CheckType() const {}
CheckCanUpdateInkOverflow()557 inline void NGPhysicalFragment::CheckCanUpdateInkOverflow() const {}
558 #endif
559
560 } // namespace blink
561
562 #endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_PHYSICAL_FRAGMENT_H_
563