/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2007 David Smith (catfish.man@gmail.com)
 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc.
 *               All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_BLOCK_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_BLOCK_H_

#include <memory>
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/platform/wtf/list_hash_set.h"

namespace blink {

struct PaintInfo;
class LineLayoutBox;
class NGConstraintSpace;
class WordMeasurement;

typedef WTF::ListHashSet<LayoutBox*, 16> TrackedLayoutBoxListHashSet;
typedef WTF::HashMap<const LayoutBlock*,
                     std::unique_ptr<TrackedLayoutBoxListHashSet>>
    TrackedDescendantsMap;
typedef WTF::HashMap<const LayoutBox*, LayoutBlock*> TrackedContainerMap;
typedef Vector<WordMeasurement, 64> WordMeasurements;

enum ContainingBlockState { kNewContainingBlock, kSameContainingBlock };

// LayoutBlock is the class that is used by any LayoutObject
// that is a containing block.
// http://www.w3.org/TR/CSS2/visuren.html#containing-block
// See also LayoutObject::containingBlock() that is the function
// used to get the containing block of a LayoutObject.
//
// CSS is inconsistent and allows inline elements (LayoutInline) to be
// containing blocks, even though they are not blocks. Our
// implementation is as confused with inlines. See e.g.
// LayoutObject::containingBlock() vs LayoutObject::container().
//
// Containing blocks are a central concept for layout, in
// particular to the layout of out-of-flow positioned
// elements. They are used to determine the sizing as well
// as the positioning of the LayoutObjects.
//
// LayoutBlock is the class that handles out-of-flow positioned elements in
// Blink, in particular for layout (see layoutPositionedObjects()). That's why
// LayoutBlock keeps track of them through |gPositionedDescendantsMap| (see
// LayoutBlock.cpp).
// Note that this is a design decision made in Blink that doesn't reflect CSS:
// CSS allows relatively positioned inlines (LayoutInline) to be containing
// blocks, but they don't have the logic to handle out-of-flow positioned
// objects. This induces some complexity around choosing an enclosing
// LayoutBlock (for inserting out-of-flow objects during layout) vs the CSS
// containing block (for sizing, invalidation).
//
//
// ***** WHO LAYS OUT OUT-OF-FLOW POSITIONED OBJECTS? *****
// A positioned object gets inserted into an enclosing LayoutBlock's positioned
// map. This is determined by LayoutObject::containingBlock().
//
//
// ***** HANDLING OUT-OF-FLOW POSITIONED OBJECTS *****
// Care should be taken to handle out-of-flow positioned objects during
// certain tree walks (e.g. layout()). The rule is that anything that
// cares about containing blocks should skip the out-of-flow elements
// in the normal tree walk and do an optional follow-up pass for them
// using LayoutBlock::positionedObjects().
// Not doing so will result in passing the wrong containing
// block as tree walks will always pass the parent as the
// containing block.
//
// Sample code of how to handle positioned objects in LayoutBlock:
//
// for (LayoutObject* child = firstChild(); child; child = child->nextSibling())
// {
//     if (child->isOutOfFlowPositioned())
//         continue;
//
//     // Handle normal flow children.
//     ...
// }
// for (LayoutBox* positionedObject : positionedObjects()) {
//     // Handle out-of-flow positioned objects.
//     ...
// }
class CORE_EXPORT LayoutBlock : public LayoutBox {
 protected:
  explicit LayoutBlock(ContainerNode*);
  ~LayoutBlock() override;

 public:
  LayoutObject* FirstChild() const {
    DCHECK_EQ(Children(), VirtualChildren());
    return Children()->FirstChild();
  }
  LayoutObject* LastChild() const {
    DCHECK_EQ(Children(), VirtualChildren());
    return Children()->LastChild();
  }

  // If you have a LayoutBlock, use firstChild or lastChild instead.
  void SlowFirstChild() const = delete;
  void SlowLastChild() const = delete;

  const LayoutObjectChildList* Children() const { return &children_; }
  LayoutObjectChildList* Children() { return &children_; }

  // These two functions are overridden for inline-block.
  LayoutUnit LineHeight(
      bool first_line,
      LineDirectionMode,
      LinePositionMode = kPositionOnContainingLine) const final;
  LayoutUnit BaselinePosition(
      FontBaseline,
      bool first_line,
      LineDirectionMode,
      LinePositionMode = kPositionOnContainingLine) const override;
  bool UseLogicalBottomMarginEdgeForInlineBlockBaseline() const;

