| /* |
| * Copyright (C) 2019 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
| * THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "config.h" |
| #include "TableGrid.h" |
| |
| #if ENABLE(LAYOUT_FORMATTING_CONTEXT) |
| |
| #include <wtf/IsoMallocInlines.h> |
| |
| namespace WebCore { |
| namespace Layout { |
| |
| WTF_MAKE_ISO_ALLOCATED_IMPL(TableGrid); |
| |
| void TableGrid::Column::setWidthConstraints(FormattingContext::IntrinsicWidthConstraints widthConstraints) |
| { |
| #ifndef NDEBUG |
| m_hasWidthConstraints = true; |
| #endif |
| m_widthConstraints = widthConstraints; |
| } |
| |
| FormattingContext::IntrinsicWidthConstraints TableGrid::Column::widthConstraints() const |
| { |
| ASSERT(m_hasWidthConstraints); |
| return m_widthConstraints; |
| } |
| |
| void TableGrid::Column::setLogicalWidth(LayoutUnit computedLogicalWidth) |
| { |
| #ifndef NDEBUG |
| m_hasComputedWidth = true; |
| #endif |
| m_computedLogicalWidth = computedLogicalWidth; |
| } |
| |
| LayoutUnit TableGrid::Column::logicalWidth() const |
| { |
| ASSERT(m_hasComputedWidth); |
| return m_computedLogicalWidth; |
| } |
| |
| void TableGrid::Column::setLogicalLeft(LayoutUnit computedLogicalLeft) |
| { |
| #ifndef NDEBUG |
| m_hasComputedLeft = true; |
| #endif |
| m_computedLogicalLeft = computedLogicalLeft; |
| } |
| |
| LayoutUnit TableGrid::Column::logicalLeft() const |
| { |
| ASSERT(m_hasComputedLeft); |
| return m_computedLogicalLeft; |
| } |
| |
| void TableGrid::ColumnsContext::addColumn() |
| { |
| m_columns.append({ }); |
| } |
| |
| TableGrid::Row::Row(const Box& rowBox) |
| : m_layoutBox(rowBox) |
| { |
| } |
| |
| TableGrid::CellInfo::CellInfo(const Box& tableCellBox, SlotPosition position, CellSize size) |
| : tableCellBox(tableCellBox) |
| , position(position) |
| , size(size) |
| { |
| } |
| |
| TableGrid::SlotInfo::SlotInfo(CellInfo& cell) |
| : cell(makeWeakPtr(cell)) |
| { |
| } |
| |
| TableGrid::TableGrid() |
| { |
| } |
| |
| TableGrid::SlotInfo* TableGrid::slot(SlotPosition position) |
| { |
| return m_slotMap.get(position); |
| } |
| |
| void TableGrid::appendCell(const Box& tableCellBox) |
| { |
| int rowSpan = tableCellBox.rowSpan(); |
| int columnSpan = tableCellBox.columnSpan(); |
| auto isInNewRow = !tableCellBox.previousSibling(); |
| auto initialSlotPosition = SlotPosition { }; |
| |
| if (!m_cellList.isEmpty()) { |
| auto& lastCell = m_cellList.last(); |
| auto lastSlotPosition = lastCell->position; |
| // First table cell in this row? |
| if (isInNewRow) |
| initialSlotPosition = SlotPosition { 0, lastSlotPosition.y() + 1 }; |
| else |
| initialSlotPosition = SlotPosition { lastSlotPosition.x() + 1, lastSlotPosition.y() }; |
| |
| // Pick the next available slot by avoiding row and column spanners. |
| while (true) { |
| if (!m_slotMap.contains(initialSlotPosition)) |
| break; |
| initialSlotPosition.move(1, 0); |
| } |
| } |
| auto cellInfo = makeUnique<CellInfo>(tableCellBox, initialSlotPosition, CellSize { rowSpan, columnSpan }); |
| // Row and column spanners create additional slots. |
| for (int row = 1; row <= rowSpan; ++row) { |
| for (int column = 1; column <= columnSpan; ++column) { |
| auto position = SlotPosition { initialSlotPosition.x() + row - 1, initialSlotPosition.y() + column - 1 }; |
| ASSERT(!m_slotMap.contains(position)); |
| m_slotMap.add(position, makeUnique<SlotInfo>(*cellInfo)); |
| } |
| } |
| // Initialize columns/rows if needed. |
| auto missingNumberOfColumns = std::max<int>(0, initialSlotPosition.x() + columnSpan - m_columnsContext.columns().size()); |
| for (auto column = 0; column < missingNumberOfColumns; ++column) |
| m_columnsContext.addColumn(); |
| |
| if (isInNewRow) |
| m_rows.append({ *tableCellBox.parent() }); |
| |
| m_cellList.add(WTFMove(cellInfo)); |
| } |
| |
| void TableGrid::insertCell(const Box& tableCellBox, const Box& before) |
| { |
| UNUSED_PARAM(tableCellBox); |
| UNUSED_PARAM(before); |
| } |
| |
| void TableGrid::removeCell(const Box& tableCellBox) |
| { |
| UNUSED_PARAM(tableCellBox); |
| } |
| |
| FormattingContext::IntrinsicWidthConstraints TableGrid::widthConstraints() const |
| { |
| // FIXME: We should probably cache this value. |
| auto widthConstraints = FormattingContext::IntrinsicWidthConstraints { }; |
| for (auto& column : m_columnsContext.columns()) |
| widthConstraints += column.widthConstraints(); |
| widthConstraints.expand((m_columnsContext.columns().size() + 1) * m_horizontalSpacing); |
| return widthConstraints; |
| } |
| |
| } |
| } |
| #endif |