chromium/third_party/blink/renderer/core/layout/table/table_layout_utils.cc

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

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include "third_party/blink/renderer/core/layout/table/table_layout_utils.h"

#include "third_party/blink/renderer/core/layout/block_layout_algorithm_utils.h"
#include "third_party/blink/renderer/core/layout/block_node.h"
#include "third_party/blink/renderer/core/layout/box_fragment_builder.h"
#include "third_party/blink/renderer/core/layout/constraint_space.h"
#include "third_party/blink/renderer/core/layout/constraint_space_builder.h"
#include "third_party/blink/renderer/core/layout/disable_layout_side_effects_scope.h"
#include "third_party/blink/renderer/core/layout/fragmentation_utils.h"
#include "third_party/blink/renderer/core/layout/geometry/logical_size.h"
#include "third_party/blink/renderer/core/layout/layout_result.h"
#include "third_party/blink/renderer/core/layout/length_utils.h"
#include "third_party/blink/renderer/core/layout/logical_box_fragment.h"
#include "third_party/blink/renderer/core/layout/physical_box_fragment.h"
#include "third_party/blink/renderer/core/layout/table/layout_table.h"
#include "third_party/blink/renderer/core/layout/table/layout_table_cell.h"
#include "third_party/blink/renderer/core/layout/table/layout_table_column.h"
#include "third_party/blink/renderer/core/layout/table/layout_table_column_visitor.h"
#include "third_party/blink/renderer/core/layout/table/layout_table_row.h"
#include "third_party/blink/renderer/core/layout/table/layout_table_section.h"
#include "third_party/blink/renderer/core/layout/table/table_borders.h"
#include "third_party/blink/renderer/core/layout/table/table_node.h"

