// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/layout/container_box.h"

#include <algorithm>

#include "cobalt/cssom/keyword_value.h"
#include "cobalt/cssom/number_value.h"
#include "cobalt/layout/used_style.h"
#include "cobalt/math/transform_2d.h"

namespace cobalt {
namespace layout {

ContainerBox::ContainerBox(
    const scoped_refptr<cssom::CSSComputedStyleDeclaration>&
        css_computed_style_declaration,
    UsedStyleProvider* used_style_provider,
    LayoutStatTracker* layout_stat_tracker)
    : Box(css_computed_style_declaration, used_style_provider,
          layout_stat_tracker),
      update_size_results_valid_(false),
      are_cross_references_valid_(false),
      are_bidi_levels_runs_split_(false),
      next_draw_order_position_(0) {}

ContainerBox::~ContainerBox() {}

// Given a non-const container and a const iterator from that container, this
// will return a non-const iterator.
Boxes::iterator ContainerBox::RemoveConst(Boxes* container,
                                          Boxes::const_iterator const_iter) {
  // Since ChildBoxes is a vector, std::distance and std::advance are both
  // constant time.
  Boxes::iterator iter = container->begin();
  std::advance(iter, std::distance<Boxes::const_iterator>(iter, const_iter));
  return iter;
}

void ContainerBox::PushBackDirectChild(const scoped_refptr<Box>& child_box) {
  // Verify that the child doesn't have a pre-existing parent.
  DCHECK(!child_box->parent());

  // Verify that this container hasn't had its sizes and cross references
  // already updated. This is because children should only ever be added to
  // containers created during the current box generation run.
  DCHECK(!update_size_results_valid_);
  DCHECK(!are_cross_references_valid_);

  child_box->parent_ = this;
  child_boxes_.push_back(child_box);
}

Boxes::const_iterator ContainerBox::InsertSplitSiblingOfDirectChild(
    Boxes::const_iterator child_position) {
  Box* split_sibling = (*child_position)->GetSplitSibling();

  // Verify that the split sibling exists and that it doesn't have a
  // pre-existing parent.
  DCHECK(split_sibling);
  DCHECK(!split_sibling->parent());

  // Set the parent of the split sibling to this container.
  split_sibling->parent_ = this;

  // Add the split sibling to this container after it's sibling.
  Boxes::const_iterator split_sibling_position = child_boxes_.insert(
      RemoveConst(&child_boxes_, ++child_position), split_sibling);

  // Invalidate the size now that the children have changed.
  update_size_results_valid_ = false;

  // Check to see if the split sibling is positioned, which means that it
  // needs to invalidate its containing block's cross references.
  bool is_positioned = split_sibling->IsPositioned();
  if (is_positioned) {
    split_sibling->GetContainingBlock()->are_cross_references_valid_ = false;
  }
  // Check to see if the split sibling is a stacking context child, which means
  // that it needs to invalidate its stacking context's cross references.
  if (is_positioned || split_sibling->IsStackingContext()) {
    split_sibling->GetStackingContext()->are_cross_references_valid_ = false;
  }

  // Invalidate the render tree nodes now that the children have changed.
  InvalidateRenderTreeNodesOfBoxAndAncestors();

  return split_sibling_position;
}

void ContainerBox::MoveDirectChildrenToSplitSibling(
    Boxes::const_iterator start_position) {
  // Verify that the move includes children.
  DCHECK(start_position != child_boxes_.end());

  ContainerBox* split_sibling = GetSplitSibling()->AsContainerBox();

  // Verify that the split sibling exists and that it hasn't been processed yet.
  DCHECK(split_sibling);
  DCHECK(!split_sibling->parent());
  DCHECK(!split_sibling->update_size_results_valid_);
  DCHECK(!split_sibling->are_cross_references_valid_);

  // Update the parent of the children being moved.
  for (Boxes::const_iterator iter = start_position; iter != child_boxes_.end();
       ++iter) {
    (*iter)->parent_ = split_sibling;
  }

  // Add the children to the split sibling's list of children.
  Boxes::iterator source_start_non_const =
      RemoveConst(&child_boxes_, start_position);
  Boxes::iterator source_end_non_const =
      RemoveConst(&child_boxes_, child_boxes_.end());
  split_sibling->child_boxes_.insert(
      RemoveConst(&split_sibling->child_boxes_,
                  split_sibling->child_boxes_.end()),
      source_start_non_const, source_end_non_const);

  // Erase the children from this container's list of children.
  child_boxes_.erase(source_start_non_const, source_end_non_const);

  // Invalidate the size now that the children have changed.
  update_size_results_valid_ = false;

  // Handle invalidating cross references. Children are only being removed from
  // this container, so cross references only need to be invalidated if there is
  // a non-empty cross reference list that can potentially be impacted.

  // If there are any positioned boxes, then they need to be re-generated.
  if (!positioned_child_boxes_.empty()) {
    are_cross_references_valid_ = false;
  }

  // There are two cases where the stacking context's cross references can be
  // impacted by children moving from one container to another. With both cases,
  // stacking context children must exist or there is nothing to update.
  //   1. Stacking context children are potentially moving from this child
  //      container to the split sibling child container.
  //   2. Stacking context children contained within this overflow hidden
  //      container are potentially moving to the split sibling overflow hidden
  //      container.
  if (HasStackingContextChildren() ||
      computed_style()->overflow() == cssom::KeywordValue::GetHidden()) {
    // Walk up the tree until the nearest stacking context is found. If this box
    // is a stacking context, then it will be used.
    ContainerBox* nearest_stacking_context = this;
    while (!nearest_stacking_context->IsStackingContext()) {
      nearest_stacking_context = nearest_stacking_context->parent();
    }
    if (nearest_stacking_context->HasStackingContextChildren()) {
      nearest_stacking_context->are_cross_references_valid_ = false;
    }
  }

  // Invalidate the render tree nodes now that the children have changed.
  InvalidateRenderTreeNodesOfBoxAndAncestors();
}

bool ContainerBox::IsContainingBlockForPositionAbsoluteElements() const {
  return parent() == NULL || IsPositioned() || IsTransformed();
}

bool ContainerBox::IsContainingBlockForPositionFixedElements() const {
  return parent() == NULL || IsTransformed();
}

bool ContainerBox::IsStackingContext() const {
  // The core stacking context creation criteria is given here
  // (https://www.w3.org/TR/CSS21/visuren.html#z-index) however it is extended
  // by various other specification documents such as those describing opacity
  // (https://www.w3.org/TR/css3-color/#transparency) and transforms
  // (https://www.w3.org/TR/css3-transforms/#transform-rendering).
  // NOTE: Fixed position elements are treated as stacking contexts. While the
  // spec does not specify that they create a stacking context, this is the
  // functionality of Chrome, Firefox, Edge, and Safari.
  return parent() == NULL ||
         (base::polymorphic_downcast<const cssom::NumberValue*>(
              computed_style()->opacity().get())
              ->value() < 1.0f) ||
         IsTransformed() ||
         (IsPositioned() &&
          computed_style()->z_index() != cssom::KeywordValue::GetAuto()) ||
         computed_style()->position() == cssom::KeywordValue::GetFixed();
}

void ContainerBox::UpdateCrossReferences() {
  if (!are_cross_references_valid_) {
    // If this point is reached, then the cross references for this container
    // box are being re-generated.
    layout_stat_tracker()->OnUpdateCrossReferences();

    bool is_stacking_context = IsStackingContext();

    // Cross references are not cleared when they are invalidated. This is
    // because they can be invalidated while they are being walked if a
    // relatively positioned descendant is split. Therefore, they need to be
    // cleared now before they are regenerated.
    positioned_child_boxes_.clear();
    if (is_stacking_context) {
      negative_z_index_stacking_context_children_.clear();
      non_negative_z_index_stacking_context_children_.clear();
    }

    // This stack tracks all container boxes within the stacking context. The
    // container boxes will only be pushed and popped if the current box is
    // their stacking context.
    StackingContextContainerBoxStack stacking_context_container_box_stack;

    const RelationshipToBox kNearestContainingBlockOfChildren = kIsBox;
    RelationshipToBox nearest_absolute_containing_block =
        IsContainingBlockForPositionAbsoluteElements() ? kIsBox
                                                       : kIsBoxAncestor;
    RelationshipToBox nearest_fixed_containing_block =
        IsContainingBlockForPositionFixedElements() ? kIsBox : kIsBoxAncestor;
    RelationshipToBox nearest_stacking_context =
        is_stacking_context ? kIsBox : kIsBoxAncestor;

    for (Boxes::const_iterator child_box_iterator = child_boxes_.begin();
         child_box_iterator != child_boxes_.end(); ++child_box_iterator) {
      Box* child_box = *child_box_iterator;
      child_box->UpdateCrossReferencesOfContainerBox(
          this, kNearestContainingBlockOfChildren,
          nearest_absolute_containing_block, nearest_fixed_containing_block,
          nearest_stacking_context, &stacking_context_container_box_stack);
    }

    are_cross_references_valid_ = true;
  }
}

void ContainerBox::AddContainingBlockChild(Box* child_box) {
  DCHECK_NE(this, child_box);
  DCHECK_EQ(this, child_box->GetContainingBlock());
  positioned_child_boxes_.push_back(child_box);
}

void ContainerBox::AddStackingContextChild(
    Box* child_box, int child_z_index,
    RelationshipToBox containing_block_relationship,
    const ContainingBlocksWithOverflowHidden& overflow_hidden_to_apply) {
  DCHECK_NE(this, child_box);
  DCHECK_EQ(child_z_index, child_box->GetZIndex());
  // If this is a stacking context, then verify that the child box's stacking
  // context is this stacking context.
  // Otherwise, verify that this box's stacking context is also the child box's
  // stacking context and that the z_index of the child is 0 (non-zero z-index
  // children must be added directly to the stacking context).
  DCHECK(this->IsStackingContext()
             ? this == child_box->GetStackingContext()
             : this->GetStackingContext() == child_box->GetStackingContext() &&
                   child_z_index == 0);

  ZIndexSortedList& stacking_context_children =
      child_z_index < 0 ? negative_z_index_stacking_context_children_
                        : non_negative_z_index_stacking_context_children_;
  stacking_context_children.insert(StackingContextChildInfo(
      child_box, child_z_index, containing_block_relationship,
      overflow_hidden_to_apply));
}

bool ContainerBox::HasStackingContextChildren() const {
  return !negative_z_index_stacking_context_children_.empty() ||
         !non_negative_z_index_stacking_context_children_.empty();
}

namespace {

Vector2dLayoutUnit GetOffsetFromContainingBlockToParent(Box* child_box) {
  Vector2dLayoutUnit relative_position;
  for (Box *ancestor_box = child_box->parent(),
           *containing_block = child_box->GetContainingBlock();
       ancestor_box != containing_block;
       ancestor_box = ancestor_box->parent()) {
    DCHECK(ancestor_box)
        << "Unable to find containing block while traversing parents.";
    // It is not possible for the containing block to be more distant than an
    // ancestor that is transformed.
    DCHECK(!ancestor_box->IsTransformed());

    relative_position += ancestor_box->GetContentBoxOffsetFromMarginBox();
    relative_position +=
        ancestor_box->margin_box_offset_from_containing_block();
  }
  return relative_position;
}

}  // namespace

bool ContainerBox::ValidateUpdateSizeInputs(const LayoutParams& params) {
  // Take into account whether our children have been modified to determine
  // if our sizes are invalid and need to be recomputed.
  if (Box::ValidateUpdateSizeInputs(params) && update_size_results_valid_) {
    return true;
  } else {
    update_size_results_valid_ = true;
    return false;
  }
}

void ContainerBox::InvalidateCrossReferencesOfBoxAndAncestors() {
  // NOTE: The cross reference containers are not cleared here. Instead they are
  // cleared when the cross references are updated.
  are_cross_references_valid_ = false;
  Box::InvalidateCrossReferencesOfBoxAndAncestors();
}

ContainerBox* ContainerBox::AsContainerBox() { return this; }
const ContainerBox* ContainerBox::AsContainerBox() const { return this; }

void ContainerBox::UpdateRectOfPositionedChildBoxes(
    const LayoutParams& relative_child_layout_params,
    const LayoutParams& absolute_child_layout_params) {
  // Ensure that the cross references are up to date.
  UpdateCrossReferences();

  for (std::vector<Box*>::const_iterator child_box_iterator =
           positioned_child_boxes_.begin();
       child_box_iterator != positioned_child_boxes_.end();
       ++child_box_iterator) {
    Box* child_box = *child_box_iterator;
    DCHECK_EQ(this, child_box->GetContainingBlock());

    const scoped_refptr<cssom::PropertyValue>& child_box_position =
        child_box->computed_style()->position();

    if (child_box_position == cssom::KeywordValue::GetAbsolute()) {
      UpdateRectOfAbsolutelyPositionedChildBox(child_box,
                                               absolute_child_layout_params);
    } else if (child_box_position == cssom::KeywordValue::GetFixed()) {
      UpdateRectOfAbsolutelyPositionedChildBox(child_box,
                                               relative_child_layout_params);
    } else {
      DCHECK(child_box_position == cssom::KeywordValue::GetRelative());
      UpdateOffsetOfRelativelyPositionedChildBox(child_box,
                                                 relative_child_layout_params);
    }

    // Verify that the positioned child boxes didn't get cleared during the
    // walk. This should never happen because the cross references being
    // invalidated should not cause them to be cleared.
    DCHECK_GT(positioned_child_boxes_.size(), size_t(0));
  }
}

void ContainerBox::UpdateOffsetOfRelativelyPositionedChildBox(
    Box* child_box, const LayoutParams& child_layout_params) {
  DCHECK_EQ(child_box->computed_style()->position(),
            cssom::KeywordValue::GetRelative());

  base::optional<LayoutUnit> maybe_left = GetUsedLeftIfNotAuto(
      child_box->computed_style(), child_layout_params.containing_block_size);
  base::optional<LayoutUnit> maybe_right = GetUsedRightIfNotAuto(
      child_box->computed_style(), child_layout_params.containing_block_size);
  base::optional<LayoutUnit> maybe_top = GetUsedTopIfNotAuto(
      child_box->computed_style(), child_layout_params.containing_block_size);
  base::optional<LayoutUnit> maybe_bottom = GetUsedBottomIfNotAuto(
      child_box->computed_style(), child_layout_params.containing_block_size);

  Vector2dLayoutUnit offset;

  // The following steps are performed according to the procedure described
  // here: https://www.w3.org/TR/CSS21/visuren.html#relative-positioning

  // For relatively positioned elements, 'left' and 'right' move the box(es)
  // horizontally, without changing their size.
  if (!maybe_left && !maybe_right) {
    // If both 'left' and 'right' are 'auto' (their initial values), the used
    // values are '0' (i.e., the boxes stay in their original position).
    offset.set_x(LayoutUnit());
  } else if (maybe_left && !maybe_right) {
    // If 'right' is 'auto', its used value is minus the value of 'left'.
    offset.set_x(*maybe_left);
  } else if (!maybe_left && maybe_right) {
    // If 'left' is 'auto', its used value is minus the value of 'right'
    offset.set_x(-*maybe_right);
  } else {
    // If neither 'left' nor 'right' is 'auto', the position is
    // over-constrained, and one of them has to be ignored. If the 'direction'
    // property of the containing block is 'ltr', the value of 'left' wins and
    // 'right' becomes -'left'. If 'direction' of the containing block is 'rtl',
    // 'right' wins and 'left' is ignored.

    // TODO: Take into account the value of the 'direction' property, which
    //       doesn't exist at the time of this writing.
    offset.set_x(*maybe_left);
  }

  // The 'top' and 'bottom' properties move relatively positioned element(s) up
  // or down without changing their size.
  if (!maybe_top && !maybe_bottom) {
    // If both are 'auto', their used values are both '0'.
    offset.set_y(LayoutUnit());
  } else if (maybe_top && !maybe_bottom) {
    // If one of them is 'auto', it becomes the negative of the other.
    offset.set_y(*maybe_top);
  } else if (!maybe_top && maybe_bottom) {
    // If one of them is 'auto', it becomes the negative of the other.
    offset.set_y(-*maybe_bottom);
  } else {
    // If neither is 'auto', 'bottom' is ignored (i.e., the used value of
    // 'bottom' will be minus the value of 'top').
    offset.set_y(*maybe_top);
  }

  child_box->set_left(child_box->left() + offset.x());
  child_box->set_top(child_box->top() + offset.y());
}

void ContainerBox::UpdateRectOfAbsolutelyPositionedChildBox(
    Box* child_box, const LayoutParams& child_layout_params) {
  Vector2dLayoutUnit offset_from_containing_block_to_parent =
      GetOffsetFromContainingBlockToParent(child_box);
  // The containing block is formed by the padding box instead of the content
  // box, as described in
  // http://www.w3.org/TR/CSS21/visudet.html#containing-block-details.
  // NOTE: While not explicitly stated in the spec, which specifies that
  // the containing block of a 'fixed' position element must always be the
  // viewport, all major browsers use the padding box of a transformed ancestor
  // as the containing block for 'fixed' position elements.
  offset_from_containing_block_to_parent += GetContentBoxOffsetFromPaddingBox();
  child_box->SetStaticPositionLeftFromContainingBlockToParent(
      offset_from_containing_block_to_parent.x());
  child_box->SetStaticPositionTopFromContainingBlockToParent(
      offset_from_containing_block_to_parent.y());
  child_box->UpdateSize(child_layout_params);
}

namespace {

// This class handles all logic involved with calling RenderAndAnimate() on
// stacking context children., including determining their offset from the child
// container and applying overflow hidden from its containing blocks.
class RenderAndAnimateStackingContextChildrenCoordinator {
 public:
  RenderAndAnimateStackingContextChildrenCoordinator(
      ContainerBox* stacking_context, const ContainerBox* child_container,
      const Vector2dLayoutUnit& child_container_offset_from_parent_node,
      render_tree::CompositionNode::Builder* base_node_builder)
      : stacking_context_(stacking_context),
        child_container_(child_container),
        child_container_offset_from_parent_node_(
            child_container_offset_from_parent_node),
        base_node_builder_(base_node_builder) {}

