// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/renderer/core/layout/grid_track_sizing_algorithm.h"

#include "third_party/blink/renderer/core/frame/deprecation.h"
#include "third_party/blink/renderer/core/layout/grid.h"
#include "third_party/blink/renderer/core/layout/grid_layout_utils.h"
#include "third_party/blink/renderer/core/layout/layout_grid.h"
#include "third_party/blink/renderer/platform/geometry/length_functions.h"

namespace blink {

class GridSizingData;

LayoutUnit GridTrack::BaseSize() const {
  DCHECK(IsGrowthLimitBiggerThanBaseSize());
  return base_size_;
}

LayoutUnit GridTrack::GrowthLimit() const {
  DCHECK(IsGrowthLimitBiggerThanBaseSize());
  DCHECK(!growth_limit_cap_ || growth_limit_cap_.value() >= growth_limit_ ||
         base_size_ >= growth_limit_cap_.value());
  return growth_limit_;
}

void GridTrack::SetBaseSize(LayoutUnit base_size) {
  base_size_ = base_size;
  EnsureGrowthLimitIsBiggerThanBaseSize();
}

void GridTrack::SetGrowthLimit(LayoutUnit growth_limit) {
  growth_limit_ =
      growth_limit == kInfinity
          ? growth_limit
          : std::min(growth_limit, growth_limit_cap_.value_or(growth_limit));
  EnsureGrowthLimitIsBiggerThanBaseSize();
}

bool GridTrack::InfiniteGrowthPotential() const {
  return GrowthLimitIsInfinite() || infinitely_growable_;
}

void GridTrack::SetPlannedSize(LayoutUnit planned_size) {
  DCHECK(planned_size >= 0 || planned_size == kInfinity);
  planned_size_ = planned_size;
}

void GridTrack::SetSizeDuringDistribution(LayoutUnit size_during_distribution) {
  DCHECK_GE(size_during_distribution, 0);
  DCHECK(GrowthLimitIsInfinite() || GrowthLimit() >= size_during_distribution);
  size_during_distribution_ = size_during_distribution;
}

void GridTrack::GrowSizeDuringDistribution(
    LayoutUnit size_during_distribution) {
  DCHECK_GE(size_during_distribution, 0);
  size_during_distribution_ += size_during_distribution;
}

void GridTrack::SetInfinitelyGrowable(bool infinitely_growable) {
  infinitely_growable_ = infinitely_growable;
}

void GridTrack::SetGrowthLimitCap(base::Optional<LayoutUnit> growth_limit_cap) {
  DCHECK(!growth_limit_cap || *growth_limit_cap >= 0);
  growth_limit_cap_ = growth_limit_cap;
}

void GridTrack::SetCachedTrackSize(const GridTrackSize& cached_track_size) {
  cached_track_size_ = cached_track_size;
}

bool GridTrack::IsGrowthLimitBiggerThanBaseSize() const {
  return GrowthLimitIsInfinite() || growth_limit_ >= base_size_;
}

void GridTrack::EnsureGrowthLimitIsBiggerThanBaseSize() {
  if (growth_limit_ != kInfinity && growth_limit_ < base_size_)
    growth_limit_ = base_size_;
}

static GridAxis GridAxisForDirection(GridTrackSizingDirection direction) {
  return direction == kForColumns ? kGridRowAxis : kGridColumnAxis;
}

static GridTrackSizingDirection GridDirectionForAxis(GridAxis axis) {
  return axis == kGridRowAxis ? kForColumns : kForRows;
}

template <typename F>
static void IterateGridItemsInTrackIndices(const Grid& grid,
                                           GridTrackSizingDirection direction,
                                           Vector<size_t>& track_indices,
                                           F callback) {
#if DCHECK_IS_ON()
  HashSet<LayoutBox*> items_set;
#endif
  for (size_t i = 0; i < track_indices.size(); ++i) {
    auto iterator = grid.CreateIterator(direction, track_indices[i]);
    while (LayoutBox* grid_item = iterator->NextGridItem()) {
      const GridSpan& span = grid.GridItemSpan(*grid_item, direction);
      if (i > 0) {
        // Skip items already processed in an earlier track.
        DCHECK_LT(track_indices[i - 1], track_indices[i]);
        if (span.StartLine() <= track_indices[i - 1])
          continue;
      }
#if DCHECK_IS_ON()
      DCHECK(items_set.insert(grid_item).is_new_entry);
#endif
      callback(grid_item, span);
    }
  }
}

class IndefiniteSizeStrategy final : public GridTrackSizingAlgorithmStrategy {
 public:
  IndefiniteSizeStrategy(GridTrackSizingAlgorithm& algorithm)
      : GridTrackSizingAlgorithmStrategy(algorithm) {}

 private:
  void LayoutGridItemForMinSizeComputation(
      LayoutBox&,
      bool override_size_has_changed) const override;
  void MaximizeTracks(Vector<GridTrack>&,
                      base::Optional<LayoutUnit>& free_space) override;
  double FindUsedFlexFraction(
      Vector<size_t>& flexible_sized_tracks_index,
      GridTrackSizingDirection,
      base::Optional<LayoutUnit> free_space) const override;
  bool RecomputeUsedFlexFractionIfNeeded(
      Vector<size_t>& flexible_sized_tracks_index,
      double& flex_fraction,
      Vector<LayoutUnit>& increments,
      LayoutUnit& total_growth) const override;
  LayoutUnit FreeSpaceForStretchAutoTracksStep() const override;
  LayoutUnit MinContentForChild(LayoutBox&) const override;
  LayoutUnit MaxContentForChild(LayoutBox&) const override;
  bool IsComputingSizeContainment() const override;
};

class DefiniteSizeStrategy final : public GridTrackSizingAlgorithmStrategy {
 public:
  DefiniteSizeStrategy(GridTrackSizingAlgorithm& algorithm)
      : GridTrackSizingAlgorithmStrategy(algorithm) {}

