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

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

#include <algorithm>
#include <limits>
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/layout/hit_test_result.h"
#include "third_party/blink/renderer/core/layout/layout_analyzer.h"
#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
#include "third_party/blink/renderer/core/layout/layout_table_col.h"
#include "third_party/blink/renderer/core/layout/layout_table_row.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/subtree_layout_scope.h"
#include "third_party/blink/renderer/core/paint/table_section_painter.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"

namespace blink {

void LayoutTableSection::TableGridRow::
    SetRowLogicalHeightToRowStyleLogicalHeight() {
  DCHECK(row);
  logical_height = row->StyleRef().LogicalHeight();
}

void LayoutTableSection::TableGridRow::UpdateLogicalHeightForCell(
    const LayoutTableCell* cell) {
  // We ignore height settings on rowspan cells.
  if (cell->ResolvedRowSpan() != 1)
    return;

  Length cell_logical_height = cell->StyleRef().LogicalHeight();
  if (cell_logical_height.IsPositive()) {
    switch (cell_logical_height.GetType()) {
      case kPercent:
        // TODO(alancutter): Make this work correctly for calc lengths.
        if (!(logical_height.IsPercentOrCalc()) ||
            (logical_height.IsPercent() &&
             logical_height.Percent() < cell_logical_height.Percent()))
          logical_height = cell_logical_height;
        break;
      case kFixed:
        if (logical_height.GetType() < kPercent ||
            (logical_height.IsFixed() &&
             logical_height.Value() < cell_logical_height.Value()))
          logical_height = cell_logical_height;
        break;
      default:
        break;
    }
  }
}

void CellSpan::EnsureConsistency(const unsigned maximum_span_size) {
  static_assert(std::is_same<decltype(start_), unsigned>::value,
                "Asserts below assume start_ is unsigned");
  static_assert(std::is_same<decltype(end_), unsigned>::value,
                "Asserts below assume end_ is unsigned");
  CHECK_LE(start_, maximum_span_size);
  CHECK_LE(end_, maximum_span_size);
  CHECK_LE(start_, end_);
}

LayoutTableSection::LayoutTableSection(Element* element)
    : LayoutTableBoxComponent(element),
      c_col_(0),
      c_row_(0),
      needs_cell_recalc_(false),
      force_full_paint_(false),
      has_multiple_cell_levels_(false),
      has_spanning_cells_(false),
      is_repeating_header_group_(false),
      is_repeating_footer_group_(false) {
  // init LayoutObject attributes
  SetInline(false);  // our object is not Inline
}

LayoutTableSection::~LayoutTableSection() = default;

void LayoutTableSection::StyleDidChange(StyleDifference diff,
                                        const ComputedStyle* old_style) {
  DCHECK(StyleRef().Display() == EDisplay::kTableFooterGroup ||
         StyleRef().Display() == EDisplay::kTableRowGroup ||
         StyleRef().Display() == EDisplay::kTableHeaderGroup);

  LayoutTableBoxComponent::StyleDidChange(diff, old_style);
  PropagateStyleToAnonymousChildren();

  if (!old_style)
    return;

  LayoutTable* table = Table();
  if (!table)
    return;

  LayoutTableBoxComponent::InvalidateCollapsedBordersOnStyleChange(
      *this, *table, diff, *old_style);

  if (LayoutTableBoxComponent::DoCellsHaveDirtyWidth(*this, *table, diff,
                                                     *old_style)) {
    MarkAllCellsWidthsDirtyAndOrNeedsLayout(
        LayoutTable::kMarkDirtyAndNeedsLayout);
  }
}

void LayoutTableSection::WillBeRemovedFromTree() {
  LayoutTableBoxComponent::WillBeRemovedFromTree();

  // Preventively invalidate our cells as we may be re-inserted into
  // a new table which would require us to rebuild our structure.
  SetNeedsCellRecalc();
}

void LayoutTableSection::AddChild(LayoutObject* child,
                                  LayoutObject* before_child) {
  if (!child->IsTableRow()) {
    LayoutObject* last = before_child;
    if (!last)
      last = LastRow();
    if (last && last->IsAnonymous() && last->IsTablePart() &&
        !last->IsBeforeOrAfterContent()) {
      if (before_child == last)
        before_child = last->SlowFirstChild();
      last->AddChild(child, before_child);
      return;
    }

    if (before_child && !before_child->IsAnonymous() &&
        before_child->Parent() == this) {
      LayoutObject* row = before_child->PreviousSibling();
      if (row && row->IsTableRow() && row->IsAnonymous()) {
        row->AddChild(child);
        return;
      }
    }

    // If beforeChild is inside an anonymous cell/row, insert into the cell or
    // into the anonymous row containing it, if there is one.
    LayoutObject* last_box = last;
    while (last_box && last_box->Parent()->IsAnonymous() &&
           !last_box->IsTableRow())
      last_box = last_box->Parent();
    if (last_box && last_box->IsAnonymous() &&
        !last_box->IsBeforeOrAfterContent()) {
      last_box->AddChild(child, before_child);
      return;
    }

    LayoutObject* row = LayoutTableRow::CreateAnonymousWithParent(this);
    AddChild(row, before_child);
    row->AddChild(child);
    return;
  }

  if (before_child)
    SetNeedsCellRecalc();

  unsigned insertion_row = c_row_;
  ++c_row_;
  c_col_ = 0;

  EnsureRows(c_row_);

  LayoutTableRow* row = ToLayoutTableRow(child);
  grid_[insertion_row].row = row;
  row->SetRowIndex(insertion_row);

  if (!before_child)
    grid_[insertion_row].SetRowLogicalHeightToRowStyleLogicalHeight();

  if (before_child && before_child->Parent() != this)
    before_child = SplitAnonymousBoxesAroundChild(before_child);

  DCHECK(!before_child || before_child->IsTableRow());
  LayoutTableBoxComponent::AddChild(child, before_child);
}

static inline void CheckThatVectorIsDOMOrdered(
    const Vector<LayoutTableCell*, 1>& cells) {
#ifndef NDEBUG
  // This function should be called on a non-empty vector.
  DCHECK_GT(cells.size(), 0u);

  const LayoutTableCell* previous_cell = cells[0];
  for (wtf_size_t i = 1; i < cells.size(); ++i) {
    const LayoutTableCell* current_cell = cells[i];
    // The check assumes that all cells belong to the same row group.
    DCHECK_EQ(previous_cell->Section(), current_cell->Section());

    // 2 overlapping cells can't be on the same row.
    DCHECK_NE(current_cell->Row(), previous_cell->Row());

    // Look backwards in the tree for the previousCell's row. If we are
    // DOM ordered, we should find it.
    const LayoutTableRow* row = current_cell->Row();
    for (; row && row != previous_cell->Row(); row = row->PreviousRow()) {
    }
    DCHECK_EQ(row, previous_cell->Row());

    previous_cell = current_cell;
  }
#endif  // NDEBUG
}

void LayoutTableSection::AddCell(LayoutTableCell* cell, LayoutTableRow* row) {
  // We don't insert the cell if we need cell recalc as our internal columns'
  // representation will have drifted from the table's representation. Also
  // recalcCells will call addCell at a later time after sync'ing our columns'
  // with the table's.
  if (NeedsCellRecalc())
    return;

  DCHECK(cell);
  unsigned r_span = cell->ResolvedRowSpan();
  unsigned c_span = cell->ColSpan();
  if (r_span > 1 || c_span > 1)
    has_spanning_cells_ = true;

  const Vector<LayoutTable::ColumnStruct>& columns =
      Table()->EffectiveColumns();
  unsigned insertion_row = row->RowIndex();

  // ### mozilla still seems to do the old HTML way, even for strict DTD
  // (see the annotation on table cell layouting in the CSS specs and the
  // testcase below:
  // <TABLE border>
  // <TR><TD>1 <TD rowspan="2">2 <TD>3 <TD>4
  // <TR><TD colspan="2">5
  // </TABLE>
  unsigned n_cols = NumCols(insertion_row);
  while (c_col_ < n_cols && (GridCellAt(insertion_row, c_col_).HasCells() ||
                             GridCellAt(insertion_row, c_col_).InColSpan()))
    c_col_++;

  grid_[insertion_row].UpdateLogicalHeightForCell(cell);

  EnsureRows(insertion_row + r_span);

  grid_[insertion_row].row = row;

  unsigned col = c_col_;
  // tell the cell where it is
  bool in_col_span = false;
  unsigned col_size = columns.size();
  while (c_span) {
    unsigned current_span;
    if (c_col_ >= col_size) {
      Table()->AppendEffectiveColumn(c_span);
      current_span = c_span;
    } else {
      if (c_span < columns[c_col_].span)
        Table()->SplitEffectiveColumn(c_col_, c_span);
      current_span = columns[c_col_].span;
    }
    for (unsigned r = 0; r < r_span; r++) {
      EnsureCols(insertion_row + r, c_col_ + 1);
      auto& grid_cell = GridCellAt(insertion_row + r, c_col_);
      grid_cell.Cells().push_back(cell);
      CheckThatVectorIsDOMOrdered(grid_cell.Cells());
      // If cells overlap then we take the special paint path for them.
      if (grid_cell.Cells().size() > 1)
        has_multiple_cell_levels_ = true;
      if (in_col_span)
        grid_cell.SetInColSpan(true);
    }
    c_col_++;
    c_span -= current_span;
    in_col_span = true;
  }
  cell->SetAbsoluteColumnIndex(Table()->EffectiveColumnToAbsoluteColumn(col));
}

bool LayoutTableSection::RowHasOnlySpanningCells(unsigned row) {
  if (grid_[row].grid_cells.IsEmpty())
    return false;

  for (const auto& grid_cell : grid_[row].grid_cells) {
    // Empty cell is not a valid cell so it is not a rowspan cell.
    if (!grid_cell.HasCells())
      return false;

    if (grid_cell.Cells()[0]->ResolvedRowSpan() == 1)
      return false;
  }

  return true;
}

void LayoutTableSection::PopulateSpanningRowsHeightFromCell(
    LayoutTableCell* cell,
    struct SpanningRowsHeight& spanning_rows_height) {
  const unsigned row_span = cell->ResolvedRowSpan();
  const unsigned row_index = cell->RowIndex();