  LayoutUnit MinLineHeightForReplacedObject(bool is_first_line,
                                            LayoutUnit replaced_height) const;

  virtual bool CreatesNewFormattingContext() const { return true; }

  const char* GetName() const override;

 protected:
  // Insert a child correctly into the tree when |beforeDescendant| isn't a
  // direct child of |this|. This happens e.g. when there's an anonymous block
  // child of |this| and |beforeDescendant| has been reparented into that one.
  // Such things are invisible to the DOM, and addChild() is typically called
  // with the DOM tree (and not the layout tree) in mind.
  void AddChildBeforeDescendant(LayoutObject* new_child,
                                LayoutObject* before_descendant);

 public:
  void AddChild(LayoutObject* new_child,
                LayoutObject* before_child = nullptr) override;

  virtual void UpdateBlockLayout(bool relayout_children);

  void InsertPositionedObject(LayoutBox*);
  static void RemovePositionedObject(LayoutBox*);
  void RemovePositionedObjects(LayoutObject*,
                               ContainingBlockState = kSameContainingBlock);

  TrackedLayoutBoxListHashSet* PositionedObjects() const {
    return HasPositionedObjects() ? PositionedObjectsInternal() : nullptr;
  }
  bool HasPositionedObjects() const {
    DCHECK(has_positioned_objects_ ? (PositionedObjectsInternal() &&
                                      !PositionedObjectsInternal()->IsEmpty())
                                   : !PositionedObjectsInternal());
    return has_positioned_objects_;
  }

  void AddPercentHeightDescendant(LayoutBox*);
  void RemovePercentHeightDescendant(LayoutBox*);
  bool HasPercentHeightDescendant(LayoutBox* o) const {
    return HasPercentHeightDescendants() &&
           PercentHeightDescendantsInternal()->Contains(o);
  }

  TrackedLayoutBoxListHashSet* PercentHeightDescendants() const {
    return HasPercentHeightDescendants() ? PercentHeightDescendantsInternal()
                                         : nullptr;
  }
  bool HasPercentHeightDescendants() const {
    DCHECK(has_percent_height_descendants_
               ? (PercentHeightDescendantsInternal() &&
                  !PercentHeightDescendantsInternal()->IsEmpty())
               : !PercentHeightDescendantsInternal());
    return has_percent_height_descendants_;
  }

  void NotifyScrollbarThicknessChanged() {
    width_available_to_children_changed_ = true;
  }

  void SetHasMarkupTruncation(bool b) { has_markup_truncation_ = b; }
  bool HasMarkupTruncation() const { return has_markup_truncation_; }

  void SetHasMarginBeforeQuirk(bool b) { has_margin_before_quirk_ = b; }
  void SetHasMarginAfterQuirk(bool b) { has_margin_after_quirk_ = b; }

  bool HasMarginBeforeQuirk() const { return has_margin_before_quirk_; }
  bool HasMarginAfterQuirk() const { return has_margin_after_quirk_; }

  bool HasMarginBeforeQuirk(const LayoutBox* child) const;
  bool HasMarginAfterQuirk(const LayoutBox* child) const;

  void MarkPositionedObjectsForLayout();

  LayoutUnit TextIndentOffset() const;

  PositionWithAffinity PositionForPoint(const LayoutPoint&) const override;

  static LayoutBlock* CreateAnonymousWithParentAndDisplay(
      const LayoutObject*,
      EDisplay = EDisplay::kBlock);
  LayoutBlock* CreateAnonymousBlock(EDisplay display = EDisplay::kBlock) const {
    return CreateAnonymousWithParentAndDisplay(this, display);
  }

  LayoutBox* CreateAnonymousBoxWithSameTypeAs(
      const LayoutObject* parent) const override;