 private:
  void LayoutGridItemForMinSizeComputation(
      LayoutBox&,
      bool override_size_has_changed) const override;
  void MaximizeTracks(Vector<GridTrack>&,
                      base::Optional<LayoutUnit>& free_space) override;
  double FindUsedFlexFraction(
      Vector<size_t>& flexible_sized_tracks_index,
      GridTrackSizingDirection,
      base::Optional<LayoutUnit> free_space) const override;
  bool RecomputeUsedFlexFractionIfNeeded(
      Vector<size_t>& flexible_sized_tracks_index,
      double& flex_fraction,
      Vector<LayoutUnit>& increments,
      LayoutUnit& total_growth) const override {
    return false;
  }
  LayoutUnit FreeSpaceForStretchAutoTracksStep() const override;
  LayoutUnit MinContentForChild(LayoutBox&) const override;
  LayoutUnit MinLogicalSizeForChild(LayoutBox&,
                                    const Length& child_min_size,
                                    LayoutUnit available_size) const override;
  bool IsComputingSizeContainment() const override { return false; }
};

GridTrackSizingAlgorithmStrategy::~GridTrackSizingAlgorithmStrategy() = default;

bool GridTrackSizingAlgorithmStrategy::HasRelativeMarginOrPaddingForChild(
    const LayoutGrid& grid,
    const LayoutBox& child,
    GridTrackSizingDirection direction) {
  GridTrackSizingDirection child_inline_direction =
      GridLayoutUtils::FlowAwareDirectionForChild(grid, child, kForColumns);
  if (direction == child_inline_direction) {
    return child.StyleRef().MarginStart().IsPercentOrCalc() ||
           child.StyleRef().MarginEnd().IsPercentOrCalc() ||
           child.StyleRef().PaddingStart().IsPercentOrCalc() ||
           child.StyleRef().PaddingEnd().IsPercentOrCalc();
  }
  return child.StyleRef().MarginBefore().IsPercentOrCalc() ||
         child.StyleRef().MarginAfter().IsPercentOrCalc() ||
         child.StyleRef().PaddingBefore().IsPercentOrCalc() ||
         child.StyleRef().PaddingAfter().IsPercentOrCalc();
}

bool GridTrackSizingAlgorithmStrategy::HasRelativeOrIntrinsicSizeForChild(
    const LayoutGrid& grid,
    const LayoutBox& child,
    GridTrackSizingDirection direction) {
  GridTrackSizingDirection child_inline_direction =
      GridLayoutUtils::FlowAwareDirectionForChild(grid, child, kForColumns);
  if (direction == child_inline_direction) {
    return child.HasRelativeLogicalWidth() ||
           !child.StyleRef().LogicalWidth().IsSpecified();
  }
  return child.HasRelativeLogicalHeight() ||
         !child.StyleRef().LogicalHeight().IsSpecified();
}

bool GridTrackSizingAlgorithmStrategy::
    ShouldClearOverrideContainingBlockContentSizeForChild(
        const LayoutGrid& grid,
        const LayoutBox& child,
        GridTrackSizingDirection direction) {
  return HasRelativeOrIntrinsicSizeForChild(grid, child, direction) ||
         HasRelativeMarginOrPaddingForChild(grid, child, direction);
}

void GridTrackSizingAlgorithmStrategy::
    SetOverrideContainingBlockContentSizeForChild(
        LayoutBox& child,
        GridTrackSizingDirection direction,
        LayoutUnit size) {
  if (direction == kForColumns)
    child.SetOverrideContainingBlockContentLogicalWidth(size);
  else
    child.SetOverrideContainingBlockContentLogicalHeight(size);
}

LayoutSize GridTrackSizingAlgorithm::EstimatedGridAreaBreadthForChild(
    const LayoutBox& child) const {
  return {EstimatedGridAreaBreadthForChild(child, kForColumns),
          EstimatedGridAreaBreadthForChild(child, kForRows)};
}

LayoutUnit GridTrackSizingAlgorithm::EstimatedGridAreaBreadthForChild(
    const LayoutBox& child,
    GridTrackSizingDirection direction) const {
  const GridSpan& span = grid_.GridItemSpan(child, direction);
  LayoutUnit grid_area_size;
  bool grid_area_is_indefinite = false;
  base::Optional<LayoutUnit> available_size = AvailableSpace(direction);
  for (auto track_position : span) {
    // We may need to estimate the grid area size before running the track
    // sizing algorithm in order to perform the pre-layout of orthogonal
    // items.
    // We cannot use Tracks(direction)[track_position].CachedTrackSize()
    // because Tracks(direction) is empty, since we are either performing
    // pre-layout or are running the track sizing algorithm in the opposite
    // direction and haven't run it in the desired direction yet.
    const GridTrackSize& track_size =
        WasSetup() ? CalculateGridTrackSize(direction, track_position)
                   : RawGridTrackSize(direction, track_position);
    GridLength max_track_size = track_size.MaxTrackBreadth();
    if (max_track_size.IsContentSized() || max_track_size.IsFlex() ||
        IsRelativeGridLengthAsAuto(max_track_size, direction)) {
      grid_area_is_indefinite = true;
    } else {
      grid_area_size += ValueForLength(max_track_size.length(),
                                       available_size.value_or(LayoutUnit()));
    }
  }

  grid_area_size += layout_grid_->GuttersSize(
      grid_, direction, span.StartLine(), span.IntegerSpan(), available_size);

  GridTrackSizingDirection child_inline_direction =
      GridLayoutUtils::FlowAwareDirectionForChild(*layout_grid_, child,
                                                  kForColumns);
  if (grid_area_is_indefinite) {
    return direction == child_inline_direction
               ? std::max(child.PreferredLogicalWidths().max_size,
                          grid_area_size)
               : LayoutUnit(-1);
  }
  return grid_area_size;
}

LayoutUnit GridTrackSizingAlgorithm::GridAreaBreadthForChild(
    const LayoutBox& child,
    GridTrackSizingDirection direction) const {
  bool add_content_alignment_offset =
      direction == kForColumns && sizing_state_ == kRowSizingFirstIteration;
  if (direction == kForRows &&
      (sizing_state_ == kColumnSizingFirstIteration ||
       sizing_state_ == kColumnSizingSecondIteration)) {
    DCHECK(GridLayoutUtils::IsOrthogonalChild(*layout_grid_, child));
    // TODO (jfernandez) Content Alignment should account for this heuristic
    // https://github.com/w3c/csswg-drafts/issues/2697
    if (sizing_state_ == kColumnSizingFirstIteration)
      return EstimatedGridAreaBreadthForChild(child, kForRows);
    add_content_alignment_offset = true;
  }

  const Vector<GridTrack>& all_tracks = Tracks(direction);
  const GridSpan& span = grid_.GridItemSpan(child, direction);
  LayoutUnit grid_area_breadth;
  for (const auto& track_position : span)
    grid_area_breadth += all_tracks[track_position].BaseSize();

  if (add_content_alignment_offset) {
    grid_area_breadth +=
        (span.IntegerSpan() - 1) * layout_grid_->GridItemOffset(direction);
  }

  grid_area_breadth +=
      layout_grid_->GuttersSize(grid_, direction, span.StartLine(),
                                span.IntegerSpan(), AvailableSpace(direction));

  return grid_area_breadth;
}

bool GridTrackSizingAlgorithm::IsIntrinsicSizedGridArea(const LayoutBox& child,
                                                        GridAxis axis) const {
  DCHECK(WasSetup());
  GridTrackSizingDirection direction = GridDirectionForAxis(axis);
  const GridSpan& span = grid_.GridItemSpan(child, direction);
  for (const auto& track_position : span) {
    const GridTrackSize& track_size =
        RawGridTrackSize(direction, track_position);
    // We consider fr units as 'auto' for the min sizing function.
    // TODO(jfernandez): https://github.com/w3c/csswg-drafts/issues/2611
    //
    // The use of AvailableSize function may imply different results
    // for the same item when assuming indefinite or definite size
    // constraints depending on the phase we evaluate the item's
    // baseline participation.
    // TODO(jfernandez): https://github.com/w3c/csswg-drafts/issues/3046
    if (track_size.IsContentSized() || track_size.IsFitContent() ||
        track_size.MinTrackBreadth().IsFlex() ||
        (track_size.MaxTrackBreadth().IsFlex() && !AvailableSpace(direction)))
      return true;
  }
  return false;
}

bool GridTrackSizingAlgorithmStrategy::
    UpdateOverrideContainingBlockContentSizeForChild(
        LayoutBox& child,
        GridTrackSizingDirection direction,
        base::Optional<LayoutUnit> override_size) const {
  if (!override_size)
    override_size = algorithm_.GridAreaBreadthForChild(child, direction);
  if (GridLayoutUtils::OverrideContainingBlockContentSizeForChild(
          child, direction) == override_size.value())
    return false;

  SetOverrideContainingBlockContentSizeForChild(child, direction,
                                                override_size.value());
  return true;
}

LayoutUnit GridTrackSizingAlgorithmStrategy::LogicalHeightForChild(
    LayoutBox& child) const {
  GridTrackSizingDirection child_block_direction =
      GridLayoutUtils::FlowAwareDirectionForChild(*GetLayoutGrid(), child,
                                                  kForRows);
  // If |child| has a relative block-axis size, we shouldn't let it override its
  // intrinsic size, which is what we are interested in here. Thus we
  // need to set the block-axis OverrideContainingBlock size to -1 (no possible
  // resolution).
  if (ShouldClearOverrideContainingBlockContentSizeForChild(
          *GetLayoutGrid(), child, child_block_direction)) {
    SetOverrideContainingBlockContentSizeForChild(child, child_block_direction,
                                                  LayoutUnit(-1));
    child.SetSelfNeedsLayoutForAvailableSpace(true);
  }

  child.LayoutIfNeeded();

  return child.LogicalHeight() +
         GridLayoutUtils::MarginLogicalHeightForChild(*GetLayoutGrid(), child) +
         algorithm_.BaselineOffsetForChild(child,
                                           GridAxisForDirection(Direction()));
}

DISABLE_CFI_PERF
LayoutUnit GridTrackSizingAlgorithmStrategy::MinContentForChild(
    LayoutBox& child) const {
  GridTrackSizingDirection child_inline_direction =
      GridLayoutUtils::FlowAwareDirectionForChild(*GetLayoutGrid(), child,
                                                  kForColumns);
  if (Direction() == child_inline_direction) {
    // FIXME: It's unclear if we should return the intrinsic width or the
    // preferred width.
    // See http://lists.w3.org/Archives/Public/www-style/2013Jan/0245.html
    if (child.NeedsPreferredWidthsRecalculation())
      child.SetIntrinsicLogicalWidthsDirty();
    return child.PreferredLogicalWidths().min_size +
           GridLayoutUtils::MarginLogicalWidthForChild(*GetLayoutGrid(),
                                                       child) +
           algorithm_.BaselineOffsetForChild(child,
                                             GridAxisForDirection(Direction()));
  }

  if (UpdateOverrideContainingBlockContentSizeForChild(
          child, child_inline_direction)) {
    child.SetSelfNeedsLayoutForAvailableSpace(true);
  }
  return LogicalHeightForChild(child);
}

DISABLE_CFI_PERF
LayoutUnit GridTrackSizingAlgorithmStrategy::MaxContentForChild(
    LayoutBox& child) const {
  GridTrackSizingDirection child_inline_direction =
      GridLayoutUtils::FlowAwareDirectionForChild(*GetLayoutGrid(), child,
                                                  kForColumns);
  if (Direction() == child_inline_direction) {
    // FIXME: It's unclear if we should return the intrinsic width or the
    // preferred width.
    // See http://lists.w3.org/Archives/Public/www-style/2013Jan/0245.html
    if (child.NeedsPreferredWidthsRecalculation())
      child.SetIntrinsicLogicalWidthsDirty();
    return child.PreferredLogicalWidths().max_size +
           GridLayoutUtils::MarginLogicalWidthForChild(*GetLayoutGrid(),
                                                       child) +
           algorithm_.BaselineOffsetForChild(child,
                                             GridAxisForDirection(Direction()));
  }

  if (UpdateOverrideContainingBlockContentSizeForChild(
          child, child_inline_direction)) {
    child.SetSelfNeedsLayoutForAvailableSpace(true);
  }
  return LogicalHeightForChild(child);
}

LayoutUnit GridTrackSizingAlgorithmStrategy::MinSizeForChild(
    LayoutBox& child) const {
  GridTrackSizingDirection child_inline_direction =
      GridLayoutUtils::FlowAwareDirectionForChild(*GetLayoutGrid(), child,
                                                  kForColumns);
  bool is_row_axis = Direction() == child_inline_direction;
  const Length& child_size = is_row_axis ? child.StyleRef().LogicalWidth()
                                         : child.StyleRef().LogicalHeight();
  if (!child_size.IsAuto() && !child_size.IsPercentOrCalc())
    return MinContentForChild(child);

  const Length& child_min_size = is_row_axis
                                     ? child.StyleRef().LogicalMinWidth()
                                     : child.StyleRef().LogicalMinHeight();
  bool overflow_is_visible =
      is_row_axis
          ? child.StyleRef().OverflowInlineDirection() == EOverflow::kVisible
          : child.StyleRef().OverflowBlockDirection() == EOverflow::kVisible;
  LayoutUnit baseline_shim = algorithm_.BaselineOffsetForChild(
      child, GridAxisForDirection(Direction()));

  if (child_min_size.IsAuto() && overflow_is_visible) {
    LayoutUnit min_size = MinContentForChild(child);
    const GridSpan& span =
        algorithm_.GetGrid().GridItemSpan(child, Direction());
    LayoutUnit max_breadth;
    const Vector<GridTrack>& all_tracks = algorithm_.Tracks(Direction());
    for (const auto& track_position : span) {
      const GridTrackSize& track_size =
          all_tracks[track_position].CachedTrackSize();
      if (!track_size.HasFixedMaxTrackBreadth())
        return min_size;
      max_breadth += ValueForLength(track_size.MaxTrackBreadth().length(),
                                    AvailableSpace().value_or(LayoutUnit()));
    }
    if (min_size > max_breadth) {
      LayoutUnit margin_and_border_and_padding =
          is_row_axis ? GridLayoutUtils::MarginLogicalWidthForChild(
                            *GetLayoutGrid(), child) +
                            child.BorderAndPaddingLogicalWidth()
                      : GridLayoutUtils::MarginLogicalHeightForChild(
                            *GetLayoutGrid(), child) +
                            child.BorderAndPaddingLogicalHeight();
      min_size =
          std::max(max_breadth, margin_and_border_and_padding + baseline_shim);
    }
    return min_size;
  }

  LayoutUnit grid_area_size =
      algorithm_.GridAreaBreadthForChild(child, child_inline_direction);
  return MinLogicalSizeForChild(child, child_min_size, grid_area_size) +
         baseline_shim;
}

bool GridTrackSizingAlgorithm::CanParticipateInBaselineAlignment(
    const LayoutBox& child,
    GridAxis baseline_axis) const {
  DCHECK(baseline_axis == kGridColumnAxis
             ? column_baseline_items_map_.Contains(&child)
             : row_baseline_items_map_.Contains(&child));

  // Baseline cyclic dependencies only happen with synthesized
  // baselines. These cases include orthogonal or empty grid items
  // and replaced elements.
  bool is_parallel_to_baseline_axis =
      baseline_axis == kGridColumnAxis
          ? !GridLayoutUtils::IsOrthogonalChild(*layout_grid_, child)
          : GridLayoutUtils::IsOrthogonalChild(*layout_grid_, child);
  if (is_parallel_to_baseline_axis && child.FirstLineBoxBaseline() != -1)
    return true;

  // Baseline cyclic dependencies only happen in grid areas with
  // intrinsically-sized tracks.
  if (!IsIntrinsicSizedGridArea(child, baseline_axis))
    return true;

  return is_parallel_to_baseline_axis
             ? !child.HasRelativeLogicalHeight()
             : !child.HasRelativeLogicalWidth() &&
                   !child.StyleRef().LogicalWidth().IsAuto();
}

bool GridTrackSizingAlgorithm::ParticipateInBaselineAlignment(
    const LayoutBox& child,
    GridAxis baseline_axis) const {
  return baseline_axis == kGridColumnAxis
             ? column_baseline_items_map_.at(&child)
             : row_baseline_items_map_.at(&child);
}

void GridTrackSizingAlgorithm::UpdateBaselineAlignmentContext(
    const LayoutBox& child,
    GridAxis baseline_axis) {
  DCHECK(WasSetup());
  DCHECK(CanParticipateInBaselineAlignment(child, baseline_axis));
  DCHECK(!child.NeedsLayout());

  ItemPosition align =
      layout_grid_->SelfAlignmentForChild(baseline_axis, child).GetPosition();
  const auto& span =
      grid_.GridItemSpan(child, GridDirectionForAxis(baseline_axis));
  baseline_alignment_.UpdateBaselineAlignmentContext(align, span.StartLine(),
                                                     child, baseline_axis);
}

LayoutUnit GridTrackSizingAlgorithm::BaselineOffsetForChild(
    const LayoutBox& child,
    GridAxis baseline_axis) const {
  if (!ParticipateInBaselineAlignment(child, baseline_axis))
    return LayoutUnit();

  ItemPosition align =
      layout_grid_->SelfAlignmentForChild(baseline_axis, child).GetPosition();
  const auto& span =
      grid_.GridItemSpan(child, GridDirectionForAxis(baseline_axis));
  return baseline_alignment_.BaselineOffsetForChild(align, span.StartLine(),
                                                    child, baseline_axis);
}

void GridTrackSizingAlgorithm::ClearBaselineItemsCache() {
  column_baseline_items_map_.clear();
  row_baseline_items_map_.clear();
}

void GridTrackSizingAlgorithm::CacheBaselineAlignedItem(const LayoutBox& item,
                                                        GridAxis axis) {
  DCHECK(layout_grid_->IsBaselineAlignmentForChild(item, axis));
  if (axis == kGridColumnAxis)
    column_baseline_items_map_.insert(&item, true);
  else
    row_baseline_items_map_.insert(&item, true);
}

void GridTrackSizingAlgorithm::CopyBaselineItemsCache(
    const GridTrackSizingAlgorithm& source,
    GridAxis axis) {
  if (axis == kGridColumnAxis)
    column_baseline_items_map_ = source.column_baseline_items_map_;
  else
    row_baseline_items_map_ = source.row_baseline_items_map_;
}

LayoutUnit GridTrackSizingAlgorithmStrategy::ComputeTrackBasedSize() const {
  return algorithm_.ComputeTrackBasedSize();
}

double GridTrackSizingAlgorithmStrategy::FindFrUnitSize(
    const GridSpan& tracks_span,
    LayoutUnit left_over_space) const {
  return algorithm_.FindFrUnitSize(tracks_span, left_over_space);
}

void GridTrackSizingAlgorithmStrategy::DistributeSpaceToTracks(
    Vector<GridTrack*>& tracks,
    LayoutUnit& available_logical_space) const {
  algorithm_.DistributeSpaceToTracks<kMaximizeTracks>(tracks, nullptr,
                                                      available_logical_space);
}

LayoutUnit GridTrackSizingAlgorithmStrategy::MinLogicalSizeForChild(
    LayoutBox& child,
    const Length& child_min_size,
    LayoutUnit available_size) const {
  GridTrackSizingDirection child_inline_direction =
      GridLayoutUtils::FlowAwareDirectionForChild(*GetLayoutGrid(), child,
                                                  kForColumns);
  bool is_row_axis = Direction() == child_inline_direction;

  if (is_row_axis) {
    return child.ComputeLogicalWidthUsing(kMinSize, child_min_size,
                                          available_size, GetLayoutGrid()) +
           GridLayoutUtils::MarginLogicalWidthForChild(*GetLayoutGrid(), child);
  }

  bool override_size_has_changed =
      UpdateOverrideContainingBlockContentSizeForChild(
          child, child_inline_direction, available_size);
  LayoutGridItemForMinSizeComputation(child, override_size_has_changed);

  return child.ComputeLogicalHeightUsing(kMinSize, child_min_size,
                                         child.IntrinsicLogicalHeight()) +
         GridLayoutUtils::MarginLogicalHeightForChild(*GetLayoutGrid(), child);
}

LayoutUnit DefiniteSizeStrategy::MinLogicalSizeForChild(
    LayoutBox& child,
    const Length& child_min_size,
    LayoutUnit available_size) const {
  GridTrackSizingDirection child_inline_direction =
      GridLayoutUtils::FlowAwareDirectionForChild(*GetLayoutGrid(), child,
                                                  kForColumns);
  LayoutUnit indefinite_size =
      Direction() == child_inline_direction ? LayoutUnit() : LayoutUnit(-1);
  if (HasRelativeMarginOrPaddingForChild(*GetLayoutGrid(), child,
                                         Direction()) ||
      (Direction() != child_inline_direction &&
       HasRelativeOrIntrinsicSizeForChild(*GetLayoutGrid(), child,
                                          Direction()))) {
    SetOverrideContainingBlockContentSizeForChild(child, Direction(),
                                                  indefinite_size);
  }
  return GridTrackSizingAlgorithmStrategy::MinLogicalSizeForChild(
      child, child_min_size, available_size);
}

void DefiniteSizeStrategy::LayoutGridItemForMinSizeComputation(
    LayoutBox& child,
    bool override_size_has_changed) const {
  if (override_size_has_changed) {
    child.SetSelfNeedsLayoutForAvailableSpace(true);
    child.LayoutIfNeeded();
  }
}

void DefiniteSizeStrategy::MaximizeTracks(
    Vector<GridTrack>& tracks,
    base::Optional<LayoutUnit>& free_space) {
  size_t tracks_size = tracks.size();
  Vector<GridTrack*> tracks_for_distribution(tracks_size);
  for (size_t i = 0; i < tracks_size; ++i) {
    tracks_for_distribution[i] = tracks.data() + i;
    tracks_for_distribution[i]->SetPlannedSize(
        tracks_for_distribution[i]->BaseSize());
  }

  DCHECK(free_space);
  DistributeSpaceToTracks(tracks_for_distribution, free_space.value());

  for (auto* track : tracks_for_distribution)
    track->SetBaseSize(track->PlannedSize());
}

double DefiniteSizeStrategy::FindUsedFlexFraction(
    Vector<size_t>& flexible_sized_tracks_index,
    GridTrackSizingDirection direction,
    base::Optional<LayoutUnit> free_space) const {
  GridSpan all_tracks_span = GridSpan::TranslatedDefiniteGridSpan(
      0, algorithm_.Tracks(direction).size());
  DCHECK(free_space);
  return FindFrUnitSize(all_tracks_span, free_space.value());
}

LayoutUnit DefiniteSizeStrategy::FreeSpaceForStretchAutoTracksStep() const {
  DCHECK(algorithm_.FreeSpace(Direction()));
  return algorithm_.FreeSpace(Direction()).value();
}

DISABLE_CFI_PERF
LayoutUnit DefiniteSizeStrategy::MinContentForChild(LayoutBox& child) const {
  GridTrackSizingDirection child_inline_direction =
      GridLayoutUtils::FlowAwareDirectionForChild(*GetLayoutGrid(), child,
                                                  kForColumns);
  if (Direction() == child_inline_direction && child.NeedsLayout() &&
      ShouldClearOverrideContainingBlockContentSizeForChild(
          *GetLayoutGrid(), child, child_inline_direction)) {
    SetOverrideContainingBlockContentSizeForChild(child, child_inline_direction,
                                                  LayoutUnit());
  }

  return GridTrackSizingAlgorithmStrategy::MinContentForChild(child);
}

void IndefiniteSizeStrategy::LayoutGridItemForMinSizeComputation(
    LayoutBox& child,
    bool override_size_has_changed) const {
  if (override_size_has_changed && Direction() != kForColumns) {
    child.SetSelfNeedsLayoutForAvailableSpace(true);
    child.LayoutIfNeeded();
  }
}

void IndefiniteSizeStrategy::MaximizeTracks(Vector<GridTrack>& tracks,
                                            base::Optional<LayoutUnit>&) {
  for (auto& track : tracks)
    track.SetBaseSize(track.GrowthLimit());
}

static inline double NormalizedFlexFraction(const GridTrack& track) {
  double flex_factor = track.CachedTrackSize().MaxTrackBreadth().Flex();
  return track.BaseSize() / std::max<double>(1, flex_factor);
}

double IndefiniteSizeStrategy::FindUsedFlexFraction(
    Vector<size_t>& flexible_sized_tracks_index,
    GridTrackSizingDirection direction,
    base::Optional<LayoutUnit>) const {
  auto all_tracks = algorithm_.Tracks(direction);

  double flex_fraction = 0;
  for (const auto& track_index : flexible_sized_tracks_index) {
    flex_fraction = std::max(flex_fraction,
                             NormalizedFlexFraction(all_tracks[track_index]));
  }

  const Grid& grid = algorithm_.GetGrid();
  if (!grid.HasGridItems())
    return flex_fraction;

  IterateGridItemsInTrackIndices(
      grid, direction, flexible_sized_tracks_index,
      [&](LayoutBox* grid_item, const GridSpan& span) {
        // Removing gutters from the max-content contribution of the item,
        // so they are not taken into account in FindFrUnitSize().
        LayoutUnit left_over_space =
            MaxContentForChild(*grid_item) -
            GetLayoutGrid()->GuttersSize(algorithm_.GetGrid(), direction,
                                         span.StartLine(), span.IntegerSpan(),
                                         AvailableSpace());
        flex_fraction =
            std::max(flex_fraction, FindFrUnitSize(span, left_over_space));
      });

  return flex_fraction;
}

bool IndefiniteSizeStrategy::RecomputeUsedFlexFractionIfNeeded(
    Vector<size_t>& flexible_sized_tracks_index,
    double& flex_fraction,
    Vector<LayoutUnit>& increments,
    LayoutUnit& total_growth) const {
  if (Direction() == kForColumns)
    return false;

  const LayoutGrid* layout_grid = GetLayoutGrid();
  LayoutUnit min_size = layout_grid->ComputeContentLogicalHeight(
      kMinSize, layout_grid->StyleRef().LogicalMinHeight(), LayoutUnit(-1));
  LayoutUnit max_size = layout_grid->ComputeContentLogicalHeight(
      kMaxSize, layout_grid->StyleRef().LogicalMaxHeight(), LayoutUnit(-1));

  // Redo the flex fraction computation using min|max-height as definite
  // available space in case the total height is smaller than min-height or
  // larger than max-height.
  LayoutUnit rows_size = total_growth + ComputeTrackBasedSize();
  bool check_min_size = min_size && rows_size < min_size;
  bool check_max_size = max_size != -1 && rows_size > max_size;
  if (!check_min_size && !check_max_size)
    return false;

  LayoutUnit free_space = check_max_size ? max_size : LayoutUnit(-1);
  const Grid& grid = algorithm_.GetGrid();
  free_space =
      std::max(free_space, min_size) -
      layout_grid->GuttersSize(grid, kForRows, 0, grid.NumTracks(kForRows),
                               AvailableSpace());

  size_t number_of_tracks = algorithm_.Tracks(Direction()).size();
  flex_fraction = FindFrUnitSize(
      GridSpan::TranslatedDefiniteGridSpan(0, number_of_tracks), free_space);
  return true;
}

LayoutUnit IndefiniteSizeStrategy::FreeSpaceForStretchAutoTracksStep() const {
  DCHECK(!algorithm_.FreeSpace(Direction()));
  if (Direction() == kForColumns)
    return LayoutUnit();

  LayoutUnit min_size = GetLayoutGrid()->ComputeContentLogicalHeight(
      kMinSize, GetLayoutGrid()->StyleRef().LogicalMinHeight(), LayoutUnit(-1));
  return min_size - ComputeTrackBasedSize();
}

DISABLE_CFI_PERF
LayoutUnit IndefiniteSizeStrategy::MinContentForChild(LayoutBox& child) const {
  GridTrackSizingDirection child_inline_direction =
      GridLayoutUtils::FlowAwareDirectionForChild(*GetLayoutGrid(), child,
                                                  kForColumns);
  if (Direction() == child_inline_direction || Direction() == kForRows)
    return GridTrackSizingAlgorithmStrategy::MinContentForChild(child);

  // This code is executed only when computing the grid's intrinsic
  // width based on an orthogonal child. We rely on the pre-layout
  // performed in LayoutGrid::LayoutOrthogonalWritingModeRoots.
  DCHECK(GridLayoutUtils::IsOrthogonalChild(*GetLayoutGrid(), child));

  return child.LogicalHeight() +
         GridLayoutUtils::MarginLogicalHeightForChild(*GetLayoutGrid(), child) +
         algorithm_.BaselineOffsetForChild(child,
                                           GridAxisForDirection(Direction()));
}

DISABLE_CFI_PERF
LayoutUnit IndefiniteSizeStrategy::MaxContentForChild(LayoutBox& child) const {
  GridTrackSizingDirection child_inline_direction =
      GridLayoutUtils::FlowAwareDirectionForChild(*GetLayoutGrid(), child,
                                                  kForColumns);
  if (Direction() == child_inline_direction || Direction() == kForRows)
    return GridTrackSizingAlgorithmStrategy::MaxContentForChild(child);

  // This code is executed only when computing the grid's intrinsic
  // width based on an orthogonal child. We rely on the pre-layout
  // performed in LayoutGrid::LayoutOrthogonalWritingModeRoots.
  DCHECK(GridLayoutUtils::IsOrthogonalChild(*GetLayoutGrid(), child));

  return child.LogicalHeight() +
         GridLayoutUtils::MarginLogicalHeightForChild(*GetLayoutGrid(), child) +
         algorithm_.BaselineOffsetForChild(child,
                                           GridAxisForDirection(Direction()));
}

bool IndefiniteSizeStrategy::IsComputingSizeContainment() const {
  return GetLayoutGrid()->ShouldApplySizeContainment();
}

base::Optional<LayoutUnit> GridTrackSizingAlgorithm::FreeSpace(
    GridTrackSizingDirection direction) const {
  return direction == kForRows ? free_space_rows_ : free_space_columns_;
}

base::Optional<LayoutUnit> GridTrackSizingAlgorithm::AvailableSpace(
    GridTrackSizingDirection direction) const {
  return direction == kForRows ? available_space_rows_
                               : available_space_columns_;
}

base::Optional<LayoutUnit> GridTrackSizingAlgorithm::AvailableSpace() const {
  DCHECK(WasSetup());
  return AvailableSpace(direction_);
}

void GridTrackSizingAlgorithm::SetAvailableSpace(
    GridTrackSizingDirection direction,
    base::Optional<LayoutUnit> available_space) {
  if (direction == kForColumns)
    available_space_columns_ = available_space;
  else
    available_space_rows_ = available_space;
}

Vector<GridTrack>& GridTrackSizingAlgorithm::Tracks(
    GridTrackSizingDirection direction) {
  return direction == kForColumns ? columns_ : rows_;
}

const Vector<GridTrack>& GridTrackSizingAlgorithm::Tracks(
    GridTrackSizingDirection direction) const {
  return direction == kForColumns ? columns_ : rows_;
}

void GridTrackSizingAlgorithm::SetFreeSpace(
    GridTrackSizingDirection direction,
    base::Optional<LayoutUnit> free_space) {
  if (direction == kForColumns)
    free_space_columns_ = free_space;
  else
    free_space_rows_ = free_space;
}

const GridTrackSize& GridTrackSizingAlgorithm::RawGridTrackSize(
    GridTrackSizingDirection direction,
    size_t translated_index) const {
  bool is_row_axis = direction == kForColumns;
  const Vector<GridTrackSize>& track_styles =
      is_row_axis
          ? layout_grid_->StyleRef().GridTemplateColumns().LegacyTrackList()
          : layout_grid_->StyleRef().GridTemplateRows().LegacyTrackList();
  const Vector<GridTrackSize>& auto_repeat_track_styles =
      is_row_axis ? layout_grid_->StyleRef().GridAutoRepeatColumns()
                  : layout_grid_->StyleRef().GridAutoRepeatRows();
  const Vector<GridTrackSize>& auto_track_styles =
      is_row_axis ? layout_grid_->StyleRef().GridAutoColumns().LegacyTrackList()
                  : layout_grid_->StyleRef().GridAutoRows().LegacyTrackList();
  size_t insertion_point =
      is_row_axis
          ? layout_grid_->StyleRef().GridAutoRepeatColumnsInsertionPoint()
          : layout_grid_->StyleRef().GridAutoRepeatRowsInsertionPoint();
  size_t auto_repeat_tracks_count = grid_.AutoRepeatTracks(direction);

  // We should not use GridPositionsResolver::explicitGridXXXCount() for this
  // because the explicit grid might be larger than the number of tracks in
  // grid-template-rows|columns (if grid-template-areas is specified for
  // example).
  size_t explicit_tracks_count = track_styles.size() + auto_repeat_tracks_count;

  int untranslated_index_as_int =
      translated_index - grid_.ExplicitGridStart(direction);
  size_t auto_track_styles_size = auto_track_styles.size();
  if (untranslated_index_as_int < 0) {
    int index =
        untranslated_index_as_int % static_cast<int>(auto_track_styles_size);
    // We need to traspose the index because the first negative implicit line
    // will get the last defined auto track and so on.
    index += index ? auto_track_styles_size : 0;
    return auto_track_styles[index];
  }

  size_t untranslated_index = static_cast<size_t>(untranslated_index_as_int);
  if (untranslated_index >= explicit_tracks_count) {
    return auto_track_styles[(untranslated_index - explicit_tracks_count) %
                             auto_track_styles_size];
  }

  if (LIKELY(!auto_repeat_tracks_count) || untranslated_index < insertion_point)
    return track_styles[untranslated_index];

  if (untranslated_index < (insertion_point + auto_repeat_tracks_count)) {
    size_t auto_repeat_local_index =
        untranslated_index_as_int - insertion_point;
    return auto_repeat_track_styles[auto_repeat_local_index %
                                    auto_repeat_track_styles.size()];
  }

  return track_styles[untranslated_index - auto_repeat_tracks_count];
}

bool GridTrackSizingAlgorithm::IsRelativeGridLengthAsAuto(
    const GridLength& length,
    GridTrackSizingDirection direction) const {
  return length.HasPercentage() && !AvailableSpace(direction);
}

bool GridTrackSizingAlgorithm::IsRelativeSizedTrackAsAuto(
    const GridTrackSize& track_size,
    GridTrackSizingDirection direction) const {
  if (track_size.MinTrackBreadth().HasPercentage())
    return IsRelativeGridLengthAsAuto(track_size.MinTrackBreadth(), direction);
  if (track_size.MaxTrackBreadth().HasPercentage())
    return IsRelativeGridLengthAsAuto(track_size.MaxTrackBreadth(), direction);
  return false;
}

GridTrackSize GridTrackSizingAlgorithm::CalculateGridTrackSize(
    GridTrackSizingDirection direction,
    size_t translated_index) const {
  DCHECK(WasSetup());
  // Collapse empty auto repeat tracks if auto-fit.
  if (grid_.HasAutoRepeatEmptyTracks(direction) &&
      grid_.IsEmptyAutoRepeatTrack(direction, translated_index))
    return {Length::Fixed(), kLengthTrackSizing};

  const GridTrackSize& track_size =
      RawGridTrackSize(direction, translated_index);
  if (track_size.IsFitContent()) {
    return IsRelativeGridLengthAsAuto(track_size.FitContentTrackBreadth(),
                                      direction)
               ? GridTrackSize(Length::Auto(), Length::MaxContent())
               : track_size;
  }

  GridLength min_track_breadth = track_size.MinTrackBreadth();
  GridLength max_track_breadth = track_size.MaxTrackBreadth();

  // If the logical width/height of the grid container is indefinite, percentage
  // values are treated as <auto>.
  if (IsRelativeSizedTrackAsAuto(track_size, direction)) {
    if (direction == kForRows) {
      // We avoid counting the cases in which it doesn't matter if we resolve
      // the percentages row tracks against the intrinsic height of the grid
      // container or we treat them as auto. Basically if we have just one row,
      // it has 100% size and the max-block-size is none.
      if ((grid_.NumTracks(direction) != 1) || !min_track_breadth.IsLength() ||
          !min_track_breadth.length().IsPercent() ||
          (min_track_breadth.length().Percent() != 100.0f) ||
          !max_track_breadth.IsLength() ||
          !max_track_breadth.length().IsPercent() ||
          (max_track_breadth.length().Percent() != 100.0f) ||
          !layout_grid_->StyleRef().LogicalMaxHeight().IsNone()) {
        UseCounter::Count(layout_grid_->GetDocument(),
                          WebFeature::kGridRowTrackPercentIndefiniteHeight);
      }
    }
    if (min_track_breadth.HasPercentage())
      min_track_breadth = Length::Auto();
    if (max_track_breadth.HasPercentage())
      max_track_breadth = Length::Auto();
  }

  // Flex sizes are invalid as a min sizing function. However we still can have
  // a flexible |minTrackBreadth| if the track had a flex size directly (e.g.
  // "1fr"), the spec says that in this case it implies an automatic minimum.
  // TODO(jfernandez): https://github.com/w3c/csswg-drafts/issues/2611
  // TODO(jfernandez): We may have to change IsIntrinsicSizedGridArea too.
  if (min_track_breadth.IsFlex())
    min_track_breadth = Length::Auto();

  return GridTrackSize(min_track_breadth, max_track_breadth);
}

LayoutUnit GridTrackSizingAlgorithm::InitialBaseSize(
    const GridTrackSize& track_size) const {
  const GridLength& grid_length = track_size.MinTrackBreadth();

  // TODO(obrufau): https://github.com/w3c/csswg-drafts/issues/2611 may allow
  // flexible lengths to be used as min track sizing functions.
  DCHECK(!grid_length.IsFlex());

  const Length& track_length = grid_length.length();
  if (track_length.IsSpecified()) {
    DCHECK(!grid_length.HasPercentage() || AvailableSpace());
    return ValueForLength(track_length,
                          AvailableSpace().value_or(LayoutUnit()));
  }

  DCHECK(track_length.IsMinContent() || track_length.IsAuto() ||
         track_length.IsMaxContent());
  return LayoutUnit();
}

LayoutUnit GridTrackSizingAlgorithm::InitialGrowthLimit(
    const GridTrackSize& track_size,
    LayoutUnit base_size) const {
  const GridLength& grid_length = track_size.MaxTrackBreadth();
  if (grid_length.IsFlex())
    return base_size;

  const Length& track_length = grid_length.length();
  if (track_length.IsSpecified()) {
    DCHECK(!grid_length.HasPercentage() || AvailableSpace());
    return ValueForLength(track_length,
                          AvailableSpace().value_or(LayoutUnit()));
  }

  DCHECK(track_length.IsMinContent() || track_length.IsAuto() ||
         track_length.IsMaxContent());
  return LayoutUnit(kInfinity);
}

void GridTrackSizingAlgorithm::InitializeTrackSizes() {
  DCHECK(content_sized_tracks_index_.IsEmpty());
  DCHECK(flexible_sized_tracks_index_.IsEmpty());
  DCHECK(auto_sized_tracks_for_stretch_index_.IsEmpty());
  DCHECK(!has_percent_sized_rows_indefinite_height_);
  Vector<GridTrack>& track_list = Tracks(direction_);
  bool indefinite_height =
      direction_ == kForRows && !layout_grid_->CachedHasDefiniteLogicalHeight();
  size_t num_tracks = track_list.size();
  for (size_t i = 0; i < num_tracks; ++i) {
    const GridTrackSize& track_size = CalculateGridTrackSize(direction_, i);
    GridTrack& track = track_list[i];
    track.SetCachedTrackSize(track_size);
    track.SetBaseSize(InitialBaseSize(track_size));
    track.SetGrowthLimit(InitialGrowthLimit(track_size, track.BaseSize()));
    track.SetInfinitelyGrowable(false);

    if (track_size.IsFitContent()) {
      track.SetGrowthLimitCap(
          ValueForLength(track_size.FitContentTrackBreadth().length(),
                         AvailableSpace().value_or(LayoutUnit())));
    }

    if (track_size.IsContentSized())
      content_sized_tracks_index_.push_back(i);
    if (track_size.MaxTrackBreadth().IsFlex())
      flexible_sized_tracks_index_.push_back(i);
    if (track_size.HasAutoMaxTrackBreadth() && !track_size.IsFitContent())
      auto_sized_tracks_for_stretch_index_.push_back(i);

    if (!has_percent_sized_rows_indefinite_height_ && indefinite_height) {
      const GridTrackSize& raw_track_size = RawGridTrackSize(direction_, i);
      if (raw_track_size.MinTrackBreadth().HasPercentage() ||
          raw_track_size.MaxTrackBreadth().HasPercentage())
        has_percent_sized_rows_indefinite_height_ = true;
    }
  }
}

void GridTrackSizingAlgorithm::SizeTrackToFitNonSpanningItem(
    const GridSpan& span,
    LayoutBox& grid_item,
    GridTrack& track) {
  const size_t track_position = span.StartLine();
  const GridTrackSize& track_size =
      Tracks(direction_)[track_position].CachedTrackSize();

  if (track_size.HasMinContentMinTrackBreadth()) {
    track.SetBaseSize(
        std::max(track.BaseSize(), strategy_->MinContentForChild(grid_item)));
  } else if (track_size.HasMaxContentMinTrackBreadth()) {
    track.SetBaseSize(
        std::max(track.BaseSize(), strategy_->MaxContentForChild(grid_item)));
  } else if (track_size.HasAutoMinTrackBreadth()) {
    track.SetBaseSize(
        std::max(track.BaseSize(), strategy_->MinSizeForChild(grid_item)));
  }

  if (track_size.HasMinContentMaxTrackBreadth()) {
    track.SetGrowthLimit(std::max(track.GrowthLimit(),
                                  strategy_->MinContentForChild(grid_item)));
  } else if (track_size.HasMaxContentOrAutoMaxTrackBreadth()) {
    LayoutUnit growth_limit = strategy_->MaxContentForChild(grid_item);
    if (track_size.IsFitContent()) {
      growth_limit =
          std::min(growth_limit,
                   ValueForLength(track_size.FitContentTrackBreadth().length(),
                                  AvailableSpace().value_or(LayoutUnit())));
    }
    track.SetGrowthLimit(std::max(track.GrowthLimit(), growth_limit));
  }
}

bool GridTrackSizingAlgorithm::SpanningItemCrossesFlexibleSizedTracks(
    const GridSpan& span) const {
  const Vector<GridTrack>& track_list = Tracks(direction_);
  for (const auto& track_position : span) {
    const GridTrackSize& track_size =
        track_list[track_position].CachedTrackSize();
    if (track_size.MinTrackBreadth().IsFlex() ||
        track_size.MaxTrackBreadth().IsFlex())
      return true;
  }

  return false;
}

// We're basically using a class instead of a std::pair because of accessing
// gridItem() or getGridSpan() is much more self-explanatory that using .first
// or .second members in the pair. Having a std::pair<LayoutBox*, size_t>
// does not work either because we still need the GridSpan so we'd have to add
// an extra hash lookup for each item.
class GridItemWithSpan {
 public:
  GridItemWithSpan(LayoutBox& grid_item, const GridSpan& grid_span)
      : grid_item_(&grid_item), grid_span_(grid_span) {}

