/*
 * Copyright (C) 2002 Lars Knoll (knoll@kde.org)
 *           (C) 2002 Dirk Mueller (mueller@kde.org)
 * Copyright (C) 2003, 2006, 2008, 2010 Apple Inc. All rights reserved.
 *
 * 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.
 *
 * 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 "core/layout/TableLayoutAlgorithmAuto.h"

#include "core/layout/LayoutTable.h"
#include "core/layout/LayoutTableCell.h"
#include "core/layout/LayoutTableCol.h"
#include "core/layout/LayoutTableSection.h"
#include "core/layout/TextAutosizer.h"

namespace blink {

TableLayoutAlgorithmAuto::TableLayoutAlgorithmAuto(LayoutTable* table)
    : TableLayoutAlgorithm(table),
      has_percent_(false),
      effective_logical_width_dirty_(true),
      scaled_width_from_percent_columns_() {}

TableLayoutAlgorithmAuto::~TableLayoutAlgorithmAuto() = default;

void TableLayoutAlgorithmAuto::RecalcColumn(unsigned eff_col) {
  Layout& column_layout = layout_struct_[eff_col];

  LayoutTableCell* fixed_contributor = nullptr;
  LayoutTableCell* max_contributor = nullptr;

  for (LayoutObject* child = table_->Children()->FirstChild(); child;
       child = child->NextSibling()) {
    if (child->IsLayoutTableCol()) {
      // LayoutTableCols don't have the concept of preferred logical width, but
      // we need to clear their dirty bits so that if we call
      // setPreferredWidthsDirty(true) on a col or one of its descendants, we'll
      // mark it's ancestors as dirty.
      ToLayoutTableCol(child)->ClearPreferredLogicalWidthsDirtyBits();
    } else if (child->IsTableSection()) {
      LayoutTableSection* section = ToLayoutTableSection(child);
      unsigned num_rows = section->NumRows();
      for (unsigned i = 0; i < num_rows; i++) {
        if (eff_col >= section->NumCols(i))
          continue;
        auto& grid_cell = section->GridCellAt(i, eff_col);
        LayoutTableCell* cell = grid_cell.PrimaryCell();

        if (grid_cell.InColSpan() || !cell)
          continue;
        column_layout.column_has_no_cells = false;

        if (cell->MaxPreferredLogicalWidth())
          column_layout.empty_cells_only = false;

        if (cell->ColSpan() == 1) {
          column_layout.min_logical_width =
              std::max<int>(cell->MinPreferredLogicalWidth().ToInt(),
                            column_layout.min_logical_width);
          if (cell->MaxPreferredLogicalWidth() >
              column_layout.max_logical_width) {
            column_layout.max_logical_width =
                cell->MaxPreferredLogicalWidth().ToInt();
            max_contributor = cell;
          }

          // All browsers implement a size limit on the cell's max width.
          // Our limit is based on KHTML's representation that used 16 bits
          // widths.
          // FIXME: Other browsers have a lower limit for the cell's max width.
          const int kCCellMaxWidth = 32760;
          Length cell_logical_width = cell->StyleOrColLogicalWidth();
          // FIXME: calc() on tables should be handled consistently with other
          // lengths. See bug: https://crbug.com/382725
          if (cell_logical_width.IsCalculated())
            cell_logical_width = Length();  // Make it Auto
          if (cell_logical_width.Value() > kCCellMaxWidth)
            cell_logical_width.SetValue(kCCellMaxWidth);
          if (cell_logical_width.IsNegative())
            cell_logical_width.SetValue(0);
          switch (cell_logical_width.GetType()) {
            case kFixed:
              // ignore width=0
              if (cell_logical_width.IsPositive() &&
                  !column_layout.logical_width.IsPercentOrCalc()) {
                int logical_width =
                    cell->AdjustBorderBoxLogicalWidthForBoxSizing(
                            cell_logical_width.Value())
                        .ToInt();
                if (column_layout.logical_width.IsFixed()) {
                  // Nav/IE weirdness
                  if ((logical_width > column_layout.logical_width.Value()) ||
                      ((column_layout.logical_width.Value() == logical_width) &&
                       (max_contributor == cell))) {
                    column_layout.logical_width.SetValue(kFixed, logical_width);
                    fixed_contributor = cell;
                  }
                } else {
                  column_layout.logical_width.SetValue(kFixed, logical_width);
                  fixed_contributor = cell;
                }
              }
              break;
            case kPercent:
              has_percent_ = true;
              // TODO(alancutter): Make this work correctly for calc lengths.
              if (cell_logical_width.IsPositive() &&
                  (!column_layout.logical_width.IsPercentOrCalc() ||
                   cell_logical_width.Value() >
                       column_layout.logical_width.Value()))
                column_layout.logical_width = cell_logical_width;
              break;
            default:
              break;
          }
        } else if (!eff_col || section->PrimaryCellAt(i, eff_col - 1) != cell) {
          // If a cell originates in this spanning column ensure we have a
          // min/max width of at least 1px for it.
          column_layout.min_logical_width =
              std::max<int>(column_layout.min_logical_width,
                            cell->MaxPreferredLogicalWidth() ? 1 : 0);

          // This spanning cell originates in this column. Insert the cell into
          // spanning cells list.
          InsertSpanCell(cell);
        }
      }
    }
  }

  // Nav/IE weirdness
  if (column_layout.logical_width.IsFixed()) {
    if (table_->GetDocument().InQuirksMode() &&
        column_layout.max_logical_width > column_layout.logical_width.Value() &&
        fixed_contributor != max_contributor) {
      column_layout.logical_width = Length();
      fixed_contributor = nullptr;
    }
  }

  column_layout.max_logical_width = std::max(column_layout.max_logical_width,
                                             column_layout.min_logical_width);
}

void TableLayoutAlgorithmAuto::FullRecalc() {
  has_percent_ = false;
  effective_logical_width_dirty_ = true;

  unsigned n_eff_cols = table_->NumEffectiveColumns();
  layout_struct_.resize(n_eff_cols);
  layout_struct_.Fill(Layout());
  span_cells_.Fill(0);

  Length group_logical_width;
  unsigned current_column = 0;
  for (LayoutTableCol* column = table_->FirstColumn(); column;
       column = column->NextColumn()) {
    if (column->IsTableColumnGroupWithColumnChildren()) {
      group_logical_width = column->Style()->LogicalWidth();
    } else {
      Length col_logical_width = column->Style()->LogicalWidth();
      // FIXME: calc() on tables should be handled consistently with other
      // lengths. See bug: https://crbug.com/382725
      if (col_logical_width.IsCalculated() || col_logical_width.IsAuto())
        col_logical_width = group_logical_width;
      // TODO(alancutter): Make this work correctly for calc lengths.
      if ((col_logical_width.IsFixed() ||
           col_logical_width.IsPercentOrCalc()) &&
          col_logical_width.IsZero())
        col_logical_width = Length();
      unsigned eff_col =
          table_->AbsoluteColumnToEffectiveColumn(current_column);
      unsigned span = column->Span();
      if (!col_logical_width.IsAuto() && span == 1 && eff_col < n_eff_cols &&
          table_->SpanOfEffectiveColumn(eff_col) == 1) {
        layout_struct_[eff_col].logical_width = col_logical_width;
        if (col_logical_width.IsFixed() &&
            layout_struct_[eff_col].max_logical_width <
                col_logical_width.Value())
          layout_struct_[eff_col].max_logical_width = col_logical_width.Value();
      }
      current_column += span;
    }

    // For the last column in a column-group, we invalidate our group logical
    // width.
    if (column->IsTableColumn() && !column->NextSibling())
      group_logical_width = Length();
  }

  for (unsigned i = 0; i < n_eff_cols; i++)
    RecalcColumn(i);
}

static bool ShouldScaleColumnsForParent(LayoutTable* table) {
  LayoutBlock* cb = table->ContainingBlock();
  while (!cb->IsLayoutView()) {
    // It doesn't matter if our table is auto or fixed: auto means we don't
    // scale. Fixed doesn't care if we do or not because it doesn't depend
    // on the cell contents' preferred widths.
    if (cb->IsTableCell())
      return false;
    cb = cb->ContainingBlock();
  }
  return true;
}

// FIXME: This needs to be adapted for vertical writing modes.
static bool ShouldScaleColumnsForSelf(LayoutTable* table) {
  // Normally, scale all columns to satisfy this from CSS2.2:
  // "A percentage value for a column width is relative to the table width.
  // If the table has 'width: auto', a percentage represents a constraint on the
  // column's width"

  // A special case.  If this table is not fixed width and contained inside
  // a cell, then don't bloat the maxwidth by examining percentage growth.
  while (true) {
    Length tw = table->Style()->Width();
    if ((!tw.IsAuto() && !tw.IsPercentOrCalc()) ||
        table->IsOutOfFlowPositioned())
      return true;
    LayoutBlock* cb = table->ContainingBlock();

    while (!cb->IsLayoutView() && !cb->IsTableCell() &&
           cb->Style()->Width().IsAuto() && !cb->IsOutOfFlowPositioned())
      cb = cb->ContainingBlock();

    // TODO(dgrogan): Should the second clause check for isFixed() instead?
    if (!cb->IsTableCell() || (!cb->Style()->Width().IsAuto() &&
                               !cb->Style()->Width().IsPercentOrCalc()))
      return true;

    LayoutTableCell* cell = ToLayoutTableCell(cb);
    table = cell->Table();
    if (cell->ColSpan() > 1 || table->IsLogicalWidthAuto())
      return false;
  }
  NOTREACHED();
  return true;
}

void TableLayoutAlgorithmAuto::ComputeIntrinsicLogicalWidths(
    LayoutUnit& min_width,
    LayoutUnit& max_width) {
  TextAutosizer::TableLayoutScope text_autosizer_table_layout_scope(table_);

  FullRecalc();

  int span_max_logical_width = CalcEffectiveLogicalWidth();
  min_width = LayoutUnit();
  max_width = LayoutUnit();
  float max_percent = 0;
  float max_non_percent = 0;
  bool scale_columns_for_self = ShouldScaleColumnsForSelf(table_);

  float remaining_percent = 100;
  for (size_t i = 0; i < layout_struct_.size(); ++i) {
    min_width += layout_struct_[i].effective_min_logical_width;
    max_width += layout_struct_[i].effective_max_logical_width;
    if (scale_columns_for_self) {
      if (layout_struct_[i].effective_logical_width.IsPercentOrCalc()) {
        float percent =
            std::min(static_cast<float>(
                         layout_struct_[i].effective_logical_width.Percent()),
                     remaining_percent);
        // When percent columns meet or exceed 100% and there are remaining
        // columns, the other browsers (FF, Edge) use an artificially high max
        // width, so we do too. Instead of division by zero, logical_width and
        // max_non_percent are set to kTableMaxWidth. Issue:
        // https://github.com/w3c/csswg-drafts/issues/1501
        float logical_width =
            (percent > 0) ? static_cast<float>(
                                layout_struct_[i].effective_max_logical_width) *
                                100 / percent
                          : kTableMaxWidth;
        max_percent = std::max(logical_width, max_percent);
        remaining_percent -= percent;
      } else {
        max_non_percent += layout_struct_[i].effective_max_logical_width;
      }
    }
  }

  if (scale_columns_for_self) {
    if (max_non_percent != 0) {
      max_non_percent = (remaining_percent > 0)
                            ? max_non_percent * 100 / remaining_percent
                            : kTableMaxWidth;
    }
    scaled_width_from_percent_columns_ =
        std::min(LayoutUnit(kTableMaxWidth),
                 LayoutUnit(std::max(max_percent, max_non_percent)));
    if (scaled_width_from_percent_columns_ > max_width &&
        ShouldScaleColumnsForParent(table_))
      max_width = scaled_width_from_percent_columns_;
  }

  max_width = LayoutUnit(std::max(max_width.Floor(), span_max_logical_width));
}

void TableLayoutAlgorithmAuto::ApplyPreferredLogicalWidthQuirks(
    LayoutUnit& min_width,
    LayoutUnit& max_width) const {
  Length table_logical_width = table_->Style()->LogicalWidth();
  if (table_logical_width.IsFixed() && table_logical_width.IsPositive()) {
    // |minWidth| is the result of measuring the intrinsic content's size. Keep
    // it to make sure we are *never* smaller than the actual content.
    LayoutUnit min_content_width = min_width;
    // FIXME: This line looks REALLY suspicious as it could allow the minimum
    // preferred logical width to be smaller than the table content. This has
    // to be cross-checked against other browsers.
    min_width = max_width = LayoutUnit(
        std::max<int>(min_width.Floor(), table_logical_width.Value()));

    const Length& style_max_logical_width = table_->Style()->LogicalMaxWidth();
    if (style_max_logical_width.IsFixed() &&
        !style_max_logical_width.IsNegative()) {
      min_width = LayoutUnit(
          std::min<int>(min_width.Floor(), style_max_logical_width.Value()));
      min_width = std::max(min_width, min_content_width);
      max_width = min_width;
    }
  }
}

/*
  This method takes care of colspans.
  effWidth is the same as width for cells without colspans. If we have colspans,
  they get modified.
 */
