// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"

#include "third_party/blink/renderer/core/dom/document_lifecycle.h"
#include "third_party/blink/renderer/core/html/shadow/shadow_element_utils.h"
#include "third_party/blink/renderer/core/layout/geometry/writing_mode_converter.h"
#include "third_party/blink/renderer/core/layout/layout_block.h"
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_ruby_utils.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
#include "third_party/blink/renderer/core/layout/ng/ng_fragment_builder.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h"
#include "third_party/blink/renderer/platform/wtf/size_assertions.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"

namespace blink {
namespace {

struct SameSizeAsNGPhysicalFragment
    : RefCounted<const NGPhysicalFragment, NGPhysicalFragmentTraits> {
  // |flags_for_free_maybe| is used to support an additional increase in size
  // needed for DCHECK and 32-bit builds.
  unsigned flags_for_free_maybe;
  void* layout_object;
  PhysicalSize size;
  unsigned flags;
};

ASSERT_SIZE(NGPhysicalFragment, SameSizeAsNGPhysicalFragment);

String StringForBoxType(const NGPhysicalFragment& fragment) {
  StringBuilder result;
  switch (fragment.BoxType()) {
    case NGPhysicalFragment::NGBoxType::kNormalBox:
      break;
    case NGPhysicalFragment::NGBoxType::kInlineBox:
      result.Append("inline");
      break;
    case NGPhysicalFragment::NGBoxType::kColumnBox:
      result.Append("column");
      break;
    case NGPhysicalFragment::NGBoxType::kAtomicInline:
      result.Append("atomic-inline");
      break;
    case NGPhysicalFragment::NGBoxType::kFloating:
      result.Append("floating");
      break;
    case NGPhysicalFragment::NGBoxType::kOutOfFlowPositioned:
      result.Append("out-of-flow-positioned");
      break;
    case NGPhysicalFragment::NGBoxType::kBlockFlowRoot:
      result.Append("block-flow-root");
      break;
    case NGPhysicalFragment::NGBoxType::kRenderedLegend:
      result.Append("rendered-legend");
      break;
  }
  if (fragment.IsLegacyLayoutRoot()) {
    if (result.length())
      result.Append(" ");
    result.Append("legacy-layout-root");
  }
  if (fragment.IsBlockFlow()) {
    if (result.length())
      result.Append(" ");
    result.Append("block-flow");
  }
  if (fragment.IsFieldsetContainer()) {
    if (result.length())
      result.Append(" ");
    result.Append("fieldset-container");
  }
  if (fragment.IsBox() &&
      To<NGPhysicalBoxFragment>(fragment).IsInlineFormattingContext()) {
    if (result.length())
      result.Append(" ");
    result.Append("children-inline");
  }

  return result.ToString();
}

class FragmentTreeDumper {
  STACK_ALLOCATED();

 public:
  FragmentTreeDumper(StringBuilder* builder,
                     NGPhysicalFragment::DumpFlags flags)
      : builder_(builder), flags_(flags) {}