  spanning_rows_height.spanning_cell_height_ignoring_border_spacing =
      cell->LogicalHeightForRowSizing();

  spanning_rows_height.row_height.resize(row_span);
  spanning_rows_height.total_rows_height = 0;
  for (unsigned row = 0; row < row_span; row++) {
    unsigned actual_row = row + row_index;

    spanning_rows_height.row_height[row] = row_pos_[actual_row + 1] -
                                           row_pos_[actual_row] -
                                           BorderSpacingForRow(actual_row);
    if (!spanning_rows_height.row_height[row])
      spanning_rows_height.is_any_row_with_only_spanning_cells |=
          RowHasOnlySpanningCells(actual_row);

    spanning_rows_height.total_rows_height +=
        spanning_rows_height.row_height[row];
    spanning_rows_height.spanning_cell_height_ignoring_border_spacing -=
        BorderSpacingForRow(actual_row);
  }
  // We don't span the following row so its border-spacing (if any) should be
  // included.
  spanning_rows_height.spanning_cell_height_ignoring_border_spacing +=
      BorderSpacingForRow(row_index + row_span - 1);
}

void LayoutTableSection::DistributeExtraRowSpanHeightToPercentRows(
    LayoutTableCell* cell,
    float total_percent,
    int& extra_row_spanning_height,
    Vector<int>& rows_height) {
  if (!extra_row_spanning_height || !total_percent)
    return;

  const unsigned row_span = cell->ResolvedRowSpan();
  const unsigned row_index = cell->RowIndex();
  float percent = std::min(total_percent, 100.0f);
  const int table_height = row_pos_[grid_.size()] + extra_row_spanning_height;

  // Our algorithm matches Firefox. Extra spanning height would be distributed
  // Only in first percent height rows those total percent is 100. Other percent
  // rows would be uneffected even extra spanning height is remain.
  int accumulated_position_increase = 0;
  for (unsigned row = row_index; row < (row_index + row_span); row++) {
    if (percent > 0 && extra_row_spanning_height > 0) {
      // TODO(alancutter): Make this work correctly for calc lengths.
      if (grid_[row].logical_height.IsPercent()) {
        int to_add =
            (table_height *
             std::min(grid_[row].logical_height.Percent(), percent) / 100) -
            rows_height[row - row_index];

        to_add = std::max(std::min(to_add, extra_row_spanning_height), 0);
        accumulated_position_increase += to_add;
        extra_row_spanning_height -= to_add;
        percent -= grid_[row].logical_height.Percent();
      }
    }
    row_pos_[row + 1] += accumulated_position_increase;
  }
}

static void UpdatePositionIncreasedWithRowHeight(
    int extra_height,
    float row_height,
    float total_height,
    int& accumulated_position_increase,
    double& remainder) {
  // Without the cast we lose enough precision to cause heights to miss pixels
  // (and trigger asserts) in some layout tests.
  double proportional_position_increase =
      remainder + (extra_height * double(row_height)) / total_height;
  // The epsilon is to push any values that are close to a whole number but
  // aren't due to floating point imprecision. The epsilons are not accumulated,
  // any that aren't necessary are lost in the cast to int.
  int position_increase_int = proportional_position_increase + 0.000001;
  accumulated_position_increase += position_increase_int;
  remainder = proportional_position_increase - position_increase_int;
}

// This is mainly used to distribute whole extra rowspanning height in percent
// rows when all spanning rows are percent rows.
// Distributing whole extra rowspanning height in percent rows based on the
// ratios of percent because this method works same as percent distribution when
// only percent rows are present and percent is 100. Also works perfectly fine
// when percent is not equal to 100.
void LayoutTableSection::DistributeWholeExtraRowSpanHeightToPercentRows(
    LayoutTableCell* cell,
    float total_percent,
    int& extra_row_spanning_height,
    Vector<int>& rows_height) {
  if (!extra_row_spanning_height || !total_percent)
    return;

  const unsigned row_span = cell->ResolvedRowSpan();
  const unsigned row_index = cell->RowIndex();
  double remainder = 0;

  int accumulated_position_increase = 0;
  for (unsigned row = row_index; row < (row_index + row_span); row++) {
    // TODO(alancutter): Make this work correctly for calc lengths.
    if (grid_[row].logical_height.IsPercent()) {
      UpdatePositionIncreasedWithRowHeight(
          extra_row_spanning_height, grid_[row].logical_height.Percent(),
          total_percent, accumulated_position_increase, remainder);
    }
    row_pos_[row + 1] += accumulated_position_increase;
  }

  DCHECK(!round(remainder)) << "remainder was " << remainder;

  extra_row_spanning_height -= accumulated_position_increase;
}

void LayoutTableSection::DistributeExtraRowSpanHeightToAutoRows(
    LayoutTableCell* cell,
    int total_auto_rows_height,
    int& extra_row_spanning_height,
    Vector<int>& rows_height) {
  if (!extra_row_spanning_height || !total_auto_rows_height)
    return;

  const unsigned row_span = cell->ResolvedRowSpan();
  const unsigned row_index = cell->RowIndex();
  int accumulated_position_increase = 0;
  double remainder = 0;

  // Aspect ratios of auto rows should not change otherwise table may look
  // different than user expected. So extra height distributed in auto spanning
  // rows based on their weight in spanning cell.
  for (unsigned row = row_index; row < (row_index + row_span); row++) {
    if (grid_[row].logical_height.IsAuto()) {
      UpdatePositionIncreasedWithRowHeight(
          extra_row_spanning_height, rows_height[row - row_index],
          total_auto_rows_height, accumulated_position_increase, remainder);
    }
    row_pos_[row + 1] += accumulated_position_increase;
  }

  DCHECK(!round(remainder)) << "remainder was " << remainder;

  extra_row_spanning_height -= accumulated_position_increase;
}

void LayoutTableSection::DistributeExtraRowSpanHeightToRemainingRows(
    LayoutTableCell* cell,
    int total_remaining_rows_height,
    int& extra_row_spanning_height,
    Vector<int>& rows_height) {
  if (!extra_row_spanning_height || !total_remaining_rows_height)
    return;

  const unsigned row_span = cell->ResolvedRowSpan();
  const unsigned row_index = cell->RowIndex();
  int accumulated_position_increase = 0;
  double remainder = 0;

  // Aspect ratios of the rows should not change otherwise table may look
  // different than user expected. So extra height distribution in remaining
  // spanning rows based on their weight in spanning cell.
  for (unsigned row = row_index; row < (row_index + row_span); row++) {
    if (!grid_[row].logical_height.IsPercentOrCalc()) {
      UpdatePositionIncreasedWithRowHeight(
          extra_row_spanning_height, rows_height[row - row_index],
          total_remaining_rows_height, accumulated_position_increase,
          remainder);
    }
    row_pos_[row + 1] += accumulated_position_increase;
  }

  DCHECK(!round(remainder)) << "remainder was " << remainder;

  extra_row_spanning_height -= accumulated_position_increase;
}

static bool CellIsFullyIncludedInOtherCell(const LayoutTableCell* cell1,
                                           const LayoutTableCell* cell2) {
  return (cell1->RowIndex() >= cell2->RowIndex() &&
          (cell1->RowIndex() + cell1->ResolvedRowSpan()) <=
              (cell2->RowIndex() + cell2->ResolvedRowSpan()));
}

// To avoid unneeded extra height distributions, we apply the following sorting
// algorithm:
static bool CompareRowSpanCellsInHeightDistributionOrder(
    const LayoutTableCell* cell1,
    const LayoutTableCell* cell2) {
  // Sorting bigger height cell first if cells are at same index with same span
  // because we will skip smaller height cell to distribute it's extra height.
  if (cell1->RowIndex() == cell2->RowIndex() &&
      cell1->ResolvedRowSpan() == cell2->ResolvedRowSpan())
    return (cell1->LogicalHeightForRowSizing() >
            cell2->LogicalHeightForRowSizing());
  // Sorting inner most cell first because if inner spanning cell'e extra height
  // is distributed then outer spanning cell's extra height will adjust
  // accordingly. In reverse order, there is more chances that outer spanning
  // cell's height will exceed than defined by user.
  if (CellIsFullyIncludedInOtherCell(cell1, cell2))
    return true;
  // Sorting lower row index first because first we need to apply the extra
  // height of spanning cell which comes first in the table so lower rows's
  // position would increment in sequence.
  if (!CellIsFullyIncludedInOtherCell(cell2, cell1))
    return (cell1->RowIndex() < cell2->RowIndex());

  return false;
}

unsigned LayoutTableSection::CalcRowHeightHavingOnlySpanningCells(
    unsigned row,
    int& accumulated_cell_position_increase,
    unsigned row_to_apply_extra_height,
    unsigned& extra_table_height_to_propgate,
    Vector<int>& rows_count_with_only_spanning_cells) {
  DCHECK(RowHasOnlySpanningCells(row));

  unsigned row_height = 0;

  for (const auto& row_span_cell : grid_[row].grid_cells) {
    DCHECK(row_span_cell.HasCells());
    LayoutTableCell* cell = row_span_cell.Cells()[0];
    DCHECK_GE(cell->ResolvedRowSpan(), 2u);

    const unsigned cell_row_index = cell->RowIndex();
    const unsigned cell_row_span = cell->ResolvedRowSpan();

    // As we are going from the top of the table to the bottom to calculate the
    // row heights for rows that only contain spanning cells and all previous
    // rows are processed we only need to find the number of rows with spanning
    // cells from the current cell to the end of the current cells spanning
    // height.
    unsigned start_row_for_spanning_cell_count = std::max(cell_row_index, row);
    unsigned end_row = cell_row_index + cell_row_span;
    unsigned spanning_cells_rows_count_having_zero_height =
        rows_count_with_only_spanning_cells[end_row - 1];

    if (start_row_for_spanning_cell_count)
      spanning_cells_rows_count_having_zero_height -=
          rows_count_with_only_spanning_cells
              [start_row_for_spanning_cell_count - 1];

    int total_rowspan_cell_height =
        (row_pos_[end_row] - row_pos_[cell_row_index]) -
        BorderSpacingForRow(end_row - 1);

    total_rowspan_cell_height += accumulated_cell_position_increase;
    if (row_to_apply_extra_height >= cell_row_index &&
        row_to_apply_extra_height < end_row)
      total_rowspan_cell_height += extra_table_height_to_propgate;

    if (total_rowspan_cell_height < cell->LogicalHeightForRowSizing()) {
      unsigned extra_height_required =
          cell->LogicalHeightForRowSizing() - total_rowspan_cell_height;

      row_height = std::max(
          row_height,
          extra_height_required / spanning_cells_rows_count_having_zero_height);
    }
  }

  return row_height;
}

void LayoutTableSection::UpdateRowsHeightHavingOnlySpanningCells(
    LayoutTableCell* cell,
    struct SpanningRowsHeight& spanning_rows_height,
    unsigned& extra_height_to_propagate,
    Vector<int>& rows_count_with_only_spanning_cells) {
  DCHECK(spanning_rows_height.row_height.size());

  int accumulated_position_increase = 0;
  const unsigned row_span = cell->ResolvedRowSpan();
  const unsigned row_index = cell->RowIndex();

  DCHECK_EQ(row_span, spanning_rows_height.row_height.size());

  for (unsigned row = 0; row < spanning_rows_height.row_height.size(); row++) {
    unsigned actual_row = row + row_index;
    if (!spanning_rows_height.row_height[row] &&
        RowHasOnlySpanningCells(actual_row)) {
      spanning_rows_height.row_height[row] =
          CalcRowHeightHavingOnlySpanningCells(
              actual_row, accumulated_position_increase, row_index + row_span,
              extra_height_to_propagate, rows_count_with_only_spanning_cells);
      accumulated_position_increase += spanning_rows_height.row_height[row];
    }
    row_pos_[actual_row + 1] += accumulated_position_increase;
  }

  spanning_rows_height.total_rows_height += accumulated_position_increase;
}

// Distribute rowSpan cell height in rows those comes in rowSpan cell based on
// the ratio of row's height if 1 RowSpan cell height is greater than the total
// height of rows in rowSpan cell.
void LayoutTableSection::DistributeRowSpanHeightToRows(
    SpanningLayoutTableCells& row_span_cells) {
  DCHECK(row_span_cells.size());

  // 'rowSpanCells' list is already sorted based on the cells rowIndex in
  // ascending order
  // Arrange row spanning cell in the order in which we need to process first.
  std::sort(row_span_cells.begin(), row_span_cells.end(),
            CompareRowSpanCellsInHeightDistributionOrder);

  unsigned extra_height_to_propagate = 0;
  unsigned last_row_index = 0;
  unsigned last_row_span = 0;

  Vector<int> rows_count_with_only_spanning_cells;

  // At this stage, Height of the rows are zero for the one containing only
  // spanning cells.
  int count = 0;
  for (unsigned row = 0; row < grid_.size(); row++) {
    if (RowHasOnlySpanningCells(row))
      count++;
    rows_count_with_only_spanning_cells.push_back(count);
  }

  for (unsigned i = 0; i < row_span_cells.size(); i++) {
    LayoutTableCell* cell = row_span_cells[i];

    unsigned row_index = cell->RowIndex();

    unsigned row_span = cell->ResolvedRowSpan();

    unsigned spanning_cell_end_index = row_index + row_span;
    unsigned last_spanning_cell_end_index = last_row_index + last_row_span;

    // Only the highest spanning cell will distribute its extra height in a row
    // if more than one spanning cell is present at the same level.
    if (row_index == last_row_index && row_span == last_row_span)
      continue;

    int original_before_position = row_pos_[spanning_cell_end_index];

    // When 2 spanning cells are ending at same row index then while extra
    // height distribution of first spanning cell updates position of the last
    // row so getting the original position of the last row in second spanning
    // cell need to reduce the height changed by first spanning cell.
    if (spanning_cell_end_index == last_spanning_cell_end_index)
      original_before_position -= extra_height_to_propagate;

    if (extra_height_to_propagate) {
      for (unsigned row = last_spanning_cell_end_index + 1;
           row <= spanning_cell_end_index; row++)
        row_pos_[row] += extra_height_to_propagate;
    }

    last_row_index = row_index;
    last_row_span = row_span;

    struct SpanningRowsHeight spanning_rows_height;

    PopulateSpanningRowsHeightFromCell(cell, spanning_rows_height);

    // Here we are handling only row(s) who have only rowspanning cells and do
    // not have any empty cell.
    if (spanning_rows_height.is_any_row_with_only_spanning_cells)
      UpdateRowsHeightHavingOnlySpanningCells(
          cell, spanning_rows_height, extra_height_to_propagate,
          rows_count_with_only_spanning_cells);

    // This code handle row(s) that have rowspanning cell(s) and at least one
    // empty cell. Such rows are not handled below and end up having a height of
    // 0. That would mean content overlapping if one of their cells has any
    // content. To avoid the problem, we add all the remaining spanning cells'
    // height to the last spanned row. This means that we could grow a row past
    // its 'height' or break percentage spreading however this is better than
    // overlapping content.
    // FIXME: Is there a better algorithm?
    if (!spanning_rows_height.total_rows_height) {
      if (spanning_rows_height.spanning_cell_height_ignoring_border_spacing)
        row_pos_[spanning_cell_end_index] +=
            spanning_rows_height.spanning_cell_height_ignoring_border_spacing +
            BorderSpacingForRow(spanning_cell_end_index - 1);

      extra_height_to_propagate =
          row_pos_[spanning_cell_end_index] - original_before_position;
      continue;
    }

    if (spanning_rows_height.spanning_cell_height_ignoring_border_spacing <=
        spanning_rows_height.total_rows_height) {
      extra_height_to_propagate =
          row_pos_[row_index + row_span] - original_before_position;
      continue;
    }

    // Below we are handling only row(s) who have at least one visible cell
    // without rowspan value.
    float total_percent = 0;
    int total_auto_rows_height = 0;
    int total_remaining_rows_height = spanning_rows_height.total_rows_height;

    // FIXME: Inner spanning cell height should not change if it have fixed
    // height when it's parent spanning cell is distributing it's extra height
    // in rows.

    // Calculate total percentage, total auto rows height and total rows height
    // except percent rows.
    for (unsigned row = row_index; row < spanning_cell_end_index; row++) {
      // TODO(alancutter): Make this work correctly for calc lengths.
      if (grid_[row].logical_height.IsPercent()) {
        total_percent += grid_[row].logical_height.Percent();
        total_remaining_rows_height -=
            spanning_rows_height.row_height[row - row_index];
      } else if (grid_[row].logical_height.IsAuto()) {
        total_auto_rows_height +=
            spanning_rows_height.row_height[row - row_index];
      }
    }

    int extra_row_spanning_height =
        spanning_rows_height.spanning_cell_height_ignoring_border_spacing -
        spanning_rows_height.total_rows_height;

    if (total_percent < 100 && !total_auto_rows_height &&
        !total_remaining_rows_height) {
      // Distributing whole extra rowspanning height in percent row when only
      // non-percent rows height is 0.
      DistributeWholeExtraRowSpanHeightToPercentRows(
          cell, total_percent, extra_row_spanning_height,
          spanning_rows_height.row_height);
    } else {
      DistributeExtraRowSpanHeightToPercentRows(
          cell, total_percent, extra_row_spanning_height,
          spanning_rows_height.row_height);
      DistributeExtraRowSpanHeightToAutoRows(cell, total_auto_rows_height,
                                             extra_row_spanning_height,
                                             spanning_rows_height.row_height);
      DistributeExtraRowSpanHeightToRemainingRows(
          cell, total_remaining_rows_height, extra_row_spanning_height,
          spanning_rows_height.row_height);
    }

    DCHECK(!extra_row_spanning_height);

    // Getting total changed height in the table
    extra_height_to_propagate =
        row_pos_[spanning_cell_end_index] - original_before_position;
  }

  if (extra_height_to_propagate) {
    // Apply changed height by rowSpan cells to rows present at the end of the
    // table
    for (unsigned row = last_row_index + last_row_span + 1; row <= grid_.size();
         row++)
      row_pos_[row] += extra_height_to_propagate;
  }
}

bool LayoutTableSection::RowHasVisibilityCollapse(unsigned row) const {
  return ((grid_[row].row &&
           grid_[row].row->StyleRef().Visibility() == EVisibility::kCollapse) ||
          StyleRef().Visibility() == EVisibility::kCollapse);
}

// Find out the baseline of the cell
// If the cell's baseline is more than the row's baseline then the cell's
// baseline become the row's baseline and if the row's baseline goes out of the
// row's boundaries then adjust row height accordingly.
void LayoutTableSection::UpdateBaselineForCell(LayoutTableCell* cell,
                                               unsigned row,
                                               LayoutUnit& baseline_descent) {
  if (!cell->IsBaselineAligned())
    return;

  // Ignoring the intrinsic padding as it depends on knowing the row's baseline,
  // which won't be accurate until the end of this function.
  LayoutUnit baseline_position =
      cell->CellBaselinePosition() - cell->IntrinsicPaddingBefore();
  if (baseline_position >
      cell->BorderBefore() +
          (cell->PaddingBefore() - cell->IntrinsicPaddingBefore())) {
    grid_[row].baseline = std::max(grid_[row].baseline, baseline_position);

    LayoutUnit cell_start_row_baseline_descent;
    if (cell->ResolvedRowSpan() == 1) {
      baseline_descent =
          std::max(baseline_descent,
                   cell->LogicalHeightForRowSizing() - baseline_position);
      cell_start_row_baseline_descent = baseline_descent;
    }
    row_pos_[row + 1] = std::max(
        row_pos_[row + 1],
        (row_pos_[row] + grid_[row].baseline + cell_start_row_baseline_descent)
            .ToInt());
  }
}

int LayoutTableSection::VBorderSpacingBeforeFirstRow() const {
  // We ignore the border-spacing on any non-top section, as it is already
  // included in the previous section's last row position.
  if (this != Table()->TopSection())
    return 0;
  return Table()->VBorderSpacing();
}

int LayoutTableSection::CalcRowLogicalHeight() {
#if DCHECK_IS_ON()
  SetLayoutNeededForbiddenScope layout_forbidden_scope(*this);
#endif

  DCHECK(!NeedsLayout());

  // We may have to forcefully lay out cells here, in which case we need a
  // layout state.
  LayoutState state(*this);

  row_pos_.resize(grid_.size() + 1);
  row_pos_[0] = VBorderSpacingBeforeFirstRow();

  SpanningLayoutTableCells row_span_cells;

  // At fragmentainer breaks we need to prevent rowspanned cells (and whatever
  // else) from distributing their extra height requirements over the rows that
  // it spans. Otherwise we'd need to refragment afterwards.
  unsigned index_of_first_stretchable_row = 0;

  is_any_row_collapsed_ = false;

  for (unsigned r = 0; r < grid_.size(); r++) {
    grid_[r].baseline = LayoutUnit(-1);
    LayoutUnit baseline_descent;

    if (!is_any_row_collapsed_)
      is_any_row_collapsed_ = RowHasVisibilityCollapse(r);

    if (state.IsPaginated() && grid_[r].row)
      row_pos_[r] += grid_[r].row->PaginationStrut().Ceil();

    if (grid_[r].logical_height.IsSpecified()) {
      // Our base size is the biggest logical height from our cells' styles
      // (excluding row spanning cells).
      row_pos_[r + 1] =
          std::max(row_pos_[r] + MinimumValueForLength(grid_[r].logical_height,
                                                       LayoutUnit())
                                     .Round(),
                   0);
    } else {
      // Non-specified lengths are ignored because the row already accounts for
      // the cells intrinsic logical height.
      row_pos_[r + 1] = std::max(row_pos_[r], 0);
    }

    for (auto& grid_cell : grid_[r].grid_cells) {
      if (grid_cell.InColSpan())
        continue;
      for (auto* cell : grid_cell.Cells()) {
        // For row spanning cells, we only handle them for the first row they
        // span. This ensures we take their baseline into account.
        if (cell->RowIndex() != r)
          continue;

        if (r < index_of_first_stretchable_row ||
            (state.IsPaginated() &&
             CrossesPageBoundary(
                 LayoutUnit(row_pos_[r]),
                 LayoutUnit(cell->LogicalHeightForRowSizing())))) {
          // Entering or extending a range of unstretchable rows. We enter this
          // mode when a cell in a row crosses a fragmentainer boundary, and
          // we'll stay in this mode until we get to a row where we're past all
          // rowspanned cells that we encountered while in this mode.
          DCHECK(state.IsPaginated());
          unsigned row_index_below_cell = r + cell->ResolvedRowSpan();
          index_of_first_stretchable_row =
              std::max(index_of_first_stretchable_row, row_index_below_cell);
        } else if (cell->ResolvedRowSpan() > 1) {
          DCHECK(!row_span_cells.Contains(cell));

          cell->SetIsSpanningCollapsedRow(false);
          unsigned end_row = cell->ResolvedRowSpan() + r;
          for (unsigned spanning = r; spanning < end_row; spanning++) {
            if (RowHasVisibilityCollapse(spanning)) {
              cell->SetIsSpanningCollapsedRow(true);
              break;
            }
          }

          row_span_cells.push_back(cell);
        }

        if (cell->HasOverrideLogicalHeight()) {
          cell->ClearIntrinsicPadding();
          cell->ClearOverrideSize();
          cell->ForceChildLayout();
        }

        if (cell->ResolvedRowSpan() == 1)
          row_pos_[r + 1] = std::max(
              row_pos_[r + 1], row_pos_[r] + cell->LogicalHeightForRowSizing());

        // Find out the baseline. The baseline is set on the first row in a
        // rowSpan.
        UpdateBaselineForCell(cell, r, baseline_descent);
      }
    }

    if (r < index_of_first_stretchable_row && grid_[r].row) {
      // We're not allowed to resize this row. Just scratch what we've
      // calculated so far, and use the height that we got during initial
      // layout instead.
      row_pos_[r + 1] = row_pos_[r] + grid_[r].row->LogicalHeight().ToInt();
    }

    // Add the border-spacing to our final position.
    row_pos_[r + 1] += BorderSpacingForRow(r);
    row_pos_[r + 1] = std::max(row_pos_[r + 1], row_pos_[r]);
  }

  if (!row_span_cells.IsEmpty())
    DistributeRowSpanHeightToRows(row_span_cells);

  DCHECK(!NeedsLayout());

  // Collapsed rows are dealt with after distributing row span height to rows.
  // This is because the distribution calculations should be as if the row were
  // not collapsed. First, all rows' collapsed heights are set. After, row
  // positions are adjusted accordingly.
  if (is_any_row_collapsed_) {
    row_collapsed_height_.resize(grid_.size());
    for (unsigned r = 0; r < grid_.size(); r++) {
      if (RowHasVisibilityCollapse(r)) {
        // Update vector that keeps track of collapsed height of each row.
        row_collapsed_height_[r] = row_pos_[r + 1] - row_pos_[r];
      } else {
        // Reset rows that are no longer collapsed.
        row_collapsed_height_[r] = 0;
      }
    }

    int total_collapsed_height = 0;
    for (unsigned r = 0; r < grid_.size(); r++) {
      total_collapsed_height += row_collapsed_height_[r];
      // Adjust row position according to the height collapsed so far.
      row_pos_[r + 1] -= total_collapsed_height;
      DCHECK_GE(row_pos_[r + 1], row_pos_[r]);
    }
  }

  return row_pos_[grid_.size()];
}

void LayoutTableSection::UpdateLayout() {
  DCHECK(NeedsLayout());
  LayoutAnalyzer::Scope analyzer(*this);
  CHECK(!NeedsCellRecalc());
  DCHECK(!Table()->NeedsSectionRecalc());

  // addChild may over-grow grid_ but we don't want to throw away the memory
  // too early as addChild can be called in a loop (e.g during parsing). Doing
  // it now ensures we have a stable-enough structure.
  grid_.ShrinkToFit();

  LayoutState state(*this);

  const Vector<int>& column_pos = Table()->EffectiveColumnPositions();
  LayoutUnit row_logical_top(VBorderSpacingBeforeFirstRow());

  SubtreeLayoutScope layouter(*this);
  for (unsigned r = 0; r < grid_.size(); ++r) {
    auto& grid_cells = grid_[r].grid_cells;
    unsigned cols = grid_cells.size();
    // First, propagate our table layout's information to the cells. This will
    // mark the row as needing layout if there was a column logical width
    // change.
    for (unsigned start_column = 0; start_column < cols; ++start_column) {
      auto& grid_cell = grid_cells[start_column];
      LayoutTableCell* cell = grid_cell.PrimaryCell();
      if (!cell || grid_cell.InColSpan())
        continue;

      unsigned end_col = start_column;
      unsigned cspan = cell->ColSpan();
      while (cspan && end_col < cols) {
        DCHECK_LT(end_col, Table()->EffectiveColumns().size());
        cspan -= Table()->EffectiveColumns()[end_col].span;
        end_col++;
      }
      int table_layout_logical_width = column_pos[end_col] -
                                       column_pos[start_column] -
                                       Table()->HBorderSpacing();
      cell->SetCellLogicalWidth(table_layout_logical_width, layouter);
    }

    if (LayoutTableRow* row = grid_[r].row) {
      if (state.IsPaginated())
        row->SetLogicalTop(row_logical_top);
      if (!row->NeedsLayout())
        MarkChildForPaginationRelayoutIfNeeded(*row, layouter);
      row->LayoutIfNeeded();
      if (state.IsPaginated()) {
        AdjustRowForPagination(*row, layouter);
        UpdateFragmentationInfoForChild(*row);
        row_logical_top = row->LogicalBottom();
        row_logical_top += LayoutUnit(Table()->VBorderSpacing());
      }

      if (!Table()->HasSameDirectionAs(row)) {
        UseCounter::Count(GetDocument(),
                          WebFeature::kTableRowDirectionDifferentFromTable);
      }
    }
  }

  if (!Table()->HasSameDirectionAs(this)) {
    UseCounter::Count(GetDocument(),
                      WebFeature::kTableSectionDirectionDifferentFromTable);
  }

  ClearNeedsLayout();
}

void LayoutTableSection::DistributeExtraLogicalHeightToPercentRows(
    int& extra_logical_height,
    int total_percent) {
  if (!total_percent)
    return;

  unsigned total_rows = grid_.size();
  int total_height = row_pos_[total_rows] + extra_logical_height;
  int total_logical_height_added = 0;
  total_percent = std::min(total_percent, 100);
  int row_height = row_pos_[1] - row_pos_[0];
  for (unsigned r = 0; r < total_rows; ++r) {
    // TODO(alancutter): Make this work correctly for calc lengths.
    if (total_percent > 0 && grid_[r].logical_height.IsPercent()) {
      int to_add = std::min<int>(
          extra_logical_height,
          (total_height * grid_[r].logical_height.Percent() / 100) -
              row_height);
      // If toAdd is negative, then we don't want to shrink the row (this bug
      // affected Outlook Web Access).
      to_add = std::max(0, to_add);
      total_logical_height_added += to_add;
      extra_logical_height -= to_add;
      total_percent -= grid_[r].logical_height.Percent();
    }
    DCHECK_GE(total_rows, 1u);
    if (r < total_rows - 1)
      row_height = row_pos_[r + 2] - row_pos_[r + 1];
    row_pos_[r + 1] += total_logical_height_added;
  }
}

void LayoutTableSection::DistributeExtraLogicalHeightToAutoRows(
    int& extra_logical_height,
    unsigned auto_rows_count) {
  if (!auto_rows_count)
    return;

  int total_logical_height_added = 0;
  for (unsigned r = 0; r < grid_.size(); ++r) {
    if (auto_rows_count > 0 && grid_[r].logical_height.IsAuto()) {
      // Recomputing |extraLogicalHeightForRow| guarantees that we properly
      // ditribute round |extraLogicalHeight|.
      int extra_logical_height_for_row = extra_logical_height / auto_rows_count;
      total_logical_height_added += extra_logical_height_for_row;
      extra_logical_height -= extra_logical_height_for_row;
      --auto_rows_count;
    }
    row_pos_[r + 1] += total_logical_height_added;
  }
}

void LayoutTableSection::DistributeRemainingExtraLogicalHeight(
    int& extra_logical_height) {
  unsigned total_rows = grid_.size();

  if (extra_logical_height <= 0 || !row_pos_[total_rows])
    return;

  int total_logical_height_added = 0;
  int previous_row_position = row_pos_[0];
  float total_row_size = row_pos_[total_rows] - previous_row_position;
  for (unsigned r = 0; r < total_rows; r++) {
    // weight with the original height
    float height_to_add = extra_logical_height *
                          (row_pos_[r + 1] - previous_row_position) /
                          total_row_size;
    total_logical_height_added =
        std::min<int>(total_logical_height_added + std::ceil(height_to_add),
                      extra_logical_height);
    previous_row_position = row_pos_[r + 1];
    row_pos_[r + 1] += total_logical_height_added;
  }

  extra_logical_height -= total_logical_height_added;
}

int LayoutTableSection::DistributeExtraLogicalHeightToRows(
    int extra_logical_height) {
  if (!extra_logical_height)
    return extra_logical_height;

  unsigned total_rows = grid_.size();
  if (!total_rows)
    return extra_logical_height;

  if (!row_pos_[total_rows] && NextSibling())
    return extra_logical_height;

  unsigned auto_rows_count = 0;
  int total_percent = 0;
  for (unsigned r = 0; r < total_rows; r++) {
    if (grid_[r].logical_height.IsAuto())
      ++auto_rows_count;
    else if (grid_[r].logical_height.IsPercent())
      total_percent += grid_[r].logical_height.Percent();
  }

  int remaining_extra_logical_height = extra_logical_height;
  DistributeExtraLogicalHeightToPercentRows(remaining_extra_logical_height,
                                            total_percent);
  DistributeExtraLogicalHeightToAutoRows(remaining_extra_logical_height,
                                         auto_rows_count);
  DistributeRemainingExtraLogicalHeight(remaining_extra_logical_height);
  return extra_logical_height - remaining_extra_logical_height;
}

bool CellHasExplicitlySpecifiedHeight(const LayoutTableCell& cell) {
  if (cell.StyleRef().LogicalHeight().IsFixed())
    return true;
  LayoutBlock* cb = cell.ContainingBlock();
  if (cb->AvailableLogicalHeightForPercentageComputation() == -1)
    return false;
  return true;
}

static bool ShouldFlexCellChild(const LayoutTableCell& cell,
                                LayoutObject* cell_descendant) {
  if (!CellHasExplicitlySpecifiedHeight(cell))
    return false;
  if (cell_descendant->StyleRef().OverflowY() == EOverflow::kVisible ||
      cell_descendant->StyleRef().OverflowY() == EOverflow::kHidden)
    return true;
  return cell_descendant->IsBox() &&
         ToLayoutBox(cell_descendant)->ShouldBeConsideredAsReplaced();
}

void LayoutTableSection::LayoutRows() {
#if DCHECK_IS_ON()
  SetLayoutNeededForbiddenScope layout_forbidden_scope(*this);
#endif

  DCHECK(!NeedsLayout());

  LayoutAnalyzer::Scope analyzer(*this);

  // FIXME: Changing the height without a layout can change the overflow so it
  // seems wrong.

  unsigned total_rows = grid_.size();

  // Set the width of our section now.  The rows will also be this width.
  SetLogicalWidth(Table()->ContentLogicalWidth());

  int vspacing = Table()->VBorderSpacing();
  LayoutState state(*this);

  // Set the rows' location and size.
  for (unsigned r = 0; r < total_rows; r++) {
    if (LayoutTableRow* row = grid_[r].row) {
      row->SetLogicalLocation(LayoutPoint(0, row_pos_[r]));
      row->SetLogicalWidth(LogicalWidth());
      LayoutUnit row_logical_height;
      // If the row is collapsed then it has 0 height. vspacing was implicitly
      // removed earlier, when row_pos_[r+1] was set to row_pos[r].
      if (!RowHasVisibilityCollapse(r)) {
        row_logical_height =
            LayoutUnit(row_pos_[r + 1] - row_pos_[r] - vspacing);
      }
      DCHECK_GE(row_logical_height, 0);
      if (state.IsPaginated() && r + 1 < total_rows) {
        // If the next row has a pagination strut, we need to subtract it. It
        // should not be included in this row's height.
        if (LayoutTableRow* next_row_object = grid_[r + 1].row)
          row_logical_height -= next_row_object->PaginationStrut();
      }
      DCHECK_GE(row_logical_height, 0);
      row->SetLogicalHeight(row_logical_height);
      row->UpdateAfterLayout();
    }
  }

  // Vertically align and flex the cells in each row.
  for (unsigned r = 0; r < total_rows; r++) {
    LayoutTableRow* row = grid_[r].row;

    unsigned n_cols = NumCols(r);
    for (unsigned c = 0; c < n_cols; c++) {
      LayoutTableCell* cell = OriginatingCellAt(r, c);
      if (!cell)
        continue;

      int r_height;
      int row_logical_top;
      unsigned row_span = std::max(1U, cell->ResolvedRowSpan());
      unsigned end_row_index = std::min(r + row_span, total_rows) - 1;
      LayoutTableRow* last_row_object = grid_[end_row_index].row;
      if (last_row_object && row) {
        row_logical_top = row->LogicalTop().ToInt();
        r_height = last_row_object->LogicalBottom().ToInt() - row_logical_top;
      } else {
        r_height = row_pos_[end_row_index + 1] - row_pos_[r] - vspacing;
        row_logical_top = row_pos_[r];
      }

      RelayoutCellIfFlexed(*cell, r, r_height);

      SubtreeLayoutScope layouter(*cell);
      EVerticalAlign cell_vertical_align;
      // If the cell crosses a fragmentainer boundary, just align it at the
      // top. That's how it was laid out initially, before we knew the final
      // row height, and re-aligning it now could result in the cell being
      // fragmented differently, which could change its height and thus violate
      // the requested alignment. Give up instead of risking circular
      // dependencies and unstable layout.
      if (state.IsPaginated() &&
          CrossesPageBoundary(LayoutUnit(row_logical_top),
                              LayoutUnit(r_height)))
        cell_vertical_align = EVerticalAlign::kTop;
      else
        cell_vertical_align = cell->StyleRef().VerticalAlign();

      // Calculate total collapsed height affecting one cell.
      int collapsed_height = 0;
      if (is_any_row_collapsed_) {
        unsigned end_row = cell->ResolvedRowSpan() + r;
        for (unsigned spanning = r; spanning < end_row; spanning++) {
          collapsed_height += row_collapsed_height_[spanning];
        }
      }

      cell->ComputeIntrinsicPadding(collapsed_height, r_height,
                                    cell_vertical_align, layouter);

      LayoutRect old_cell_rect = cell->FrameRect();

      SetLogicalPositionForCell(cell, c);

      cell->LayoutIfNeeded();

      LayoutSize child_offset(cell->Location() - old_cell_rect.Location());
      if (child_offset.Width() || child_offset.Height()) {
        // If the child moved, we have to issue paint invalidations to it as
        // well as any floating/positioned descendants. An exception is if we
        // need a layout. In this case, we know we're going to issue paint
        // invalidations ourselves (and the child) anyway.
        if (!Table()->SelfNeedsLayout())
          cell->SetShouldCheckForPaintInvalidation();
      }
    }
    if (row)
      row->ComputeOverflow();
  }

  DCHECK(!NeedsLayout());

  SetLogicalHeight(LayoutUnit(row_pos_[total_rows]));

  ComputeOverflowFromDescendants();
}

void LayoutTableSection::UpdateLogicalWidthForCollapsedCells(
    const Vector<int>& col_collapsed_width) {
  if (!RuntimeEnabledFeatures::VisibilityCollapseColumnEnabled())
    return;
  unsigned total_rows = grid_.size();
  for (unsigned r = 0; r < total_rows; r++) {
    unsigned n_cols = NumCols(r);
    for (unsigned c = 0; c < n_cols; c++) {
      LayoutTableCell* cell = OriginatingCellAt(r, c);
      if (!cell)
        continue;
      if (!col_collapsed_width.size()) {
        cell->SetIsSpanningCollapsedColumn(false);
        continue;
      }
      // TODO(joysyu): Current behavior assumes that collapsing the first column
      // in a col-spanning cell makes the cell width zero. This is consistent
      // with collapsing row-spanning cells, but still needs to be specified.
      if (cell->IsFirstColumnCollapsed()) {
        // Collapsed cells have zero width.
        cell->SetLogicalWidth(LayoutUnit());
      } else if (cell->ColSpan() > 1) {
        // A column-spanning cell may be affected by collapsed columns, so its
        // width needs to be adjusted accordingly
        int collapsed_width = 0;
        cell->SetIsSpanningCollapsedColumn(false);
        unsigned end_col = std::min(cell->ColSpan() + c, n_cols);
        for (unsigned spanning = c; spanning < end_col; spanning++)
          collapsed_width += col_collapsed_width[spanning];
        cell->SetLogicalWidth(cell->LogicalWidth() - collapsed_width);
        if (collapsed_width != 0)
          cell->SetIsSpanningCollapsedColumn(true);
        // Recompute overflow in case overflow clipping is necessary.
        cell->ComputeOverflow(cell->ClientLogicalBottom());
        DCHECK_GE(cell->LogicalWidth(), 0);
      }
    }
  }
}

int LayoutTableSection::PaginationStrutForRow(LayoutTableRow* row,
                                              LayoutUnit logical_offset) const {
  DCHECK(row);
  const LayoutTableSection* footer = Table()->Footer();
  bool make_room_for_repeating_footer =
      footer && footer->IsRepeatingFooterGroup() && row->RowIndex();
  if (!make_room_for_repeating_footer &&
      row->GetPaginationBreakability() == kAllowAnyBreaks)
    return 0;
  if (!IsPageLogicalHeightKnown())
    return 0;
  LayoutUnit page_logical_height = PageLogicalHeightForOffset(logical_offset);
  // If the row is too tall for the page don't insert a strut.
  LayoutUnit row_logical_height = row->LogicalHeight();
  if (row_logical_height > page_logical_height)
    return 0;

  LayoutUnit remaining_logical_height = PageRemainingLogicalHeightForOffset(
      logical_offset, LayoutBlock::kAssociateWithLatterPage);
  if (remaining_logical_height >= row_logical_height)
    return 0;  // It fits fine where it is. No need to break.
  LayoutUnit pagination_strut =
      CalculatePaginationStrutToFitContent(logical_offset, row_logical_height);
  if (pagination_strut == remaining_logical_height &&
      remaining_logical_height == page_logical_height) {
    // Don't break if we were at the top of a page, and we failed to fit the
    // content completely. No point in leaving a page completely blank.
    return 0;
  }
  // Table layout parts only work on integers, so we have to round. Round up, to
  // make sure that no fraction ever gets left behind in the previous
  // fragmentainer.
  return pagination_strut.Ceil();
}

void LayoutTableSection::ComputeOverflowFromDescendants() {
  auto old_self_visual_overflow_rect = SelfVisualOverflowRect();
  overflow_.reset();
  overflowing_cells_.clear();
  force_full_paint_ = false;

  ComputeVisualOverflowFromDescendants();

  // Overflow rect contributes to the visual rect, so if it has changed then we
  // need to signal a possible paint invalidation.
  if (old_self_visual_overflow_rect != SelfVisualOverflowRect())
    SetShouldCheckForPaintInvalidation();

  ComputeLayoutOverflowFromDescendants();
}

void LayoutTableSection::ComputeVisualOverflowFromDescendants() {
  // These 2 variables are used to balance the memory consumption vs the paint
  // time on big sections with overflowing cells:
  // 1. For small sections, don't track overflowing cells because for them the
  //    full paint path is actually faster than the partial paint path.
  // 2. For big sections, if overflowing cells are scarce, track overflowing
  //    cells to enable the partial paint path.
  // 3. Otherwise don't track overflowing cells to avoid adding a lot of cells
  //    to the HashSet, and force the full paint path.
  // See TableSectionPainter::PaintObject() for the full paint path and the
  // partial paint path.
  static const unsigned kMinCellCountToUsePartialPaint = 75 * 75;
  static const float kMaxOverflowingCellRatioForPartialPaint = 0.1f;

  unsigned total_cell_count = NumRows() * Table()->NumEffectiveColumns();
  unsigned max_overflowing_cell_count =
      total_cell_count < kMinCellCountToUsePartialPaint
          ? 0
          : kMaxOverflowingCellRatioForPartialPaint * total_cell_count;

#if DCHECK_IS_ON()
  bool has_overflowing_cell = false;
#endif

  for (auto* row = FirstRow(); row; row = row->NextRow()) {
    AddVisualOverflowFromChild(*row);

    for (auto* cell = row->FirstCell(); cell; cell = cell->NextCell()) {
      // Let the section's self visual overflow cover the cell's whole collapsed
      // borders. This ensures correct raster invalidation on section border
      // style change.
      // TODO(wangxianzhu): When implementing row as DisplayItemClient of
      // collapsed borders, the following logic should be replaced by
      // invalidation of rows on section border style change. crbug.com/663208.
      if (const auto* collapsed_borders = cell->GetCollapsedBorderValues()) {
        LayoutRect rect = cell->RectForOverflowPropagation(
            collapsed_borders->LocalVisualRect());
        rect.MoveBy(cell->Location());
        AddSelfVisualOverflow(rect);
      }

      if (force_full_paint_ || !cell->HasVisualOverflow())
        continue;

#if DCHECK_IS_ON()
      has_overflowing_cell = true;
#endif
      if (overflowing_cells_.size() >= max_overflowing_cell_count) {
        force_full_paint_ = true;
        // The full paint path does not make any use of the overflowing cells
        // info, so don't hold on to the memory.
        overflowing_cells_.clear();
        continue;
      }

      overflowing_cells_.insert(cell);
    }
  }

#if DCHECK_IS_ON()
  DCHECK_EQ(has_overflowing_cell, HasOverflowingCell());
#endif
}

void LayoutTableSection::ComputeLayoutOverflowFromDescendants() {
  for (auto* row = FirstRow(); row; row = row->NextRow())
    AddLayoutOverflowFromChild(*row);
}

bool LayoutTableSection::RecalcOverflow() {
  if (!ChildNeedsOverflowRecalc())
    return false;
  ChildNeedsOverflowRecalc();
  unsigned total_rows = grid_.size();
  bool children_overflow_changed = false;
  for (unsigned r = 0; r < total_rows; r++) {
    LayoutTableRow* row_layouter = RowLayoutObjectAt(r);
    if (!row_layouter || !row_layouter->ChildNeedsOverflowRecalc())
      continue;
    row_layouter->ClearChildNeedsLayoutOverflowRecalc();
    row_layouter->ClearChildNeedsVisualOverflowRecalc();
    bool row_children_overflow_changed = false;
    unsigned n_cols = NumCols(r);
    for (unsigned c = 0; c < n_cols; c++) {
      auto* cell = OriginatingCellAt(r, c);
      if (!cell)
        continue;
      row_children_overflow_changed |= cell->RecalcOverflow();
    }
    if (row_children_overflow_changed)
      row_layouter->ComputeOverflow();
    children_overflow_changed |= row_children_overflow_changed;
  }
  if (children_overflow_changed)
    ComputeOverflowFromDescendants();
  return children_overflow_changed;
}

void LayoutTableSection::MarkAllCellsWidthsDirtyAndOrNeedsLayout(
    LayoutTable::WhatToMarkAllCells what_to_mark) {
  for (LayoutTableRow* row = FirstRow(); row; row = row->NextRow()) {
    for (LayoutTableCell* cell = row->FirstCell(); cell;
         cell = cell->NextCell()) {
      cell->SetPreferredLogicalWidthsDirty();
      if (what_to_mark == LayoutTable::kMarkDirtyAndNeedsLayout)
        cell->SetChildNeedsLayout();
    }
  }
}

LayoutUnit LayoutTableSection::FirstLineBoxBaseline() const {
  if (!grid_.size())
    return LayoutUnit(-1);

  LayoutUnit first_line_baseline(grid_[0].baseline);
  if (first_line_baseline >= 0)
    return first_line_baseline + row_pos_[0];

  for (const auto& grid_cell : grid_[0].grid_cells) {
    if (const auto* cell = grid_cell.PrimaryCell()) {
      first_line_baseline = std::max<LayoutUnit>(
          first_line_baseline, cell->LogicalTop() + cell->BorderBefore() +
                                   cell->PaddingBefore() +
                                   cell->ContentLogicalHeight());
    }
  }

  return first_line_baseline;
}

void LayoutTableSection::Paint(const PaintInfo& paint_info) const {
  TableSectionPainter(*this).Paint(paint_info);
}

LayoutRect LayoutTableSection::LogicalRectForWritingModeAndDirection(
    const LayoutRect& rect) const {
  LayoutRect table_aligned_rect(rect);

  FlipForWritingMode(table_aligned_rect);

  if (!TableStyle().IsHorizontalWritingMode())
    table_aligned_rect = table_aligned_rect.TransposedRect();

  const Vector<int>& column_pos = Table()->EffectiveColumnPositions();
  if (!TableStyle().IsLeftToRightDirection()) {
    table_aligned_rect.SetX(column_pos[column_pos.size() - 1] -
                            table_aligned_rect.MaxX());
  }

  return table_aligned_rect;
}

void LayoutTableSection::DirtiedRowsAndEffectiveColumns(
    const LayoutRect& damage_rect,
    CellSpan& rows,
    CellSpan& columns) const {
  if (!grid_.size()) {
    rows = CellSpan();
    columns = CellSpan(1, 1);
    return;
  }

  if (force_full_paint_) {
    rows = FullSectionRowSpan();
    columns = FullTableEffectiveColumnSpan();
    return;
  }

  rows = SpannedRows(damage_rect);
  columns = SpannedEffectiveColumns(damage_rect);

  // Expand by one cell in each direction to cover any collapsed borders.
  if (Table()->ShouldCollapseBorders()) {
    if (rows.Start() > 0)
      rows.DecreaseStart();
    if (rows.End() < grid_.size())
      rows.IncreaseEnd();
    if (columns.Start() > 0)
      columns.DecreaseStart();
    if (columns.End() < Table()->NumEffectiveColumns())
      columns.IncreaseEnd();
  }

  rows.EnsureConsistency(grid_.size());
  columns.EnsureConsistency(Table()->NumEffectiveColumns());

  if (!has_spanning_cells_)
    return;

  if (rows.Start() > 0 && rows.Start() < grid_.size()) {
    // If there are any cells spanning into the first row, expand |rows| to
    // cover the cells.
    unsigned n_cols = NumCols(rows.Start());
    unsigned smallest_row = rows.Start();
    for (unsigned c = columns.Start(); c < std::min(columns.End(), n_cols);
         ++c) {
      for (const auto* cell : GridCellAt(rows.Start(), c).Cells()) {
        smallest_row = std::min(smallest_row, cell->RowIndex());
        if (!smallest_row)
          break;
      }
    }
    rows = CellSpan(smallest_row, rows.End());
  }

  if (columns.Start() > 0 && columns.Start() < Table()->NumEffectiveColumns()) {
    // If there are any cells spanning into the first column, expand |columns|
    // to cover the cells.
    unsigned smallest_column = columns.Start();
    for (unsigned r = rows.Start(); r < rows.End(); ++r) {
      const auto& grid_cells = grid_[r].grid_cells;
      if (columns.Start() < grid_cells.size()) {
        unsigned c = columns.Start();
        while (c && grid_cells[c].InColSpan())
          --c;
        smallest_column = std::min(c, smallest_column);
        if (!smallest_column)
          break;
      }
    }
    columns = CellSpan(smallest_column, columns.End());
  }
}

CellSpan LayoutTableSection::SpannedRows(const LayoutRect& flipped_rect) const {
  // Find the first row that starts after rect top.
  unsigned next_row = static_cast<unsigned>(
      std::upper_bound(row_pos_.begin(), row_pos_.end(), flipped_rect.Y()) -
      row_pos_.begin());

  // After all rows.
  if (next_row == row_pos_.size())
    return CellSpan(row_pos_.size() - 1, row_pos_.size() - 1);

  unsigned start_row = next_row > 0 ? next_row - 1 : 0;

  // Find the first row that starts after rect bottom.
  unsigned end_row;
  if (row_pos_[next_row] >= flipped_rect.MaxY()) {
    end_row = next_row;
  } else {
    end_row = static_cast<unsigned>(
        std::upper_bound(row_pos_.begin() + next_row, row_pos_.end(),
                         flipped_rect.MaxY()) -
        row_pos_.begin());
    if (end_row == row_pos_.size())
      end_row = row_pos_.size() - 1;
  }

  return CellSpan(start_row, end_row);
}

CellSpan LayoutTableSection::SpannedEffectiveColumns(
    const LayoutRect& flipped_rect) const {
  const Vector<int>& column_pos = Table()->EffectiveColumnPositions();

  // Find the first column that starts after rect left.
  // lower_bound doesn't handle the edge between two cells properly as it would
  // wrongly return the cell on the logical top/left.
  // upper_bound on the other hand properly returns the cell on the logical
  // bottom/right, which also matches the behavior of other browsers.
  unsigned next_column = static_cast<unsigned>(
      std::upper_bound(column_pos.begin(), column_pos.end(), flipped_rect.X()) -
      column_pos.begin());

  if (next_column == column_pos.size())
    return CellSpan(column_pos.size() - 1,
                    column_pos.size() - 1);  // After all columns.

  unsigned start_column = next_column > 0 ? next_column - 1 : 0;

  // Find the first column that starts after rect right.
  unsigned end_column;
  if (column_pos[next_column] >= flipped_rect.MaxX()) {
    end_column = next_column;
  } else {
    end_column = static_cast<unsigned>(
        std::upper_bound(column_pos.begin() + next_column, column_pos.end(),
                         flipped_rect.MaxX()) -
        column_pos.begin());
    if (end_column == column_pos.size())
      end_column = column_pos.size() - 1;
  }

  return CellSpan(start_column, end_column);
}

void LayoutTableSection::RecalcCells() {
  DCHECK(needs_cell_recalc_);
  // We reset the flag here to ensure that |addCell| works. This is safe to do
  // as fillRowsWithDefaultStartingAtPosition makes sure we match the table's
  // columns representation.
  needs_cell_recalc_ = false;

  c_col_ = 0;
  c_row_ = 0;
  grid_.clear();

  bool resized_grid = false;
  for (LayoutTableRow* row = FirstRow(); row; row = row->NextRow()) {
    unsigned insertion_row = c_row_;
    ++c_row_;
    c_col_ = 0;
    EnsureRows(c_row_);

    grid_[insertion_row].row = row;
    row->SetRowIndex(insertion_row);
    grid_[insertion_row].SetRowLogicalHeightToRowStyleLogicalHeight();

    for (LayoutTableCell* cell = row->FirstCell(); cell;
         cell = cell->NextCell()) {
      // For rowspan, "the value zero means that the cell is to span all the
      // remaining rows in the row group." Calculate the size of the full
      // row grid now so that we can use it to count the remaining rows in
      // ResolvedRowSpan().
      if (!cell->ParsedRowSpan() && !resized_grid) {
        unsigned c_row = row->RowIndex() + 1;
        for (LayoutTableRow* remaining_row = row; remaining_row;
             remaining_row = remaining_row->NextRow())
          c_row++;
        EnsureRows(c_row);
        resized_grid = true;
      }
      AddCell(cell, row);
    }
  }

  grid_.ShrinkToFit();
  SetNeedsLayoutAndFullPaintInvalidation(layout_invalidation_reason::kUnknown);
}

// FIXME: This function could be made O(1) in certain cases (like for the
// non-most-constrainive cells' case).
void LayoutTableSection::RowLogicalHeightChanged(LayoutTableRow* row) {
  if (NeedsCellRecalc())
    return;

  unsigned row_index = row->RowIndex();
  grid_[row_index].SetRowLogicalHeightToRowStyleLogicalHeight();

  for (LayoutTableCell* cell = grid_[row_index].row->FirstCell(); cell;
       cell = cell->NextCell())
    grid_[row_index].UpdateLogicalHeightForCell(cell);
}

void LayoutTableSection::SetNeedsCellRecalc() {
  needs_cell_recalc_ = true;
  if (LayoutTable* t = Table())
    t->SetNeedsSectionRecalc();
}

unsigned LayoutTableSection::NumEffectiveColumns() const {
  unsigned result = 0;

  for (unsigned r = 0; r < grid_.size(); ++r) {
    unsigned n_cols = NumCols(r);
    for (unsigned c = result; c < n_cols; ++c) {
      const auto& grid_cell = GridCellAt(r, c);
      if (grid_cell.HasCells() || grid_cell.InColSpan())
        result = c;
    }
  }

  return result + 1;
}

LayoutTableCell* LayoutTableSection::OriginatingCellAt(
    unsigned row,
    unsigned effective_column) {
  if (effective_column >= NumCols(row))
    return nullptr;
  auto& grid_cell = GridCellAt(row, effective_column);
  if (grid_cell.InColSpan())
    return nullptr;
  if (auto* cell = grid_cell.PrimaryCell()) {
    if (cell->RowIndex() == row)
      return cell;
  }
  return nullptr;
}

void LayoutTableSection::AppendEffectiveColumn(unsigned pos) {
  DCHECK(!needs_cell_recalc_);

  for (auto& row : grid_)
    row.grid_cells.resize(pos + 1);
}

void LayoutTableSection::SplitEffectiveColumn(unsigned pos, unsigned first) {
  DCHECK(!needs_cell_recalc_);

  if (c_col_ > pos)
    c_col_++;
  for (unsigned row = 0; row < grid_.size(); ++row) {
    auto& grid_cells = grid_[row].grid_cells;
    EnsureCols(row, pos + 1);
    grid_cells.insert(pos + 1, TableGridCell());
    if (grid_cells[pos].HasCells()) {
      grid_cells[pos + 1].Cells().AppendVector(grid_cells[pos].Cells());
      LayoutTableCell* cell = grid_cells[pos].PrimaryCell();
      DCHECK(cell);
      DCHECK_GE(cell->ColSpan(), (grid_cells[pos].InColSpan() ? 1u : 0));
      unsigned colleft = cell->ColSpan() - grid_cells[pos].InColSpan();
      if (first > colleft)
        grid_cells[pos + 1].SetInColSpan(false);
      else
        grid_cells[pos + 1].SetInColSpan(first || grid_cells[pos].InColSpan());
    } else {
      grid_cells[pos + 1].SetInColSpan(false);
    }
  }
}

// Hit Testing
bool LayoutTableSection::NodeAtPoint(
    HitTestResult& result,
    const HitTestLocation& location_in_container,
    const LayoutPoint& accumulated_offset,
    HitTestAction action) {
  // If we have no children then we have nothing to do.
  if (!FirstRow())
    return false;

  // Table sections cannot ever be hit tested.  Effectively they do not exist.
  // Just forward to our children always.
  LayoutPoint adjusted_location = accumulated_offset + Location();

  if (HasOverflowClip() &&
      !location_in_container.Intersects(OverflowClipRect(adjusted_location)))
    return false;

  if (HasOverflowingCell()) {
    for (LayoutTableRow* row = LastRow(); row; row = row->PreviousRow()) {
      // FIXME: We have to skip over inline flows, since they can show up inside
      // table rows at the moment (a demoted inline <form> for example). If we
      // ever implement a table-specific hit-test method (which we should do for
      // performance reasons anyway), then we can remove this check.
      if (!row->HasSelfPaintingLayer()) {
        LayoutPoint child_point =
            FlipForWritingModeForChild(row, adjusted_location);
        if (row->NodeAtPoint(result, location_in_container, child_point,
                             action)) {
          UpdateHitTestResult(
              result,
              ToLayoutPoint(location_in_container.Point() - child_point));
          return true;
        }
      }
    }
    return false;
  }

  RecalcCellsIfNeeded();

  LayoutRect hit_test_rect = LayoutRect(location_in_container.BoundingBox());
  hit_test_rect.MoveBy(-adjusted_location);

  LayoutRect table_aligned_rect =
      LogicalRectForWritingModeAndDirection(hit_test_rect);
  CellSpan row_span = SpannedRows(table_aligned_rect);
  CellSpan column_span = SpannedEffectiveColumns(table_aligned_rect);

  // Now iterate over the spanned rows and columns.
  for (unsigned hit_row = row_span.Start(); hit_row < row_span.End();
       ++hit_row) {
    unsigned n_cols = NumCols(hit_row);
    for (unsigned hit_column = column_span.Start();
         hit_column < n_cols && hit_column < column_span.End(); ++hit_column) {
      auto& grid_cell = GridCellAt(hit_row, hit_column);

      // If the cell is empty, there's nothing to do
      if (!grid_cell.HasCells())
        continue;

      for (unsigned i = grid_cell.Cells().size(); i;) {
        --i;
        LayoutTableCell* cell = grid_cell.Cells()[i];
        LayoutPoint cell_point =
            FlipForWritingModeForChild(cell, adjusted_location);
        if (static_cast<LayoutObject*>(cell)->NodeAtPoint(
                result, location_in_container, cell_point, action)) {
          UpdateHitTestResult(
              result, location_in_container.Point() - ToLayoutSize(cell_point));
          return true;
        }
      }
      if (!result.GetHitTestRequest().ListBased())
        break;
    }
    if (!result.GetHitTestRequest().ListBased())
      break;
  }

  return false;
}

LayoutTableSection* LayoutTableSection::CreateAnonymousWithParent(
    const LayoutObject* parent) {
  scoped_refptr<ComputedStyle> new_style =
      ComputedStyle::CreateAnonymousStyleWithDisplay(parent->StyleRef(),
                                                     EDisplay::kTableRowGroup);
  LayoutTableSection* new_section = new LayoutTableSection(nullptr);
  new_section->SetDocumentForAnonymous(&parent->GetDocument());
  new_section->SetStyle(std::move(new_style));
  return new_section;
}

void LayoutTableSection::SetLogicalPositionForCell(
    LayoutTableCell* cell,
    unsigned effective_column) const {
  LayoutPoint cell_location(0, row_pos_[cell->RowIndex()]);
  int horizontal_border_spacing = Table()->HBorderSpacing();

  if (!TableStyle().IsLeftToRightDirection()) {
    cell_location.SetX(LayoutUnit(
        Table()->EffectiveColumnPositions()[Table()->NumEffectiveColumns()] -
        Table()->EffectiveColumnPositions()
            [Table()->AbsoluteColumnToEffectiveColumn(
                cell->AbsoluteColumnIndex() + cell->ColSpan())] +
        horizontal_border_spacing));
  } else {
    cell_location.SetX(
        LayoutUnit(Table()->EffectiveColumnPositions()[effective_column] +
                   horizontal_border_spacing));
  }

  cell->SetLogicalLocation(cell_location);
}

void LayoutTableSection::RelayoutCellIfFlexed(LayoutTableCell& cell,
                                              int row_index,
                                              int row_height) {
  // Force percent height children to lay themselves out again.
  // This will cause these children to grow to fill the cell.
  // FIXME: There is still more work to do here to fully match WinIE (should
  // it become necessary to do so).  In quirks mode, WinIE behaves like we
  // do, but it will clip the cells that spill out of the table section.
  // strict mode, Mozilla and WinIE both regrow the table to accommodate the
  // new height of the cell (thus letting the percentages cause growth one
  // time only). We may also not be handling row-spanning cells correctly.
  //
  // Note also the oddity where replaced elements always flex, and yet blocks/
  // tables do not necessarily flex. WinIE is crazy and inconsistent, and we
  // can't hope to match the behavior perfectly, but we'll continue to refine it
  // as we discover new bugs. :)
  bool cell_children_flex = false;
  bool flex_all_children = CellHasExplicitlySpecifiedHeight(cell) ||
                           (!Table()->StyleRef().LogicalHeight().IsAuto() &&
                            row_height != cell.LogicalHeight());

  for (LayoutObject* child = cell.FirstChild(); child;
       child = child->NextSibling()) {
    if (!child->IsText() &&
        child->StyleRef().LogicalHeight().IsPercentOrCalc() &&
        (flex_all_children || ShouldFlexCellChild(cell, child)) &&
        (!child->IsTable() || ToLayoutTable(child)->HasSections())) {
      cell_children_flex = true;
      break;
    }
  }

  if (!cell_children_flex) {
    if (TrackedLayoutBoxListHashSet* percent_height_descendants =
            cell.PercentHeightDescendants()) {
      for (auto* descendant : *percent_height_descendants) {
        if (flex_all_children || ShouldFlexCellChild(cell, descendant)) {
          cell_children_flex = true;
          break;
        }
      }
    }
  }

  if (!cell_children_flex)
    return;

  // Alignment within a cell is based off the calculated height, which becomes
  // irrelevant once the cell has been resized based off its percentage.
  cell.SetOverrideLogicalHeightFromRowHeight(LayoutUnit(row_height));
  cell.ForceChildLayout();

  // If the baseline moved, we may have to update the data for our row. Find
  // out the new baseline.
  if (cell.IsBaselineAligned()) {
    LayoutUnit baseline = cell.CellBaselinePosition();
    if (baseline > cell.BorderBefore() + cell.PaddingBefore())
      grid_[row_index].baseline = std::max(grid_[row_index].baseline, baseline);
  }
}

int LayoutTableSection::LogicalHeightForRow(
    const LayoutTableRow& row_object) const {
  unsigned row_index = row_object.RowIndex();
  DCHECK_LT(row_index, grid_.size());
  int logical_height = 0;
  for (auto& grid_cell : grid_[row_index].grid_cells) {
    const LayoutTableCell* cell = grid_cell.PrimaryCell();
    if (!cell || grid_cell.InColSpan())
      continue;
    unsigned row_span = cell->ResolvedRowSpan();
    if (row_span == 1) {
      logical_height =
          std::max(logical_height, cell->LogicalHeightForRowSizing());
      continue;
    }
    unsigned row_index_for_cell = cell->RowIndex();
    if (row_index == grid_.size() - 1 ||
        (row_span > 1 && row_index - row_index_for_cell == row_span - 1)) {
      // This is the last row of the rowspanned cell. Add extra height if
      // needed.
      if (LayoutTableRow* first_row_for_cell = grid_[row_index_for_cell].row) {
        int min_logical_height = cell->LogicalHeightForRowSizing();
        // Subtract space provided by previous rows.
        min_logical_height -= row_object.LogicalTop().ToInt() -
                              first_row_for_cell->LogicalTop().ToInt();

        logical_height = std::max(logical_height, min_logical_height);
      }
    }
  }

  if (grid_[row_index].logical_height.IsSpecified()) {
    LayoutUnit specified_logical_height =
        MinimumValueForLength(grid_[row_index].logical_height, LayoutUnit());
    // We round here to match computations for row_pos_ in
    // CalcRowLogicalHeight().
    logical_height = std::max(logical_height, specified_logical_height.Round());
  }
  return logical_height;
}

int LayoutTableSection::OffsetForRepeatedHeader() const {
  LayoutTableSection* header = Table()->Header();
  if (header && header != this)
    return Table()->RowOffsetFromRepeatingHeader().ToInt();
  LayoutState* layout_state = View()->GetLayoutState();
  return layout_state->HeightOffsetForTableHeaders().ToInt();
}

void LayoutTableSection::AdjustRowForPagination(LayoutTableRow& row_object,
                                                SubtreeLayoutScope& layouter) {
  row_object.SetPaginationStrut(LayoutUnit());
  row_object.SetLogicalHeight(LayoutUnit(LogicalHeightForRow(row_object)));
  if (!IsPageLogicalHeightKnown())
    return;
  int pagination_strut =
      PaginationStrutForRow(&row_object, row_object.LogicalTop());
  bool row_is_at_top_of_column = false;
  LayoutUnit offset_from_top_of_page;
  if (!pagination_strut) {
    LayoutUnit page_logical_height =
        PageLogicalHeightForOffset(row_object.LogicalTop());
    if (OffsetForRepeatedHeader()) {
      offset_from_top_of_page =
          page_logical_height -
          PageRemainingLogicalHeightForOffset(row_object.LogicalTop(),
                                              kAssociateWithLatterPage);
      row_is_at_top_of_column =
          !offset_from_top_of_page ||
          offset_from_top_of_page <= OffsetForRepeatedHeader() ||
          offset_from_top_of_page <= Table()->VBorderSpacing();
    }

    if (!row_is_at_top_of_column)
      return;
  }
  // We need to push this row to the next fragmentainer. If there are repeated
  // table headers, we need to make room for those at the top of the next
  // fragmentainer, above this row. Otherwise, this row will just go at the top
  // of the next fragmentainer.

  // Border spacing from the previous row has pushed this row just past the top
  // of the page, so we must reposition it to the top of the page and avoid any
  // repeating header.
  if (row_is_at_top_of_column && offset_from_top_of_page)
    pagination_strut -= offset_from_top_of_page.ToInt();

  // If we have a header group we will paint it at the top of each page,
  // move the rows down to accommodate it.
  int additional_adjustment = OffsetForRepeatedHeader();

  // If the table collapses borders, push the row down by the max height of the
  // outer half borders to make the whole collapsed borders on the next page.
  if (Table()->ShouldCollapseBorders()) {
    for (const auto* cell = row_object.FirstCell(); cell;
         cell = cell->NextCell()) {
      additional_adjustment = std::max<int>(additional_adjustment,
                                            cell->CollapsedOuterBorderBefore());
    }
  }

  pagination_strut += additional_adjustment;
  row_object.SetPaginationStrut(LayoutUnit(pagination_strut));

  // We have inserted a pagination strut before the row. Adjust the logical top
  // and re-lay out. We no longer want to break inside the row, but rather
  // *before* it. From the previous layout pass, there are most likely
  // pagination struts inside some cell in this row that we need to get rid of.
  row_object.SetLogicalTop(row_object.LogicalTop() + pagination_strut);
  layouter.SetChildNeedsLayout(&row_object);
  row_object.LayoutIfNeeded();

  // It's very likely that re-laying out (and nuking pagination struts inside
  // cells) gave us a new height.
  row_object.SetLogicalHeight(LayoutUnit(LogicalHeightForRow(row_object)));
}

bool LayoutTableSection::GroupShouldRepeat() const {
  DCHECK(Table()->Header() == this || Table()->Footer() == this);
  if (GetPaginationBreakability() == kAllowAnyBreaks)
    return false;

  // If we don't know the page height yet, just assume we fit.
  if (!IsPageLogicalHeightKnown())
    return true;
  LayoutUnit page_height = PageLogicalHeightForOffset(LayoutUnit());

  LayoutUnit logical_height = LogicalHeight() - OffsetForRepeatedHeader();
  if (logical_height > page_height)
    return false;

  // See https://drafts.csswg.org/css-tables-3/#repeated-headers which says
  // a header/footer can repeat if it takes up less than a quarter of the page.
  if (logical_height > 0 && page_height / logical_height < 4)
    return false;

  return true;
}

bool LayoutTableSection::MapToVisualRectInAncestorSpaceInternal(
    const LayoutBoxModelObject* ancestor,
    TransformState& transform_state,
    VisualRectFlags flags) const {
  if (ancestor == this)
    return true;
  // Repeating table headers and footers are painted once per
  // page/column. So we need to use the rect for the entire table because
  // the repeating headers/footers will appear throughout it.
  // This does not go through the regular fragmentation machinery, so we need
  // special code to expand the invalidation rect to contain all positions of
  // the header in all columns.
  // Note that this is in flow thread coordinates, not visual coordinates. The
  // enclosing LayoutFlowThread will convert to visual coordinates.
  if (IsRepeatingHeaderGroup() || IsRepeatingFooterGroup()) {
    transform_state.Flatten();
    FloatRect rect = transform_state.LastPlanarQuad().BoundingBox();
    rect.SetHeight(Table()->LogicalHeight());
    transform_state.SetQuad(FloatQuad(rect));
    return Table()->MapToVisualRectInAncestorSpaceInternal(
        ancestor, transform_state, flags);
  }
  return LayoutTableBoxComponent::MapToVisualRectInAncestorSpaceInternal(
      ancestor, transform_state, flags);
}

bool LayoutTableSection::PaintedOutputOfObjectHasNoEffectRegardlessOfSize()
    const {
  // LayoutTableSection paints background from columns.
  if (Table()->HasColElements())
    return false;
  return LayoutTableBoxComponent::
      PaintedOutputOfObjectHasNoEffectRegardlessOfSize();
}

}  // namespace blink