int TableLayoutAlgorithmAuto::CalcEffectiveLogicalWidth() {
  int max_logical_width = 0;

  size_t n_eff_cols = layout_struct_.size();
  int spacing_in_row_direction = table_->HBorderSpacing();

  for (size_t i = 0; i < n_eff_cols; ++i) {
    layout_struct_[i].effective_logical_width = layout_struct_[i].logical_width;
    layout_struct_[i].effective_min_logical_width =
        layout_struct_[i].min_logical_width;
    layout_struct_[i].effective_max_logical_width =
        layout_struct_[i].max_logical_width;
  }

  for (size_t i = 0; i < span_cells_.size(); ++i) {
    LayoutTableCell* cell = span_cells_[i];
    if (!cell)
      break;

    unsigned span = cell->ColSpan();

    Length cell_logical_width = cell->StyleOrColLogicalWidth();
    // FIXME: calc() on tables should be handled consistently with other
    // lengths. See bug: https://crbug.com/382725
    if (cell_logical_width.IsZero() || cell_logical_width.IsCalculated())
      cell_logical_width = Length();  // Make it Auto

    unsigned eff_col =
        table_->AbsoluteColumnToEffectiveColumn(cell->AbsoluteColumnIndex());
    size_t last_col = eff_col;
    int cell_min_logical_width =
        (cell->MinPreferredLogicalWidth() + spacing_in_row_direction).ToInt();
    int cell_max_logical_width =
        (cell->MaxPreferredLogicalWidth() + spacing_in_row_direction).ToInt();
    float total_percent = 0;
    int span_min_logical_width = 0;
    int span_max_logical_width = 0;
    bool all_cols_are_percent = true;
    bool all_cols_are_fixed = true;
    bool have_auto = false;
    bool span_has_empty_cells_only = true;
    int fixed_width = 0;
    while (last_col < n_eff_cols && span > 0) {
      Layout& column_layout = layout_struct_[last_col];
      switch (column_layout.logical_width.GetType()) {
        case kPercent:
          total_percent += column_layout.logical_width.Percent();
          all_cols_are_fixed = false;
          break;
        case kFixed:
          if (column_layout.logical_width.Value() > 0) {
            fixed_width += column_layout.logical_width.Value();
            all_cols_are_percent = false;
            // IE resets effWidth to Auto here, but this breaks the konqueror
            // about page and seems to be some bad legacy behaviour anyway.
            // mozilla doesn't do this so I decided we don't neither.
            break;
          }
        // fall through
        case kAuto:
          have_auto = true;
        // fall through
        default:
          // If the column is a percentage width, do not let the spanning cell
          // overwrite the width value.  This caused a mis-layout on amazon.com.
          // Sample snippet:
          // <table border=2 width=100%><
          //   <tr><td>1</td><td colspan=2>2-3</tr>
          //   <tr><td>1</td><td colspan=2 width=100%>2-3</td></tr>
          // </table>
          // TODO(alancutter): Make this work correctly for calc lengths.
          if (!column_layout.effective_logical_width.IsPercentOrCalc()) {
            column_layout.effective_logical_width = Length();
            all_cols_are_percent = false;
          } else {
            total_percent += column_layout.effective_logical_width.Percent();
          }
          all_cols_are_fixed = false;
      }
      if (!column_layout.empty_cells_only)
        span_has_empty_cells_only = false;
      span -= table_->SpanOfEffectiveColumn(last_col);
      span_min_logical_width += column_layout.effective_min_logical_width;
      span_max_logical_width += column_layout.effective_max_logical_width;
      last_col++;
      cell_min_logical_width -= spacing_in_row_direction;
      cell_max_logical_width -= spacing_in_row_direction;
    }

    // adjust table max width if needed
    if (cell_logical_width.IsPercentOrCalc()) {
      if (total_percent > cell_logical_width.Percent() ||
          all_cols_are_percent) {
        // can't satify this condition, treat as variable
        cell_logical_width = Length();
      } else {
        max_logical_width =
            std::max(max_logical_width,
                     static_cast<int>(std::max(span_max_logical_width,
                                               cell_max_logical_width) *
                                      100 / cell_logical_width.Percent()));

        // all non percent columns in the span get percent values to sum up
        // correctly.
        float percent_missing = cell_logical_width.Percent() - total_percent;
        int total_width = 0;
        for (unsigned pos = eff_col; pos < last_col; ++pos) {
          if (!layout_struct_[pos].effective_logical_width.IsPercentOrCalc())
            total_width +=
                layout_struct_[pos].ClampedEffectiveMaxLogicalWidth();
        }

        for (unsigned pos = eff_col; pos < last_col && total_width > 0; ++pos) {
          if (!layout_struct_[pos].effective_logical_width.IsPercentOrCalc()) {
            float percent =
                percent_missing *
                static_cast<float>(
                    layout_struct_[pos].effective_max_logical_width) /
                total_width;
            total_width -=
                layout_struct_[pos].ClampedEffectiveMaxLogicalWidth();
            percent_missing -= percent;
            if (percent > 0)
              layout_struct_[pos].effective_logical_width.SetValue(kPercent,
                                                                   percent);
            else
              layout_struct_[pos].effective_logical_width = Length();
          }
        }
      }
    }

    // make sure minWidth and maxWidth of the spanning cell are honoured
    if (cell_min_logical_width > span_min_logical_width) {
      if (all_cols_are_fixed) {
        for (unsigned pos = eff_col; fixed_width > 0 && pos < last_col; ++pos) {
          int cell_logical_width = std::max(
              layout_struct_[pos].effective_min_logical_width,
              static_cast<int>(cell_min_logical_width *
                               layout_struct_[pos].logical_width.Value() /
                               fixed_width));
          fixed_width -= layout_struct_[pos].logical_width.Value();
          cell_min_logical_width -= cell_logical_width;
          layout_struct_[pos].effective_min_logical_width = cell_logical_width;
        }
      } else if (all_cols_are_percent) {
        // In this case, we just split the colspan's min amd max widths
        // following the percentage.
        int allocated_min_logical_width = 0;
        int allocated_max_logical_width = 0;
        for (unsigned pos = eff_col; pos < last_col; ++pos) {
          // TODO(alancutter): Make this work correctly for calc lengths.
          DCHECK(layout_struct_[pos].logical_width.IsPercentOrCalc() ||
                 layout_struct_[pos].effective_logical_width.IsPercentOrCalc());
          // |allColsArePercent| means that either the logicalWidth *or* the
          // effectiveLogicalWidth are percents, handle both of them here.
          float percent =
              layout_struct_[pos].logical_width.IsPercentOrCalc()
                  ? layout_struct_[pos].logical_width.Percent()
                  : layout_struct_[pos].effective_logical_width.Percent();
          int column_min_logical_width = static_cast<int>(
              percent * cell_min_logical_width / total_percent);
          int column_max_logical_width = static_cast<int>(
              percent * cell_max_logical_width / total_percent);
          layout_struct_[pos].effective_min_logical_width =
              std::max(layout_struct_[pos].effective_min_logical_width,
                       column_min_logical_width);
          layout_struct_[pos].effective_max_logical_width =
              column_max_logical_width;
          allocated_min_logical_width += column_min_logical_width;
          allocated_max_logical_width += column_max_logical_width;
        }
        DCHECK_LE(allocated_min_logical_width, cell_min_logical_width);
        DCHECK_LE(allocated_max_logical_width, cell_max_logical_width);
        cell_min_logical_width -= allocated_min_logical_width;
        cell_max_logical_width -= allocated_max_logical_width;
      } else {
        int remaining_max_logical_width = span_max_logical_width;
        int remaining_min_logical_width = span_min_logical_width;

        // Give min to variable first, to fixed second, and to others third.
        for (unsigned pos = eff_col;
             remaining_max_logical_width >= 0 && pos < last_col; ++pos) {
          if (layout_struct_[pos].logical_width.IsFixed() && have_auto &&
              fixed_width <= cell_min_logical_width) {
            int col_min_logical_width =
                std::max<int>(layout_struct_[pos].effective_min_logical_width,
                              layout_struct_[pos].logical_width.Value());
            fixed_width -= layout_struct_[pos].logical_width.Value();
            remaining_min_logical_width -=
                layout_struct_[pos].effective_min_logical_width;
            remaining_max_logical_width -=
                layout_struct_[pos].effective_max_logical_width;
            cell_min_logical_width -= col_min_logical_width;
            layout_struct_[pos].effective_min_logical_width =
                col_min_logical_width;
          }
        }

        for (unsigned pos = eff_col;
             remaining_max_logical_width >= 0 && pos < last_col &&
             remaining_min_logical_width < cell_min_logical_width;
             ++pos) {
          if (!(layout_struct_[pos].logical_width.IsFixed() && have_auto &&
                fixed_width <= cell_min_logical_width)) {
            int col_min_logical_width = std::max<int>(
                layout_struct_[pos].effective_min_logical_width,
                static_cast<int>(
                    remaining_max_logical_width
                        ? cell_min_logical_width *
                              static_cast<float>(
                                  layout_struct_[pos]
                                      .effective_max_logical_width) /
                              remaining_max_logical_width
                        : cell_min_logical_width));
            col_min_logical_width = std::min<int>(
                layout_struct_[pos].effective_min_logical_width +
                    (cell_min_logical_width - remaining_min_logical_width),
                col_min_logical_width);
            remaining_max_logical_width -=
                layout_struct_[pos].effective_max_logical_width;
            remaining_min_logical_width -=
                layout_struct_[pos].effective_min_logical_width;
            cell_min_logical_width -= col_min_logical_width;
            layout_struct_[pos].effective_min_logical_width =
                col_min_logical_width;
          }
        }
      }
    }
    if (!cell_logical_width.IsPercentOrCalc()) {
      if (cell_max_logical_width > span_max_logical_width) {
        for (unsigned pos = eff_col;
             span_max_logical_width >= 0 && pos < last_col; ++pos) {
          int col_max_logical_width = std::max(
              layout_struct_[pos].effective_max_logical_width,
              static_cast<int>(span_max_logical_width
                                   ? cell_max_logical_width *
                                         static_cast<float>(
                                             layout_struct_[pos]
                                                 .effective_max_logical_width) /
                                         span_max_logical_width
                                   : cell_max_logical_width));
          span_max_logical_width -=
              layout_struct_[pos].effective_max_logical_width;
          cell_max_logical_width -= col_max_logical_width;
          layout_struct_[pos].effective_max_logical_width =
              col_max_logical_width;
        }
      }
    } else {
      for (unsigned pos = eff_col; pos < last_col; ++pos)
        layout_struct_[pos].max_logical_width =
            std::max(layout_struct_[pos].max_logical_width,
                     layout_struct_[pos].min_logical_width);
    }
    // treat span ranges consisting of empty cells only as if they had content
    if (span_has_empty_cells_only) {
      for (unsigned pos = eff_col; pos < last_col; ++pos)
        layout_struct_[pos].empty_cells_only = false;
    }
  }
  effective_logical_width_dirty_ = false;

  return std::min(max_logical_width, INT_MAX / 2);
}