namespace blink {

namespace {

// We cannot distribute space to mergeable columns. Mark at least one of the
// spanned columns as distributable (i.e. non-mergeable).
//
// We'll mark the first (non-collapsed) column as non-mergeable. We should only
// merge adjacent columns that have no cells that start there.
//
// Example:
//
//             +------------------------+------------------------+
//             |          cell          |         cell           |
//    row 1    |       colspan 2        |       colspan 2        |
//             |                        |                        |
//             +------------+-----------+-----------+------------+
//             |    cell    |         cell          |   cell     |
//    row 2    | colspan 1  |       colspan 2       | colspan 1  |
//             |            |                       |            |
//             +------------+-----------------------+------------+
//
//   columns   |  column 1  |  column 2 | column 3  |  column 4  |
//
// No columns should be merged here, as there are no columns that has no cell
// starting there. We want all four columns to receive some space, or
// distribution would be uneven.
//
// Another interesting problem being solved here is the interaction between
// collapsed (visibility:collapse) and mergeable columns. We need to find the
// first column that isn't collapsed and mark it as non-mergeable. Otherwise the
// entire cell might merge into the first column, and collapse, and the whole
// cell would be hidden if the first column is collapsed.
//
// If all columns spanned actually collapse, the first column will be marked as
// non-meargeable.
void EnsureDistributableColumnExists(wtf_size_t start_column_index,
                                     wtf_size_t span,
                                     TableTypes::Columns* column_constraints) {}

// Applies cell/wide cell constraints to columns.
// Guarantees columns min/max widths have non-empty values.
void ApplyCellConstraintsToColumnConstraints(
    const TableTypes::CellInlineConstraints& cell_constraints,
    LayoutUnit inline_border_spacing,
    bool is_fixed_layout,
    TableTypes::ColspanCells* colspan_cell_constraints,
    TableTypes::Columns* column_constraints) {}

template <typename RowCountFunc>
TableTypes::Row ComputeMinimumRowBlockSize(
    const RowCountFunc& row_count_func,
    const BlockNode& row,
    const LayoutUnit cell_percentage_inline_size,
    const bool is_table_block_size_specified,
    const Vector<TableColumnLocation>& column_locations,
    const TableBorders& table_borders,
    wtf_size_t start_row_index,
    wtf_size_t row_index,
    wtf_size_t section_index,
    bool is_section_collapsed,
    TableTypes::CellBlockConstraints* cell_block_constraints,
    TableTypes::RowspanCells* rowspan_cells,
    ColspanCellTabulator* colspan_cell_tabulator) {}

// Computes inline constraints for COLGROUP/COLs.
class ColumnConstraintsBuilder {};

// Computes constraints specified on column elements.
void ComputeColumnElementConstraints(const HeapVector<BlockNode>& columns,
                                     bool is_fixed_layout,
                                     TableTypes::Columns* column_constraints) {}

void ComputeSectionInlineConstraints(
    const BlockNode& section,
    bool is_fixed_layout,
    bool is_first_section,
    WritingDirectionMode table_writing_direction,
    const TableBorders& table_borders,
    wtf_size_t section_index,
    wtf_size_t* row_index,
    TableTypes::CellInlineConstraints* cell_inline_constraints,
    TableTypes::ColspanCells* colspan_cell_inline_constraints) {}

// Implements spec distribution algorithm:
// https://www.w3.org/TR/css-tables-3/#width-distribution-algorithm
// |treat_target_size_as_constrained| constrained target can grow fixed-width
// columns. unconstrained target cannot grow fixed-width columns beyond
// specified size.
Vector<LayoutUnit> DistributeInlineSizeToComputedInlineSizeAuto(
    LayoutUnit target_inline_size,
    const TableTypes::Column* start_column,
    const TableTypes::Column* end_column,
    const bool treat_target_size_as_constrained) {}

Vector<LayoutUnit> SynchronizeAssignableTableInlineSizeAndColumnsFixed(
    LayoutUnit target_inline_size,
    const TableTypes::Columns& column_constraints) {}

void DistributeColspanCellToColumnsFixed(
    const TableTypes::ColspanCell& colspan_cell,
    LayoutUnit inline_border_spacing,
    TableTypes::Columns* column_constraints) {}

void DistributeColspanCellToColumnsAuto(
    const TableTypes::ColspanCell& colspan_cell,
    LayoutUnit inline_border_spacing,
    TableTypes::Columns* column_constraints) {}

// Handles distribution of excess block size from: table, sections,
// rows, and rowspanned cells, to rows.
// Rowspanned cells distribute with slight differences from
// general distribution algorithm.
void DistributeExcessBlockSizeToRows(
    const wtf_size_t start_row_index,
    const wtf_size_t row_count,
    LayoutUnit desired_block_size,
    bool is_rowspan_distribution,
    LayoutUnit border_block_spacing,
    LayoutUnit percentage_resolution_block_size,
    TableTypes::Rows* rows) {}

}  // namespace

CellBlockSizeData ComputeCellBlockSize(
    const TableTypes::CellBlockConstraint& cell_block_constraint,
    const TableTypes::Rows& rows,
    wtf_size_t row_index,
    const LogicalSize& border_spacing,
    bool is_table_block_size_specified) {}

void SetupTableCellConstraintSpaceBuilder(
    const WritingDirectionMode table_writing_direction,
    const BlockNode cell,
    const BoxStrut& cell_borders,
    const Vector<TableColumnLocation>& column_locations,
    LayoutUnit cell_block_size,
    LayoutUnit percentage_inline_size,
    std::optional<LayoutUnit> alignment_baseline,
    wtf_size_t start_column,
    bool is_initial_block_size_indefinite,
    bool is_table_block_size_specified,
    bool has_collapsed_borders,
    LayoutResultCacheSlot cache_slot,
    ConstraintSpaceBuilder* builder) {}

// Computes maximum possible number of non-mergeable columns.
wtf_size_t ComputeMaximumNonMergeableColumnCount(
    const HeapVector<BlockNode>& columns,
    bool is_fixed_layout) {}

scoped_refptr<TableTypes::Columns> ComputeColumnConstraints(
    const BlockNode& table,
    const TableGroupedChildren& grouped_children,
    const TableBorders& table_borders,
    const BoxStrut& border_padding) {}

void ComputeSectionMinimumRowBlockSizes(
    const BlockNode& section,
    const LayoutUnit cell_percentage_inline_size,
    const bool is_table_block_size_specified,
    const Vector<TableColumnLocation>& column_locations,
    const TableBorders& table_borders,
    const LayoutUnit block_border_spacing,
    wtf_size_t section_index,
    bool treat_section_as_tbody,
    TableTypes::Sections* sections,
    TableTypes::Rows* rows,
    TableTypes::CellBlockConstraints* cell_block_constraints) {}

void FinalizeTableCellLayout(LayoutUnit unconstrained_intrinsic_block_size,
                             BoxFragmentBuilder* builder) {}

void ColspanCellTabulator::StartRow() {}

// Remove colspanned cells that are not spanning any more rows.
void ColspanCellTabulator::EndRow() {}

// Advance current column to position not occupied by colspanned cells.
void ColspanCellTabulator::FindNextFreeColumn() {}

void ColspanCellTabulator::ProcessCell(const BlockNode& cell) {}

void RowBaselineTabulator::ProcessCell(
    const LogicalBoxFragment& fragment,
    BlockContentAlignment align,
    const bool is_rowspanned,
    const bool descendant_depends_on_percentage_block_size) {}

LayoutUnit RowBaselineTabulator::ComputeRowBlockSize(
    const LayoutUnit max_cell_block_size) {}

LayoutUnit RowBaselineTabulator::ComputeBaseline(
    const LayoutUnit row_block_size) {}

bool RowBaselineTabulator::BaselineDependsOnPercentageBlockDescendant() {}

MinMaxSizes ComputeGridInlineMinMax(
    const TableNode& node,
    const TableTypes::Columns& column_constraints,
    LayoutUnit undistributable_space,
    bool is_fixed_layout,
    bool is_layout_pass) {}

void DistributeColspanCellsToColumns(
    const TableTypes::ColspanCells& colspan_cells,
    LayoutUnit inline_border_spacing,
    bool is_fixed_layout,
    TableTypes::Columns* column_constraints) {}

// Standard: https://www.w3.org/TR/css-tables-3/#width-distribution-algorithm
// After synchroniziation, assignable table inline size and sum of column
// final inline sizes will be equal.
Vector<LayoutUnit> SynchronizeAssignableTableInlineSizeAndColumns(
    LayoutUnit assignable_table_inline_size,
    bool is_fixed_layout,
    const TableTypes::Columns& column_constraints) {}

void DistributeRowspanCellToRows(const TableTypes::RowspanCell& rowspan_cell,
                                 LayoutUnit border_block_spacing,
                                 TableTypes::Rows* rows) {}

// Legacy code ignores section block size.
void DistributeSectionFixedBlockSizeToRows(
    const wtf_size_t start_row,
    const wtf_size_t rowspan,
    LayoutUnit section_fixed_block_size,
    LayoutUnit border_block_spacing,
    LayoutUnit percentage_resolution_block_size,
    TableTypes::Rows* rows) {}

void DistributeTableBlockSizeToSections(LayoutUnit border_block_spacing,
                                        LayoutUnit table_block_size,
                                        TableTypes::Sections* sections,
                                        TableTypes::Rows* rows) {}

}  // namespace blink