// Copyright 2020 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_layout_overflow_calculator.h"

#include "third_party/blink/renderer/core/layout/geometry/writing_mode_converter.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
#include "third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
#include "third_party/blink/renderer/core/layout/ng/ng_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_length_utils.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h"

namespace blink {

// static
PhysicalRect NGLayoutOverflowCalculator::RecalculateLayoutOverflowForFragment(
    const NGPhysicalBoxFragment& fragment) {
  DCHECK(!fragment.IsLegacyLayoutRoot());
  const NGBlockNode node(const_cast<LayoutBox*>(
      To<LayoutBox>(fragment.GetSelfOrContainerLayoutObject())));
  const WritingDirectionMode writing_direction =
      node.Style().GetWritingDirection();

  // TODO(ikilpatrick): The final computed scrollbars for a fragment should
  // likely live on the NGPhysicalBoxFragment.
  NGPhysicalBoxStrut scrollbar;
  if (fragment.IsCSSBox()) {
    scrollbar = ComputeScrollbarsForNonAnonymous(node).ConvertToPhysical(
        writing_direction);
  }

  NGLayoutOverflowCalculator calculator(
      node, fragment.IsCSSBox(), fragment.Borders(), scrollbar,
      fragment.Padding(), fragment.Size(), writing_direction);

  if (const NGFragmentItems* items = fragment.Items())
    calculator.AddItems(*items);

  for (const auto& child : fragment.PostLayoutChildren()) {
    const auto* box_fragment =
        DynamicTo<NGPhysicalBoxFragment>(*child.fragment);
    if (!box_fragment)
      continue;

    if (box_fragment->IsFragmentainerBox()) {
      // When this function is called nothing has updated the layout-overflow
      // of any fragmentainers (as they are not directly associated with a
      // layout-object). Recalculate their layout-overflow directly.
      PhysicalRect child_overflow =
          RecalculateLayoutOverflowForFragment(*box_fragment);
      child_overflow.offset += child.offset;
      calculator.AddOverflow(child_overflow);
    } else {
      calculator.AddChild(*box_fragment, child.offset);
    }
  }

  return calculator.Result(fragment.InflowBounds());
}

NGLayoutOverflowCalculator::NGLayoutOverflowCalculator(
    const NGBlockNode& node,
    bool is_css_box,
    const NGPhysicalBoxStrut& borders,
    const NGPhysicalBoxStrut& scrollbar,
    const NGPhysicalBoxStrut& padding,
    PhysicalSize size,
    WritingDirectionMode writing_direction)
    : node_(node),
      writing_direction_(writing_direction),
      is_scroll_container_(is_css_box && node_.IsScrollContainer()),
      has_left_overflow_(is_css_box && node_.HasLeftOverflow()),
      has_top_overflow_(is_css_box && node_.HasTopOverflow()),
      has_non_visible_overflow_(is_css_box && node_.HasNonVisibleOverflow()),
      padding_(padding),
      size_(size) {
  const auto border_scrollbar = borders + scrollbar;

  // TODO(layout-dev): This isn't correct for <fieldset> elements as we may
  // have a legend which is taller than the block-start border.
  padding_rect_ = {PhysicalOffset(border_scrollbar.left, border_scrollbar.top),
                   PhysicalSize((size_.width - border_scrollbar.HorizontalSum())
                                    .ClampNegativeToZero(),
                                (size_.height - border_scrollbar.VerticalSum())
                                    .ClampNegativeToZero())};
  layout_overflow_ = padding_rect_;
}

const PhysicalRect NGLayoutOverflowCalculator::Result(
    const base::Optional<PhysicalRect> inflow_bounds) {
  if (!inflow_bounds || !is_scroll_container_)
    return layout_overflow_;

  PhysicalOffset start_offset = inflow_bounds->MinXMinYCorner() -
                                PhysicalOffset(padding_.left, padding_.top);
  PhysicalOffset end_offset = inflow_bounds->MaxXMaxYCorner() +
                              PhysicalOffset(padding_.right, padding_.bottom);

  PhysicalRect inflow_overflow = {
      start_offset, PhysicalSize(end_offset.left - start_offset.left,
                                 end_offset.top - start_offset.top)};
  inflow_overflow = AdjustOverflowForScrollOrigin(inflow_overflow);

  PhysicalRect normal_overflow = layout_overflow_;
  normal_overflow.UniteEvenIfEmpty(inflow_overflow);

  if (node_.IsInlineFormattingContextRoot())
    return normal_overflow;

  WritingModeConverter converter(writing_direction_, size_);

  LogicalRect block_end_padding_rect = {
      LogicalOffset(converter.ToLogical(padding_rect_).offset.inline_offset,
                    converter.ToLogical(*inflow_bounds).BlockEndOffset()),
      LogicalSize(LayoutUnit(),
                  padding_.ConvertToLogical(writing_direction_).block_end)};

  PhysicalRect alternate_overflow = layout_overflow_;
  alternate_overflow.UniteEvenIfEmpty(AdjustOverflowForScrollOrigin(
      converter.ToPhysical(block_end_padding_rect)));

  // We'd like everything to be |normal_overflow|, lets see what the impact
  // would be.
  if (node_.Style().OverflowInlineDirection() == EOverflow::kAuto ||
      node_.Style().OverflowInlineDirection() == EOverflow::kScroll) {
    if (alternate_overflow.size.width != normal_overflow.size.width) {
      if (alternate_overflow.size.width != padding_rect_.size.width) {
        UseCounter::Count(
            node_.GetDocument(),
            node_.IsFlexibleBox()
                ? WebFeature::kNewLayoutOverflowDifferentAndAlreadyScrollsFlex
                : WebFeature::
                      kNewLayoutOverflowDifferentAndAlreadyScrollsBlock);
      } else {
        UseCounter::Count(node_.GetDocument(),
                          node_.IsFlexibleBox()
                              ? WebFeature::kNewLayoutOverflowDifferentFlex
                              : WebFeature::kNewLayoutOverflowDifferentBlock);
      }
    }
  }

  return alternate_overflow;
}

template <typename Items>
void NGLayoutOverflowCalculator::AddItemsInternal(const Items& items) {
  bool has_hanging = false;
  PhysicalRect line_rect;

  for (const auto& item : items) {
    if (const auto* line_box = item->LineBoxFragment()) {
      has_hanging = line_box->HasHanging();
      line_rect = item->RectInContainerFragment();

      if (line_rect.IsEmpty())
        continue;

      // Currently line-boxes don't contribute overflow in the block-axis. This
      // was added for web-compat reasons.
      PhysicalRect child_overflow = line_rect;
      if (writing_direction_.IsHorizontal())
        child_overflow.size.height = LayoutUnit();
      else
        child_overflow.size.width = LayoutUnit();

      layout_overflow_.UniteEvenIfEmpty(child_overflow);
      continue;
    }

    if (item->IsText()) {
      PhysicalRect child_overflow = item->RectInContainerFragment();

      // Adjust the text's overflow if the line-box has hanging.
      if (UNLIKELY(has_hanging))
        child_overflow = AdjustOverflowForHanging(line_rect, child_overflow);

      AddOverflow(child_overflow);
      continue;
    }

    if (const auto* child_box_fragment = item->BoxFragment()) {
      // Use the default box-fragment overflow logic.
      PhysicalRect child_overflow =
          LayoutOverflowForPropagation(*child_box_fragment);
      child_overflow.offset += item->OffsetInContainerFragment();

      // Only inline-boxes (not atomic-inlines) should be adjusted if the
      // line-box has hanging.
      if (child_box_fragment->IsInlineBox() && has_hanging)
        child_overflow = AdjustOverflowForHanging(line_rect, child_overflow);

      AddOverflow(child_overflow);
      continue;
    }
  }
}

void NGLayoutOverflowCalculator::AddItems(
    const NGFragmentItemsBuilder::ItemWithOffsetList& items) {
  AddItemsInternal(items);
}

void NGLayoutOverflowCalculator::AddItems(const NGFragmentItems& items) {
  AddItemsInternal(items.Items());
}

PhysicalRect NGLayoutOverflowCalculator::AdjustOverflowForHanging(
    const PhysicalRect& line_rect,
    PhysicalRect overflow) {
  if (writing_direction_.IsHorizontal()) {
    if (overflow.offset.left < line_rect.offset.left)
      overflow.offset.left = line_rect.offset.left;
    if (overflow.Right() > line_rect.Right())
      overflow.ShiftRightEdgeTo(line_rect.Right());
  } else {
    if (overflow.offset.top < line_rect.offset.top)
      overflow.offset.top = line_rect.offset.top;
    if (overflow.Bottom() > line_rect.Bottom())
      overflow.ShiftBottomEdgeTo(line_rect.Bottom());
  }

  return overflow;
}

PhysicalRect NGLayoutOverflowCalculator::AdjustOverflowForScrollOrigin(
    const PhysicalRect& overflow) {
  LayoutUnit left_offset =
      has_left_overflow_
          ? std::min(padding_rect_.Right(), overflow.offset.left)
          : std::max(padding_rect_.offset.left, overflow.offset.left);

  LayoutUnit right_offset =
      has_left_overflow_
          ? std::min(padding_rect_.Right(), overflow.Right())
          : std::max(padding_rect_.offset.left, overflow.Right());

  LayoutUnit top_offset =
      has_top_overflow_
          ? std::min(padding_rect_.Bottom(), overflow.offset.top)
          : std::max(padding_rect_.offset.top, overflow.offset.top);

  LayoutUnit bottom_offset =
      has_top_overflow_ ? std::min(padding_rect_.Bottom(), overflow.Bottom())
                        : std::max(padding_rect_.offset.top, overflow.Bottom());

  return {PhysicalOffset(left_offset, top_offset),
          PhysicalSize(right_offset - left_offset, bottom_offset - top_offset)};
}

PhysicalRect NGLayoutOverflowCalculator::LayoutOverflowForPropagation(
    const NGPhysicalBoxFragment& child_fragment) {
  // If the fragment is anonymous, just return its layout-overflow (don't apply
  // any incorrect transforms, etc).
  if (!child_fragment.IsCSSBox())
    return child_fragment.LayoutOverflow();

  PhysicalRect overflow = {{}, child_fragment.Size()};
  const auto& child_style = child_fragment.Style();
  if (!child_fragment.ShouldApplyLayoutContainment() &&
      (!child_fragment.ShouldClipOverflowAlongBothAxis() ||
       child_style.OverflowClipMargin() != LayoutUnit()) &&
      !child_fragment.IsInlineBox()) {
    PhysicalRect child_overflow = child_fragment.LayoutOverflow();
    if (child_fragment.HasNonVisibleOverflow()) {
      const OverflowClipAxes overflow_clip_axes =
          child_fragment.GetOverflowClipAxes();
      const LayoutUnit overflow_clip_margin = child_style.OverflowClipMargin();
      if (overflow_clip_margin != LayoutUnit()) {
        // overflow_clip_margin should only be set if 'overflow' is 'clip' along
        // both axis.
        DCHECK_EQ(overflow_clip_axes, kOverflowClipBothAxis);
        PhysicalRect child_padding_rect({}, child_fragment.Size());
        child_padding_rect.Contract(child_fragment.Borders());
        child_padding_rect.Inflate(overflow_clip_margin);
        child_overflow.Intersect(child_padding_rect);
      } else {
        if (overflow_clip_axes & kOverflowClipX) {
          child_overflow.offset.left = LayoutUnit();
          child_overflow.size.width = child_fragment.Size().width;
        }
        if (overflow_clip_axes & kOverflowClipY) {
          child_overflow.offset.top = LayoutUnit();
          child_overflow.size.height = child_fragment.Size().height;
        }
      }
    }
    overflow.UniteEvenIfEmpty(child_overflow);
  }

  // Apply any transforms to the overflow.
  if (base::Optional<TransformationMatrix> transform =
          node_.GetTransformForChildFragment(child_fragment, size_)) {
    overflow =
        PhysicalRect::EnclosingRect(transform->MapRect(FloatRect(overflow)));
  }

  return overflow;
}

}  // namespace blink