  // Accessors for logical width/height and margins in the containing block's
  // block-flow direction.
  LayoutUnit LogicalWidthForChild(const LayoutBox& child) const {
    return LogicalWidthForChildSize(child.Size());
  }
  LayoutUnit LogicalWidthForChildSize(LayoutSize child_size) const {
    return IsHorizontalWritingMode() ? child_size.Width() : child_size.Height();
  }
  LayoutUnit LogicalHeightForChild(const LayoutBox& child) const {
    return IsHorizontalWritingMode() ? child.Size().Height()
                                     : child.Size().Width();
  }
  LayoutSize LogicalSizeForChild(const LayoutBox& child) const {
    return IsHorizontalWritingMode() ? child.Size()
                                     : child.Size().TransposedSize();
  }
  LayoutUnit LogicalTopForChild(const LayoutBox& child) const {
    return IsHorizontalWritingMode() ? child.Location().Y()
                                     : child.Location().X();
  }
  DISABLE_CFI_PERF LayoutUnit
  MarginBeforeForChild(const LayoutBoxModelObject& child) const {
    return child.MarginBefore(Style());
  }
  DISABLE_CFI_PERF LayoutUnit
  MarginAfterForChild(const LayoutBoxModelObject& child) const {
    return child.MarginAfter(Style());
  }
  DISABLE_CFI_PERF LayoutUnit
  MarginStartForChild(const LayoutBoxModelObject& child) const {
    return child.MarginStart(Style());
  }
  LayoutUnit MarginEndForChild(const LayoutBoxModelObject& child) const {
    return child.MarginEnd(Style());
  }
  void SetMarginStartForChild(LayoutBox& child, LayoutUnit value) const {
    child.SetMarginStart(value, Style());
  }
  void SetMarginEndForChild(LayoutBox& child, LayoutUnit value) const {
    child.SetMarginEnd(value, Style());
  }
  void SetMarginBeforeForChild(LayoutBox& child, LayoutUnit value) const {
    child.SetMarginBefore(value, Style());
  }
  void SetMarginAfterForChild(LayoutBox& child, LayoutUnit value) const {
    child.SetMarginAfter(value, Style());
  }
  LayoutUnit CollapsedMarginBeforeForChild(const LayoutBox& child) const;
  LayoutUnit CollapsedMarginAfterForChild(const LayoutBox& child) const;

  enum ScrollbarChangeContext { kStyleChange, kLayout };
  virtual void ScrollbarsChanged(bool horizontal_scrollbar_changed,
                                 bool vertical_scrollbar_changed,
                                 ScrollbarChangeContext = kLayout);

  LayoutUnit AvailableLogicalWidthForContent() const {
    return (LogicalRightOffsetForContent() - LogicalLeftOffsetForContent())
        .ClampNegativeToZero();
  }
  DISABLE_CFI_PERF LayoutUnit LogicalLeftOffsetForContent() const {
    return IsHorizontalWritingMode() ? ContentLeft() : ContentTop();
  }
  LayoutUnit LogicalRightOffsetForContent() const {
    return LogicalLeftOffsetForContent() + AvailableLogicalWidth();
  }
  LayoutUnit StartOffsetForContent() const {
    return StyleRef().IsLeftToRightDirection()
               ? LogicalLeftOffsetForContent()
               : LogicalWidth() - LogicalRightOffsetForContent();
  }
  LayoutUnit EndOffsetForContent() const {
    return !StyleRef().IsLeftToRightDirection()
               ? LogicalLeftOffsetForContent()
               : LogicalWidth() - LogicalRightOffsetForContent();
  }

#if DCHECK_IS_ON()
  void CheckPositionedObjectsNeedLayout();
#endif

  LayoutUnit AvailableLogicalHeightForPercentageComputation() const;
  bool HasDefiniteLogicalHeight() const;

  const NGConstraintSpace* CachedConstraintSpace() const;
  void SetCachedConstraintSpace(const NGConstraintSpace& space);

 protected:
  bool RecalcNormalFlowChildOverflowIfNeeded(LayoutObject*);
  bool RecalcPositionedDescendantsOverflowAfterStyleChange();
  bool RecalcSelfOverflowAfterStyleChange();

 public:
  bool RecalcChildOverflowAfterStyleChange();
  bool RecalcOverflowAfterStyleChange() override;

  // An example explaining layout tree structure about first-line style:
  // <style>
  //   #enclosingFirstLineStyleBlock::first-line { ... }
  // </style>
  // <div id="enclosingFirstLineStyleBlock">
  //   <div>
  //     <div id="nearestInnerBlockWithFirstLine">
  //       [<span>]first line text[</span>]
  //     </div>
  //   </div>
  // </div>

  // Returns the nearest enclosing block (including this block) that contributes
  // a first-line style to our first line.
  const LayoutBlock* EnclosingFirstLineStyleBlock() const;
  // Returns this block or the nearest inner block containing the actual first
  // line.
  LayoutBlockFlow* NearestInnerBlockWithFirstLine();

 protected:
  void WillBeDestroyed() override;

  void DirtyForLayoutFromPercentageHeightDescendants(SubtreeLayoutScope&);

  void UpdateLayout() override;