  LayoutBox& GridItem() const { return *grid_item_; }
  GridSpan GetGridSpan() const { return grid_span_; }

  bool operator<(const GridItemWithSpan other) const {
    return grid_span_.IntegerSpan() < other.grid_span_.IntegerSpan();
  }

 private:
  LayoutBox* grid_item_;
  GridSpan grid_span_;
};

struct GridItemsSpanGroupRange {
  Vector<GridItemWithSpan>::iterator range_start;
  Vector<GridItemWithSpan>::iterator range_end;
};

enum TrackSizeRestriction {
  kAllowInfinity,
  kForbidInfinity,
};

static LayoutUnit TrackSizeForTrackSizeComputationPhase(
    TrackSizeComputationPhase phase,
    const GridTrack& track,
    TrackSizeRestriction restriction) {
  switch (phase) {
    case kResolveIntrinsicMinimums:
    case kResolveContentBasedMinimums:
    case kResolveMaxContentMinimums:
    case kMaximizeTracks:
      return track.BaseSize();
    case kResolveIntrinsicMaximums:
    case kResolveMaxContentMaximums:
      const LayoutUnit& growth_limit = track.GrowthLimit();
      if (restriction == kAllowInfinity)
        return growth_limit;
      return growth_limit == kInfinity ? track.BaseSize() : growth_limit;
  }

  NOTREACHED();
  return track.BaseSize();
}

static bool ShouldProcessTrackForTrackSizeComputationPhase(
    TrackSizeComputationPhase phase,
    const GridTrackSize& track_size) {
  switch (phase) {
    case kResolveIntrinsicMinimums:
      return track_size.HasIntrinsicMinTrackBreadth();
    case kResolveContentBasedMinimums:
      return track_size.HasMinOrMaxContentMinTrackBreadth();
    case kResolveMaxContentMinimums:
      return track_size.HasMaxContentMinTrackBreadth();
    case kResolveIntrinsicMaximums:
      return track_size.HasIntrinsicMaxTrackBreadth();
    case kResolveMaxContentMaximums:
      return track_size.HasMaxContentOrAutoMaxTrackBreadth();
    case kMaximizeTracks:
      NOTREACHED();
      return false;
  }

  NOTREACHED();
  return false;
}

static bool TrackShouldGrowBeyondGrowthLimitsForTrackSizeComputationPhase(
    TrackSizeComputationPhase phase,
    const GridTrackSize& track_size) {
  switch (phase) {
    case kResolveIntrinsicMinimums:
    case kResolveContentBasedMinimums:
      return track_size
          .HasAutoOrMinContentMinTrackBreadthAndIntrinsicMaxTrackBreadth();
    case kResolveMaxContentMinimums:
      return track_size
          .HasMaxContentMinTrackBreadthAndMaxContentMaxTrackBreadth();
    case kResolveIntrinsicMaximums:
    case kResolveMaxContentMaximums:
      return true;
    case kMaximizeTracks:
      NOTREACHED();
      return false;
  }

  NOTREACHED();
  return false;
}

static void MarkAsInfinitelyGrowableForTrackSizeComputationPhase(
    TrackSizeComputationPhase phase,
    GridTrack& track) {
  switch (phase) {
    case kResolveIntrinsicMinimums:
    case kResolveContentBasedMinimums:
    case kResolveMaxContentMinimums:
      return;
    case kResolveIntrinsicMaximums:
      if (TrackSizeForTrackSizeComputationPhase(phase, track, kAllowInfinity) ==
              kInfinity &&
          track.PlannedSize() != kInfinity)
        track.SetInfinitelyGrowable(true);
      return;
    case kResolveMaxContentMaximums:
      if (track.InfinitelyGrowable())
        track.SetInfinitelyGrowable(false);
      return;
    case kMaximizeTracks:
      NOTREACHED();
      return;
  }

  NOTREACHED();
}

static void UpdateTrackSizeForTrackSizeComputationPhase(
    TrackSizeComputationPhase phase,
    GridTrack& track) {
  switch (phase) {
    case kResolveIntrinsicMinimums:
    case kResolveContentBasedMinimums:
    case kResolveMaxContentMinimums:
      track.SetBaseSize(track.PlannedSize());
      return;
    case kResolveIntrinsicMaximums:
    case kResolveMaxContentMaximums:
      track.SetGrowthLimit(track.PlannedSize());
      return;
    case kMaximizeTracks:
      NOTREACHED();
      return;
  }

  NOTREACHED();
}

LayoutUnit GridTrackSizingAlgorithm::ItemSizeForTrackSizeComputationPhase(
    TrackSizeComputationPhase phase,
    LayoutBox& grid_item) const {
  switch (phase) {
    case kResolveIntrinsicMinimums:
      return strategy_->MinSizeForChild(grid_item);
    case kResolveContentBasedMinimums:
    case kResolveIntrinsicMaximums:
      return strategy_->MinContentForChild(grid_item);
    case kResolveMaxContentMinimums:
    case kResolveMaxContentMaximums:
      return strategy_->MaxContentForChild(grid_item);
    case kMaximizeTracks:
      NOTREACHED();
      return LayoutUnit();
  }

  NOTREACHED();
  return LayoutUnit();
}

static bool SortByGridTrackGrowthPotential(const GridTrack* track1,
                                           const GridTrack* track2) {
  // This check ensures that we respect the irreflexivity property of the strict
  // weak ordering required by std::sort(forall x: NOT x < x).
  bool track1_has_infinite_growth_potential_without_cap =
      track1->InfiniteGrowthPotential() && !track1->GrowthLimitCap();
  bool track2_has_infinite_growth_potential_without_cap =
      track2->InfiniteGrowthPotential() && !track2->GrowthLimitCap();

  if (track1_has_infinite_growth_potential_without_cap &&
      track2_has_infinite_growth_potential_without_cap)
    return false;

  if (track1_has_infinite_growth_potential_without_cap ||
      track2_has_infinite_growth_potential_without_cap)
    return track2_has_infinite_growth_potential_without_cap;

  LayoutUnit track1_limit =
      track1->GrowthLimitCap().value_or(track1->GrowthLimit());
  LayoutUnit track2_limit =
      track2->GrowthLimitCap().value_or(track2->GrowthLimit());
  return (track1_limit - track1->BaseSize()) <
         (track2_limit - track2->BaseSize());
}

static void ClampGrowthShareIfNeeded(TrackSizeComputationPhase phase,
                                     const GridTrack& track,
                                     LayoutUnit& growth_share) {
  if (phase != kResolveMaxContentMaximums || !track.GrowthLimitCap())
    return;

  LayoutUnit distance_to_cap =
      track.GrowthLimitCap().value() - track.SizeDuringDistribution();
  if (distance_to_cap <= 0)
    return;

  growth_share = std::min(growth_share, distance_to_cap);
}

template <TrackSizeComputationPhase phase>
void GridTrackSizingAlgorithm::DistributeSpaceToTracks(
    Vector<GridTrack*>& tracks,
    Vector<GridTrack*>* grow_beyond_growth_limits_tracks,
    LayoutUnit& available_logical_space) const {
  DCHECK_GE(available_logical_space, 0);

  for (auto* track : tracks) {
    track->SetSizeDuringDistribution(
        TrackSizeForTrackSizeComputationPhase(phase, *track, kForbidInfinity));
  }

  if (available_logical_space > 0) {
    std::sort(tracks.begin(), tracks.end(), SortByGridTrackGrowthPotential);

    size_t tracks_size = tracks.size();
    for (size_t i = 0; i < tracks_size; ++i) {
      GridTrack& track = *tracks[i];
      LayoutUnit available_logical_space_share =
          available_logical_space / (tracks_size - i);
      const LayoutUnit& track_breadth =
          TrackSizeForTrackSizeComputationPhase(phase, track, kForbidInfinity);
      LayoutUnit growth_share =
          track.InfiniteGrowthPotential()
              ? available_logical_space_share
              : std::min(available_logical_space_share,
                         track.GrowthLimit() - track_breadth);
      ClampGrowthShareIfNeeded(phase, track, growth_share);
      DCHECK_GE(growth_share, 0) << "We must never shrink any grid track or "
                                    "else we can't guarantee we abide by our "
                                    "min-sizing function.";
      track.GrowSizeDuringDistribution(growth_share);
      available_logical_space -= growth_share;
    }
  }

  if (available_logical_space > 0 && grow_beyond_growth_limits_tracks) {
    // We need to sort them because there might be tracks with growth limit caps
    // (like the ones with fit-content()) which cannot indefinitely grow over
    // the limits.
    if (phase == kResolveMaxContentMaximums) {
      std::sort(grow_beyond_growth_limits_tracks->begin(),
                grow_beyond_growth_limits_tracks->end(),
                SortByGridTrackGrowthPotential);
    }

    size_t tracks_growing_above_max_breadth_size =
        grow_beyond_growth_limits_tracks->size();
    for (size_t i = 0; i < tracks_growing_above_max_breadth_size; ++i) {
      GridTrack* track = grow_beyond_growth_limits_tracks->at(i);
      LayoutUnit growth_share =
          available_logical_space / (tracks_growing_above_max_breadth_size - i);
      ClampGrowthShareIfNeeded(phase, *track, growth_share);
      DCHECK_GE(growth_share, 0) << "We must never shrink any grid track or "
                                    "else we can't guarantee we abide by our "
                                    "min-sizing function.";
      track->GrowSizeDuringDistribution(growth_share);
      available_logical_space -= growth_share;
    }
  }

  for (auto* track : tracks) {
    track->SetPlannedSize(
        track->PlannedSize() == kInfinity
            ? track->SizeDuringDistribution()
            : std::max(track->PlannedSize(), track->SizeDuringDistribution()));
  }
}

template <TrackSizeComputationPhase phase>
void GridTrackSizingAlgorithm::IncreaseSizesToAccommodateSpanningItems(
    const GridItemsSpanGroupRange& grid_items_with_span) {
  Vector<GridTrack>& all_tracks = Tracks(direction_);
  for (const auto& track_index : content_sized_tracks_index_) {
    GridTrack& track = all_tracks[track_index];
    track.SetPlannedSize(
        TrackSizeForTrackSizeComputationPhase(phase, track, kAllowInfinity));
  }

  Vector<GridTrack*> grow_beyond_growth_limits_tracks;
  Vector<GridTrack*> filtered_tracks;
  for (auto* it = grid_items_with_span.range_start;
       it != grid_items_with_span.range_end; ++it) {
    GridItemWithSpan& grid_item_with_span = *it;
    DCHECK_GT(grid_item_with_span.GetGridSpan().IntegerSpan(), 1u);
    const GridSpan& item_span = grid_item_with_span.GetGridSpan();

    grow_beyond_growth_limits_tracks.Shrink(0);
    filtered_tracks.Shrink(0);
    LayoutUnit spanning_tracks_size;
    for (const auto& track_position : item_span) {
      GridTrack& track = all_tracks[track_position];
      const GridTrackSize& track_size = track.CachedTrackSize();
      spanning_tracks_size +=
          TrackSizeForTrackSizeComputationPhase(phase, track, kForbidInfinity);
      if (!ShouldProcessTrackForTrackSizeComputationPhase(phase, track_size))
        continue;

      filtered_tracks.push_back(&track);

      if (TrackShouldGrowBeyondGrowthLimitsForTrackSizeComputationPhase(
              phase, track_size))
        grow_beyond_growth_limits_tracks.push_back(&track);
    }

    if (filtered_tracks.IsEmpty())
      continue;

    spanning_tracks_size +=
        layout_grid_->GuttersSize(grid_, direction_, item_span.StartLine(),
                                  item_span.IntegerSpan(), AvailableSpace());

    LayoutUnit extra_space = ItemSizeForTrackSizeComputationPhase(
                                 phase, grid_item_with_span.GridItem()) -
                             spanning_tracks_size;
    extra_space = extra_space.ClampNegativeToZero();
    auto& tracks_to_grow_beyond_growth_limits =
        grow_beyond_growth_limits_tracks.IsEmpty()
            ? filtered_tracks
            : grow_beyond_growth_limits_tracks;
    DistributeSpaceToTracks<phase>(
        filtered_tracks, &tracks_to_grow_beyond_growth_limits, extra_space);
  }

  for (const auto& track_index : content_sized_tracks_index_) {
    GridTrack& track = all_tracks[track_index];
    MarkAsInfinitelyGrowableForTrackSizeComputationPhase(phase, track);
    UpdateTrackSizeForTrackSizeComputationPhase(phase, track);
  }
}

void GridTrackSizingAlgorithm::ResolveIntrinsicTrackSizes() {
  Vector<GridTrack>& all_tracks = Tracks(direction_);
  Vector<GridItemWithSpan> items_sorted_by_increasing_span;
  if (grid_.HasGridItems()) {
    IterateGridItemsInTrackIndices(
        grid_, direction_, content_sized_tracks_index_,
        [&](LayoutBox* grid_item, const GridSpan& span) {
          if (span.IntegerSpan() == 1) {
            SizeTrackToFitNonSpanningItem(span, *grid_item,
                                          all_tracks[span.StartLine()]);
          } else if (!SpanningItemCrossesFlexibleSizedTracks(span)) {
            items_sorted_by_increasing_span.push_back(
                GridItemWithSpan(*grid_item, span));
          }
        });
    std::sort(items_sorted_by_increasing_span.begin(),
              items_sorted_by_increasing_span.end());
  }

  auto* it = items_sorted_by_increasing_span.begin();
  auto* end = items_sorted_by_increasing_span.end();
  while (it != end) {
    GridItemsSpanGroupRange span_group_range = {it,
                                                std::upper_bound(it, end, *it)};
    IncreaseSizesToAccommodateSpanningItems<kResolveIntrinsicMinimums>(
        span_group_range);
    IncreaseSizesToAccommodateSpanningItems<kResolveContentBasedMinimums>(
        span_group_range);
    IncreaseSizesToAccommodateSpanningItems<kResolveMaxContentMinimums>(
        span_group_range);
    IncreaseSizesToAccommodateSpanningItems<kResolveIntrinsicMaximums>(
        span_group_range);
    IncreaseSizesToAccommodateSpanningItems<kResolveMaxContentMaximums>(
        span_group_range);
    it = span_group_range.range_end;
  }

  for (const auto& track_index : content_sized_tracks_index_) {
    GridTrack& track = all_tracks[track_index];
    if (track.GrowthLimit() == kInfinity)
      track.SetGrowthLimit(track.BaseSize());
  }
}

void GridTrackSizingAlgorithm::ComputeGridContainerIntrinsicSizes() {
  min_content_size_ = max_content_size_ = LayoutUnit();

  Vector<GridTrack>& all_tracks = Tracks(direction_);
  for (auto& track : all_tracks) {
    DCHECK(strategy_->IsComputingSizeContainment() ||
           !track.InfiniteGrowthPotential());
    min_content_size_ += track.BaseSize();
    max_content_size_ +=
        track.GrowthLimitIsInfinite() ? track.BaseSize() : track.GrowthLimit();
    // The growth limit caps must be cleared now in order to properly sort
    // tracks by growth potential on an eventual "Maximize Tracks".
    track.SetGrowthLimitCap(base::nullopt);
  }
}

LayoutUnit GridTrackSizingAlgorithm::ComputeTrackBasedSize() const {
  LayoutUnit size;

  const Vector<GridTrack>& all_tracks = Tracks(direction_);
  for (auto& track : all_tracks) {
    size +=
        track.GrowthLimitIsInfinite() ? track.BaseSize() : track.GrowthLimit();
  }

  size += layout_grid_->GuttersSize(grid_, direction_, 0, all_tracks.size(),
                                    AvailableSpace());

  return size;
}

double GridTrackSizingAlgorithm::FindFrUnitSize(
    const GridSpan& tracks_span,
    LayoutUnit left_over_space) const {
  if (left_over_space <= 0)
    return 0;

  const Vector<GridTrack>& all_tracks = Tracks(direction_);
  double flex_factor_sum = 0;
  Vector<size_t, 8> flexible_tracks_indexes;
  for (const auto& track_index : tracks_span) {
    const GridTrackSize& track_size = all_tracks[track_index].CachedTrackSize();
    if (!track_size.MaxTrackBreadth().IsFlex()) {
      left_over_space -= all_tracks[track_index].BaseSize();
    } else {
      flexible_tracks_indexes.push_back(track_index);
      flex_factor_sum += track_size.MaxTrackBreadth().Flex();
    }
  }
  // We don't remove the gutters from left_over_space here, because that was
  // already done before.

  // The function is not called if we don't have <flex> grid tracks.
  DCHECK(!flexible_tracks_indexes.IsEmpty());

  return ComputeFlexFactorUnitSize(all_tracks, flex_factor_sum, left_over_space,
                                   flexible_tracks_indexes);
}

double GridTrackSizingAlgorithm::ComputeFlexFactorUnitSize(
    const Vector<GridTrack>& tracks,
    double flex_factor_sum,
    LayoutUnit& left_over_space,
    const Vector<size_t, 8>& flexible_tracks_indexes,
    std::unique_ptr<TrackIndexSet> tracks_to_treat_as_inflexible) const {
  // We want to avoid the effect of flex factors sum below 1 making the factor
  // unit size to grow exponentially.
  double hypothetical_factor_unit_size =
      left_over_space / std::max<double>(1, flex_factor_sum);

  // product of the hypothetical "flex factor unit" and any flexible track's
  // "flex factor" must be grater than such track's "base size".
  std::unique_ptr<TrackIndexSet> additional_tracks_to_treat_as_inflexible =
      std::move(tracks_to_treat_as_inflexible);
  bool valid_flex_factor_unit = true;
  for (auto index : flexible_tracks_indexes) {
    if (additional_tracks_to_treat_as_inflexible &&
        additional_tracks_to_treat_as_inflexible->Contains(index))
      continue;
    LayoutUnit base_size = tracks[index].BaseSize();
    double flex_factor =
        tracks[index].CachedTrackSize().MaxTrackBreadth().Flex();
    // treating all such tracks as inflexible.
    if (base_size > hypothetical_factor_unit_size * flex_factor) {
      left_over_space -= base_size;
      flex_factor_sum -= flex_factor;
      if (!additional_tracks_to_treat_as_inflexible) {
        additional_tracks_to_treat_as_inflexible =
            std::make_unique<TrackIndexSet>();
      }
      additional_tracks_to_treat_as_inflexible->insert(index);
      valid_flex_factor_unit = false;
    }
  }
  if (!valid_flex_factor_unit) {
    return ComputeFlexFactorUnitSize(
        tracks, flex_factor_sum, left_over_space, flexible_tracks_indexes,
        std::move(additional_tracks_to_treat_as_inflexible));
  }
  return hypothetical_factor_unit_size;
}

void GridTrackSizingAlgorithm::ComputeFlexSizedTracksGrowth(
    double flex_fraction,
    Vector<LayoutUnit>& increments,
    LayoutUnit& total_growth) const {
  size_t num_flex_tracks = flexible_sized_tracks_index_.size();
  DCHECK_EQ(increments.size(), num_flex_tracks);
  const Vector<GridTrack>& all_tracks = Tracks(direction_);
  for (size_t i = 0; i < num_flex_tracks; ++i) {
    size_t track_index = flexible_sized_tracks_index_[i];
    const GridTrackSize& track_size = all_tracks[track_index].CachedTrackSize();
    DCHECK(track_size.MaxTrackBreadth().IsFlex());
    LayoutUnit old_base_size = all_tracks[track_index].BaseSize();
    LayoutUnit new_base_size = std::max(
        old_base_size,
        LayoutUnit(flex_fraction * track_size.MaxTrackBreadth().Flex()));
    increments[i] = new_base_size - old_base_size;
    total_growth += increments[i];
  }
}

void GridTrackSizingAlgorithm::StretchFlexibleTracks(
    base::Optional<LayoutUnit> free_space) {
  if (flexible_sized_tracks_index_.IsEmpty())
    return;

  double flex_fraction = strategy_->FindUsedFlexFraction(
      flexible_sized_tracks_index_, direction_, free_space);

  LayoutUnit total_growth;
  Vector<LayoutUnit> increments;
  increments.Grow(flexible_sized_tracks_index_.size());
  ComputeFlexSizedTracksGrowth(flex_fraction, increments, total_growth);

  if (strategy_->RecomputeUsedFlexFractionIfNeeded(flexible_sized_tracks_index_,
                                                   flex_fraction, increments,
                                                   total_growth)) {
    total_growth = LayoutUnit(0);
    ComputeFlexSizedTracksGrowth(flex_fraction, increments, total_growth);
  }

  size_t i = 0;
  Vector<GridTrack>& all_tracks = Tracks(direction_);
  for (auto track_index : flexible_sized_tracks_index_) {
    auto& track = all_tracks[track_index];
    if (LayoutUnit increment = increments[i++])
      track.SetBaseSize(track.BaseSize() + increment);
  }
  if (FreeSpace(direction_)) {
    SetFreeSpace(direction_, FreeSpace(direction_).value() - total_growth);
  }
  max_content_size_ += total_growth;
}

void GridTrackSizingAlgorithm::StretchAutoTracks() {
  LayoutUnit free_space = strategy_->FreeSpaceForStretchAutoTracksStep();
  if (auto_sized_tracks_for_stretch_index_.IsEmpty() || (free_space <= 0) ||
      (layout_grid_->ContentAlignment(direction_).Distribution() !=
       ContentDistributionType::kStretch))
    return;

  unsigned number_of_auto_sized_tracks =
      auto_sized_tracks_for_stretch_index_.size();
  LayoutUnit size_to_increase = free_space / number_of_auto_sized_tracks;
  Vector<GridTrack>& all_tracks = Tracks(direction_);
  for (const auto& track_index : auto_sized_tracks_for_stretch_index_) {
    auto& track = all_tracks[track_index];
    LayoutUnit base_size = track.BaseSize() + size_to_increase;
    track.SetBaseSize(base_size);
  }
  SetFreeSpace(direction_, LayoutUnit());
}

void GridTrackSizingAlgorithm::AdvanceNextState() {
  switch (sizing_state_) {
    case kColumnSizingFirstIteration:
      sizing_state_ = kRowSizingFirstIteration;
      return;
    case kRowSizingFirstIteration:
      if (!strategy_->IsComputingSizeContainment())
        sizing_state_ = kColumnSizingSecondIteration;
      return;
    case kColumnSizingSecondIteration:
      sizing_state_ = kRowSizingSecondIteration;
      return;
    case kRowSizingSecondIteration:
      sizing_state_ = kColumnSizingFirstIteration;
      return;
  }
  NOTREACHED();
  sizing_state_ = kColumnSizingFirstIteration;
}

bool GridTrackSizingAlgorithm::IsValidTransition() const {
  switch (sizing_state_) {
    case kColumnSizingFirstIteration:
    case kColumnSizingSecondIteration:
      return direction_ == kForColumns;
    case kRowSizingFirstIteration:
    case kRowSizingSecondIteration:
      return direction_ == kForRows;
  }
  NOTREACHED();
  return false;
}

void GridTrackSizingAlgorithm::Setup(
    GridTrackSizingDirection direction,
    size_t num_tracks,
    base::Optional<LayoutUnit> available_space) {
  DCHECK(needs_setup_);
  direction_ = direction;
  SetAvailableSpace(
      direction, available_space ? available_space.value().ClampNegativeToZero()
                                 : available_space);

  if (available_space)
    strategy_ = std::make_unique<DefiniteSizeStrategy>(*this);
  else
    strategy_ = std::make_unique<IndefiniteSizeStrategy>(*this);

  content_sized_tracks_index_.Shrink(0);
  flexible_sized_tracks_index_.Shrink(0);
  auto_sized_tracks_for_stretch_index_.Shrink(0);
  has_percent_sized_rows_indefinite_height_ = false;

  if (available_space) {
    LayoutUnit gutters_size = layout_grid_->GuttersSize(
        grid_, direction, 0, grid_.NumTracks(direction), available_space);
    SetFreeSpace(direction, available_space.value() - gutters_size);
  } else {
    SetFreeSpace(direction, base::nullopt);
  }
  Tracks(direction).resize(num_tracks);

  ComputeBaselineAlignmentContext();

  needs_setup_ = false;
}

void GridTrackSizingAlgorithm::ComputeBaselineAlignmentContext() {
  GridAxis axis = GridAxisForDirection(direction_);
  baseline_alignment_.Clear(axis);
  baseline_alignment_.SetBlockFlow(layout_grid_->StyleRef().GetWritingMode());
  BaselineItemsCache& baseline_items_cache = axis == kGridColumnAxis
                                                 ? column_baseline_items_map_
                                                 : row_baseline_items_map_;
  for (auto* child : baseline_items_cache.Keys()) {
    // TODO (jfernandez): We may have to get rid of the baseline participation
    // flag (hence just using a HashSet) depending on the CSS WG resolution on
    // https://github.com/w3c/csswg-drafts/issues/3046
    if (CanParticipateInBaselineAlignment(*child, axis)) {
      UpdateBaselineAlignmentContext(*child, axis);
      baseline_items_cache.Set(child, true);
    } else {
      baseline_items_cache.Set(child, false);
    }
  }
}

// Described in https://drafts.csswg.org/css-grid/#algo-track-sizing
void GridTrackSizingAlgorithm::Run() {
  DCHECK(WasSetup());
  StateMachine state_machine(*this);

  // Step 1.
  base::Optional<LayoutUnit> initial_free_space = FreeSpace(direction_);
  InitializeTrackSizes();

  if (strategy_->IsComputingSizeContainment()) {
    ComputeGridContainerIntrinsicSizes();
    return;
  }

  // Step 2.
  if (!content_sized_tracks_index_.IsEmpty())
    ResolveIntrinsicTrackSizes();

  // This is not exactly a step of the track sizing algorithm, but we use the
  // track sizes computed
  // up to this moment (before maximization) to calculate the grid container
  // intrinsic sizes.
  ComputeGridContainerIntrinsicSizes();

  if (FreeSpace(direction_)) {
    LayoutUnit updated_free_space =
        FreeSpace(direction_).value() - min_content_size_;
    SetFreeSpace(direction_, updated_free_space);
    if (updated_free_space <= 0)
      return;
  }

  // Step 3.
  strategy_->MaximizeTracks(Tracks(direction_), direction_ == kForColumns
                                                    ? free_space_columns_
                                                    : free_space_rows_);

  // Step 4.
  StretchFlexibleTracks(initial_free_space);

  // Step 5.
  StretchAutoTracks();
}

void GridTrackSizingAlgorithm::Reset() {
  DCHECK(WasSetup());
  sizing_state_ = kColumnSizingFirstIteration;
  columns_.Shrink(0);
  rows_.Shrink(0);
  content_sized_tracks_index_.Shrink(0);
  flexible_sized_tracks_index_.Shrink(0);
  auto_sized_tracks_for_stretch_index_.Shrink(0);
  has_percent_sized_rows_indefinite_height_ = false;
  SetAvailableSpace(kForRows, base::nullopt);
  SetAvailableSpace(kForColumns, base::nullopt);
}

#if DCHECK_IS_ON()
bool GridTrackSizingAlgorithm::TracksAreWiderThanMinTrackBreadth() const {
  const Vector<GridTrack>& all_tracks = Tracks(direction_);
  for (size_t i = 0; i < all_tracks.size(); ++i) {
    const GridTrackSize& track_size = all_tracks[i].CachedTrackSize();
    if (InitialBaseSize(track_size) > all_tracks[i].BaseSize())
      return false;
  }
  return true;
}
#endif

GridTrackSizingAlgorithm::StateMachine::StateMachine(
    GridTrackSizingAlgorithm& algorithm)
    : algorithm_(algorithm) {
  DCHECK(algorithm_.IsValidTransition());
  DCHECK(!algorithm_.needs_setup_);
}

GridTrackSizingAlgorithm::StateMachine::~StateMachine() {
  algorithm_.AdvanceNextState();
  algorithm_.needs_setup_ = true;
}

}  // namespace blink