/* gets all cells that originate in a column and have a cellspan > 1
   Sorts them by increasing cellspan
*/
void TableLayoutAlgorithmAuto::InsertSpanCell(LayoutTableCell* cell) {
  DCHECK(cell);
  DCHECK_NE(cell->ColSpan(), 1u);
  if (!cell || cell->ColSpan() == 1)
    return;

  unsigned size = span_cells_.size();
  if (!size || span_cells_[size - 1] != 0) {
    span_cells_.Grow(size + 10);
    for (unsigned i = 0; i < 10; i++)
      span_cells_[size + i] = 0;
    size += 10;
  }

  // Add them in sort. This is a slow algorithm, and a binary search or a fast
  // sorting after collection would be better.
  unsigned pos = 0;
  unsigned span = cell->ColSpan();
  while (pos < span_cells_.size() && span_cells_[pos] &&
         span > span_cells_[pos]->ColSpan())
    pos++;
  memmove(span_cells_.data() + pos + 1, span_cells_.data() + pos,
          (size - pos - 1) * sizeof(LayoutTableCell*));
  span_cells_[pos] = cell;
}

void TableLayoutAlgorithmAuto::UpdateLayout() {
  // table layout based on the values collected in the layout structure.
  int table_logical_width = (table_->LogicalWidth() -
                             table_->BordersPaddingAndSpacingInRowDirection())
                                .ToInt();
  int available = table_logical_width;
  size_t n_eff_cols = table_->NumEffectiveColumns();

  // FIXME: It is possible to be called without having properly updated our
  // internal representation.  This means that our preferred logical widths were
  // not recomputed as expected.
  if (n_eff_cols != layout_struct_.size()) {
    FullRecalc();
    // FIXME: Table layout shouldn't modify our table structure (but does due to
    // columns and column-groups).
    n_eff_cols = table_->NumEffectiveColumns();
  }

  if (effective_logical_width_dirty_)
    CalcEffectiveLogicalWidth();

  bool have_percent = false;
  int num_auto = 0;
  int num_fixed = 0;
  float total_auto = 0;
  float total_fixed = 0;
  float total_percent = 0;
  int alloc_auto = 0;
  unsigned num_auto_empty_cells_only = 0;

  // fill up every cell with its minWidth
  for (size_t i = 0; i < n_eff_cols; ++i) {
    int cell_logical_width = layout_struct_[i].effective_min_logical_width;
    layout_struct_[i].computed_logical_width = cell_logical_width;
    available -= cell_logical_width;
    Length& logical_width = layout_struct_[i].effective_logical_width;
    switch (logical_width.GetType()) {
      case kPercent:
        have_percent = true;
        total_percent += logical_width.Percent();
        break;
      case kFixed:
        num_fixed++;
        total_fixed += layout_struct_[i].ClampedEffectiveMaxLogicalWidth();
        // fall through
        break;
      case kAuto:
        if (layout_struct_[i].empty_cells_only) {
          num_auto_empty_cells_only++;
        } else {
          num_auto++;
          total_auto += layout_struct_[i].ClampedEffectiveMaxLogicalWidth();
        }
        if (!layout_struct_[i].column_has_no_cells)
          alloc_auto += cell_logical_width;
        break;
      default:
        break;
    }
  }

  // allocate width to percent cols
  if (available > 0 && have_percent) {
    for (size_t i = 0; i < n_eff_cols; ++i) {
      Length& logical_width = layout_struct_[i].effective_logical_width;
      if (logical_width.IsPercentOrCalc()) {
        int cell_logical_width =
            std::max<int>(layout_struct_[i].effective_min_logical_width,
                          MinimumValueForLength(logical_width,
                                                LayoutUnit(table_logical_width))
                              .ToInt());
        available +=
            layout_struct_[i].computed_logical_width - cell_logical_width;
        layout_struct_[i].computed_logical_width = cell_logical_width;
      }
    }
    if (total_percent > 100) {
      // remove overallocated space from the last columns
      int excess = table_logical_width * (total_percent - 100) / 100;
      for (unsigned i = n_eff_cols; i;) {
        --i;
        if (layout_struct_[i].effective_logical_width.IsPercentOrCalc()) {
          int cell_logical_width = layout_struct_[i].computed_logical_width;
          int reduction = std::min(cell_logical_width, excess);
          // The lines below might look inconsistent, but that's the way it's
          // handled in mozilla.
          excess -= reduction;
          int new_logical_width =
              std::max<int>(layout_struct_[i].effective_min_logical_width,
                            cell_logical_width - reduction);
          available += cell_logical_width - new_logical_width;
          layout_struct_[i].computed_logical_width = new_logical_width;
        }
      }
    }
  }

  // then allocate width to fixed cols
  if (available > 0) {
    for (size_t i = 0; i < n_eff_cols; ++i) {
      Length& logical_width = layout_struct_[i].effective_logical_width;
      if (logical_width.IsFixed() &&
          logical_width.Value() > layout_struct_[i].computed_logical_width) {
        available +=
            layout_struct_[i].computed_logical_width - logical_width.Value();
        layout_struct_[i].computed_logical_width = logical_width.Value();
      }
    }
  }

  // Give each auto width column its share of the available width, non-empty
  // columns then empty columns.
  if (available > 0 && (num_auto || num_auto_empty_cells_only)) {
    available += alloc_auto;
    if (num_auto)
      DistributeWidthToColumns<float, kAuto, kNonEmptyCells, kInitialWidth,
                               kStartToEnd>(available, total_auto);
    if (num_auto_empty_cells_only)
      DistributeWidthToColumns<unsigned, kAuto, kEmptyCells, kInitialWidth,
                               kStartToEnd>(available,
                                            num_auto_empty_cells_only);
  }

  // Any remaining available width expands fixed width, percent width, and
  // non-empty auto width columns, in that order.
  if (available > 0 && num_fixed)
    DistributeWidthToColumns<float, kFixed, kAllCells, kExtraWidth,
                             kStartToEnd>(available, total_fixed);

  if (available > 0 && has_percent_ && total_percent < 100)
    DistributeWidthToColumns<float, kPercent, kAllCells, kExtraWidth,
                             kStartToEnd>(available, total_percent);

  if (available > 0 && n_eff_cols > num_auto_empty_cells_only) {
    unsigned total = n_eff_cols - num_auto_empty_cells_only;
    // Starting from the last cell is for compatibility with FF/IE - it isn't
    // specified anywhere.
    DistributeWidthToColumns<unsigned, kAuto, kNonEmptyCells, kLeftoverWidth,
                             kEndToStart>(available, total);
  }

  // If we have overallocated, reduce every cell according to the difference
  // between desired width and minwidth. This seems to produce to the pixel
  // exact results with IE. Wonder is some of this also holds for width
  // distributing. This is basically the reverse of how we grew the cells.
  if (available < 0)
    ShrinkColumnWidth(kAuto, available);
  if (available < 0)
    ShrinkColumnWidth(kFixed, available);
  if (available < 0)
    ShrinkColumnWidth(kPercent, available);

  DCHECK_EQ(table_->EffectiveColumnPositions().size(), n_eff_cols + 1);
  int pos = 0;
  for (size_t i = 0; i < n_eff_cols; ++i) {
    table_->SetEffectiveColumnPosition(i, pos);
    pos += layout_struct_[i].computed_logical_width + table_->HBorderSpacing();
  }
  // The extra position is for the imaginary column after the last column.
  table_->SetEffectiveColumnPosition(n_eff_cols, pos);
}

