/*
 * 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 IN..0TERRUPTION) 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/LayoutMultiColumnFlowThread.h"

#include "core/layout/LayoutMultiColumnSet.h"
#include "core/layout/LayoutMultiColumnSpannerPlaceholder.h"
#include "core/layout/LayoutView.h"
#include "core/layout/MultiColumnFragmentainerGroup.h"
#include "core/layout/ViewFragmentationContext.h"

namespace blink {

#if DCHECK_IS_ON()
const LayoutBox* LayoutMultiColumnFlowThread::style_changed_box_;
#endif
bool LayoutMultiColumnFlowThread::could_contain_spanners_;
bool LayoutMultiColumnFlowThread::toggle_spanners_if_needed_;

LayoutMultiColumnFlowThread::LayoutMultiColumnFlowThread()
    : last_set_worked_on_(nullptr),
      column_count_(1),
      column_heights_changed_(false),
      progression_is_inline_(true),
      is_being_evacuated_(false) {
  SetIsInsideFlowThread(true);
}

LayoutMultiColumnFlowThread::~LayoutMultiColumnFlowThread() = default;

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

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

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

static inline bool IsMultiColumnContainer(const LayoutObject& object) {
  if (!object.IsLayoutBlockFlow())
    return false;
  return ToLayoutBlockFlow(object).MultiColumnFlowThread();
}

// Return true if there's nothing that prevents the specified object from being
// in the ancestor chain between some column spanner and its containing multicol
// container. A column spanner needs the multicol container to be its containing
// block, so that the spanner is able to escape the flow thread. (Everything
// contained by the flow thread is split into columns, but this is precisely
// what shouldn't be done to a spanner, since it's supposed to span all
// columns.)
//
// We require that the parent of the spanner participate in the block formatting
// context established by the multicol container (i.e. that there are no BFCs or
// other formatting contexts in-between). We also require that there be no
// transforms, since transforms insist on being in the containing block chain
// for everything inside it, which conflicts with a spanners's need to have the
// multicol container as its direct containing block. We may also not put
// spanners inside objects that don't support fragmentation.
static inline bool CanContainSpannerInParentFragmentationContext(
    const LayoutObject& object) {
  if (!object.IsLayoutBlockFlow())
    return false;
  const LayoutBlockFlow& block_flow = ToLayoutBlockFlow(object);
  return !block_flow.CreatesNewFormattingContext() &&
         !block_flow.HasTransformRelatedProperty() &&
         block_flow.GetPaginationBreakability() != LayoutBox::kForbidBreaks &&
         !IsMultiColumnContainer(block_flow);
}

static inline bool HasAnyColumnSpanners(
    const LayoutMultiColumnFlowThread& flow_thread) {
  LayoutBox* first_box = flow_thread.FirstMultiColumnBox();
  return first_box && (first_box != flow_thread.LastMultiColumnBox() ||
                       first_box->IsLayoutMultiColumnSpannerPlaceholder());
}

// Find the next layout object that has the multicol container in its containing
// block chain, skipping nested multicol containers.
static LayoutObject* NextInPreOrderAfterChildrenSkippingOutOfFlow(
    LayoutMultiColumnFlowThread* flow_thread,
    LayoutObject* descendant) {
  DCHECK(descendant->IsDescendantOf(flow_thread));
  LayoutObject* object = descendant->NextInPreOrderAfterChildren(flow_thread);
  while (object) {
    // Walk through the siblings and find the first one which is either in-flow
    // or has this flow thread as its containing block flow thread.
    if (!object->IsOutOfFlowPositioned())
      break;
    if (object->ContainingBlock()->FlowThreadContainingBlock() == flow_thread) {
      // This out-of-flow object is still part of the flow thread, because its
      // containing block (probably relatively positioned) is part of the flow
      // thread.
      break;
    }
    object = object->NextInPreOrderAfterChildren(flow_thread);
  }
  if (!object)
    return nullptr;
#if DCHECK_IS_ON()
  // Make sure that we didn't stumble into an inner multicol container.
  for (LayoutObject* walker = object->Parent(); walker && walker != flow_thread;
       walker = walker->Parent())
    DCHECK(!IsMultiColumnContainer(*walker));
#endif
  return object;
}

// Find the previous layout object that has the multicol container in its
// containing block chain, skipping nested multicol containers.
static LayoutObject* PreviousInPreOrderSkippingOutOfFlow(
    LayoutMultiColumnFlowThread* flow_thread,
    LayoutObject* descendant) {
  DCHECK(descendant->IsDescendantOf(flow_thread));
  LayoutObject* object = descendant->PreviousInPreOrder(flow_thread);
  while (object && object != flow_thread) {
    if (object->IsColumnSpanAll()) {
      LayoutMultiColumnFlowThread* placeholder_flow_thread =
          ToLayoutBox(object)->SpannerPlaceholder()->FlowThread();
      if (placeholder_flow_thread == flow_thread)
        break;
      // We're inside an inner multicol container. We have no business there.
      // Continue on the outside.
      object = placeholder_flow_thread->Parent();
      DCHECK(object->IsDescendantOf(flow_thread));
      continue;
    }
    if (object->FlowThreadContainingBlock() == flow_thread) {
      LayoutObject* ancestor;
      for (ancestor = object->Parent();; ancestor = ancestor->Parent()) {
        if (ancestor == flow_thread)
          return object;
        if (IsMultiColumnContainer(*ancestor)) {
          // We're inside an inner multicol container. We have no business
          // there.
          break;
        }
      }
      object = ancestor;
      DCHECK(ancestor->IsDescendantOf(flow_thread));
      continue;  // Continue on the outside of the inner flow thread.
    }
    // We're inside something that's out-of-flow. Keep looking upwards and
    // backwards in the tree.
    object = object->PreviousInPreOrder(flow_thread);
  }
  if (!object || object == flow_thread)
    return nullptr;
#if DCHECK_IS_ON()
  // Make sure that we didn't stumble into an inner multicol container.
  for (LayoutObject* walker = object->Parent(); walker && walker != flow_thread;
       walker = walker->Parent())
    DCHECK(!IsMultiColumnContainer(*walker));
#endif
  return object;
}

static LayoutObject* FirstLayoutObjectInSet(
    LayoutMultiColumnSet* multicol_set) {
  LayoutBox* sibling = multicol_set->PreviousSiblingMultiColumnBox();
  if (!sibling)
    return multicol_set->FlowThread()->FirstChild();
  // Adjacent column content sets should not occur. We would have no way of
  // figuring out what each of them contains then.
  DCHECK(sibling->IsLayoutMultiColumnSpannerPlaceholder());
  LayoutBox* spanner = ToLayoutMultiColumnSpannerPlaceholder(sibling)
                           ->LayoutObjectInFlowThread();
  return NextInPreOrderAfterChildrenSkippingOutOfFlow(
      multicol_set->MultiColumnFlowThread(), spanner);
}

static LayoutObject* LastLayoutObjectInSet(LayoutMultiColumnSet* multicol_set) {
  LayoutBox* sibling = multicol_set->NextSiblingMultiColumnBox();
  // By right we should return lastLeafChild() here, but the caller doesn't
  // care, so just return nullptr.
  if (!sibling)
    return nullptr;
  // Adjacent column content sets should not occur. We would have no way of
  // figuring out what each of them contains then.
  DCHECK(sibling->IsLayoutMultiColumnSpannerPlaceholder());
  LayoutBox* spanner = ToLayoutMultiColumnSpannerPlaceholder(sibling)
                           ->LayoutObjectInFlowThread();
  return PreviousInPreOrderSkippingOutOfFlow(
      multicol_set->MultiColumnFlowThread(), spanner);
}

LayoutMultiColumnSet* LayoutMultiColumnFlowThread::MapDescendantToColumnSet(
    LayoutObject* layout_object) const {
  // Should not be used for spanners or content inside them.
  DCHECK(!ContainingColumnSpannerPlaceholder(layout_object));
  DCHECK_NE(layout_object, this);
  DCHECK(layout_object->IsDescendantOf(this));
  // Out-of-flow objects don't belong in column sets.
  DCHECK(layout_object->ContainingBlock()->IsDescendantOf(this));
  DCHECK_EQ(layout_object->FlowThreadContainingBlock(), this);
  DCHECK(!layout_object->IsLayoutMultiColumnSet());
  DCHECK(!layout_object->IsLayoutMultiColumnSpannerPlaceholder());
  LayoutMultiColumnSet* multicol_set = FirstMultiColumnSet();
  if (!multicol_set)
    return nullptr;
  if (!multicol_set->NextSiblingMultiColumnSet())
    return multicol_set;

  // This is potentially SLOW! But luckily very uncommon. You would have to
  // dynamically insert a spanner into the middle of column contents to need
  // this.
  for (; multicol_set;
       multicol_set = multicol_set->NextSiblingMultiColumnSet()) {
    LayoutObject* first_layout_object = FirstLayoutObjectInSet(multicol_set);
    LayoutObject* last_layout_object = LastLayoutObjectInSet(multicol_set);
    DCHECK(first_layout_object);

    for (LayoutObject* walker = first_layout_object; walker;
         walker = walker->NextInPreOrder(this)) {
      if (walker == layout_object)
        return multicol_set;
      if (walker == last_layout_object)
        break;
    }
  }

  return nullptr;
}

LayoutMultiColumnSpannerPlaceholder*
LayoutMultiColumnFlowThread::ContainingColumnSpannerPlaceholder(
    const LayoutObject* descendant) const {
  DCHECK(descendant->IsDescendantOf(this));

  if (!HasAnyColumnSpanners(*this))
    return nullptr;

  // We have spanners. See if the layoutObject in question is one or inside of
  // one then.
  for (const LayoutObject* ancestor = descendant; ancestor && ancestor != this;
       ancestor = ancestor->Parent()) {
    if (LayoutMultiColumnSpannerPlaceholder* placeholder =
            ancestor->SpannerPlaceholder())
      return placeholder;
  }
  return nullptr;
}

void LayoutMultiColumnFlowThread::Populate() {
  LayoutBlockFlow* multicol_container = MultiColumnBlockFlow();
  DCHECK(!NextSibling());
  // Reparent children preceding the flow thread into the flow thread. It's
  // multicol content now. At this point there's obviously nothing after the
  // flow thread, but layoutObjects (column sets and spanners) will be inserted
  // there as we insert elements into the flow thread.
  multicol_container->RemoveFloatingObjectsFromDescendants();
  multicol_container->MoveChildrenTo(this, multicol_container->FirstChild(),
                                     this, true);
}

void LayoutMultiColumnFlowThread::EvacuateAndDestroy() {
  LayoutBlockFlow* multicol_container = MultiColumnBlockFlow();
  is_being_evacuated_ = true;

  // Remove all sets and spanners.
  while (LayoutBox* column_box = FirstMultiColumnBox()) {
    DCHECK(column_box->IsAnonymous());
    column_box->Destroy();
  }

  DCHECK(!PreviousSibling());
  DCHECK(!NextSibling());

  // Finally we can promote all flow thread's children. Before we move them to
  // the flow thread's container, we need to unregister the flow thread, so that
  // they aren't just re-added again to the flow thread that we're trying to
  // empty.
  multicol_container->ResetMultiColumnFlowThread();
  MoveAllChildrenIncludingFloatsTo(multicol_container, true);

  // We used to manually nuke the line box tree here, but that should happen
  // automatically when moving children around (the code above).
  DCHECK(!FirstLineBox());

  Destroy();
}

LayoutUnit LayoutMultiColumnFlowThread::MaxColumnLogicalHeight() const {
  if (column_height_available_) {
    // If height is non-auto, it's already constrained against max-height as
    // well. Just return it.
    return column_height_available_;
  }
  const LayoutBlockFlow* multicol_block = MultiColumnBlockFlow();
  Length logical_max_height = multicol_block->Style()->LogicalMaxHeight();
  if (!logical_max_height.IsMaxSizeNone()) {
    LayoutUnit resolved_logical_max_height =
        multicol_block->ComputeContentLogicalHeight(
            kMaxSize, logical_max_height, LayoutUnit(-1));
    if (resolved_logical_max_height != -1)
      return resolved_logical_max_height;
  }
  return LayoutUnit::Max();
}

LayoutUnit LayoutMultiColumnFlowThread::TallestUnbreakableLogicalHeight(
    LayoutUnit offset_in_flow_thread) const {
  if (LayoutMultiColumnSet* multicol_set = ColumnSetAtBlockOffset(
          offset_in_flow_thread, kAssociateWithLatterPage))
    return multicol_set->TallestUnbreakableLogicalHeight();
  return LayoutUnit();
}

LayoutSize LayoutMultiColumnFlowThread::ColumnOffset(
    const LayoutPoint& point) const {
  return FlowThreadTranslationAtPoint(point,
                                      CoordinateSpaceConversion::kContaining);
}

bool LayoutMultiColumnFlowThread::NeedsNewWidth() const {
  LayoutUnit new_width;
  unsigned dummy_column_count;  // We only care if used column-width changes.
  CalculateColumnCountAndWidth(new_width, dummy_column_count);
  return new_width != LogicalWidth();
}

bool LayoutMultiColumnFlowThread::IsPageLogicalHeightKnown() const {
  return all_columns_have_known_height_;
}

bool LayoutMultiColumnFlowThread::MayHaveNonUniformPageLogicalHeight() const {
  const LayoutMultiColumnSet* column_set = FirstMultiColumnSet();
  if (!column_set)
    return false;
  if (column_set->NextSiblingMultiColumnSet())
    return true;
  return EnclosingFragmentationContext();
}

LayoutSize LayoutMultiColumnFlowThread::FlowThreadTranslationAtOffset(
    LayoutUnit offset_in_flow_thread,
    PageBoundaryRule rule,
    CoordinateSpaceConversion mode) const {
  if (!HasValidColumnSetInfo())
    return LayoutSize(0, 0);
  LayoutMultiColumnSet* column_set =
      ColumnSetAtBlockOffset(offset_in_flow_thread, rule);
  if (!column_set)
    return LayoutSize(0, 0);
  return column_set->FlowThreadTranslationAtOffset(offset_in_flow_thread, rule,
                                                   mode);
}

LayoutSize LayoutMultiColumnFlowThread::FlowThreadTranslationAtPoint(
    const LayoutPoint& flow_thread_point,
    CoordinateSpaceConversion mode) const {
  LayoutPoint flipped_point = FlipForWritingMode(flow_thread_point);
  LayoutUnit block_offset =
      IsHorizontalWritingMode() ? flipped_point.Y() : flipped_point.X();

  // If block direction is flipped, points at a column boundary belong in the
  // former column, not the latter.
  PageBoundaryRule rule = HasFlippedBlocksWritingMode()
                              ? kAssociateWithFormerPage
                              : kAssociateWithLatterPage;

  return FlowThreadTranslationAtOffset(block_offset, rule, mode);
}

LayoutPoint LayoutMultiColumnFlowThread::FlowThreadPointToVisualPoint(
    const LayoutPoint& flow_thread_point) const {
  return flow_thread_point +
         FlowThreadTranslationAtPoint(flow_thread_point,
                                      CoordinateSpaceConversion::kVisual);
}

LayoutPoint LayoutMultiColumnFlowThread::VisualPointToFlowThreadPoint(
    const LayoutPoint& visual_point) const {
  LayoutUnit block_offset =
      IsHorizontalWritingMode() ? visual_point.Y() : visual_point.X();
  const LayoutMultiColumnSet* column_set = nullptr;
  for (const LayoutMultiColumnSet* candidate = FirstMultiColumnSet(); candidate;
       candidate = candidate->NextSiblingMultiColumnSet()) {
    column_set = candidate;
    if (candidate->LogicalBottom() > block_offset)
      break;
  }
  return column_set ? column_set->VisualPointToFlowThreadPoint(ToLayoutPoint(
                          visual_point + Location() - column_set->Location()))
                    : visual_point;
}

LayoutUnit LayoutMultiColumnFlowThread::InlineBlockBaseline(
    LineDirectionMode line_direction) const {
  LayoutUnit baseline_in_flow_thread =
      LayoutFlowThread::InlineBlockBaseline(line_direction);
  LayoutMultiColumnSet* column_set =
      ColumnSetAtBlockOffset(baseline_in_flow_thread, kAssociateWithLatterPage);
  if (!column_set)
    return baseline_in_flow_thread;
  return LayoutUnit(
      (baseline_in_flow_thread -
       column_set->PageLogicalTopForOffset(baseline_in_flow_thread))
          .Ceil());
}

LayoutMultiColumnSet* LayoutMultiColumnFlowThread::ColumnSetAtBlockOffset(
    LayoutUnit offset,
    PageBoundaryRule page_boundary_rule) const {
  LayoutMultiColumnSet* column_set = last_set_worked_on_;
  if (column_set) {
    // Layout in progress. We are calculating the set heights as we speak, so
    // the column set range information is not up to date.
    while (column_set->LogicalTopInFlowThread() > offset) {
      // Sometimes we have to use a previous set. This happens when we're
      // working with a block that contains a spanner (so that there's a column
      // set both before and after the spanner, and both sets contain said
      // block).
      LayoutMultiColumnSet* previous_set =
          column_set->PreviousSiblingMultiColumnSet();
      if (!previous_set)
        break;
      column_set = previous_set;
    }
  } else {
    DCHECK(!column_sets_invalidated_);
    if (multi_column_set_list_.IsEmpty())
      return nullptr;
    if (offset < LayoutUnit()) {
      column_set = multi_column_set_list_.front();
    } else {
      MultiColumnSetSearchAdapter adapter(offset);
      multi_column_set_interval_tree_
          .AllOverlapsWithAdapter<MultiColumnSetSearchAdapter>(adapter);

      // If no set was found, the offset is in the flow thread overflow.
      if (!adapter.Result() && !multi_column_set_list_.IsEmpty())
        column_set = multi_column_set_list_.back();
      else
        column_set = adapter.Result();
    }
  }
  if (page_boundary_rule == kAssociateWithFormerPage && column_set &&
      offset == column_set->LogicalTopInFlowThread()) {
    // The column set that we found starts at the exact same flow thread offset
    // as we specified. Since we are to associate offsets at boundaries with the
    // former fragmentainer, the fragmentainer we're looking for is in the
    // previous column set.
    if (LayoutMultiColumnSet* previous_set =
            column_set->PreviousSiblingMultiColumnSet())
      column_set = previous_set;
  }
  // Avoid returning zero-height column sets, if possible. We found a column set
  // based on a flow thread coordinate. If multiple column sets share that
  // coordinate (because we have zero-height column sets between column
  // spanners, for instance), look for one that has a height.
  for (LayoutMultiColumnSet* walker = column_set; walker;
       walker = walker->NextSiblingMultiColumnSet()) {
    if (!walker->IsPageLogicalHeightKnown())
      continue;
    if (page_boundary_rule == kAssociateWithFormerPage) {
      if (walker->LogicalTopInFlowThread() < offset &&
          walker->LogicalBottomInFlowThread() >= offset)
        return walker;
    }
    if (walker->LogicalTopInFlowThread() <= offset &&
        walker->LogicalBottomInFlowThread() > offset)
      return walker;
    break;
  }
  return column_set;
}

void LayoutMultiColumnFlowThread::LayoutColumns(
    SubtreeLayoutScope& layout_scope) {
  // Since we ended up here, it means that the multicol container (our parent)
  // needed layout. Since contents of the multicol container are diverted to the
  // flow thread, the flow thread needs layout as well.
  layout_scope.SetChildNeedsLayout(this);

  CalculateColumnHeightAvailable();

  if (FragmentationContext* enclosing_fragmentation_context =
          EnclosingFragmentationContext()) {
    block_offset_in_enclosing_fragmentation_context_ =
        MultiColumnBlockFlow()->OffsetFromLogicalTopOfFirstPage();
    block_offset_in_enclosing_fragmentation_context_ +=
        MultiColumnBlockFlow()->BorderAndPaddingBefore();

    if (LayoutMultiColumnFlowThread* enclosing_flow_thread =
            enclosing_fragmentation_context->AssociatedFlowThread()) {
      if (LayoutMultiColumnSet* first_set = FirstMultiColumnSet()) {
        // Before we can start to lay out the contents of this multicol
        // container, we need to make sure that all ancestor multicol containers
        // have established a row to hold the first column contents of this
        // container (this multicol container may start at the beginning of a
        // new outer row). Without sufficient rows in all ancestor multicol
        // containers, we may use the wrong column height.
        LayoutUnit offset = block_offset_in_enclosing_fragmentation_context_ +
                            first_set->LogicalTopFromMulticolContentEdge();
        enclosing_flow_thread->AppendNewFragmentainerGroupIfNeeded(
            offset, kAssociateWithLatterPage);
      }
    }
  }

  // We'll start by assuming that all columns have some known height, and flip
  // it to false if we discover that this isn't the case.
  all_columns_have_known_height_ = true;

  for (LayoutBox* column_box = FirstMultiColumnBox(); column_box;
       column_box = column_box->NextSiblingMultiColumnBox()) {
    if (!column_box->IsLayoutMultiColumnSet()) {
      // No other type is expected.
      DCHECK(column_box->IsLayoutMultiColumnSpannerPlaceholder());
      continue;
    }
    LayoutMultiColumnSet* column_set = ToLayoutMultiColumnSet(column_box);
    layout_scope.SetChildNeedsLayout(column_set);
    if (!column_heights_changed_) {
      // This is the initial layout pass. We need to reset the column height,
      // because contents typically have changed.
      column_set->ResetColumnHeight();
    }
    if (all_columns_have_known_height_ &&
        !column_set->IsPageLogicalHeightKnown()) {
      // If any of the column sets requires a layout pass before it has any
      // clue about its height, we cannot fragment in this pass, just measure
      // the block sizes.
      all_columns_have_known_height_ = false;
    }
    // Since column sets are regular block flow objects, and their position is
    // changed in regular block layout code (with no means for the multicol code
    // to notice unless we add hooks there), store the previous position now. If
    // it changes in the imminent layout pass, we may have to rebalance its
    // columns.
    column_set->StoreOldPosition();
  }

  column_heights_changed_ = false;
  InvalidateColumnSets();
  UpdateLayout();
  ValidateColumnSets();
}

void LayoutMultiColumnFlowThread::ColumnRuleStyleDidChange() {
  for (LayoutMultiColumnSet* column_set = FirstMultiColumnSet(); column_set;
       column_set = column_set->NextSiblingMultiColumnSet()) {
    column_set->SetShouldDoFullPaintInvalidation(
        PaintInvalidationReason::kStyle);
  }
}

bool LayoutMultiColumnFlowThread::RemoveSpannerPlaceholderIfNoLongerValid(
    LayoutBox* spanner_object_in_flow_thread) {
  DCHECK(spanner_object_in_flow_thread->SpannerPlaceholder());
  if (DescendantIsValidColumnSpanner(spanner_object_in_flow_thread))
    return false;  // Still a valid spanner.

  // No longer a valid spanner. Get rid of the placeholder.
  DestroySpannerPlaceholder(
      spanner_object_in_flow_thread->SpannerPlaceholder());
  DCHECK(!spanner_object_in_flow_thread->SpannerPlaceholder());

  // We may have a new containing block, since we're no longer a spanner. Mark
  // it for relayout.
  spanner_object_in_flow_thread->ContainingBlock()
      ->SetNeedsLayoutAndPrefWidthsRecalc(
          LayoutInvalidationReason::kColumnsChanged);

  // Now generate a column set for this ex-spanner, if needed and none is there
  // for us already.
  FlowThreadDescendantWasInserted(spanner_object_in_flow_thread);

  return true;
}

LayoutMultiColumnFlowThread* LayoutMultiColumnFlowThread::EnclosingFlowThread(
    AncestorSearchConstraint constraint) const {
  if (IsLayoutPagedFlowThread()) {
    // Paged overflow containers should never be fragmented by enclosing
    // fragmentation contexts. They are to be treated as unbreakable content.
    return nullptr;
  }
  if (!MultiColumnBlockFlow()->IsInsideFlowThread())
    return nullptr;
  return ToLayoutMultiColumnFlowThread(
      LocateFlowThreadContainingBlockOf(*MultiColumnBlockFlow(), constraint));
}

FragmentationContext*
LayoutMultiColumnFlowThread::EnclosingFragmentationContext(
    AncestorSearchConstraint constraint) const {
  // If this multicol container is strictly unbreakable (due to having
  // scrollbars, for instance), it's also strictly unbreakable in any outer
  // fragmentation context. As such, what kind of fragmentation that goes on
  // inside this multicol container is completely opaque to the ancestors.
  if (constraint == kIsolateUnbreakableContainers &&
      MultiColumnBlockFlow()->GetPaginationBreakability() == kForbidBreaks)
    return nullptr;
  if (auto* enclosing_flow_thread = EnclosingFlowThread(constraint))
    return enclosing_flow_thread;
  return View()->FragmentationContext();
}

void LayoutMultiColumnFlowThread::AppendNewFragmentainerGroupIfNeeded(
    LayoutUnit offset_in_flow_thread,
    PageBoundaryRule page_boundary_rule) {
  LayoutMultiColumnSet* column_set =
      ColumnSetAtBlockOffset(offset_in_flow_thread, page_boundary_rule);
  if (!column_set->NewFragmentainerGroupsAllowed())
    return;

  if (column_set->NeedsNewFragmentainerGroupAt(offset_in_flow_thread,
                                               page_boundary_rule)) {
    // We should never create additional fragmentainer groups unless we're in a
    // nested fragmentation context.
    DCHECK(EnclosingFragmentationContext());

    DCHECK(!IsLayoutPagedFlowThread());

    // We have run out of columns here, so we need to add at least one more row
    // to hold more columns.
    LayoutMultiColumnFlowThread* enclosing_flow_thread =
        EnclosingFragmentationContext()->AssociatedFlowThread();
    do {
      if (enclosing_flow_thread) {
        // When we add a new row here, it implicitly means that we're inserting
        // another column in our enclosing multicol container. That in turn may
        // mean that we've run out of columns there too. Need to insert
        // additional rows in ancestral multicol containers before doing it in
        // the descendants, in order to get the height constraints right down
        // there.
        const MultiColumnFragmentainerGroup& last_row =
            column_set->LastFragmentainerGroup();
        // The top offset where where the new fragmentainer group will start in
        // this column set, converted to the coordinate space of the enclosing
        // multicol container.
        LayoutUnit logical_offset_in_outer =
            last_row.BlockOffsetInEnclosingFragmentationContext() +
            last_row.GroupLogicalHeight();
        enclosing_flow_thread->AppendNewFragmentainerGroupIfNeeded(
            logical_offset_in_outer, kAssociateWithLatterPage);
      }

      column_set->AppendNewFragmentainerGroup();
    } while (column_set->NeedsNewFragmentainerGroupAt(offset_in_flow_thread,
                                                      page_boundary_rule));
  }
}

bool LayoutMultiColumnFlowThread::IsFragmentainerLogicalHeightKnown() {
  return IsPageLogicalHeightKnown();
}

LayoutUnit LayoutMultiColumnFlowThread::FragmentainerLogicalHeightAt(
    LayoutUnit block_offset) {
  DCHECK(IsPageLogicalHeightKnown());
  return PageLogicalHeightForOffset(block_offset);
}

LayoutUnit LayoutMultiColumnFlowThread::RemainingLogicalHeightAt(
    LayoutUnit block_offset) {
  DCHECK(IsPageLogicalHeightKnown());
  return PageRemainingLogicalHeightForOffset(block_offset,
                                             kAssociateWithLatterPage);
}

void LayoutMultiColumnFlowThread::CalculateColumnHeightAvailable() {
  // Calculate the non-auto content box height, or set it to 0 if it's auto. We
  // need to know this before layout, so that we can figure out where to insert
  // column breaks. We also treat LayoutView (which may be paginated, which uses
  // the multicol implementation) as having a fixed height, since its height is
  // deduced from the viewport height. We use computeLogicalHeight() to
  // calculate the content box height. That method will clamp against max-height
  // and min-height. Since we're now at the beginning of layout, and we don't
  // know the actual height of the content yet, only call that method when
  // height is definite, or we might fool ourselves into believing that columns
  // have a definite height when they in fact don't.
  LayoutBlockFlow* container = MultiColumnBlockFlow();
  LayoutUnit column_height;
  if (container->HasDefiniteLogicalHeight() || container->IsLayoutView()) {
    LogicalExtentComputedValues computed_values;
    container->ComputeLogicalHeight(LayoutUnit(), container->LogicalTop(),
                                    computed_values);
    column_height = computed_values.extent_ -
                    container->BorderAndPaddingLogicalHeight() -
                    container->ScrollbarLogicalHeight();
  }
  SetColumnHeightAvailable(std::max(column_height, LayoutUnit()));
}

void LayoutMultiColumnFlowThread::CalculateColumnCountAndWidth(
    LayoutUnit& width,
    unsigned& count) const {
  LayoutBlock* column_block = MultiColumnBlockFlow();
  const ComputedStyle* column_style = column_block->Style();
  LayoutUnit available_width = column_block->ContentLogicalWidth();
  LayoutUnit column_gap = ColumnGap(*column_style, available_width);
  LayoutUnit computed_column_width =
      max(LayoutUnit(1), LayoutUnit(column_style->ColumnWidth()));
  unsigned computed_column_count = max<int>(1, column_style->ColumnCount());

  DCHECK(!column_style->HasAutoColumnCount() ||
         !column_style->HasAutoColumnWidth());
  if (column_style->HasAutoColumnWidth() &&
      !column_style->HasAutoColumnCount()) {
    count = computed_column_count;
    width = ((available_width - ((count - 1) * column_gap)) / count)
                .ClampNegativeToZero();
  } else if (!column_style->HasAutoColumnWidth() &&
             column_style->HasAutoColumnCount()) {
    count = std::max(LayoutUnit(1), (available_width + column_gap) /
                                        (computed_column_width + column_gap))
                .ToUnsigned();
    width = ((available_width + column_gap) / count) - column_gap;
  } else {
    count = std::max(std::min(LayoutUnit(computed_column_count),
                              (available_width + column_gap) /
                                  (computed_column_width + column_gap)),
                     LayoutUnit(1))
                .ToUnsigned();
    width = ((available_width + column_gap) / count) - column_gap;
  }
}

LayoutUnit LayoutMultiColumnFlowThread::ColumnGap(const ComputedStyle& style,
                                                  LayoutUnit available_width) {
  if (style.ColumnGap().IsNormal()) {
    // "1em" is recommended as the normal gap setting. Matches <p> margins.
    return LayoutUnit(style.GetFontDescription().ComputedSize());
  }
  return ValueForLength(style.ColumnGap().GetLength(), available_width);
}

void LayoutMultiColumnFlowThread::CreateAndInsertMultiColumnSet(
    LayoutBox* insert_before) {
  LayoutBlockFlow* multicol_container = MultiColumnBlockFlow();
  LayoutMultiColumnSet* new_set = LayoutMultiColumnSet::CreateAnonymous(
      *this, multicol_container->StyleRef());
  multicol_container->LayoutBlock::AddChild(new_set, insert_before);
  InvalidateColumnSets();

  // We cannot handle immediate column set siblings (and there's no need for it,
  // either). There has to be at least one spanner separating them.
  DCHECK(!new_set->PreviousSiblingMultiColumnBox() ||
         !new_set->PreviousSiblingMultiColumnBox()->IsLayoutMultiColumnSet());
  DCHECK(!new_set->NextSiblingMultiColumnBox() ||
         !new_set->NextSiblingMultiColumnBox()->IsLayoutMultiColumnSet());
}

void LayoutMultiColumnFlowThread::CreateAndInsertSpannerPlaceholder(
    LayoutBox* spanner_object_in_flow_thread,
    LayoutObject* inserted_before_in_flow_thread) {
  LayoutBox* insert_before_column_box = nullptr;
  LayoutMultiColumnSet* set_to_split = nullptr;
  if (inserted_before_in_flow_thread) {
    // The spanner is inserted before something. Figure out what this entails.
    // If the next object is a spanner too, it means that we can simply insert a
    // new spanner placeholder in front of its placeholder.
    insert_before_column_box =
        inserted_before_in_flow_thread->SpannerPlaceholder();
    if (!insert_before_column_box) {
      // The next object isn't a spanner; it's regular column content. Examine
      // what comes right before us in the flow thread, then.
      LayoutObject* previous_layout_object =
          PreviousInPreOrderSkippingOutOfFlow(this,
                                              spanner_object_in_flow_thread);
      if (!previous_layout_object || previous_layout_object == this) {
        // The spanner is inserted as the first child of the multicol container,
        // which means that we simply insert a new spanner placeholder at the
        // beginning.
        insert_before_column_box = FirstMultiColumnBox();
      } else if (LayoutMultiColumnSpannerPlaceholder* previous_placeholder =
                     ContainingColumnSpannerPlaceholder(
                         previous_layout_object)) {
        // Before us is another spanner. We belong right after it then.
        insert_before_column_box =
            previous_placeholder->NextSiblingMultiColumnBox();
      } else {
        // We're inside regular column content with both feet. Find out which
        // column set this is. It needs to be split it into two sets, so that we
        // can insert a new spanner placeholder between them.
        set_to_split = MapDescendantToColumnSet(previous_layout_object);
        DCHECK_EQ(set_to_split,
                  MapDescendantToColumnSet(inserted_before_in_flow_thread));
        insert_before_column_box = set_to_split->NextSiblingMultiColumnBox();
        // We've found out which set that needs to be split. Now proceed to
        // inserting the spanner placeholder, and then insert a second column
        // set.
      }
    }
    DCHECK(set_to_split || insert_before_column_box);
  }

  LayoutBlockFlow* multicol_container = MultiColumnBlockFlow();
  LayoutMultiColumnSpannerPlaceholder* new_placeholder =
      LayoutMultiColumnSpannerPlaceholder::CreateAnonymous(
          multicol_container->StyleRef(), *spanner_object_in_flow_thread);
  DCHECK(!insert_before_column_box ||
         insert_before_column_box->Parent() == multicol_container);
  multicol_container->LayoutBlock::AddChild(new_placeholder,
                                            insert_before_column_box);
  spanner_object_in_flow_thread->SetSpannerPlaceholder(*new_placeholder);

  if (set_to_split)
    CreateAndInsertMultiColumnSet(insert_before_column_box);
}

void LayoutMultiColumnFlowThread::DestroySpannerPlaceholder(
    LayoutMultiColumnSpannerPlaceholder* placeholder) {
  if (LayoutBox* next_column_box = placeholder->NextSiblingMultiColumnBox()) {
    LayoutBox* previous_column_box =
        placeholder->PreviousSiblingMultiColumnBox();
    if (next_column_box && next_column_box->IsLayoutMultiColumnSet() &&
        previous_column_box && previous_column_box->IsLayoutMultiColumnSet()) {
      // Need to merge two column sets.
      next_column_box->Destroy();
      InvalidateColumnSets();
    }
  }
  placeholder->Destroy();
}

bool LayoutMultiColumnFlowThread::DescendantIsValidColumnSpanner(
    LayoutObject* descendant) const {
  // This method needs to behave correctly in the following situations:
  // - When the descendant doesn't have a spanner placeholder but should have
  //   one (return true).
  // - When the descendant doesn't have a spanner placeholder and still should
  //   not have one (return false).
  // - When the descendant has a spanner placeholder but should no longer have
  //   one (return false).
  // - When the descendant has a spanner placeholder and should still have one
  //   (return true).

  // We assume that we're inside the flow thread. This function is not to be
  // called otherwise.
  DCHECK(descendant->IsDescendantOf(this));

  // The spec says that column-span only applies to in-flow block-level
  // elements.
  if (descendant->Style()->GetColumnSpan() != EColumnSpan::kAll ||
      !descendant->IsBox() || descendant->IsInline() ||
      descendant->IsFloatingOrOutOfFlowPositioned())
    return false;

  if (!descendant->ContainingBlock()->IsLayoutBlockFlow()) {
    // Needs to be in a block-flow container, and not e.g. a table.
    return false;
  }

  // This looks like a spanner, but if we're inside something unbreakable or
  // something that establishes a new formatting context, it's not to be treated
  // as one.
  for (LayoutBox* ancestor = ToLayoutBox(descendant)->ParentBox(); ancestor;
       ancestor = ancestor->ContainingBlock()) {
    if (ancestor->IsLayoutFlowThread()) {
      DCHECK_EQ(ancestor, this);
      return true;
    }
    if (!CanContainSpannerInParentFragmentationContext(*ancestor))
      return false;
  }
  NOTREACHED();
  return false;
}

void LayoutMultiColumnFlowThread::AddColumnSetToThread(
    LayoutMultiColumnSet* column_set) {
  if (LayoutMultiColumnSet* next_set =
          column_set->NextSiblingMultiColumnSet()) {
    LayoutMultiColumnSetList::iterator it =
        multi_column_set_list_.find(next_set);
    DCHECK(it != multi_column_set_list_.end());
    multi_column_set_list_.InsertBefore(it, column_set);
  } else {
    multi_column_set_list_.insert(column_set);
  }
}

void LayoutMultiColumnFlowThread::WillBeRemovedFromTree() {
  // Detach all column sets from the flow thread. Cannot destroy them at this
  // point, since they are siblings of this object, and there may be pointers to
  // this object's sibling somewhere further up on the call stack.
  for (LayoutMultiColumnSet* column_set = FirstMultiColumnSet(); column_set;
       column_set = column_set->NextSiblingMultiColumnSet())
    column_set->DetachFromFlowThread();
  MultiColumnBlockFlow()->ResetMultiColumnFlowThread();
  LayoutFlowThread::WillBeRemovedFromTree();
}

void LayoutMultiColumnFlowThread::SkipColumnSpanner(
    LayoutBox* layout_object,
    LayoutUnit logical_top_in_flow_thread) {
  DCHECK(layout_object->IsColumnSpanAll());
  LayoutMultiColumnSpannerPlaceholder* placeholder =
      layout_object->SpannerPlaceholder();
  LayoutBox* previous_column_box = placeholder->PreviousSiblingMultiColumnBox();
  if (previous_column_box && previous_column_box->IsLayoutMultiColumnSet())
    ToLayoutMultiColumnSet(previous_column_box)
        ->EndFlow(logical_top_in_flow_thread);
  LayoutBox* next_column_box = placeholder->NextSiblingMultiColumnBox();
  if (next_column_box && next_column_box->IsLayoutMultiColumnSet()) {
    LayoutMultiColumnSet* next_set = ToLayoutMultiColumnSet(next_column_box);
    last_set_worked_on_ = next_set;
    next_set->BeginFlow(logical_top_in_flow_thread);
  }

  // We'll lay out of spanners after flow thread layout has finished (during
  // layout of the spanner placeholders). There may be containing blocks for
  // out-of-flow positioned descendants of the spanner in the flow thread, so
  // that out-of-flow objects inside the spanner will be laid out as part of
  // flow thread layout (even if the spanner itself won't). We need to add such
  // out-of-flow positioned objects to their containing blocks now, or they'll
  // never get laid out. Since it's non-trivial to determine if we need this,
  // and where such out-of-flow objects might be, just go through the whole
  // subtree.
  for (LayoutObject* descendant = layout_object->SlowFirstChild(); descendant;
       descendant = descendant->NextInPreOrder()) {
    if (descendant->IsBox() && descendant->IsOutOfFlowPositioned())
      descendant->ContainingBlock()->InsertPositionedObject(
          ToLayoutBox(descendant));
  }
}

bool LayoutMultiColumnFlowThread::FinishLayout() {
  all_columns_have_known_height_ = true;
  for (const auto* column_set = FirstMultiColumnSet(); column_set;
       column_set = column_set->NextSiblingMultiColumnSet()) {
    if (!column_set->IsPageLogicalHeightKnown()) {
      all_columns_have_known_height_ = false;
      break;
    }
  }
  return !ColumnHeightsChanged();
}

// When processing layout objects to remove or when processing layout objects
// that have just been inserted, certain types of objects should be skipped.
static bool ShouldSkipInsertedOrRemovedChild(
    LayoutMultiColumnFlowThread* flow_thread,
    const LayoutObject& child) {
  if (child.IsSVGChild()) {
    // Don't descend into SVG objects. What's in there is of no interest, and
    // there might even be a foreignObject there with column-span:all, which
    // doesn't apply to us.
    return true;
  }
  if (child.IsLayoutFlowThread()) {
    // Found an inner flow thread. We need to skip it and its descendants.
    return true;
  }
  if (child.IsLayoutMultiColumnSet() ||
      child.IsLayoutMultiColumnSpannerPlaceholder()) {
    // Column sets and spanner placeholders in a child multicol context don't
    // affect the parent flow thread.
    return true;
  }
  if (child.IsOutOfFlowPositioned() &&
      child.ContainingBlock()->FlowThreadContainingBlock() != flow_thread) {
    // Out-of-flow with its containing block on the outside of the multicol
    // container.
    return true;
  }
  return false;
}

void LayoutMultiColumnFlowThread::FlowThreadDescendantWasInserted(
    LayoutObject* descendant) {
  DCHECK(!is_being_evacuated_);
  // This method ensures that the list of column sets and spanner placeholders
  // reflects the multicol content after having inserted a descendant (or
  // descendant subtree). See the header file for more information. Go through
  // the subtree that was just inserted and create column sets (needed by
  // regular column content) and spanner placeholders (one needed by each
  // spanner) where needed.
  if (ShouldSkipInsertedOrRemovedChild(this, *descendant))
    return;
  LayoutObject* object_after_subtree =
      NextInPreOrderAfterChildrenSkippingOutOfFlow(this, descendant);
  LayoutObject* next;
  for (LayoutObject* layout_object = descendant; layout_object;
       layout_object = next) {
    if (layout_object != descendant &&
        ShouldSkipInsertedOrRemovedChild(this, *layout_object)) {
      next = layout_object->NextInPreOrderAfterChildren(descendant);
      continue;
    }
    next = layout_object->NextInPreOrder(descendant);
    if (ContainingColumnSpannerPlaceholder(layout_object))
      continue;  // Inside a column spanner. Nothing to do, then.
    if (DescendantIsValidColumnSpanner(layout_object)) {
      // This layoutObject is a spanner, so it needs to establish a spanner
      // placeholder.
      CreateAndInsertSpannerPlaceholder(ToLayoutBox(layout_object),
                                        object_after_subtree);
      continue;
    }
    // This layoutObject is regular column content (i.e. not a spanner). Create
    // a set if necessary.
    if (object_after_subtree) {
      if (LayoutMultiColumnSpannerPlaceholder* placeholder =
              object_after_subtree->SpannerPlaceholder()) {
        // If inserted right before a spanner, we need to make sure that there's
        // a set for us there.
        LayoutBox* previous = placeholder->PreviousSiblingMultiColumnBox();
        if (!previous || !previous->IsLayoutMultiColumnSet())
          CreateAndInsertMultiColumnSet(placeholder);
      } else {
        // Otherwise, since |objectAfterSubtree| isn't a spanner, it has to mean
        // that there's already a set for that content. We can use it for this
        // layoutObject too.
        DCHECK(MapDescendantToColumnSet(object_after_subtree));
        DCHECK_EQ(MapDescendantToColumnSet(layout_object),
                  MapDescendantToColumnSet(object_after_subtree));
      }
    } else {
      // Inserting at the end. Then we just need to make sure that there's a
      // column set at the end.
      LayoutBox* last_column_box = LastMultiColumnBox();
      if (!last_column_box || !last_column_box->IsLayoutMultiColumnSet())
        CreateAndInsertMultiColumnSet();
    }
  }
}

void LayoutMultiColumnFlowThread::FlowThreadDescendantWillBeRemoved(
    LayoutObject* descendant) {
  // This method ensures that the list of column sets and spanner placeholders
  // reflects the multicol content that we'll be left with after removal of a
  // descendant (or descendant subtree). See the header file for more
  // information. Removing content may mean that we need to remove column sets
  // and/or spanner placeholders.
  if (is_being_evacuated_)
    return;
  if (ShouldSkipInsertedOrRemovedChild(this, *descendant))
    return;
  bool had_containing_placeholder =
      ContainingColumnSpannerPlaceholder(descendant);
  bool processed_something = false;
  LayoutObject* next;
  // Remove spanner placeholders that are no longer needed, and merge column
  // sets around them.
  for (LayoutObject* layout_object = descendant; layout_object;
       layout_object = next) {
    if (layout_object != descendant &&
        ShouldSkipInsertedOrRemovedChild(this, *layout_object)) {
      next = layout_object->NextInPreOrderAfterChildren(descendant);
      continue;
    }
    processed_something = true;
    LayoutMultiColumnSpannerPlaceholder* placeholder =
        layout_object->SpannerPlaceholder();
    if (!placeholder) {
      next = layout_object->NextInPreOrder(descendant);
      continue;
    }
    next = layout_object->NextInPreOrderAfterChildren(
        descendant);  // It's a spanner. Its children are of no interest to us.
    DestroySpannerPlaceholder(placeholder);
  }
  if (had_containing_placeholder || !processed_something)
    return;  // No column content will be removed, so we can stop here.

  // Column content will be removed. Does this mean that we should destroy a
  // column set?
  LayoutMultiColumnSpannerPlaceholder* adjacent_previous_spanner_placeholder =
      nullptr;
  LayoutObject* previous_layout_object =
      PreviousInPreOrderSkippingOutOfFlow(this, descendant);
  if (previous_layout_object && previous_layout_object != this) {
    adjacent_previous_spanner_placeholder =
        ContainingColumnSpannerPlaceholder(previous_layout_object);
    if (!adjacent_previous_spanner_placeholder)
      return;  // Preceded by column content. Set still needed.
  }
  LayoutMultiColumnSpannerPlaceholder* adjacent_next_spanner_placeholder =
      nullptr;
  LayoutObject* next_layout_object =
      NextInPreOrderAfterChildrenSkippingOutOfFlow(this, descendant);
  if (next_layout_object) {
    adjacent_next_spanner_placeholder =
        ContainingColumnSpannerPlaceholder(next_layout_object);
    if (!adjacent_next_spanner_placeholder)
      return;  // Followed by column content. Set still needed.
  }
  // We have now determined that, with the removal of |descendant|, we should
  // remove a column set. Locate it and remove it. Do it without involving
  // mapDescendantToColumnSet(), as that might be very slow. Deduce the right
  // set from the spanner placeholders that we've already found.
  LayoutMultiColumnSet* column_set_to_remove;
  if (adjacent_next_spanner_placeholder) {
    column_set_to_remove = ToLayoutMultiColumnSet(
        adjacent_next_spanner_placeholder->PreviousSiblingMultiColumnBox());
    DCHECK(
        !adjacent_previous_spanner_placeholder ||
        column_set_to_remove ==
            adjacent_previous_spanner_placeholder->NextSiblingMultiColumnBox());
  } else if (adjacent_previous_spanner_placeholder) {
    column_set_to_remove = ToLayoutMultiColumnSet(
        adjacent_previous_spanner_placeholder->NextSiblingMultiColumnBox());
  } else {
    // If there were no adjacent spanners, it has to mean that there's only one
    // column set, since it's only spanners that may cause creation of
    // multiple sets.
    column_set_to_remove = FirstMultiColumnSet();
    DCHECK(column_set_to_remove);
    DCHECK(!column_set_to_remove->NextSiblingMultiColumnSet());
  }
  DCHECK(column_set_to_remove);
  column_set_to_remove->Destroy();
}

static inline bool NeedsToReinsertIntoFlowThread(
    const ComputedStyle& old_style,
    const ComputedStyle& new_style) {
  // If we've become (or are about to become) a container for absolutely
  // positioned descendants, or if we're no longer going to be one, we need to
  // re-evaluate the need for column sets. There may be out-of-flow descendants
  // further down that become part of the flow thread, or cease to be part of
  // the flow thread, because of this change.
  if (old_style.HasTransformRelatedProperty() !=
      new_style.HasTransformRelatedProperty())
    return true;
  return (old_style.HasInFlowPosition() &&
          new_style.GetPosition() == EPosition::kStatic) ||
         (new_style.HasInFlowPosition() &&
          old_style.GetPosition() == EPosition::kStatic);
}

static inline bool NeedsToRemoveFromFlowThread(const ComputedStyle& old_style,
                                               const ComputedStyle& new_style) {
  // If an in-flow descendant goes out-of-flow, we may have to remove column
  // sets and spanner placeholders.
  return (new_style.HasOutOfFlowPosition() &&
          !old_style.HasOutOfFlowPosition()) ||
         NeedsToReinsertIntoFlowThread(old_style, new_style);
}

static inline bool NeedsToInsertIntoFlowThread(const ComputedStyle& old_style,
                                               const ComputedStyle& new_style) {
  // If an out-of-flow descendant goes in-flow, we may have to insert column
  // sets and spanner placeholders.
  return (!new_style.HasOutOfFlowPosition() &&
          old_style.HasOutOfFlowPosition()) ||
         NeedsToReinsertIntoFlowThread(old_style, new_style);
}

void LayoutMultiColumnFlowThread::FlowThreadDescendantStyleWillChange(
    LayoutBox* descendant,
    StyleDifference diff,
    const ComputedStyle& new_style) {
  toggle_spanners_if_needed_ = false;
  if (NeedsToRemoveFromFlowThread(descendant->StyleRef(), new_style)) {
    FlowThreadDescendantWillBeRemoved(descendant);
    return;
  }
#if DCHECK_IS_ON()
  style_changed_box_ = descendant;
#endif
  // Keep track of whether this object was of such a type that it could contain
  // column-span:all descendants. If the style change in progress changes this
  // state, we need to look for spanners to add or remove in the subtree of
  // |descendant|.
  toggle_spanners_if_needed_ = true;
  could_contain_spanners_ =
      CanContainSpannerInParentFragmentationContext(*descendant);
}

void LayoutMultiColumnFlowThread::FlowThreadDescendantStyleDidChange(
    LayoutBox* descendant,
    StyleDifference diff,
    const ComputedStyle& old_style) {
  bool toggle_spanners_if_needed = toggle_spanners_if_needed_;
  toggle_spanners_if_needed_ = false;

  if (NeedsToInsertIntoFlowThread(old_style, descendant->StyleRef())) {
    FlowThreadDescendantWasInserted(descendant);
    return;
  }
  if (DescendantIsValidColumnSpanner(descendant)) {
    // We went from being regular column content to becoming a spanner.
    DCHECK(!descendant->SpannerPlaceholder());

    // First remove this as regular column content. Note that this will walk the
    // entire subtree of |descendant|. There might be spanners there (which
    // won't be spanners anymore, since we're not allowed to nest spanners),
    // whose placeholders must die.
    FlowThreadDescendantWillBeRemoved(descendant);

    CreateAndInsertSpannerPlaceholder(
        descendant,
        NextInPreOrderAfterChildrenSkippingOutOfFlow(this, descendant));
    return;
  }

  if (!toggle_spanners_if_needed)
    return;
#if DCHECK_IS_ON()
  // Make sure that we were preceded by a call to
  // flowThreadDescendantStyleWillChange() with the same descendant as we have
  // now.
  DCHECK_EQ(style_changed_box_, descendant);
#endif

  if (could_contain_spanners_ !=
      CanContainSpannerInParentFragmentationContext(*descendant))
    ToggleSpannersInSubtree(descendant);
}

void LayoutMultiColumnFlowThread::ToggleSpannersInSubtree(
    LayoutBox* descendant) {
  DCHECK_NE(could_contain_spanners_,
            CanContainSpannerInParentFragmentationContext(*descendant));

  // If there are no spanners at all in this multicol container, there's no
  // need to look for any to remove.
  if (could_contain_spanners_ && !HasAnyColumnSpanners(*this))
    return;

  bool walk_children;
  for (LayoutObject* object = descendant->NextInPreOrder(descendant); object;
       object = walk_children
                    ? object->NextInPreOrder(descendant)
                    : object->NextInPreOrderAfterChildren(descendant)) {
    walk_children = false;
    if (!object->IsBox())
      continue;
    LayoutBox& box = ToLayoutBox(*object);
    if (could_contain_spanners_) {
      // Remove all spanners (turn them into regular column content), as we can
      // no longer contain them.
      if (box.IsColumnSpanAll()) {
        DestroySpannerPlaceholder(box.SpannerPlaceholder());
        continue;
      }
    } else if (DescendantIsValidColumnSpanner(object)) {
      // We can now contain spanners, and we found a candidate. Turn it into a
      // spanner, if it's not already one. We have to check if it's already a
      // spanner, because in some cases we incorrectly think that we need to
      // toggle spanners. One known case is when some ancestor changes
      // writing-mode (which is an inherited property). Writing mode roots
      // establish block formatting context (which means that there can be no
      // column spanners inside). When changing the style on one object in the
      // tree at a time, we're going to see writing mode roots that are not
      // going to remain writing mode roots when all objects have been updated
      // (because then all will have got the same writing mode).
      if (!box.IsColumnSpanAll()) {
        CreateAndInsertSpannerPlaceholder(
            &box, NextInPreOrderAfterChildrenSkippingOutOfFlow(this, &box));
      }
      continue;
    }
    walk_children = CanContainSpannerInParentFragmentationContext(box);
  }
}

void LayoutMultiColumnFlowThread::ComputePreferredLogicalWidths() {
  LayoutFlowThread::ComputePreferredLogicalWidths();

  // The min/max intrinsic widths calculated really tell how much space elements
  // need when laid out inside the columns. In order to eventually end up with
  // the desired column width, we need to convert them to values pertaining to
  // the multicol container.
  const ComputedStyle* multicol_style = MultiColumnBlockFlow()->Style();
  LayoutUnit column_count(
      multicol_style->HasAutoColumnCount() ? 1 : multicol_style->ColumnCount());
  LayoutUnit column_width;
  LayoutUnit gap_extra((column_count - 1) *
                       ColumnGap(*multicol_style, LayoutUnit()));
  if (multicol_style->HasAutoColumnWidth()) {
    min_preferred_logical_width_ =
        min_preferred_logical_width_ * column_count + gap_extra;
  } else {
    column_width = LayoutUnit(multicol_style->ColumnWidth());
    min_preferred_logical_width_ =
        std::min(min_preferred_logical_width_, column_width);
  }
  // Note that if column-count is auto here, we should resolve it to calculate
  // the maximum intrinsic width, instead of pretending that it's 1. The only
  // way to do that is by performing a layout pass, but this is not an
  // appropriate time or place for layout. The good news is that if height is
  // unconstrained and there are no explicit breaks, the resolved column-count
  // really should be 1.
  max_preferred_logical_width_ =
      std::max(max_preferred_logical_width_, column_width) * column_count +
      gap_extra;
}

void LayoutMultiColumnFlowThread::ComputeLogicalHeight(
    LayoutUnit logical_height,
    LayoutUnit logical_top,
    LogicalExtentComputedValues& computed_values) const {
  // We simply remain at our intrinsic height.
  computed_values.extent_ = logical_height;
  computed_values.position_ = logical_top;
}

void LayoutMultiColumnFlowThread::UpdateLogicalWidth() {
  LayoutUnit column_width;
  CalculateColumnCountAndWidth(column_width, column_count_);
  SetLogicalWidth(column_width);
}

void LayoutMultiColumnFlowThread::UpdateLayout() {
  DCHECK(!last_set_worked_on_);
  last_set_worked_on_ = FirstMultiColumnSet();
  if (last_set_worked_on_)
    last_set_worked_on_->BeginFlow(LayoutUnit());
  LayoutFlowThread::UpdateLayout();
  if (LayoutMultiColumnSet* last_set = LastMultiColumnSet()) {
    DCHECK_EQ(last_set, last_set_worked_on_);
    if (!last_set->NextSiblingMultiColumnSet()) {
      // Include trailing overflow in the last column set (also if the last set
      // is followed by one or more spanner placeholders). The idea is that we
      // will generate additional columns and pages to hold that overflow,
      // since people do write bad content like <body style="height:0px"> in
      // multi-column layouts.
      // TODO(mstensho): Once we support nested multicol, adding in overflow
      // here may result in the need for creating additional rows, since there
      // may not be enough space remaining in the currently last row.
      LayoutRect layout_rect = LayoutOverflowRect();
      LayoutUnit logical_bottom_in_flow_thread =
          IsHorizontalWritingMode() ? layout_rect.MaxY() : layout_rect.MaxX();
      DCHECK_GE(logical_bottom_in_flow_thread, LogicalHeight());
      last_set->EndFlow(logical_bottom_in_flow_thread);
    }
  }
  last_set_worked_on_ = nullptr;
}

void LayoutMultiColumnFlowThread::ContentWasLaidOut(
    LayoutUnit logical_bottom_in_flow_thread_after_pagination) {
  // Check if we need another fragmentainer group. If we've run out of columns
  // in the last fragmentainer group (column row), we need to insert another
  // fragmentainer group to hold more columns.

  // First figure out if there's any chance that we're nested at all. If we can
  // be sure that we're not, bail early. This code is run very often, and since
  // locating a containing flow thread has some cost (depending on tree depth),
  // avoid calling enclosingFragmentationContext() right away. This test may
  // give some false positives (hence the "mayBe"), if we're in an out-of-flow
  // subtree and have an outer multicol container that doesn't affect us, but
  // that's okay. We'll discover that further down the road when trying to
  // locate our enclosing flow thread for real.
  bool may_be_nested = MultiColumnBlockFlow()->IsInsideFlowThread() ||
                       View()->FragmentationContext();
  if (!may_be_nested)
    return;
  AppendNewFragmentainerGroupIfNeeded(
      logical_bottom_in_flow_thread_after_pagination, kAssociateWithFormerPage);
}

bool LayoutMultiColumnFlowThread::CanSkipLayout(const LayoutBox& root) const {
  // Objects containing spanners is all we need to worry about, so if there are
  // no spanners at all in this multicol container, we can just return the good
  // news right away.
  if (!HasAnyColumnSpanners(*this))
    return true;

  LayoutObject* next;
  for (const LayoutObject* object = &root; object; object = next) {
    if (object->IsColumnSpanAll()) {
      // A spanner potentially ends one fragmentainer group and begins a new
      // one, and thus determines the flow thread portion bottom and top of
      // adjacent fragmentainer groups. It's just too hard to guess these values
      // without laying out.
      return false;
    }
    if (CanContainSpannerInParentFragmentationContext(*object))
      next = object->NextInPreOrder(&root);
    else
      next = object->NextInPreOrderAfterChildren(&root);
  }
  return true;
}

MultiColumnLayoutState LayoutMultiColumnFlowThread::GetMultiColumnLayoutState()
    const {
  return MultiColumnLayoutState(last_set_worked_on_);
}

void LayoutMultiColumnFlowThread::RestoreMultiColumnLayoutState(
    const MultiColumnLayoutState& state) {
  last_set_worked_on_ = state.ColumnSet();
}

}  // namespace blink