  void Append(const NGPhysicalFragment* fragment,
              base::Optional<PhysicalOffset> fragment_offset,
              unsigned indent = 2) {
    AppendIndentation(indent);

    bool has_content = false;
    if (const auto* box = DynamicTo<NGPhysicalBoxFragment>(fragment)) {
      const LayoutObject* layout_object = box->GetLayoutObject();
      if (flags_ & NGPhysicalFragment::DumpType) {
        builder_->Append("Box");
        String box_type = StringForBoxType(*fragment);
        has_content = true;
        if (!box_type.IsEmpty()) {
          builder_->Append(" (");
          builder_->Append(box_type);
          builder_->Append(")");
        }
        if (flags_ & NGPhysicalFragment::DumpSelfPainting &&
            box->HasSelfPaintingLayer()) {
          if (box_type.IsEmpty())
            builder_->Append(" ");
          builder_->Append("(self paint)");
        }
      }
      has_content = AppendOffsetAndSize(fragment, fragment_offset, has_content);

      if (flags_ & NGPhysicalFragment::DumpNodeName && layout_object) {
        if (has_content)
          builder_->Append(" ");
        builder_->Append(layout_object->DebugName());
      }
      builder_->Append("\n");

      bool has_fragment_items = false;
      if (flags_ & NGPhysicalFragment::DumpItems) {
        if (const NGFragmentItems* fragment_items = box->Items()) {
          NGInlineCursor cursor(*box, *fragment_items);
          Append(&cursor, indent + 2);
          has_fragment_items = true;
        }
      }
      if (flags_ & NGPhysicalFragment::DumpSubtree) {
        if (flags_ & NGPhysicalFragment::DumpLegacyDescendants &&
            layout_object && !layout_object->IsLayoutNGObject()) {
          DCHECK(box->Children().empty());
          AppendLegacySubtree(*layout_object, indent);
          return;
        }
        for (auto& child : box->Children()) {
          if (has_fragment_items && child->IsLineBox())
            continue;
          Append(child.get(), child.Offset(), indent + 2);
        }
      }
      return;
    }

    if (const auto* line_box = DynamicTo<NGPhysicalLineBoxFragment>(fragment)) {
      if (flags_ & NGPhysicalFragment::DumpType) {
        builder_->Append("LineBox");
        has_content = true;
      }
      has_content = AppendOffsetAndSize(fragment, fragment_offset, has_content);
      builder_->Append("\n");

      if (flags_ & NGPhysicalFragment::DumpSubtree) {
        for (auto& child : line_box->Children()) {
          Append(child.get(), child.Offset(), indent + 2);
        }
        return;
      }
    }

    if (flags_ & NGPhysicalFragment::DumpType) {
      builder_->Append("Unknown fragment type");
      has_content = true;
    }
    has_content = AppendOffsetAndSize(fragment, fragment_offset, has_content);
    builder_->Append("\n");
  }

  void AppendLegacySubtree(const LayoutObject& layout_object,
                           unsigned indent = 0) {
    for (const LayoutObject* descendant = &layout_object; descendant;) {
      if (!descendant->IsLayoutNGObject()) {
        if (const auto* block = DynamicTo<LayoutBlock>(descendant)) {
          if (const auto* positioned_descendants = block->PositionedObjects()) {
            for (const auto* positioned_object : *positioned_descendants) {
              if (positioned_object->IsLayoutNGObject())
                AppendNGRootInLegacySubtree(*positioned_object, indent);
              else
                AppendLegacySubtree(*positioned_object, indent);
            }
          }
        }
        if (descendant->IsOutOfFlowPositioned() && descendant != &layout_object)
          descendant = descendant->NextInPreOrderAfterChildren(&layout_object);
        else
          descendant = descendant->NextInPreOrder(&layout_object);
        continue;
      }
      AppendNGRootInLegacySubtree(*descendant, indent);
      descendant = descendant->NextInPreOrderAfterChildren(&layout_object);
    }
  }

  void AppendNGRootInLegacySubtree(const LayoutObject& layout_object,
                                   unsigned indent) {
    if (flags_ & NGPhysicalFragment::DumpHeaderText) {
      AppendIndentation(indent + 2);
      builder_->Append("(NG fragment root inside legacy subtree:)\n");
    }
    const LayoutBox& box_descendant = To<LayoutBox>(layout_object);
    DCHECK_EQ(box_descendant.PhysicalFragmentCount(), 1u);
    Append(box_descendant.GetPhysicalFragment(0), base::nullopt, indent + 4);
  }

 private:
  void Append(NGInlineCursor* cursor, unsigned indent) {
    for (; *cursor; cursor->MoveToNextSkippingChildren()) {
      const NGInlineCursorPosition& current = cursor->Current();
      if (const NGPhysicalBoxFragment* box = current.BoxFragment()) {
        if (!box->IsInlineBox()) {
          Append(box, current.OffsetInContainerFragment(), indent);
          continue;
        }
      }

      AppendIndentation(indent);

      // TODO(kojii): Use the same format as layout tree dump for now. We can
      // make this more similar to |AppendFragmentToString| above.
      builder_->Append(current->ToString());

      if (flags_ & NGPhysicalFragment::DumpOffset) {
        builder_->Append(" offset:");
        builder_->Append(current.OffsetInContainerFragment().ToString());
      }
      if (flags_ & NGPhysicalFragment::DumpSize) {
        builder_->Append(" size:");
        builder_->Append(current.Size().ToString());
      }

      builder_->Append("\n");

      if (flags_ & NGPhysicalFragment::DumpSubtree && current.HasChildren()) {
        NGInlineCursor descendants = cursor->CursorForDescendants();
        Append(&descendants, indent + 2);
      }
    }
  }

