import Ratio from "../../math/Ratio"; import Rect from "../../math/Rect"; import { Cell, CellRef, Grid, Row, RowRef } from "../../types"; export interface RenderedCell extends Cell { cellRef: CellRef; renderedRowIndex: number; rect: Rect; } export interface RenderedRow { rowRef: RowRef; rect: Rect; renderedCells: RenderedCell[]; } export interface RenderedGrid extends Grid { rect: Rect; renderedRows: RenderedRow[]; } function renderCell( grid: Grid, cell: Cell, cellRef: CellRef, renderedRowIndex: number, topLeftX: number, topLeftY: number, ): RenderedCell { const width = cell.widthRatio .divideRatio(grid.baseCellWidthRatio) .multiplyRatio(Ratio.fromInteger(grid.baseCellSize)) .toNumber(); const rect = new Rect(topLeftX, topLeftY, width, grid.baseCellSize); return { ...cell, cellRef, rect, renderedRowIndex }; } function renderRow( grid: Grid, row: Row, rowRef: RowRef, renderedRowIndex: number, topLeftY: number, ): RenderedRow { if (row.cells.length === 0) { return { ...row, rowRef, rect: new Rect(0, topLeftY, 0, 0), renderedCells: [], }; } let topLeftX = 0; const renderedCells = row.cells.map((cell, cellIndex) => { const cellRef = { ...rowRef, cellIndex }; const renderedCell = renderCell( grid, cell, cellRef, renderedRowIndex, topLeftX, topLeftY, ); topLeftX = renderedCell.rect.bottomRight.x; return renderedCell; }); const { topLeft } = renderedCells[0].rect; const { bottomRight } = renderedCells.at(-1)!.rect; const rect = new Rect( topLeft.x, topLeft.y, bottomRight.x - topLeft.x, bottomRight.y - topLeft.y, ); return { ...row, renderedCells, rect, rowRef }; } function renderRows(grid: Grid): RenderedRow[] { const renderedRows: RenderedRow[] = []; let partIndex = 0; let rowIndex = 0; let topLeftY = 0; let renderedRowIndex = 0; while (true) { if (!grid.parts[partIndex]?.rows[rowIndex]) break; const row = grid.parts[partIndex].rows[rowIndex]; const rowRef = { partIndex, rowIndex }; const renderedRow = renderRow( grid, row, rowRef, renderedRowIndex, topLeftY, ); topLeftY = renderedRow.rect.bottomRight.y; renderedRows.push(renderedRow); if (!grid.parts[++partIndex]) { partIndex = 0; rowIndex++; } renderedRowIndex++; } return renderedRows; } export default function renderGrid(grid: Grid) { const renderedRows = renderRows(grid); const rect = renderedRows[0].rect.extend(renderedRows.at(-1)!.rect); return { ...grid, rect, renderedRows }; }