/*
 * Copyright (C) 2012 Apple Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "core/layout/LayoutMultiColumnSet.h"

#include "core/editing/PositionWithAffinity.h"
#include "core/layout/LayoutMultiColumnFlowThread.h"
#include "core/layout/MultiColumnFragmentainerGroup.h"
#include "core/paint/MultiColumnSetPainter.h"

namespace blink {

LayoutMultiColumnSet::LayoutMultiColumnSet(LayoutFlowThread* flow_thread)
    : LayoutBlockFlow(nullptr),
      fragmentainer_groups_(*this),
      flow_thread_(flow_thread),
      initial_height_calculated_(false),
      last_actual_column_count_(0) {}

LayoutMultiColumnSet* LayoutMultiColumnSet::CreateAnonymous(
    LayoutFlowThread& flow_thread,
    const ComputedStyle& parent_style) {
  Document& document = flow_thread.GetDocument();
  LayoutMultiColumnSet* layout_object = new LayoutMultiColumnSet(&flow_thread);
  layout_object->SetDocumentForAnonymous(&document);
  layout_object->SetStyle(ComputedStyle::CreateAnonymousStyleWithDisplay(
      parent_style, EDisplay::kBlock));
  return layout_object;
}

unsigned LayoutMultiColumnSet::FragmentainerGroupIndexAtFlowThreadOffset(
    LayoutUnit flow_thread_offset,
    PageBoundaryRule rule) const {
  DCHECK_GT(fragmentainer_groups_.size(), 0u);
  if (flow_thread_offset <= 0)
    return 0;
  // TODO(mstensho): Introduce an interval tree or similar to speed up this.
  for (unsigned index = 0; index < fragmentainer_groups_.size(); index++) {
    const auto& row = fragmentainer_groups_[index];
    if (rule == kAssociateWithLatterPage) {
      if (row.LogicalTopInFlowThread() <= flow_thread_offset &&
          row.LogicalBottomInFlowThread() > flow_thread_offset)
        return index;
    } else if (row.LogicalTopInFlowThread() < flow_thread_offset &&
               row.LogicalBottomInFlowThread() >= flow_thread_offset) {
      return index;
    }
  }
  return fragmentainer_groups_.size() - 1;
}

const MultiColumnFragmentainerGroup&
LayoutMultiColumnSet::FragmentainerGroupAtVisualPoint(
    const LayoutPoint& visual_point) const {
  DCHECK_GT(fragmentainer_groups_.size(), 0u);
  LayoutUnit block_offset =
      IsHorizontalWritingMode() ? visual_point.Y() : visual_point.X();
  for (unsigned index = 0; index < fragmentainer_groups_.size(); index++) {
    const auto& row = fragmentainer_groups_[index];
    if (row.LogicalTop() + row.GroupLogicalHeight() > block_offset)
      return row;
  }
  return fragmentainer_groups_.Last();
}

LayoutUnit LayoutMultiColumnSet::PageLogicalHeightForOffset(
    LayoutUnit offset) const {
  DCHECK(IsPageLogicalHeightKnown());
  const MultiColumnFragmentainerGroup& last_row = LastFragmentainerGroup();
  if (offset >= last_row.LogicalTopInFlowThread() +
                    FragmentainerGroupCapacity(last_row)) {
    // The offset is outside the bounds of the fragmentainer groups that we
    // have established at this point. If we're nested inside another
    // fragmentation context, and are allowed to create additional rows, we
    // need to calculate the height on our own.
    const LayoutMultiColumnFlowThread* flow_thread = MultiColumnFlowThread();
    FragmentationContext* enclosing_fragmentation_context =
        flow_thread->EnclosingFragmentationContext();
    if (enclosing_fragmentation_context &&
        NeedsNewFragmentainerGroupAt(offset, kAssociateWithLatterPage) &&
        enclosing_fragmentation_context->IsFragmentainerLogicalHeightKnown()) {
      // We'd ideally like to translate |offset| to an offset in the coordinate
      // space of the enclosing fragmentation context here, but that's hard,
      // since the offset is out of bounds. So just use the bottom we have
      // found so far.
      LayoutUnit enclosing_context_bottom =
          last_row.BlockOffsetInEnclosingFragmentationContext() +
          last_row.GroupLogicalHeight();
      LayoutUnit extra_row_height =
          enclosing_fragmentation_context->FragmentainerLogicalHeightAt(
              enclosing_context_bottom);
      LayoutUnit current_multicol_height = LogicalTopFromMulticolContentEdge() +
                                           last_row.LogicalTop() +
                                           last_row.GroupLogicalHeight();
      // Constrain against specified height / max-height.
      LayoutUnit multicol_height_with_extra_row =
          std::min(current_multicol_height + extra_row_height,
                   flow_thread->MaxColumnLogicalHeight());
      extra_row_height =
          multicol_height_with_extra_row - current_multicol_height;
      return extra_row_height.ClampNegativeToZero();
    }
  }
  return FragmentainerGroupAtFlowThreadOffset(offset, kAssociateWithLatterPage)
      .ColumnLogicalHeight();
}

LayoutUnit LayoutMultiColumnSet::PageRemainingLogicalHeightForOffset(
    LayoutUnit offset_in_flow_thread,
    PageBoundaryRule page_boundary_rule) const {
  const MultiColumnFragmentainerGroup& row =
      FragmentainerGroupAtFlowThreadOffset(offset_in_flow_thread,
                                           page_boundary_rule);
  LayoutUnit page_logical_height = row.ColumnLogicalHeight();
  LayoutUnit page_logical_bottom =
      row.ColumnLogicalTopForOffset(offset_in_flow_thread) +
      page_logical_height;
  LayoutUnit remaining_logical_height =
      page_logical_bottom - offset_in_flow_thread;

  if (page_boundary_rule == kAssociateWithFormerPage) {
    // An offset exactly at a column boundary will act as being part of the
    // former column in question (i.e. no remaining space), rather than being
    // part of the latter (i.e. one whole column length of remaining space).
    remaining_logical_height =
        IntMod(remaining_logical_height, page_logical_height);
  } else if (!remaining_logical_height) {
    // When pageBoundaryRule is AssociateWithLatterPage, we shouldn't just
    // return 0 if there's no space left, because in that case we're at a
    // column boundary, in which case we should return the amount of space
    // remaining in the *next* column. Note that the page height itself may be
    // 0, though.
    remaining_logical_height = page_logical_height;
  }
  return remaining_logical_height;
}

bool LayoutMultiColumnSet::IsPageLogicalHeightKnown() const {
  return FirstFragmentainerGroup().IsLogicalHeightKnown();
}

bool LayoutMultiColumnSet::NewFragmentainerGroupsAllowed() const {
  if (!IsPageLogicalHeightKnown()) {
    // If we have no clue about the height of the multicol container, bail. This
    // situation occurs initially when an auto-height multicol container is
    // nested inside another auto-height multicol container. We need at least an
    // estimated height of the outer multicol container before we can check what
    // an inner fragmentainer group has room for.
    // Its height is indefinite for now.
    return false;
  }
  if (IsInitialHeightCalculated()) {
    // We only insert additional fragmentainer groups in the initial layout
    // pass. We only want to balance columns in the last fragmentainer group (if
    // we need to balance at all), so we want that last fragmentainer group to
    // be the same one in all layout passes that follow.
    return false;
  }
  return true;
}

LayoutUnit LayoutMultiColumnSet::NextLogicalTopForUnbreakableContent(
    LayoutUnit flow_thread_offset,
    LayoutUnit content_logical_height) const {
  DCHECK(flow_thread_offset.MightBeSaturated() ||
         PageLogicalTopForOffset(flow_thread_offset) == flow_thread_offset);
  if (!MultiColumnFlowThread()->EnclosingFragmentationContext()) {
    // If there's no enclosing fragmentation context, there'll ever be only one
    // row, and all columns there will have the same height.
    return flow_thread_offset;
  }

  // Assert the problematic situation. If we have no problem with the column
  // height, why are we even here?
  DCHECK_LT(PageLogicalHeightForOffset(flow_thread_offset),
            content_logical_height);

  // There's a likelihood for subsequent rows to be taller than the first one.
  // TODO(mstensho): if we're doubly nested (e.g. multicol in multicol in
  // multicol), we need to look beyond the first row here.
  const MultiColumnFragmentainerGroup& first_row = FirstFragmentainerGroup();
  LayoutUnit first_row_logical_bottom_in_flow_thread =
      first_row.LogicalTopInFlowThread() +
      FragmentainerGroupCapacity(first_row);
  if (flow_thread_offset >= first_row_logical_bottom_in_flow_thread)
    return flow_thread_offset;  // We're not in the first row. Give up.
  LayoutUnit new_logical_height =
      PageLogicalHeightForOffset(first_row_logical_bottom_in_flow_thread);
  if (content_logical_height > new_logical_height) {
    // The next outer column or page doesn't have enough space either. Give up
    // and stay where we are.
    return flow_thread_offset;
  }
  return first_row_logical_bottom_in_flow_thread;
}

LayoutMultiColumnSet* LayoutMultiColumnSet::NextSiblingMultiColumnSet() const {
  for (LayoutObject* sibling = NextSibling(); sibling;
       sibling = sibling->NextSibling()) {
    if (sibling->IsLayoutMultiColumnSet())
      return ToLayoutMultiColumnSet(sibling);
  }
  return nullptr;
}

LayoutMultiColumnSet* LayoutMultiColumnSet::PreviousSiblingMultiColumnSet()
    const {
  for (LayoutObject* sibling = PreviousSibling(); sibling;
       sibling = sibling->PreviousSibling()) {
    if (sibling->IsLayoutMultiColumnSet())
      return ToLayoutMultiColumnSet(sibling);
  }
  return nullptr;
}

bool LayoutMultiColumnSet::NeedsNewFragmentainerGroupAt(
    LayoutUnit offset_in_flow_thread,
    PageBoundaryRule page_boundary_rule) const {
  // First the cheap check: Perhaps the last fragmentainer group has sufficient
  // capacity?
  const MultiColumnFragmentainerGroup& last_row = LastFragmentainerGroup();
  LayoutUnit max_logical_bottom_in_flow_thread =
      last_row.LogicalTopInFlowThread() + FragmentainerGroupCapacity(last_row);
  if (page_boundary_rule == kAssociateWithFormerPage) {
    if (offset_in_flow_thread <= max_logical_bottom_in_flow_thread)
      return false;
  } else if (offset_in_flow_thread < max_logical_bottom_in_flow_thread) {
    return false;
  }

  // So, there's not enough room in the last fragmentainer group. However,
  // there can only ever be one fragmentainer group per column set if we're not
  // nested inside another fragmentation context. We'll just create overflowing
  // columns if the fragmentainer group cannot hold all the content.
  if (!MultiColumnFlowThread()->EnclosingFragmentationContext())
    return false;

  // If we have reached the limits of what a LayoutUnit can hold, we better
  // stop, or we'd end up with zero-height columns.
  if (offset_in_flow_thread.MightBeSaturated())
    return false;

  // We're in a nested fragmentation context, and the last fragmentainer group
  // cannot hold content at the specified offset without overflowing. This
  // usually warrants a new fragmentainer group; however, this will not be the
  // case if we have already allocated all available block space in this
  // multicol container. When setting up a new fragmentainer group, we always
  // constrain against the remaining portion of any specified
  // height/max-height. This means that we shouldn't allow creation of
  // fragmentainer groups below the bottom of the multicol container, or we'd
  // end up with zero-height fragmentainer groups (or actually 1px; see
  // heightAdjustedForRowOffset() in MultiColumnFragmentainerGroup, which
  // guards against zero-height groups), i.e. potentially a lot of pretty
  // useless fragmentainer groups, and possibly broken layout too. Instead,
  // we'll just allow additional (overflowing) columns to be created in the
  // last fragmentainer group, similar to what we do when we're not nested.
  LayoutUnit logical_bottom =
      last_row.LogicalTop() + last_row.GroupLogicalHeight();
  LayoutUnit space_used = logical_bottom + LogicalTopFromMulticolContentEdge();
  LayoutUnit max_column_height =
      MultiColumnFlowThread()->MaxColumnLogicalHeight();
  return max_column_height - space_used > LayoutUnit();
}

MultiColumnFragmentainerGroup&
LayoutMultiColumnSet::AppendNewFragmentainerGroup() {
  MultiColumnFragmentainerGroup new_group(*this);
  {  // Extra scope here for previousGroup; it's potentially invalid once we
     // modify the m_fragmentainerGroups Vector.
    MultiColumnFragmentainerGroup& previous_group =
        fragmentainer_groups_.Last();

    // This is the flow thread block offset where |previousGroup| ends and
    // |newGroup| takes over.
    LayoutUnit block_offset_in_flow_thread =
        previous_group.LogicalTopInFlowThread() +
        FragmentainerGroupCapacity(previous_group);
    previous_group.SetLogicalBottomInFlowThread(block_offset_in_flow_thread);
    new_group.SetLogicalTopInFlowThread(block_offset_in_flow_thread);
    new_group.SetLogicalTop(previous_group.LogicalTop() +
                            previous_group.GroupLogicalHeight());
    new_group.ResetColumnHeight();
  }
  fragmentainer_groups_.Append(new_group);
  return fragmentainer_groups_.Last();
}

LayoutUnit LayoutMultiColumnSet::LogicalTopFromMulticolContentEdge() const {
  // We subtract the position of the first column set or spanner placeholder,
  // rather than the "before" border+padding of the multicol container. This
  // distinction doesn't matter after layout, but during layout it does:
  // The flow thread (i.e. the multicol contents) is laid out before the column
  // sets and spanner placeholders, which means that compesating for a top
  // border+padding that hasn't yet been baked into the offset will produce the
  // wrong results in the first layout pass, and we'd end up performing a wasted
  // layout pass in many cases.
  const LayoutBox& first_column_box =
      *MultiColumnFlowThread()->FirstMultiColumnBox();
  // The top margin edge of the first column set or spanner placeholder is flush
  // with the top content edge of the multicol container. The margin here never
  // collapses with other margins, so we can just subtract it. Column sets never
  // have margins, but spanner placeholders may.
  LayoutUnit first_column_box_margin_edge =
      first_column_box.LogicalTop() -
      MultiColumnBlockFlow()->MarginBeforeForChild(first_column_box);
  return LogicalTop() - first_column_box_margin_edge;
}

LayoutUnit LayoutMultiColumnSet::LogicalTopInFlowThread() const {
  return FirstFragmentainerGroup().LogicalTopInFlowThread();
}

LayoutUnit LayoutMultiColumnSet::LogicalBottomInFlowThread() const {
  return LastFragmentainerGroup().LogicalBottomInFlowThread();
}

bool LayoutMultiColumnSet::HeightIsAuto() const {
  LayoutMultiColumnFlowThread* flow_thread = MultiColumnFlowThread();
  if (!flow_thread->IsLayoutPagedFlowThread()) {
    // If support for the column-fill property isn't enabled, we want to behave
    // as if column-fill were auto, so that multicol containers with specified
    // height don't get their columns balanced (auto-height multicol containers
    // will still get their columns balanced, even if column-fill isn't
    // 'balance' - in accordance with the spec).
    // Pretending that column-fill is auto also matches the old multicol
    // implementation, which has no support for this property.
    if (MultiColumnBlockFlow()->Style()->GetColumnFill() ==
        EColumnFill::kBalance)
      return true;
    if (LayoutBox* next = NextSiblingBox()) {
      if (next->IsLayoutMultiColumnSpannerPlaceholder()) {
        // If we're followed by a spanner, we need to balance.
        return true;
      }
    }
  }
  return !flow_thread->ColumnHeightAvailable();
}

LayoutSize LayoutMultiColumnSet::FlowThreadTranslationAtOffset(
    LayoutUnit block_offset,
    PageBoundaryRule rule,
    CoordinateSpaceConversion mode) const {
  return FragmentainerGroupAtFlowThreadOffset(block_offset, rule)
      .FlowThreadTranslationAtOffset(block_offset, rule, mode);
}

LayoutPoint LayoutMultiColumnSet::VisualPointToFlowThreadPoint(
    const LayoutPoint& visual_point) const {
  const MultiColumnFragmentainerGroup& row =
      FragmentainerGroupAtVisualPoint(visual_point);
  return row.VisualPointToFlowThreadPoint(visual_point -
                                          row.OffsetFromColumnSet());
}

LayoutUnit LayoutMultiColumnSet::PageLogicalTopForOffset(
    LayoutUnit offset) const {
  return FragmentainerGroupAtFlowThreadOffset(offset, kAssociateWithLatterPage)
      .ColumnLogicalTopForOffset(offset);
}

bool LayoutMultiColumnSet::RecalculateColumnHeight() {
  if (old_logical_top_ != LogicalTop() &&
      MultiColumnFlowThread()->EnclosingFragmentationContext()) {
    // Preceding spanners or column sets have been moved or resized. This means
    // that the fragmentainer groups that we have inserted need to be
    // re-inserted. Restart column balancing.
    ResetColumnHeight();
    return true;
  }

  bool changed = false;
  for (auto& group : fragmentainer_groups_)
    changed = group.RecalculateColumnHeight(*this) || changed;
  initial_height_calculated_ = true;
  return changed;
}

void LayoutMultiColumnSet::ResetColumnHeight() {
  fragmentainer_groups_.DeleteExtraGroups();
  fragmentainer_groups_.First().ResetColumnHeight();
  tallest_unbreakable_logical_height_ = LayoutUnit();
  initial_height_calculated_ = false;
}

void LayoutMultiColumnSet::BeginFlow(LayoutUnit offset_in_flow_thread) {
  // At this point layout is exactly at the beginning of this set. Store block
  // offset from flow thread start.
  fragmentainer_groups_.First().SetLogicalTopInFlowThread(
      offset_in_flow_thread);
}

void LayoutMultiColumnSet::EndFlow(LayoutUnit offset_in_flow_thread) {
  // At this point layout is exactly at the end of this set. Store block offset
  // from flow thread start. This set is now considered "flowed", although we
  // may have to revisit it later (with beginFlow()), e.g. if a subtree in the
  // flow thread has to be laid out over again because the initial margin
  // collapsing estimates were wrong.
  fragmentainer_groups_.Last().SetLogicalBottomInFlowThread(
      offset_in_flow_thread);
}

void LayoutMultiColumnSet::StyleDidChange(StyleDifference diff,
                                          const ComputedStyle* old_style) {
  LayoutBlockFlow::StyleDidChange(diff, old_style);

  // column-rule is specified on the parent (the multicol container) of this
  // object, but it's the column sets that are in charge of painting them.
  // A column rule is pretty much like any other box decoration, like borders.
  // We need to say that we have box decorations here, so that the columnn set
  // is invalidated when it gets laid out. We cannot check here whether the
  // multicol container actually has a visible column rule or not, because we
  // may not have been inserted into the tree yet. Painting a column set is
  // cheap anyway, because the only thing it can paint is the column rule, while
  // actual multicol content is handled by the flow thread.
  SetHasBoxDecorationBackground(true);
}

void LayoutMultiColumnSet::UpdateLayout() {
  if (RecalculateColumnHeight())
    MultiColumnFlowThread()->SetColumnHeightsChanged();
  LayoutBlockFlow::UpdateLayout();

  auto actual_column_count = ActualColumnCount();
  if (actual_column_count != last_actual_column_count_) {
    // At least we need to paint column rules differently when actual column
    // count changes.
    SetShouldDoFullPaintInvalidation();
    last_actual_column_count_ = actual_column_count;
  }
}

void LayoutMultiColumnSet::ComputeIntrinsicLogicalWidths(
    LayoutUnit& min_logical_width,
    LayoutUnit& max_logical_width) const {
  min_logical_width = flow_thread_->MinPreferredLogicalWidth();
  max_logical_width = flow_thread_->MaxPreferredLogicalWidth();
}

void LayoutMultiColumnSet::ComputeLogicalHeight(
    LayoutUnit,
    LayoutUnit logical_top,
    LogicalExtentComputedValues& computed_values) const {
  LayoutUnit logical_height;
  // Under some circumstances column heights are unknown at this point. This
  // happens e.g. when this column set got pushed down by a preceding spanner
  // (and when that affects the available space for this column set). Just set
  // the height to 0 for now. Another layout pass has already been scheduled, to
  // calculate the correct height.
  if (IsPageLogicalHeightKnown()) {
    for (const auto& group : fragmentainer_groups_)
      logical_height += group.GroupLogicalHeight();
  }
  computed_values.extent_ = logical_height;
  computed_values.position_ = logical_top;
}

PositionWithAffinity LayoutMultiColumnSet::PositionForPoint(
    const LayoutPoint& point) {
  // Convert the visual point to a flow thread point.
  const MultiColumnFragmentainerGroup& row =
      FragmentainerGroupAtVisualPoint(point);
  LayoutPoint flow_thread_point = row.VisualPointToFlowThreadPoint(
      point + row.OffsetFromColumnSet(),
      MultiColumnFragmentainerGroup::kSnapToColumn);
  // Then drill into the flow thread, where we'll find the actual content.
  return FlowThread()->PositionForPoint(flow_thread_point);
}

LayoutUnit LayoutMultiColumnSet::ColumnGap() const {
  LayoutBlockFlow* parent_block = MultiColumnBlockFlow();

  if (parent_block->Style()->ColumnGap().IsNormal()) {
    // "1em" is recommended as the normal gap setting. Matches <p> margins.
    return LayoutUnit(
        parent_block->Style()->GetFontDescription().ComputedPixelSize());
  }
  return ValueForLength(parent_block->Style()->ColumnGap().GetLength(),
                        AvailableLogicalWidth());
}

unsigned LayoutMultiColumnSet::ActualColumnCount() const {
  // FIXME: remove this method. It's a meaningless question to ask the set "how
  // many columns do you actually have?", since that may vary for each row.
  return FirstFragmentainerGroup().ActualColumnCount();
}

void LayoutMultiColumnSet::PaintObject(const PaintInfo& paint_info,
                                       const LayoutPoint& paint_offset) const {
  MultiColumnSetPainter(*this).PaintObject(paint_info, paint_offset);
}

LayoutRect LayoutMultiColumnSet::FragmentsBoundingBox(
    const LayoutRect& bounding_box_in_flow_thread) const {
  LayoutRect result;
  for (const auto& group : fragmentainer_groups_)
    result.Unite(group.FragmentsBoundingBox(bounding_box_in_flow_thread));
  return result;
}

void LayoutMultiColumnSet::AddOverflowFromChildren() {
  // It's useless to calculate overflow if we haven't determined the page
  // logical height yet.
  if (!IsPageLogicalHeightKnown())
    return;
  LayoutRect overflow_rect;
  for (const auto& group : fragmentainer_groups_) {
    LayoutRect rect = group.CalculateOverflow();
    rect.Move(group.OffsetFromColumnSet());
    overflow_rect.Unite(rect);
  }
  AddLayoutOverflow(overflow_rect);
  AddContentsVisualOverflow(overflow_rect);
}

void LayoutMultiColumnSet::InsertedIntoTree() {
  LayoutBlockFlow::InsertedIntoTree();
  AttachToFlowThread();
}

void LayoutMultiColumnSet::WillBeRemovedFromTree() {
  LayoutBlockFlow::WillBeRemovedFromTree();
  DetachFromFlowThread();
}

void LayoutMultiColumnSet::AttachToFlowThread() {
  if (DocumentBeingDestroyed())
    return;

  if (!flow_thread_)
    return;

  flow_thread_->AddColumnSetToThread(this);
}

void LayoutMultiColumnSet::DetachFromFlowThread() {
  if (flow_thread_) {
    flow_thread_->RemoveColumnSetFromThread(this);
    flow_thread_ = nullptr;
  }
}

LayoutRect LayoutMultiColumnSet::FlowThreadPortionRect() const {
  LayoutRect portion_rect(LayoutUnit(), LogicalTopInFlowThread(),
                          PageLogicalWidth(), LogicalHeightInFlowThread());
  if (!IsHorizontalWritingMode())
    return portion_rect.TransposedRect();
  return portion_rect;
}

bool LayoutMultiColumnSet::ComputeColumnRuleBounds(
    const LayoutPoint& paint_offset,
    Vector<LayoutRect>& column_rule_bounds) const {
  if (FlowThread()->IsLayoutPagedFlowThread())
    return false;

  // Reference: https://www.w3.org/TR/css3-multicol/#column-gaps-and-rules
  const ComputedStyle& block_style = MultiColumnBlockFlow()->StyleRef();
  bool rule_transparent = block_style.ColumnRuleIsTransparent();
  EBorderStyle rule_style = block_style.ColumnRuleStyle();
  LayoutUnit rule_thickness(block_style.ColumnRuleWidth());
  LayoutUnit col_gap = ColumnGap();
  bool render_rule =
      ComputedStyle::BorderStyleIsVisible(rule_style) && !rule_transparent;
  if (!render_rule)
    return false;

  unsigned col_count = ActualColumnCount();
  if (col_count <= 1)
    return false;

  bool left_to_right = Style()->IsLeftToRightDirection();
  LayoutUnit curr_logical_left_offset =
      left_to_right ? LayoutUnit() : ContentLogicalWidth();
  LayoutUnit rule_add = BorderAndPaddingLogicalLeft();
  LayoutUnit rule_logical_left =
      left_to_right ? LayoutUnit() : ContentLogicalWidth();
  LayoutUnit inline_direction_size = PageLogicalWidth();

  for (unsigned i = 0; i < col_count; i++) {
    // Move to the next position.
    if (left_to_right) {
      rule_logical_left += inline_direction_size + col_gap / 2;
      curr_logical_left_offset += inline_direction_size + col_gap;
    } else {
      rule_logical_left -= (inline_direction_size + col_gap / 2);
      curr_logical_left_offset -= (inline_direction_size + col_gap);
    }

    // Now compute the final bounds.
    if (i < col_count - 1) {
      LayoutUnit rule_left, rule_right, rule_top, rule_bottom;
      if (IsHorizontalWritingMode()) {
        rule_left = paint_offset.X() + rule_logical_left - rule_thickness / 2 +
                    rule_add;
        rule_right = rule_left + rule_thickness;
        rule_top = paint_offset.Y() + BorderTop() + PaddingTop();
        rule_bottom = rule_top + ContentHeight();
      } else {
        rule_left = paint_offset.X() + BorderLeft() + PaddingLeft();
        rule_right = rule_left + ContentWidth();
        rule_top = paint_offset.Y() + rule_logical_left - rule_thickness / 2 +
                   rule_add;
        rule_bottom = rule_top + rule_thickness;
      }

      column_rule_bounds.push_back(LayoutRect(
          rule_left, rule_top, rule_right - rule_left, rule_bottom - rule_top));
    }

    rule_logical_left = curr_logical_left_offset;
  }
  return true;
}

LayoutRect LayoutMultiColumnSet::LocalVisualRectIgnoringVisibility() const {
  LayoutRect block_flow_bounds =
      LayoutBlockFlow::LocalVisualRectIgnoringVisibility();

  // Now add in column rule bounds, if present.
  Vector<LayoutRect> column_rule_bounds;
  if (ComputeColumnRuleBounds(LayoutPoint(), column_rule_bounds)) {
    for (auto& bound : column_rule_bounds)
      block_flow_bounds.Unite(bound);
  }
  return block_flow_bounds;
}

void LayoutMultiColumnSet::UpdateFromNG() {
  DCHECK_EQ(fragmentainer_groups_.size(), 1U);
  auto& group = fragmentainer_groups_[0];
  group.UpdateFromNG(LogicalHeight());
  ComputeOverflow(LogicalHeight());
  ClearNeedsLayout();
}

}  // namespace blink