  // The destructor handles generating filter nodes for any remaining entries in
  // |overflow_hidden_stack_|.
  ~RenderAndAnimateStackingContextChildrenCoordinator();

  // Applies overflow hidden from the child's containing blocks and then calls
  // RenderAndAnimate() on it.
  void RenderAndAnimateChild(
      const ContainerBox::StackingContextChildInfo& child_info);

 private:
  struct OverflowHiddenInfo {
    explicit OverflowHiddenInfo(ContainerBox* containing_block)
        : node_builder(math::Vector2dF()), containing_block(containing_block) {}

    render_tree::CompositionNode::Builder node_builder;
    ContainerBox* containing_block;
  };

  typedef std::vector<OverflowHiddenInfo> OverflowHiddenStack;

  // Updates |overflow_hidden_stack_| with the overflow hidden containing blocks
  // of the current child. Any entries in |overflow_hidden_stack_| that are no
  // longer valid are popped. All entries that remain valid are retained, so
  // that filter nodes can be shared across stacking context children.
  void ApplyOverflowHiddenForChild(
      const Box::ContainingBlocksWithOverflowHidden& overflow_hidden_to_apply);

  // Generates a filter node from the top entry in |overflow_hidden_stack_| and
  // adds it to the active node builder after the top entry is popped.
  void PopOverflowHiddenEntryFromStack();