  enum PositionedLayoutBehavior {
    kDefaultLayout,
    kLayoutOnlyFixedPositionedObjects,
    kForcedLayoutAfterContainingBlockMoved
  };

  virtual void LayoutPositionedObjects(
      bool relayout_children,
      PositionedLayoutBehavior = kDefaultLayout);
  void LayoutPositionedObject(LayoutBox*,
                              bool relayout_children,
                              PositionedLayoutBehavior info);
  void MarkFixedPositionObjectForLayoutIfNeeded(LayoutObject* child,
                                                SubtreeLayoutScope&);

 public:
  bool IsLegacyInitiatedOutOfFlowLayout() const {
    return is_legacy_initiated_out_of_flow_layout_;
  }

  void SetIsLegacyInitiatedOutOfFlowLayout(bool b) {
    is_legacy_initiated_out_of_flow_layout_ = b;
  }

 protected:
  LayoutUnit MarginIntrinsicLogicalWidthForChild(const LayoutBox& child) const;

  LayoutUnit BeforeMarginInLineDirection(LineDirectionMode) const;

 public:
  void Paint(const PaintInfo&) const override;
  virtual void PaintObject(const PaintInfo&,
                           const LayoutPoint& paint_offset) const;
  virtual void PaintChildren(const PaintInfo&,
                             const LayoutPoint& paint_offset) const;
  void UpdateAfterLayout() override;

 protected:
  virtual void AdjustInlineDirectionLineBounds(
      unsigned /* expansionOpportunityCount */,
      LayoutUnit& /* logicalLeft */,
      LayoutUnit& /* logicalWidth */) const {}

  void ComputeIntrinsicLogicalWidths(
      LayoutUnit& min_logical_width,
      LayoutUnit& max_logical_width) const override;
  void ComputePreferredLogicalWidths() override;
  void ComputeChildPreferredLogicalWidths(
      LayoutObject& child,
      LayoutUnit& min_preferred_logical_width,
      LayoutUnit& max_preferred_logical_width) const;

  LayoutUnit FirstLineBoxBaseline() const override;
  LayoutUnit InlineBlockBaseline(LineDirectionMode) const override;

  // This function disables the 'overflow' check in inlineBlockBaseline.
  // For 'inline-block', CSS says that the baseline is the bottom margin edge
  // if 'overflow' is not visible. But some descendant classes want to ignore
  // this condition.
  virtual bool ShouldIgnoreOverflowPropertyForInlineBlockBaseline() const {
    return false;
  }

  bool HitTestOverflowControl(HitTestResult&,
                              const HitTestLocation&,
                              const LayoutPoint& adjusted_location) override;
  bool HitTestChildren(HitTestResult&,
                       const HitTestLocation& location_in_container,
                       const LayoutPoint& accumulated_offset,
                       HitTestAction) override;

  void StyleWillChange(StyleDifference,
                       const ComputedStyle& new_style) override;
  void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
  void UpdateFromStyle() override;

  // Returns true if non-visible overflow should be respected. Otherwise
  // hasOverflowClip() will be false and we won't create scrollable area for
  // this object even if overflow is non-visible.
  virtual bool AllowsOverflowClip() const;

  virtual bool HasLineIfEmpty() const;

  bool SimplifiedLayout();
  virtual void SimplifiedNormalFlowLayout();

 public:
  virtual void ComputeOverflow(LayoutUnit old_client_after_edge,
                               bool recompute_floats = false);

 protected:
  virtual void AddOverflowFromChildren();
  void AddOverflowFromPositionedObjects();
  void AddOverflowFromBlockChildren();
  void AddVisualOverflowFromTheme();

  void AddOutlineRects(Vector<LayoutRect>&,
                       const LayoutPoint& additional_offset,
                       IncludeBlockVisualOverflowOrNot) const override;

  void UpdateBlockChildDirtyBitsBeforeLayout(bool relayout_children,
                                             LayoutBox&);

  // TODO(jchaffraix): We should rename this function as inline-flex and
  // inline-grid as also covered.
  // Alternatively it should be removed as we clarify the meaning of
  // isAtomicInlineLevel to imply isInline.
  bool IsInlineBlockOrInlineTable() const final {
    return IsInline() && IsAtomicInlineLevel();
  }

  bool NeedsPreferredWidthsRecalculation() const override;

  bool IsInSelfHitTestingPhase(HitTestAction hit_test_action) const final {
    return hit_test_action == kHitTestBlockBackground ||
           hit_test_action == kHitTestChildBlockBackground;
  }

