/// <summary> /// Layout the cells by the calculated table layout /// </summary> /// <param name="g"></param> private void LayoutCells(RGraphics g) { double startx = Math.Max(_tableBox.ClientLeft + GetHorizontalSpacing(), 0); double starty = Math.Max(_tableBox.ClientTop + GetVerticalSpacing(), 0); double cury = starty; double maxRight = startx; double maxBottom = 0f; int currentrow = 0; // change start X by if the table should align to center or right if (_tableBox.TextAlign == CssConstants.Center || _tableBox.TextAlign == CssConstants.Right) { double maxRightCalc = GetWidthSum(); startx = _tableBox.TextAlign == CssConstants.Right ? GetAvailableTableWidth() - maxRightCalc : startx + (GetAvailableTableWidth() - maxRightCalc) / 2; _tableBox.Location = new RPoint(startx - _tableBox.ActualBorderLeftWidth - _tableBox.ActualPaddingLeft - GetHorizontalSpacing(), _tableBox.Location.Y); } for (int i = 0; i < _allRows.Count; i++) { var row = _allRows[i]; double curx = startx; int curCol = 0; bool breakPage = false; for (int j = 0; j < row.Boxes.Count; j++) { CssBox cell = row.Boxes[j]; if (curCol >= _columnWidths.Length) { break; } int rowspan = GetRowSpan(cell); var columnIndex = GetCellRealColumnIndex(row, cell); double width = GetCellWidth(columnIndex, cell); cell.Location = new RPoint(curx, cury); cell.Size = new RSize(width, 0f); cell.PerformLayout(g); //That will automatically set the bottom of the cell //Alter max bottom only if row is cell's row + cell's rowspan - 1 CssSpacingBox sb = cell as CssSpacingBox; if (sb != null) { if (sb.EndRow == currentrow) { maxBottom = Math.Max(maxBottom, sb.ExtendedBox.ActualBottom); } } else if (rowspan == 1) { maxBottom = Math.Max(maxBottom, cell.ActualBottom); } maxRight = Math.Max(maxRight, cell.ActualRight); curCol++; curx = cell.ActualRight + GetHorizontalSpacing(); } foreach (CssBox cell in row.Boxes) { CssSpacingBox spacer = cell as CssSpacingBox; if (spacer == null && GetRowSpan(cell) == 1) { cell.ActualBottom = maxBottom; CssLayoutEngine.ApplyCellVerticalAlignment(g, cell); } else if (spacer != null && spacer.EndRow == currentrow) { spacer.ExtendedBox.ActualBottom = maxBottom; CssLayoutEngine.ApplyCellVerticalAlignment(g, spacer.ExtendedBox); } // If one cell crosses page borders then don't need to check other cells in the row if (_tableBox.PageBreakInside == CssConstants.Avoid) { breakPage = cell.BreakPage(); if (breakPage) { cury = cell.Location.Y; break; } } } if (breakPage) // go back to move the whole row to the next page { if (i == 1) // do not leave single row in previous page { i = -1; // Start layout from the first row on new page } else { i--; } maxBottom = 0; continue; } cury = maxBottom + GetVerticalSpacing(); currentrow++; } maxRight = Math.Max(maxRight, _tableBox.Location.X + _tableBox.ActualWidth); _tableBox.ActualRight = maxRight + GetHorizontalSpacing() + _tableBox.ActualBorderRightWidth; _tableBox.ActualBottom = Math.Max(maxBottom, starty) + GetVerticalSpacing() + _tableBox.ActualBorderBottomWidth; }