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

#include "core/paint/TableSectionPainter.h"

#include <algorithm>
#include "core/layout/LayoutTableCell.h"
#include "core/layout/LayoutTableCol.h"
#include "core/layout/LayoutTableRow.h"
#include "core/paint/AdjustPaintOffsetScope.h"
#include "core/paint/BoxClipper.h"
#include "core/paint/BoxPainter.h"
#include "core/paint/BoxPainterBase.h"
#include "core/paint/CollapsedBorderPainter.h"
#include "core/paint/ObjectPainter.h"
#include "core/paint/PaintInfo.h"
#include "core/paint/TableCellPainter.h"
#include "core/paint/TableRowPainter.h"
#include "platform/graphics/paint/DisplayItemCacheSkipper.h"
#include "platform/graphics/paint/DrawingRecorder.h"

namespace blink {

void TableSectionPainter::PaintRepeatingHeaderGroup(
    const PaintInfo& paint_info,
    const LayoutPoint& paint_offset,
    ItemToPaint item_to_paint) {
  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
      // TODO(wangxianzhu): Use the PaintPropertyTreeBuilder path for printing.
      (!paint_info.IsPrinting() ||
       layout_table_section_.FirstFragment().NextFragment()))
    return;

  if (!layout_table_section_.IsRepeatingHeaderGroup())
    return;

  LayoutTable* table = layout_table_section_.Table();
  // TODO(crbug.com/757947): This shouldn't be possible but happens to
  // column-spanners in nested multi-col contexts.
  if (!table->IsPageLogicalHeightKnown())
    return;

  // We may paint the header multiple times so can't uniquely identify each
  // display item.
  DisplayItemCacheSkipper cache_skipper(paint_info.context);

  LayoutPoint pagination_offset = paint_offset;
  LayoutUnit page_height = table->PageLogicalHeightForOffset(LayoutUnit());

  LayoutUnit header_group_offset = table->BlockOffsetToFirstRepeatableHeader();
  // The header may have a pagination strut before it so we need to account for
  // that when establishing its position.
  LayoutUnit strut_on_first_row;
  if (LayoutTableRow* row = layout_table_section_.FirstRow())
    strut_on_first_row = row->PaginationStrut();
  header_group_offset += strut_on_first_row;
  LayoutUnit offset_to_next_page =
      page_height - IntMod(header_group_offset, page_height);
  // Move pagination_offset to the top of the next page.
  pagination_offset.Move(LayoutUnit(), offset_to_next_page);
  // Now move pagination_offset to the top of the page the cull rect starts on.
  if (paint_info.GetCullRect().rect_.Y() > pagination_offset.Y()) {
    pagination_offset.Move(LayoutUnit(),
                           page_height * ((paint_info.GetCullRect().rect_.Y() -
                                           pagination_offset.Y()) /
                                          page_height)
                                             .ToInt());
  }

  // We only want to consider pages where we going to paint a row, so exclude
  // captions and border spacing from the table.
  LayoutRect sections_rect(LayoutPoint(), table->Size());
  table->SubtractCaptionRect(sections_rect);
  LayoutUnit total_height_of_rows =
      sections_rect.Height() - table->VBorderSpacing();
  LayoutUnit bottom_bound =
      std::min(LayoutUnit(paint_info.GetCullRect().rect_.MaxY()),
               paint_offset.Y() + total_height_of_rows);

  while (pagination_offset.Y() < bottom_bound) {
    LayoutPoint nested_offset = pagination_offset;
    LayoutUnit height_of_previous_headers =
        table->RowOffsetFromRepeatingHeader() -
        layout_table_section_.LogicalHeight() + strut_on_first_row;
    nested_offset.Move(LayoutUnit(), height_of_previous_headers);
    if (item_to_paint == kPaintCollapsedBorders) {
      PaintCollapsedSectionBorders(paint_info, nested_offset);
    } else {
      PaintSection(paint_info, nested_offset);
    }
    pagination_offset.Move(0, page_height.ToInt());
  }
}