template <typename Total,
          LengthType lengthType,
          CellsToProcess cellsToProcess,
          DistributionMode distributionMode,
          DistributionDirection distributionDirection>
void TableLayoutAlgorithmAuto::DistributeWidthToColumns(int& available,
                                                        Total total) {
  // TODO(alancutter): Make this work correctly for calc lengths.
  int n_eff_cols = static_cast<int>(table_->NumEffectiveColumns());
  bool start_to_end = distributionDirection == kStartToEnd;
  for (int i = start_to_end ? 0 : n_eff_cols - 1;
       start_to_end ? i < n_eff_cols : i > -1; start_to_end ? ++i : --i) {
    const Length& logical_width = layout_struct_[i].effective_logical_width;
    if (cellsToProcess == kNonEmptyCells && logical_width.IsAuto() &&
        layout_struct_[i].empty_cells_only)
      continue;
    // When allocating width to columns with nothing but empty cells we avoid
    // columns that exist only to flesh out a colspan and have no actual cells.
    if (cellsToProcess == kEmptyCells && logical_width.IsAuto() &&
        (!layout_struct_[i].empty_cells_only ||
         layout_struct_[i].column_has_no_cells))
      continue;
    if (distributionMode != kLeftoverWidth &&
        logical_width.GetType() != lengthType)
      continue;

    float factor = 1;
    if (distributionMode != kLeftoverWidth) {
      if (lengthType == kPercent)
        factor = logical_width.Percent();
      else if (lengthType == kAuto || lengthType == kFixed)
        factor = layout_struct_[i].ClampedEffectiveMaxLogicalWidth();
    }

    int new_width = available * factor / total;
    int cell_logical_width =
        (distributionMode == kInitialWidth)
            ? max<int>(layout_struct_[i].computed_logical_width, new_width)
            : new_width;
    available -= cell_logical_width;
    total -= factor;
    layout_struct_[i].computed_logical_width =
        (distributionMode == kInitialWidth)
            ? cell_logical_width
            : layout_struct_[i].computed_logical_width + cell_logical_width;

    // If we have run out of width to allocate we're done.
    // TODO(rhogan): Extend this to Fixed as well.
    if (lengthType == kPercent && (!available || !total))
      return;
    if (lengthType == kAuto && !total)
      return;
  }
}

void TableLayoutAlgorithmAuto::ShrinkColumnWidth(const LengthType& length_type,
                                                 int& available) {
  size_t n_eff_cols = table_->NumEffectiveColumns();
  int logical_width_beyond_min = 0;
  for (unsigned i = n_eff_cols; i;) {
    --i;
    Length& logical_width = layout_struct_[i].effective_logical_width;
    if (logical_width.GetType() == length_type)
      logical_width_beyond_min += layout_struct_[i].computed_logical_width -
                                  layout_struct_[i].effective_min_logical_width;
  }

  for (unsigned i = n_eff_cols; i && logical_width_beyond_min > 0;) {
    --i;
    Length& logical_width = layout_struct_[i].effective_logical_width;
    if (logical_width.GetType() == length_type) {
      int min_max_diff = layout_struct_[i].computed_logical_width -
                         layout_struct_[i].effective_min_logical_width;
      int reduce = available * min_max_diff / logical_width_beyond_min;
      layout_struct_[i].computed_logical_width += reduce;
      available -= reduce;
      logical_width_beyond_min -= min_max_diff;
      if (available >= 0)
        break;
    }
  }
}
}  // namespace blink
