#pragma once
#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
#include "FormattingContext.h"
#include "LayoutUnits.h"
#include <wtf/HashMap.h>
#include <wtf/IsoMalloc.h>
#include <wtf/IsoMallocInlines.h>
#include <wtf/ListHashSet.h>
#include <wtf/WeakPtr.h>
namespace WebCore {
namespace Layout {
class Box;
class ContainerBox;
class TableGrid {
WTF_MAKE_ISO_ALLOCATED(TableGrid);
public:
TableGrid();
void appendCell(const ContainerBox&);
void insertCell(const ContainerBox&, const ContainerBox& before);
void removeCell(const ContainerBox&);
void setHorizontalSpacing(LayoutUnit horizontalSpacing) { m_horizontalSpacing = horizontalSpacing; }
LayoutUnit horizontalSpacing() const { return m_horizontalSpacing; }
void setVerticalSpacing(LayoutUnit verticalSpacing) { m_verticalSpacing = verticalSpacing; }
LayoutUnit verticalSpacing() const { return m_verticalSpacing; }
void setCollapsedBorder(const Edges& collapsedBorder) { m_collapsedBorder = collapsedBorder; }
Optional<Edges> collapsedBorder() const { return m_collapsedBorder; }
void setWidthConstraints(FormattingContext::IntrinsicWidthConstraints intrinsicWidthConstraints) { m_intrinsicWidthConstraints = intrinsicWidthConstraints; }
Optional<FormattingContext::IntrinsicWidthConstraints> widthConstraints() const { return m_intrinsicWidthConstraints; }
bool isEmpty() const { return m_slotMap.isEmpty(); }
class Column {
public:
Column(const ContainerBox*);
void setLogicalLeft(LayoutUnit);
LayoutUnit logicalLeft() const;
LayoutUnit logicalRight() const { return logicalLeft() + logicalWidth(); }
void setLogicalWidth(LayoutUnit);
LayoutUnit logicalWidth() const;
bool isFixedWidth() const;
void setHasFixedWidthCell() { m_hasFixedWidthCell = true; }
const ContainerBox* box() const { return m_layoutBox.get(); }
private:
bool hasFixedWidthCell() const { return m_hasFixedWidthCell; }
LayoutUnit m_computedLogicalWidth;
LayoutUnit m_computedLogicalLeft;
WeakPtr<const ContainerBox> m_layoutBox;
bool m_hasFixedWidthCell { false };
#if ASSERT_ENABLED
bool m_hasComputedWidth { false };
bool m_hasComputedLeft { false };
#endif
};
class Columns {
public:
using ColumnList = Vector<Column>;
ColumnList& list() { return m_columnList; }
const ColumnList& list() const { return m_columnList; }
size_t size() const { return m_columnList.size(); }
void addColumn(const ContainerBox&);
void addAnonymousColumn();
LayoutUnit logicalWidth() const { return m_columnList.last().logicalRight() - m_columnList.first().logicalLeft(); }
bool hasFixedColumnsOnly() const;
private:
ColumnList m_columnList;
};
class Row {
public:
Row(const ContainerBox&);
void setLogicalTop(LayoutUnit logicalTop) { m_logicalTop = logicalTop; }
LayoutUnit logicalTop() const { return m_logicalTop; }
LayoutUnit logicalBottom() const { return logicalTop() + logicalHeight(); }
void setLogicalHeight(LayoutUnit logicalHeight) { m_logicalHeight = logicalHeight; }
LayoutUnit logicalHeight() const { return m_logicalHeight; }
void setBaseline(InlineLayoutUnit baseline) { m_baseline = baseline; }
InlineLayoutUnit baseline() const { return m_baseline; }
const ContainerBox& box() const { return *m_layoutBox.get(); }
private:
LayoutUnit m_logicalTop;
LayoutUnit m_logicalHeight;
InlineLayoutUnit m_baseline { 0 };
WeakPtr<const ContainerBox> m_layoutBox;
};
class Rows {
public:
using RowList = Vector<Row>;
RowList& list() { return m_rowList; }
const RowList& list() const { return m_rowList; }
void addRow(const ContainerBox&);
size_t size() const { return m_rowList.size(); }
private:
RowList m_rowList;
};
class Cell : public CanMakeWeakPtr<Cell> {
WTF_MAKE_ISO_ALLOCATED_INLINE(Cell);
public:
Cell(const ContainerBox&, SlotPosition, CellSpan);
size_t startColumn() const { return m_position.column; }
size_t endColumn() const { return m_position.column + m_span.column; }
size_t startRow() const { return m_position.row; }
size_t endRow() const { return m_position.row + m_span.row; }
size_t columnSpan() const { return m_span.column; }
size_t rowSpan() const { return m_span.row; }
SlotPosition position() const { return m_position; }
CellSpan span() const { return m_span; }
void setBaseline(InlineLayoutUnit baseline) { m_baseline = baseline; }
InlineLayoutUnit baseline() const { return m_baseline; }
bool isFixedWidth() const;
const ContainerBox& box() const { return *m_layoutBox.get(); }
private:
WeakPtr<const ContainerBox> m_layoutBox;
SlotPosition m_position;
CellSpan m_span;
InlineLayoutUnit m_baseline { 0 };
};
class Slot {
public:
WTF_MAKE_STRUCT_FAST_ALLOCATED;
Slot() = default;
Slot(Cell&, bool isColumnSpanned, bool isRowSpanned);
const Cell& cell() const { return *m_cell; }
Cell& cell() { return *m_cell; }
const FormattingContext::IntrinsicWidthConstraints& widthConstraints() const { return m_widthConstraints; }
void setWidthConstraints(const FormattingContext::IntrinsicWidthConstraints& widthConstraints) { m_widthConstraints = widthConstraints; }
bool hasColumnSpan() const { return m_cell->columnSpan() > 1 && !isColumnSpanned(); }
bool hasRowSpan() const { return m_cell->rowSpan() > 1 && !isRowSpanned(); }
bool isColumnSpanned() const { return m_isColumnSpanned; }
bool isRowSpanned() const { return m_isRowSpanned; }
private:
WeakPtr<Cell> m_cell;
bool m_isColumnSpanned { false };
bool m_isRowSpanned { false };
FormattingContext::IntrinsicWidthConstraints m_widthConstraints;
};
const Columns& columns() const { return m_columns; }
Columns& columns() { return m_columns; }
const Rows& rows() const { return m_rows; }
Rows& rows() { return m_rows; }
using Cells = WTF::ListHashSet<std::unique_ptr<Cell>>;
Cells& cells() { return m_cells; }
Slot* slot(SlotPosition);
const Slot* slot(SlotPosition position) const { return m_slotMap.get(position); }
bool isSpanned(SlotPosition);
private:
using SlotMap = WTF::HashMap<SlotPosition, std::unique_ptr<Slot>>;
Columns m_columns;
Rows m_rows;
Cells m_cells;
SlotMap m_slotMap;
LayoutUnit m_horizontalSpacing;
LayoutUnit m_verticalSpacing;
Optional<FormattingContext::IntrinsicWidthConstraints> m_intrinsicWidthConstraints;
Optional<Edges> m_collapsedBorder;
};
}
}
#endif