  // Returns the node builder from the top entry in |overflow_hidden_stack_| if
  // it is not empty; otherwise, returns |base_node_builder_|.
  render_tree::CompositionNode::Builder* GetActiveNodeBuilder();

  Vector2dLayoutUnit GetOffsetFromChildContainerToContainingBlock(
      const Box* containing_block,
      const Box::RelationshipToBox
          containing_block_relationship_to_child_container) const;

  ContainerBox* stacking_context_;
  const ContainerBox* child_container_;
  const Vector2dLayoutUnit& child_container_offset_from_parent_node_;

  render_tree::CompositionNode::Builder* base_node_builder_;
  OverflowHiddenStack overflow_hidden_stack_;
};

RenderAndAnimateStackingContextChildrenCoordinator::
    ~RenderAndAnimateStackingContextChildrenCoordinator() {
  while (!overflow_hidden_stack_.empty()) {
    PopOverflowHiddenEntryFromStack();
  }
}

void RenderAndAnimateStackingContextChildrenCoordinator::RenderAndAnimateChild(
    const ContainerBox::StackingContextChildInfo& child_info) {
  ApplyOverflowHiddenForChild(child_info.overflow_hidden_to_apply);

  // Generate the offset from the child container to the child box.
  const ContainerBox* child_containing_block =
      child_info.box->GetContainingBlock();
  Vector2dLayoutUnit position_offset =
      GetOffsetFromChildContainerToContainingBlock(
          child_containing_block, child_info.containing_block_relationship) +
      child_container_offset_from_parent_node_;
  if (child_info.box->IsAbsolutelyPositioned()) {
    // The containing block is formed by the padding box instead of the content
    // box, as described in
    // http://www.w3.org/TR/CSS21/visudet.html#containing-block-details.
    // NOTE: While not explicitly stated in the spec, which specifies that
    // the containing block of a 'fixed' position element must always be the
    // viewport, all major browsers use the padding box of a transformed
    // ancestor as the containing block for 'fixed' position elements.
    position_offset -=
        child_containing_block->GetContentBoxOffsetFromPaddingBox();
  }

  child_info.box->RenderAndAnimate(GetActiveNodeBuilder(), position_offset,
                                   stacking_context_);
}

void RenderAndAnimateStackingContextChildrenCoordinator::
    ApplyOverflowHiddenForChild(const Box::ContainingBlocksWithOverflowHidden&
                                    overflow_hidden_to_apply) {
  // Walk the overflow hidden list being applied and the active overflow hidden
  // stack looking for the first index where there's a mismatch. All entries
  // prior to this are retained. This allows as many FilterNodes as possible to
  // be shared between the stacking context children.
  size_t index = 0;
  for (; index < overflow_hidden_to_apply.size() &&
         index < overflow_hidden_stack_.size();
       ++index) {
    if (overflow_hidden_to_apply[index] !=
        overflow_hidden_stack_[index].containing_block) {
      break;
    }
  }

  // Pop all entries in the active overflow hidden stack that follow the index
  // mismatch. They're no longer contained within the overflow hidden list being
  // applied.
  while (index < overflow_hidden_stack_.size()) {
    PopOverflowHiddenEntryFromStack();
  }

  // Add the new overflow hidden entries to the active stack.
  for (; index < overflow_hidden_to_apply.size(); ++index) {
    overflow_hidden_stack_.push_back(
        OverflowHiddenInfo(overflow_hidden_to_apply[index]));
  }
}

void RenderAndAnimateStackingContextChildrenCoordinator::
    PopOverflowHiddenEntryFromStack() {
  DCHECK(!overflow_hidden_stack_.empty());
  // Before popping the top of the stack, a filter node is generated from it
  // that is added to next node builder.
  OverflowHiddenInfo& overflow_hidden_info = overflow_hidden_stack_.back();

  ContainerBox* containing_block = overflow_hidden_info.containing_block;
  DCHECK_EQ(containing_block->computed_style()->overflow(),
            cssom::KeywordValue::GetHidden());

  // Determine the offset from the child container to this containing block's
  // margin box.
  Vector2dLayoutUnit containing_block_border_offset =
      GetOffsetFromChildContainerToContainingBlock(containing_block,
                                                   Box::kIsBoxAncestor) +
      Vector2dLayoutUnit(containing_block->margin_left(),
                         containing_block->margin_top());

  // Apply the overflow hidden from this containing block to its composition
  // node; the resulting filter node is added to the next active node builder.
  scoped_refptr<render_tree::Node> filter_node =
      containing_block->RenderAndAnimateOverflow(
          new render_tree::CompositionNode(
              overflow_hidden_info.node_builder.Pass()),
          math::Vector2dF(containing_block_border_offset.x().toFloat(),
                          containing_block_border_offset.y().toFloat()));

  overflow_hidden_stack_.pop_back();
  GetActiveNodeBuilder()->AddChild(filter_node);
}

render_tree::CompositionNode::Builder*
RenderAndAnimateStackingContextChildrenCoordinator::GetActiveNodeBuilder() {
  return overflow_hidden_stack_.empty()
             ? base_node_builder_
             : &(overflow_hidden_stack_.back().node_builder);
}

Vector2dLayoutUnit RenderAndAnimateStackingContextChildrenCoordinator::
    GetOffsetFromChildContainerToContainingBlock(
        const Box* containing_block,
        const Box::RelationshipToBox
            containing_block_relationship_to_child_container) const {
  if (containing_block_relationship_to_child_container == Box::kIsBox) {
    DCHECK_EQ(child_container_, containing_block);
    return Vector2dLayoutUnit();
  }

  Vector2dLayoutUnit relative_position;
  const Box* current_box =
      containing_block_relationship_to_child_container == Box::kIsBoxAncestor
          ? child_container_
          : containing_block;
  const Box* end_box =
      containing_block_relationship_to_child_container == Box::kIsBoxAncestor
          ? containing_block
          : child_container_;

  // Walk up the containing blocks from |current_box| to |end_box| adding the
  // offsets from each box to its containing block.
  // NOTE: |end_box| can be skipped during this walk both when |end_box| is not
  // positioned and when a fixed position box is encountered during the walk. In
  // this case, the walk will end when a box is found that either does not have
  // a parent (meaning that it's the root box) or is transformed (it is
  // impossible for |end_box| to be a more distant ancestor than a transformed
  // box).
  while (current_box != end_box && current_box->parent() &&
         !current_box->IsTransformed()) {
    relative_position += current_box->GetContentBoxOffsetFromMarginBox();
    relative_position += current_box->margin_box_offset_from_containing_block();

    const Box* next_box = current_box->GetContainingBlock();
    if (current_box->IsAbsolutelyPositioned()) {
      relative_position -= next_box->GetContentBoxOffsetFromPaddingBox();
    }
    current_box = next_box;
  }

  // If |current_box| does not equal |end_box|, then |end_box| was skipped
  // during the walk up the tree. Initiate a second walk up the tree from the
  // end box to the box where the first walk ended, subtracting the offsets
  // during this walk to remove the extra offsets added after passing |end_box|
  // during the first walk.
  std::swap(current_box, end_box);
  while (current_box != end_box) {
    DCHECK(current_box->parent());
    DCHECK(!current_box->IsTransformed());

    relative_position -= current_box->GetContentBoxOffsetFromMarginBox();
    relative_position -= current_box->margin_box_offset_from_containing_block();

    const Box* next_box = current_box->GetContainingBlock();
    if (current_box->IsAbsolutelyPositioned()) {
      relative_position += next_box->GetContentBoxOffsetFromPaddingBox();
    }
    current_box = next_box;
  }

  // If the containing block is an ancestor of the child container, then
  // reverse the relative position now. The earlier calculations were for the
  // containing block being a descendant of the child container.
  if (containing_block_relationship_to_child_container == Box::kIsBoxAncestor) {
    relative_position = -relative_position;
  }

  return relative_position;
}

}  // namespace

void ContainerBox::RenderAndAnimateStackingContextChildren(
    const ZIndexSortedList& stacking_context_child_list,
    render_tree::CompositionNode::Builder* content_node_builder,
    const Vector2dLayoutUnit& offset_from_parent_node,
    ContainerBox* stacking_context) const {
  // Create a coordinator that handles all logic involved with calling
  // RenderAndAnimate() on stacking context children., including determining
  // their offset from the child container and applying overflow hidden from the
  // child's containing blocks.
  RenderAndAnimateStackingContextChildrenCoordinator coordinator(
      stacking_context, this, offset_from_parent_node, content_node_builder);

  // Render all children of the passed in list in sorted order.
  for (ZIndexSortedList::const_iterator iter =
           stacking_context_child_list.begin();
       iter != stacking_context_child_list.end(); ++iter) {
    const StackingContextChildInfo& child_info = *iter;

    // If this container box is a stacking context, then verify that this child
    // box belongs to it; otherwise, verify that the container box and the child
    // box share the same stacking context and that the child's z-index is 0.
    DCHECK(this->IsStackingContext()
               ? this == child_info.box->GetStackingContext()
               : this->GetStackingContext() ==
                         child_info.box->GetStackingContext() &&
                     child_info.z_index == 0);

    coordinator.RenderAndAnimateChild(child_info);
  }
}

size_t ContainerBox::AddToDrawOrderInThisStackingContext() {
  return next_draw_order_position_++;
}

void ContainerBox::SplitBidiLevelRuns() {
  // Only split the child boxes if the bidi level runs haven't already been
  // split.
  if (!are_bidi_levels_runs_split_) {
    are_bidi_levels_runs_split_ = true;

    for (Boxes::const_iterator child_box_iterator = child_boxes_.begin();
         child_box_iterator != child_boxes_.end(); ++child_box_iterator) {
      Box* child_box = *child_box_iterator;
      child_box->SplitBidiLevelRuns();
    }
  }
}

void ContainerBox::UpdateCrossReferencesOfContainerBox(
    ContainerBox* source_box, RelationshipToBox nearest_containing_block,
    RelationshipToBox nearest_absolute_containing_block,
    RelationshipToBox nearest_fixed_containing_block,
    RelationshipToBox nearest_stacking_context,
    StackingContextContainerBoxStack* stacking_context_container_box_stack) {
  // First update the source container box's cross references with this box.
  Box::UpdateCrossReferencesOfContainerBox(
      source_box, nearest_containing_block, nearest_absolute_containing_block,
      nearest_fixed_containing_block, nearest_stacking_context,
      stacking_context_container_box_stack);

  // In addition to updating the source container box's cross references with
  // this box, we also recursively update it with our children.

  // Set the nearest flags for the children. If this container box is any of the
  // specified types, then the target container box cannot be the nearest box of
  // that type for the children.

  const RelationshipToBox kNearestContainingBlockOfChildren = kIsBoxDescendant;
  RelationshipToBox nearest_absolute_containing_block_of_children =
      nearest_absolute_containing_block != kIsBoxDescendant &&
              IsContainingBlockForPositionAbsoluteElements()
          ? kIsBoxDescendant
          : nearest_absolute_containing_block;
  RelationshipToBox nearest_fixed_containing_block_of_children =
      nearest_fixed_containing_block != kIsBoxDescendant &&
              IsContainingBlockForPositionFixedElements()
          ? kIsBoxDescendant
          : nearest_fixed_containing_block;
  RelationshipToBox nearest_stacking_context_of_children =
      nearest_stacking_context != kIsBoxDescendant && IsStackingContext()
          ? kIsBoxDescendant
          : nearest_stacking_context;

  // If the source box is the stacking context for this container box, then
  // clear out this box's stacking context children. They are being set now by
  // the stacking context. Additionally, add this container to the stack, so
  // that it will be considered as a possible destination for the stacking
  // context children.
  if (nearest_stacking_context_of_children == kIsBox) {
    negative_z_index_stacking_context_children_.clear();
    non_negative_z_index_stacking_context_children_.clear();

    bool has_absolute_position =
        computed_style()->position() == cssom::KeywordValue::GetAbsolute();
    bool has_overflow_hidden =
        computed_style()->overflow() == cssom::KeywordValue::GetHidden();

    stacking_context_container_box_stack->push_back(
        StackingContextContainerBoxInfo(
            this, IsContainingBlockForPositionAbsoluteElements(),
            has_absolute_position, has_overflow_hidden));
  }

  // Only process the children if the target container box is still the nearest
  // box of one of the types. If it is not, then it is impossible for any of the
  // children to be added to the cross references.
  if (nearest_absolute_containing_block_of_children == kIsBox ||
      nearest_fixed_containing_block_of_children == kIsBox ||
      nearest_stacking_context_of_children == kIsBox) {
    for (Boxes::const_iterator child_box_iterator = child_boxes_.begin();
         child_box_iterator != child_boxes_.end(); ++child_box_iterator) {
      Box* child_box = *child_box_iterator;
      child_box->UpdateCrossReferencesOfContainerBox(
          source_box, kNearestContainingBlockOfChildren,
          nearest_absolute_containing_block_of_children,
          nearest_fixed_containing_block_of_children,
          nearest_stacking_context_of_children,
          stacking_context_container_box_stack);
    }
  }

  // Pop this container from the stack if it was previously added.
  if (nearest_stacking_context_of_children == kIsBox) {
    stacking_context_container_box_stack->pop_back();
  }
}

void ContainerBox::AddBoxAndDescendantsToDrawOrderInStackingContext(
    ContainerBox* stacking_context) {
  Box::AddBoxAndDescendantsToDrawOrderInStackingContext(stacking_context);
  // If this is a stacking context, then there's no more work to do. None of
  // the stacking context children can be part of the ancestor stacking context.
  // If this is not a stacking context, then all of the stacking context
  // children are still part of the same stacking context.
  if (!IsStackingContext()) {
    // Non-stacking contexts can only have stacking context children with a
    // z-index of zero. Any child with non-zero z-index, must be added to the
    // stacking context itself.
    DCHECK(negative_z_index_stacking_context_children_.empty());
    for (ZIndexSortedList::const_iterator iter =
             non_negative_z_index_stacking_context_children_.begin();
         iter != non_negative_z_index_stacking_context_children_.end();
         ++iter) {
      DCHECK_EQ(iter->z_index, 0);
      iter->box->AddBoxAndDescendantsToDrawOrderInStackingContext(
          stacking_context);
    }
  }
}

void ContainerBox::RenderAndAnimateContent(
    render_tree::CompositionNode::Builder* content_node_builder,
    ContainerBox* stacking_context) const {
  // Update the stacking context if this is found to be a stacking context.
  ContainerBox* this_as_stacking_context = const_cast<ContainerBox*>(this);

  // Reset the draw order for this box. Even if it isn't explictly a stacking
  // context, it'll be used as one for in-flow, non-positioned child boxes.
  this_as_stacking_context->next_draw_order_position_ = 0;

  // If this is a stacking context, then ensure that the
  // stacking context children are up to date. This will also update the
  // stacking context children for any descendant container boxes that are
  // part of this stacking context.
  if (IsStackingContext()) {
    stacking_context = this_as_stacking_context;
    stacking_context->UpdateCrossReferences();
  }

  Vector2dLayoutUnit content_box_offset(border_left_width() + padding_left(),
                                        border_top_width() + padding_top());

  // Render all child stacking contexts and positioned children in our stacking
  // context that have negative z-index values.
  //   https://www.w3.org/TR/CSS21/visuren.html#z-index
  RenderAndAnimateStackingContextChildren(
      negative_z_index_stacking_context_children_, content_node_builder,
      content_box_offset, stacking_context);

  // Render in-flow, non-positioned child boxes.
  //   https://www.w3.org/TR/CSS21/visuren.html#z-index
  for (Boxes::const_iterator child_box_iterator = child_boxes_.begin();
       child_box_iterator != child_boxes_.end(); ++child_box_iterator) {
    Box* child_box = *child_box_iterator;
    if (!child_box->IsPositioned() && !child_box->IsStackingContext()) {
      child_box->RenderAndAnimate(content_node_builder, content_box_offset,
                                  this_as_stacking_context);
    }
  }

  // Render all child stacking contexts and positioned children in our stacking
  // context that have non-negative z-index values.
  //   https://www.w3.org/TR/CSS21/visuren.html#z-index
  RenderAndAnimateStackingContextChildren(
      non_negative_z_index_stacking_context_children_, content_node_builder,
      content_box_offset, stacking_context);
}

#ifdef COBALT_BOX_DUMP_ENABLED

void ContainerBox::DumpChildrenWithIndent(std::ostream* stream,
                                          int indent) const {
  Box::DumpChildrenWithIndent(stream, indent);

  for (Boxes::const_iterator child_box_iterator = child_boxes_.begin();
       child_box_iterator != child_boxes_.end(); ++child_box_iterator) {
    Box* child_box = *child_box_iterator;
    child_box->DumpWithIndent(stream, indent);
  }
}

#endif  // COBALT_BOX_DUMP_ENABLED

}  // namespace layout
}  // namespace cobalt