void TableSectionPainter::PaintRepeatingFooterGroup(
    const PaintInfo& paint_info,
    const LayoutPoint& paint_offset,
    ItemToPaint item_to_paint) {
  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
      // TODO(wangxianzhu): Use the PaintPropertyTreeBuilder path for printing.
      (!paint_info.IsPrinting() ||
       layout_table_section_.FirstFragment().NextFragment()))
    return;

  if (!layout_table_section_.IsRepeatingFooterGroup())
    return;

  // Work out the top position of the table so we can decide
  // which page to paint the first footer on.
  LayoutTable* table = layout_table_section_.Table();
  // TODO(crbug.com/757947): This shouldn't be possible but happens to
  // column-spanners in nested multi-col contexts.
  if (!table->IsPageLogicalHeightKnown())
    return;

  // We may paint the footer multiple times so can't uniquely identify each
  // display item.
  DisplayItemCacheSkipper cache_skipper(paint_info.context);

  LayoutRect sections_rect(LayoutPoint(), table->Size());
  table->SubtractCaptionRect(sections_rect);
  LayoutUnit page_height = table->PageLogicalHeightForOffset(LayoutUnit());
  LayoutUnit height_of_previous_footers = table->RowOffsetFromRepeatingFooter();
  LayoutUnit offset_for_footer = page_height - height_of_previous_footers;
  // TODO: Accounting for the border-spacing here is wrong.
  LayoutUnit header_group_offset =
      table->BlockOffsetToFirstRepeatableHeader() + table->VBorderSpacing();
  // The first row in the table may have a pagination strut before it so we need
  // to account for that when establishing its position.
  LayoutUnit strut_on_first_row;
  LayoutTableSection* top_section = table->TopSection();
  if (top_section) {
    if (LayoutTableRow* row = top_section->FirstRow())
      strut_on_first_row = row->PaginationStrut();
  }
  header_group_offset += strut_on_first_row;
  LayoutUnit total_height_of_rows =
      sections_rect.Height() + IntMod(header_group_offset, page_height);
  LayoutUnit first_row_strut =
      layout_table_section_.FirstRow()
          ? layout_table_section_.FirstRow()->PaginationStrut()
          : LayoutUnit();
  total_height_of_rows -=
      layout_table_section_.LogicalHeight() - first_row_strut;

  // Move the offset to the top of the page the table starts on.
  LayoutPoint pagination_offset = paint_offset;
  pagination_offset.Move(LayoutUnit(), -total_height_of_rows);

  // Paint up to the last page that needs painting.
  LayoutUnit bottom_bound =
      std::min(LayoutUnit(paint_info.GetCullRect().rect_.MaxY()),
               pagination_offset.Y() + total_height_of_rows - page_height);

  // If the first row in the table would overlap with the footer on the first
  // page then don't repeat the footer there.
  if (top_section && top_section->FirstRow() &&
      IntMod(header_group_offset, page_height) +
              top_section->FirstRow()->LogicalHeight() >
          offset_for_footer) {
    pagination_offset.Move(LayoutUnit(), page_height);
  }

  // Paint a footer on each page from first to next-to-last.
  while (pagination_offset.Y() < bottom_bound) {
    LayoutPoint nested_offset = pagination_offset;
    nested_offset.Move(LayoutUnit(), offset_for_footer);
    if (item_to_paint == kPaintCollapsedBorders) {
      PaintCollapsedSectionBorders(paint_info, nested_offset);
    } else {
      PaintSection(paint_info, nested_offset);
    }
    pagination_offset.Move(0, page_height.ToInt());
  }
}

void TableSectionPainter::Paint(const PaintInfo& paint_info,
                                const LayoutPoint& paint_offset) {
  PaintSection(paint_info, paint_offset);
  LayoutTable* table = layout_table_section_.Table();
  if (table->Header() == layout_table_section_) {
    PaintRepeatingHeaderGroup(paint_info, paint_offset, kPaintSection);
  } else if (table->Footer() == layout_table_section_) {
    PaintRepeatingFooterGroup(paint_info, paint_offset, kPaintSection);
  }
}