  bool AppendOffsetAndSize(const NGPhysicalFragment* fragment,
                           base::Optional<PhysicalOffset> fragment_offset,
                           bool has_content) {
    if (flags_ & NGPhysicalFragment::DumpOffset) {
      if (has_content)
        builder_->Append(" ");
      builder_->Append("offset:");
      if (fragment_offset)
        builder_->Append(fragment_offset->ToString());
      else
        builder_->Append("unplaced");
      has_content = true;
    }
    if (flags_ & NGPhysicalFragment::DumpSize) {
      if (has_content)
        builder_->Append(" ");
      builder_->Append("size:");
      builder_->Append(fragment->Size().ToString());
      has_content = true;
    }
    return has_content;
  }

  void AppendIndentation(unsigned indent) {
    if (flags_ & NGPhysicalFragment::DumpIndentation) {
      for (unsigned i = 0; i < indent; i++)
        builder_->Append(" ");
    }
  }

  StringBuilder* builder_;
  NGPhysicalFragment::DumpFlags flags_;
};

}  // namespace

// static
void NGPhysicalFragmentTraits::Destruct(const NGPhysicalFragment* fragment) {
  fragment->Destroy();
}

NGPhysicalFragment::NGPhysicalFragment(NGFragmentBuilder* builder,
                                       NGFragmentType type,
                                       unsigned sub_type)
    : has_floating_descendants_for_paint_(false),
      layout_object_(builder->layout_object_),
      size_(ToPhysicalSize(builder->size_, builder->GetWritingMode())),
      type_(type),
      sub_type_(sub_type),
      style_variant_((unsigned)builder->style_variant_),
      is_hidden_for_paint_(builder->is_hidden_for_paint_),
      is_fieldset_container_(false),
      is_table_ng_part_(false),
      is_legacy_layout_root_(false),
      is_painted_atomically_(false),
      has_collapsed_borders_(builder->has_collapsed_borders_),
      has_baseline_(false) {
  CHECK(builder->layout_object_);
}

NGPhysicalFragment::NGPhysicalFragment(LayoutObject* layout_object,
                                       NGStyleVariant style_variant,
                                       PhysicalSize size,
                                       NGFragmentType type,
                                       unsigned sub_type)
    : has_floating_descendants_for_paint_(false),
      has_layout_overflow_(false),
      has_inflow_bounds_(false),
      has_rare_data_(false),
      layout_object_(layout_object),
      size_(size),
      type_(type),
      sub_type_(sub_type),
      style_variant_((unsigned)style_variant),
      is_hidden_for_paint_(false),
      is_fieldset_container_(false),
      is_table_ng_part_(false),
      is_legacy_layout_root_(false),
      is_painted_atomically_(false),
      has_collapsed_borders_(false),
      has_baseline_(false),
      has_last_baseline_(false) {
  CHECK(layout_object);
}

// Even though the other constructors don't initialize many of these fields
// (instead set by their super-classes), the copy constructor does.
NGPhysicalFragment::NGPhysicalFragment(const NGPhysicalFragment& other)
    : has_floating_descendants_for_paint_(
          other.has_floating_descendants_for_paint_),
      has_adjoining_object_descendants_(
          other.has_adjoining_object_descendants_),
      depends_on_percentage_block_size_(
          other.depends_on_percentage_block_size_),
      has_propagated_descendants_(other.has_propagated_descendants_),
      has_hanging_(other.has_hanging_),
      is_inline_formatting_context_(other.is_inline_formatting_context_),
      has_fragment_items_(other.has_fragment_items_),
      include_border_top_(other.include_border_top_),
      include_border_right_(other.include_border_right_),
      include_border_bottom_(other.include_border_bottom_),
      include_border_left_(other.include_border_left_),
      has_layout_overflow_(other.has_layout_overflow_),
      has_borders_(other.has_borders_),
      has_padding_(other.has_padding_),
      has_inflow_bounds_(other.has_inflow_bounds_),
      has_rare_data_(other.has_rare_data_),
      is_first_for_node_(other.is_first_for_node_),
      layout_object_(other.layout_object_),
      size_(other.size_),
      type_(other.type_),
      sub_type_(other.sub_type_),
      style_variant_(other.style_variant_),
      is_hidden_for_paint_(other.is_hidden_for_paint_),
      is_math_fraction_(other.is_math_fraction_),
      is_math_operator_(other.is_math_operator_),
      base_or_resolved_direction_(other.base_or_resolved_direction_),
      may_have_descendant_above_block_start_(
          other.may_have_descendant_above_block_start_),
      is_fieldset_container_(other.is_fieldset_container_),
      is_table_ng_part_(other.is_table_ng_part_),
      is_legacy_layout_root_(other.is_legacy_layout_root_),
      is_painted_atomically_(other.is_painted_atomically_),
      has_collapsed_borders_(other.has_collapsed_borders_),
      has_baseline_(other.has_baseline_),
      has_last_baseline_(other.has_last_baseline_) {
  CHECK(layout_object_);
}

// Keep the implementation of the destructor here, to avoid dependencies on
// ComputedStyle in the header file.
NGPhysicalFragment::~NGPhysicalFragment() = default;

void NGPhysicalFragment::Destroy() const {
  switch (Type()) {
    case kFragmentBox:
      delete static_cast<const NGPhysicalBoxFragment*>(this);
      break;
    case kFragmentLineBox:
      delete static_cast<const NGPhysicalLineBoxFragment*>(this);
      break;
  }
}

bool NGPhysicalFragment::IsBlockFlow() const {
  return !IsLineBox() && layout_object_->IsLayoutBlockFlow();
}

bool NGPhysicalFragment::IsTextControlContainer() const {
  return blink::IsTextControlContainer(layout_object_->GetNode());
}

bool NGPhysicalFragment::IsTextControlPlaceholder() const {
  return blink::IsTextControlPlaceholder(layout_object_->GetNode());
}

bool NGPhysicalFragment::IsPlacedByLayoutNG() const {
  // TODO(kojii): Move this to a flag for |LayoutNGBlockFlow::UpdateBlockLayout|
  // to set.
  if (IsLineBox())
    return false;
  if (IsFragmentainerBox())
    return true;
  const LayoutBlock* container = layout_object_->ContainingBlock();
  if (!container)
    return false;
  return container->IsLayoutNGMixin();
}

const FragmentData* NGPhysicalFragment::GetFragmentData() const {
  DCHECK(CanTraverse());
  const LayoutBox* box = DynamicTo<LayoutBox>(GetLayoutObject());
  if (!box) {
    DCHECK(!GetLayoutObject());
    return nullptr;
  }
  return box->FragmentDataFromPhysicalFragment(
      To<NGPhysicalBoxFragment>(*this));
}

const NGPhysicalFragment* NGPhysicalFragment::PostLayout() const {
  if (const auto* box = DynamicTo<NGPhysicalBoxFragment>(this))
    return box->PostLayout();
  return this;
}

#if DCHECK_IS_ON()
void NGPhysicalFragment::CheckType() const {
  switch (Type()) {
    case kFragmentBox:
      if (IsInlineBox()) {
        DCHECK(layout_object_->IsLayoutInline());
      } else {
        DCHECK(layout_object_->IsBox());
      }
      if (IsColumnBox()) {
        // Column fragments are associated with the same layout object as their
        // multicol container. The fragments themselves are regular in-flow
        // block container fragments for most purposes.
        DCHECK(layout_object_->IsLayoutBlockFlow());
        DCHECK(IsBox());
        DCHECK(!IsFloating());
        DCHECK(!IsOutOfFlowPositioned());
        DCHECK(!IsAtomicInline());
        DCHECK(!IsFormattingContextRoot());
        break;
      }
      if (layout_object_->IsLayoutNGOutsideListMarker()) {
        // List marker is an atomic inline if it appears in a line box, or a
        // block box.
        DCHECK(!IsFloating());
        DCHECK(!IsOutOfFlowPositioned());
        DCHECK(IsAtomicInline() || (IsBox() && BoxType() == kBlockFlowRoot));
        break;
      }
      DCHECK_EQ(IsFloating(), layout_object_->IsFloating());
      DCHECK_EQ(IsOutOfFlowPositioned(),
                layout_object_->IsOutOfFlowPositioned());
      DCHECK_EQ(IsAtomicInline(), layout_object_->IsInline() &&
                                      layout_object_->IsAtomicInlineLevel());
      break;
    case kFragmentLineBox:
      DCHECK(layout_object_->IsLayoutBlockFlow());
      DCHECK(!IsFloating());
      DCHECK(!IsOutOfFlowPositioned());
      DCHECK(!IsInlineBox());
      DCHECK(!IsAtomicInline());
      break;
  }
}

void NGPhysicalFragment::CheckCanUpdateInkOverflow() const {
  if (!GetLayoutObject())
    return;
  const DocumentLifecycle& lifecycle = GetDocument().Lifecycle();
  DCHECK(lifecycle.GetState() >= DocumentLifecycle::kLayoutClean &&
         lifecycle.GetState() < DocumentLifecycle::kCompositingAssignmentsClean)
      << lifecycle.GetState();
}
#endif

PhysicalRect NGPhysicalFragment::ScrollableOverflow(
    const NGPhysicalBoxFragment& container,
    TextHeightType height_type) const {
  switch (Type()) {
    case kFragmentBox:
      return To<NGPhysicalBoxFragment>(*this).ScrollableOverflow(height_type);
    case kFragmentLineBox:
      NOTREACHED()
          << "You must call NGLineBoxFragment::ScrollableOverflow explicitly.";
      break;
  }
  NOTREACHED();
  return {{}, Size()};
}

PhysicalRect NGPhysicalFragment::ScrollableOverflowForPropagation(
    const NGPhysicalBoxFragment& container,
    TextHeightType height_type) const {
  PhysicalRect overflow = ScrollableOverflow(container, height_type);
  AdjustScrollableOverflowForPropagation(container, height_type, &overflow);
  return overflow;
}

void NGPhysicalFragment::AdjustScrollableOverflowForPropagation(
    const NGPhysicalBoxFragment& container,
    TextHeightType height_type,
    PhysicalRect* overflow) const {
  DCHECK(!IsLineBox());
  if (!IsCSSBox())
    return;
  if (UNLIKELY(IsLayoutObjectDestroyedOrMoved())) {
    NOTREACHED();
    return;
  }

  if (height_type == TextHeightType::kNormalHeight && Type() == kFragmentBox)
    overflow->Unite({{}, Size()});

  const LayoutObject* layout_object = GetLayoutObject();
  DCHECK(layout_object);
  const LayoutObject* container_layout_object = container.GetLayoutObject();
  DCHECK(container_layout_object);
  if (layout_object->ShouldUseTransformFromContainer(container_layout_object)) {
    TransformationMatrix transform;
    layout_object->GetTransformFromContainer(container_layout_object,
                                             PhysicalOffset(), transform);
    *overflow =
        PhysicalRect::EnclosingRect(transform.MapRect(FloatRect(*overflow)));
  }
}

const Vector<NGInlineItem>& NGPhysicalFragment::InlineItemsOfContainingBlock()
    const {
  DCHECK(IsInline());
  DCHECK(GetLayoutObject());
  LayoutBlockFlow* block_flow = GetLayoutObject()->ContainingNGBlockFlow();
  // TODO(xiaochengh): Code below is copied from ng_offset_mapping.cc with
  // modification. Unify them.
  DCHECK(block_flow);
  NGBlockNode block_node = NGBlockNode(block_flow);
  DCHECK(block_node.IsInlineFormattingContextRoot());
  DCHECK(block_node.CanUseNewLayout());
  NGLayoutInputNode node = block_node.FirstChild();

  // TODO(xiaochengh): Handle ::first-line.
  return To<NGInlineNode>(node).ItemsData(false).items;
}

TouchAction NGPhysicalFragment::EffectiveAllowedTouchAction() const {
  DCHECK(layout_object_);
  return layout_object_->EffectiveAllowedTouchAction();
}

bool NGPhysicalFragment::InsideBlockingWheelEventHandler() const {
  DCHECK(layout_object_);
  return layout_object_->InsideBlockingWheelEventHandler();
}

UBiDiLevel NGPhysicalFragment::BidiLevel() const {
  switch (Type()) {
    case kFragmentBox:
      return To<NGPhysicalBoxFragment>(*this).BidiLevel();
    case kFragmentLineBox:
      break;
  }
  NOTREACHED();
  return 0;
}

TextDirection NGPhysicalFragment::ResolvedDirection() const {
  switch (Type()) {
    case kFragmentBox:
      DCHECK(IsInline() && IsAtomicInline());
      // TODO(xiaochengh): Store direction in |base_direction_| flag.
      return DirectionFromLevel(BidiLevel());
    case kFragmentLineBox:
      break;
  }
  NOTREACHED();
  return TextDirection::kLtr;
}

bool NGPhysicalFragment::ShouldPaintCursorCaret() const {
  // TODO(xiaochengh): Merge cursor caret painting functions from LayoutBlock to
  // FrameSelection.
  if (const auto* block = DynamicTo<LayoutBlock>(GetLayoutObject()))
    return block->ShouldPaintCursorCaret();
  return false;
}

bool NGPhysicalFragment::ShouldPaintDragCaret() const {
  // TODO(xiaochengh): Merge drag caret painting functions from LayoutBlock to
  // DragCaret.
  if (const auto* block = DynamicTo<LayoutBlock>(GetLayoutObject()))
    return block->ShouldPaintDragCaret();
  return false;
}

LogicalRect NGPhysicalFragment::ConvertChildToLogical(
    const PhysicalRect& physical_rect) const {
  return WritingModeConverter(Style().GetWritingDirection(), Size())
      .ToLogical(physical_rect);
}

PhysicalRect NGPhysicalFragment::ConvertChildToPhysical(
    const LogicalRect& logical_rect) const {
  return WritingModeConverter(Style().GetWritingDirection(), Size())
      .ToPhysical(logical_rect);
}

String NGPhysicalFragment::ToString() const {
  StringBuilder output;
  output.AppendFormat("Type: '%d' Size: '%s'", Type(),
                      Size().ToString().Ascii().c_str());
  switch (Type()) {
    case kFragmentBox:
      output.AppendFormat(", BoxType: '%s'",
                          StringForBoxType(*this).Ascii().c_str());
      break;
    case kFragmentLineBox:
      break;
  }
  return output.ToString();
}

String NGPhysicalFragment::DumpFragmentTree(
    DumpFlags flags,
    base::Optional<PhysicalOffset> fragment_offset,
    unsigned indent) const {
  StringBuilder string_builder;
  if (flags & DumpHeaderText)
    string_builder.Append(".:: LayoutNG Physical Fragment Tree ::.\n");
  FragmentTreeDumper(&string_builder, flags)
      .Append(this, fragment_offset, indent);
  return string_builder.ToString();
}

String NGPhysicalFragment::DumpFragmentTree(const LayoutObject& root,
                                            DumpFlags flags) {
  if (root.IsLayoutNGObject()) {
    const LayoutBox& root_box = To<LayoutBox>(root);
    DCHECK_EQ(root_box.PhysicalFragmentCount(), 1u);
    return root_box.GetPhysicalFragment(0)->DumpFragmentTree(flags);
  }
  StringBuilder string_builder;
  if (flags & DumpHeaderText) {
    string_builder.Append(
        ".:: LayoutNG Physical Fragment Tree at legacy root ");
    string_builder.Append(root.DebugName());
    string_builder.Append(" ::.\n");
  }
  FragmentTreeDumper(&string_builder, flags).AppendLegacySubtree(root);
  return string_builder.ToString();
}

#if DCHECK_IS_ON()
void NGPhysicalFragment::ShowFragmentTree() const {
  DumpFlags dump_flags = DumpAll;
  LOG(INFO) << "\n" << DumpFragmentTree(dump_flags).Utf8();
}

void NGPhysicalFragment::ShowFragmentTree(const LayoutObject& root) {
  DumpFlags dump_flags = DumpAll;
  LOG(INFO) << "\n" << DumpFragmentTree(root, dump_flags).Utf8();
}
#endif

PhysicalRect NGPhysicalFragmentWithOffset::RectInContainerBox() const {
  return {offset_to_container_box, fragment->Size()};
}

std::ostream& operator<<(std::ostream& out,
                         const NGPhysicalFragment& fragment) {
  return out << fragment.ToString();
}

std::ostream& operator<<(std::ostream& out,
                         const NGPhysicalFragment* fragment) {
  if (!fragment)
    return out << "<null>";
  return out << *fragment;
}

}  // namespace blink