 private:
  LayoutObjectChildList* VirtualChildren() final { return Children(); }
  const LayoutObjectChildList* VirtualChildren() const final {
    return Children();
  }

  bool IsLayoutBlock() const final { return true; }

  virtual void RemoveLeftoverAnonymousBlock(LayoutBlock* child);

  TrackedLayoutBoxListHashSet* PositionedObjectsInternal() const;
  TrackedLayoutBoxListHashSet* PercentHeightDescendantsInternal() const;

  // Returns true if the positioned movement-only layout succeeded.
  bool TryLayoutDoingPositionedMovementOnly();

  bool IsPointInOverflowControl(HitTestResult&,
                                const LayoutPoint& location_in_container,
                                const LayoutPoint& accumulated_offset) const;

  void ComputeBlockPreferredLogicalWidths(LayoutUnit& min_logical_width,
                                          LayoutUnit& max_logical_width) const;

 public:
  bool ShouldPaintCursorCaret() const;
  bool ShouldPaintDragCaret() const;
  bool ShouldPaintCarets() const {
    return ShouldPaintCursorCaret() || ShouldPaintDragCaret();
  }

 protected:
  void InvalidatePaint(const PaintInvalidatorContext&) const override;

  void ClearPreviousVisualRects() override;

 private:
  LayoutRect LocalCaretRect(
      const InlineBox*,
      int caret_offset,
      LayoutUnit* extra_width_to_end_of_line = nullptr) const final;
  bool IsInlineBoxWrapperActuallyChild() const;

  Position PositionForBox(InlineBox*, bool start = true) const;

  // End helper functions and structs used by layoutBlockChildren.

  void RemoveFromGlobalMaps();
  bool WidthAvailableToChildrenHasChanged();

 protected:
  // Paginated content inside this block was laid out.
  // |logicalBottomOffsetAfterPagination| is the logical bottom offset of the
  // child content after applying any forced or unforced breaks as needed.
  void PaginatedContentWasLaidOut(
      LayoutUnit logical_bottom_offset_after_pagination);

  // Adjust from painting offsets to the local coords of this layoutObject
  void OffsetForContents(LayoutPoint&) const;

  PositionWithAffinity PositionForPointRespectingEditingBoundaries(
      LineLayoutBox child,
      const LayoutPoint& point_in_parent_coordinates) const;
  PositionWithAffinity PositionForPointIfOutsideAtomicInlineLevel(
      const LayoutPoint&) const;

  virtual bool UpdateLogicalWidthAndColumnWidth();

  LayoutObjectChildList children_;
  scoped_refptr<const NGConstraintSpace> cached_constraint_space_;

  unsigned
      has_margin_before_quirk_ : 1;  // Note these quirk values can't be put
                                     // in LayoutBlockRareData since they are
                                     // set too frequently.
  unsigned has_margin_after_quirk_ : 1;
  unsigned being_destroyed_ : 1;
  unsigned has_markup_truncation_ : 1;
  unsigned width_available_to_children_changed_ : 1;
  unsigned height_available_to_children_changed_ : 1;
  unsigned is_self_collapsing_ : 1;  // True if margin-before and margin-after
                                     // are adjoining.
  unsigned descendants_with_floats_marked_for_layout_ : 1;

  unsigned has_positioned_objects_ : 1;
  unsigned has_percent_height_descendants_ : 1;

  // When an object ceases to establish a fragmentation context (e.g. the
  // LayoutView when we're no longer printing), we need a deep layout
  // afterwards, to clear all pagination struts. Likewise, when an object
  // becomes fragmented, we need to re-lay out the entire subtree. There might
  // be forced breaks somewhere in there that we suddenly have to pay attention
  // to, for all we know.
  unsigned pagination_state_changed_ : 1;

  // LayoutNG-only: This flag is true if an NG out of flow layout was
  // initiated by Legacy positioning code.
  unsigned is_legacy_initiated_out_of_flow_layout_ : 1;

  // FIXME: This is temporary as we move code that accesses block flow
  // member variables out of LayoutBlock and into LayoutBlockFlow.
  friend class LayoutBlockFlow;

  // This is necessary for now for interoperability between the old and new
  // layout code. Primarily for calling layoutPositionedObjects at the moment.
  friend class NGBlockNode;

 public:
  // TODO(loonybear): Temporary in order to ensure compatibility with existing
  // layout test results.
  virtual void AdjustChildDebugRect(LayoutRect&) const {}
};

DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutBlock, IsLayoutBlock());

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_BLOCK_H_