void TableSectionPainter::PaintSection(const PaintInfo& paint_info,
                                       const LayoutPoint& paint_offset) {
  DCHECK(!layout_table_section_.NeedsLayout());
  // avoid crashing on bugs that cause us to paint with dirty layout
  if (layout_table_section_.NeedsLayout())
    return;

  unsigned total_rows = layout_table_section_.NumRows();
  unsigned total_cols = layout_table_section_.Table()->NumEffectiveColumns();

  if (!total_rows || !total_cols)
    return;

  AdjustPaintOffsetScope adjustment(layout_table_section_, paint_info,
                                    paint_offset);
  const auto& local_paint_info = adjustment.GetPaintInfo();
  auto adjusted_paint_offset = adjustment.AdjustedPaintOffset();

  if (local_paint_info.phase != PaintPhase::kSelfOutlineOnly) {
    Optional<BoxClipper> box_clipper;
    if (local_paint_info.phase != PaintPhase::kSelfBlockBackgroundOnly) {
      box_clipper.emplace(layout_table_section_, local_paint_info,
                          adjusted_paint_offset, kForceContentsClip);
    }
    PaintObject(local_paint_info, adjusted_paint_offset);
  }

  if (ShouldPaintSelfOutline(local_paint_info.phase)) {
    ObjectPainter(layout_table_section_)
        .PaintOutline(local_paint_info, adjusted_paint_offset);
  }
}

void TableSectionPainter::PaintCollapsedBorders(
    const PaintInfo& paint_info,
    const LayoutPoint& paint_offset) {
  PaintCollapsedSectionBorders(paint_info, paint_offset);
  LayoutTable* table = layout_table_section_.Table();
  if (table->Header() == layout_table_section_) {
    PaintRepeatingHeaderGroup(paint_info, paint_offset, kPaintCollapsedBorders);
  } else if (table->Footer() == layout_table_section_) {
    PaintRepeatingFooterGroup(paint_info, paint_offset, kPaintCollapsedBorders);
  }
}

void TableSectionPainter::PaintCollapsedSectionBorders(
    const PaintInfo& paint_info,
    const LayoutPoint& paint_offset) {
  if (!layout_table_section_.NumRows() ||
      !layout_table_section_.Table()->EffectiveColumns().size())
    return;

  AdjustPaintOffsetScope adjustment(layout_table_section_, paint_info,
                                    paint_offset);
  const auto& local_paint_info = adjustment.GetPaintInfo();
  auto adjusted_paint_offset = adjustment.AdjustedPaintOffset();
  BoxClipper box_clipper(layout_table_section_, local_paint_info,
                         adjusted_paint_offset, kForceContentsClip);

  LayoutRect local_visual_rect =
      LayoutRect(local_paint_info.GetCullRect().rect_);
  local_visual_rect.MoveBy(-adjusted_paint_offset);

  LayoutRect table_aligned_rect =
      layout_table_section_.LogicalRectForWritingModeAndDirection(
          local_visual_rect);

  CellSpan dirtied_rows;
  CellSpan dirtied_columns;
  if (UNLIKELY(
          layout_table_section_.Table()->ShouldPaintAllCollapsedBorders())) {
    // Ignore paint cull rect to simplify paint invalidation in such rare case.
    dirtied_rows = layout_table_section_.FullSectionRowSpan();
    dirtied_columns = layout_table_section_.FullTableEffectiveColumnSpan();
  } else {
    layout_table_section_.DirtiedRowsAndEffectiveColumns(
        table_aligned_rect, dirtied_rows, dirtied_columns);
  }

  if (dirtied_columns.Start() >= dirtied_columns.End())
    return;

  // Collapsed borders are painted from the bottom right to the top left so that
  // precedence due to cell position is respected.
  for (unsigned r = dirtied_rows.End(); r > dirtied_rows.Start(); r--) {
    if (const auto* row = layout_table_section_.RowLayoutObjectAt(r - 1)) {
      TableRowPainter(*row).PaintCollapsedBorders(
          local_paint_info, adjusted_paint_offset, dirtied_columns);
    }
  }
}

void TableSectionPainter::PaintObject(const PaintInfo& paint_info,
                                      const LayoutPoint& paint_offset) {
  LayoutRect local_visual_rect = LayoutRect(paint_info.GetCullRect().rect_);
  local_visual_rect.MoveBy(-paint_offset);

  LayoutRect table_aligned_rect =
      layout_table_section_.LogicalRectForWritingModeAndDirection(
          local_visual_rect);

  CellSpan dirtied_rows;
  CellSpan dirtied_columns;
  layout_table_section_.DirtiedRowsAndEffectiveColumns(
      table_aligned_rect, dirtied_rows, dirtied_columns);

  PaintInfo paint_info_for_descendants = paint_info.ForDescendants();

  if (ShouldPaintSelfBlockBackground(paint_info.phase)) {
    PaintBoxDecorationBackground(paint_info, paint_offset, dirtied_rows,
                                 dirtied_columns);
  }

  if (paint_info.phase == PaintPhase::kSelfBlockBackgroundOnly)
    return;

  if (ShouldPaintDescendantBlockBackgrounds(paint_info.phase)) {
    for (unsigned r = dirtied_rows.Start(); r < dirtied_rows.End(); r++) {
      const LayoutTableRow* row = layout_table_section_.RowLayoutObjectAt(r);
      // If a row has a layer, we'll paint row background though
      // TableRowPainter::paint().
      if (!row || row->HasSelfPaintingLayer())
        continue;
      TableRowPainter(*row).PaintBoxDecorationBackground(
          paint_info_for_descendants, paint_offset, dirtied_columns);
    }
  }

  // This is tested after background painting because during background painting
  // we need to check validity of the previous background display item based on
  // dirtyRows and dirtyColumns.
  if (dirtied_rows.Start() >= dirtied_rows.End() ||
      dirtied_columns.Start() >= dirtied_columns.End())
    return;

  const auto& overflowing_cells = layout_table_section_.OverflowingCells();
  if (overflowing_cells.IsEmpty()) {
    // This path is for 2 cases:
    // 1. Normal partial paint, without overflowing cells;
    // 2. Full paint, for small sections or big sections with many overflowing
    //    cells.
    // The difference between the normal partial paint and full paint is that
    // whether dirtied_rows and dirtied_columns cover the whole section.
    DCHECK(!layout_table_section_.HasOverflowingCell() ||
           (dirtied_rows == layout_table_section_.FullSectionRowSpan() &&
            dirtied_columns ==
                layout_table_section_.FullTableEffectiveColumnSpan()));

    for (unsigned r = dirtied_rows.Start(); r < dirtied_rows.End(); r++) {
      const LayoutTableRow* row = layout_table_section_.RowLayoutObjectAt(r);
      // TODO(crbug.com/577282): This painting order is inconsistent with other
      // outlines.
      if (row && !row->HasSelfPaintingLayer() &&
          ShouldPaintSelfOutline(paint_info_for_descendants.phase)) {
        TableRowPainter(*row).PaintOutline(paint_info_for_descendants,
                                           paint_offset);
      }
      for (unsigned c = dirtied_columns.Start(); c < dirtied_columns.End();
           c++) {
        if (const LayoutTableCell* cell =
                layout_table_section_.OriginatingCellAt(r, c))
          PaintCell(*cell, paint_info_for_descendants, paint_offset);
      }
    }
  } else {
    // This path paints section with a reasonable number of overflowing cells.
    // This is the "partial paint path" for overflowing cells referred in
    // LayoutTableSection::ComputeOverflowFromDescendants().
    Vector<const LayoutTableCell*> cells;
    CopyToVector(overflowing_cells, cells);

    HashSet<const LayoutTableCell*> spanning_cells;
    for (unsigned r = dirtied_rows.Start(); r < dirtied_rows.End(); r++) {
      const LayoutTableRow* row = layout_table_section_.RowLayoutObjectAt(r);
      // TODO(crbug.com/577282): This painting order is inconsistent with other
      // outlines.
      if (row && !row->HasSelfPaintingLayer() &&
          ShouldPaintSelfOutline(paint_info_for_descendants.phase)) {
        TableRowPainter(*row).PaintOutline(paint_info_for_descendants,
                                           paint_offset);
      }
      unsigned n_cols = layout_table_section_.NumCols(r);
      for (unsigned c = dirtied_columns.Start();
           c < n_cols && c < dirtied_columns.End(); c++) {
        if (const auto* cell = layout_table_section_.OriginatingCellAt(r, c)) {
          if (!overflowing_cells.Contains(cell))
            cells.push_back(cell);
        }
      }
    }

    // Sort the dirty cells by paint order.
    std::sort(cells.begin(), cells.end(), LayoutTableCell::CompareInDOMOrder);
    for (const auto* cell : cells)
      PaintCell(*cell, paint_info_for_descendants, paint_offset);
  }
}

void TableSectionPainter::PaintBoxDecorationBackground(
    const PaintInfo& paint_info,
    const LayoutPoint& paint_offset,
    const CellSpan& dirtied_rows,
    const CellSpan& dirtied_columns) {
  bool may_have_background = layout_table_section_.Table()->HasColElements() ||
                             layout_table_section_.StyleRef().HasBackground();
  bool has_box_shadow = layout_table_section_.StyleRef().BoxShadow();
  if (!may_have_background && !has_box_shadow)
    return;

  PaintResult paint_result =
      dirtied_columns == layout_table_section_.FullTableEffectiveColumnSpan() &&
              dirtied_rows == layout_table_section_.FullSectionRowSpan()
          ? kFullyPainted
          : kMayBeClippedByPaintDirtyRect;
  layout_table_section_.GetMutableForPainting().UpdatePaintResult(
      paint_result, paint_info.GetCullRect());

  if (DrawingRecorder::UseCachedDrawingIfPossible(
          paint_info.context, layout_table_section_,
          DisplayItem::kBoxDecorationBackground))
    return;

  DrawingRecorder recorder(paint_info.context, layout_table_section_,
                           DisplayItem::kBoxDecorationBackground);
  LayoutRect paint_rect(paint_offset, layout_table_section_.Size());

  if (has_box_shadow) {
    BoxPainterBase::PaintNormalBoxShadow(paint_info, paint_rect,
                                         layout_table_section_.StyleRef());
  }

  if (may_have_background) {
    PaintInfo paint_info_for_cells = paint_info.ForDescendants();
    for (auto r = dirtied_rows.Start(); r < dirtied_rows.End(); r++) {
      for (auto c = dirtied_columns.Start(); c < dirtied_columns.End(); c++) {
        if (const auto* cell = layout_table_section_.OriginatingCellAt(r, c)) {
          PaintBackgroundsBehindCell(*cell, paint_info_for_cells, paint_offset);
        }
      }
    }
  }

  if (has_box_shadow) {
    BoxPainterBase::PaintInsetBoxShadowWithInnerRect(
        paint_info, paint_rect, layout_table_section_.StyleRef());
  }
}

void TableSectionPainter::PaintBackgroundsBehindCell(
    const LayoutTableCell& cell,
    const PaintInfo& paint_info_for_cells,
    const LayoutPoint& paint_offset) {
  LayoutPoint cell_point =
      layout_table_section_.FlipForWritingModeForChild(&cell, paint_offset);

  // We need to handle painting a stack of backgrounds. This stack (from bottom
  // to top) consists of the column group, column, row group, row, and then the
  // cell.

  LayoutTable::ColAndColGroup col_and_col_group =
      layout_table_section_.Table()->ColElementAtAbsoluteColumn(
          cell.AbsoluteColumnIndex());
  LayoutTableCol* column = col_and_col_group.col;
  LayoutTableCol* column_group = col_and_col_group.colgroup;
  TableCellPainter table_cell_painter(cell);

  // Column groups and columns first.
  // FIXME: Columns and column groups do not currently support opacity, and they
  // are being painted "too late" in the stack, since we have already opened a
  // transparency layer (potentially) for the table row group.  Note that we
  // deliberately ignore whether or not the cell has a layer, since these
  // backgrounds paint "behind" the cell.
  if (column_group && column_group->StyleRef().HasBackground()) {
    table_cell_painter.PaintContainerBackgroundBehindCell(
        paint_info_for_cells, cell_point, *column_group);
  }
  if (column && column->StyleRef().HasBackground()) {
    table_cell_painter.PaintContainerBackgroundBehindCell(paint_info_for_cells,
                                                          cell_point, *column);
  }

  // Paint the row group next.
  if (layout_table_section_.StyleRef().HasBackground()) {
    table_cell_painter.PaintContainerBackgroundBehindCell(
        paint_info_for_cells, cell_point, layout_table_section_);
  }
}

void TableSectionPainter::PaintCell(const LayoutTableCell& cell,
                                    const PaintInfo& paint_info_for_cells,
                                    const LayoutPoint& paint_offset) {
  if (!cell.HasSelfPaintingLayer() && !cell.Row()->HasSelfPaintingLayer()) {
    LayoutPoint cell_point =
        layout_table_section_.FlipForWritingModeForChild(&cell, paint_offset);
    cell.Paint(paint_info_for_cells, cell_point);
  }
}

}  // namespace blink
