/** * Adds a new table to * @param table Table to add. Rendered rows will be deleted after processing. * @param onlyFirstPage Render only the first full page * @throws DocumentException */ private void AddPdfTable(Table t) { // before every table, we flush all lines FlushLines(); PdfTable table = new PdfTable(t, IndentLeft, IndentRight, IndentTop - currentHeight); RenderingContext ctx = new RenderingContext(); ctx.pagetop = IndentTop; ctx.oldHeight = currentHeight; ctx.cellGraphics = new PdfContentByte(writer); ctx.rowspanMap = new Hashtable(); ctx.table = table; // initialisation of parameters PdfCell cell; // drawing the table ArrayList headercells = table.HeaderCells; ArrayList cells = table.Cells; ArrayList rows = ExtractRows(cells, ctx); bool isContinue = false; while (cells.Count != 0) { // initialisation of some extra parameters; ctx.lostTableBottom = 0; // loop over the cells bool cellsShown = false; // draw the cells (line by line) ListIterator iterator = new ListIterator(rows); bool atLeastOneFits = false; while (iterator.HasNext()) { ArrayList row = (ArrayList) iterator.Next(); AnalyzeRow(rows, ctx); RenderCells(ctx, row, table.HasToFitPageCells() & atLeastOneFits); if (!MayBeRemoved(row)) { break; } ConsumeRowspan(row, ctx); iterator.Remove(); atLeastOneFits = true; } // compose cells array list for subsequent code cells.Clear(); Hashtable opt = new Hashtable(); foreach (ArrayList row in rows) { foreach (PdfCell cellp in row) { if (!opt.ContainsKey(cellp)) { cells.Add(cellp); opt[cellp] = null; } } } // we paint the graphics of the table after looping through all the cells Rectangle tablerec = new Rectangle(table); tablerec.Border = table.Border; tablerec.BorderWidth = table.BorderWidth; tablerec.BorderColor = table.BorderColor; tablerec.BackgroundColor = table.BackgroundColor; PdfContentByte under = writer.DirectContentUnder; under.Rectangle(tablerec.GetRectangle(Top, IndentBottom)); under.Add(ctx.cellGraphics); // bugfix by Gerald Fehringer: now again add the border for the table // since it might have been covered by cell backgrounds tablerec.BackgroundColor = null; tablerec = tablerec.GetRectangle(Top, IndentBottom); tablerec.Border = table.Border; under.Rectangle(tablerec); // end bugfix ctx.cellGraphics = new PdfContentByte(null); // if the table continues on the next page if (rows.Count != 0) { isContinue = true; graphics.SetLineWidth(table.BorderWidth); if (cellsShown && (table.Border & Rectangle.BOTTOM_BORDER) == Rectangle.BOTTOM_BORDER) { // Draw the bottom line // the color is set to the color of the element Color tColor = table.BorderColor; if (tColor != null) { graphics.SetColorStroke(tColor); } graphics.MoveTo(table.Left, Math.Max(table.Bottom, IndentBottom)); graphics.LineTo(table.Right, Math.Max(table.Bottom, IndentBottom)); graphics.Stroke(); if (tColor != null) { graphics.ResetRGBColorStroke(); } } // old page pageEmpty = false; float difference = ctx.lostTableBottom; // new page NewPage(); // G.F.: if something added in page event i.e. currentHeight > 0 float heightCorrection = 0; bool somethingAdded = false; if (currentHeight > 0) { heightCorrection = 6; currentHeight += heightCorrection; somethingAdded = true; NewLine(); FlushLines(); indentation.indentTop = currentHeight - leading; currentHeight = 0; } else { FlushLines(); } // this part repeats the table headers (if any) int size = headercells.Count; if (size > 0) { // this is the top of the headersection cell = (PdfCell) headercells[0]; float oldTop = cell.GetTop(0); // loop over all the cells of the table header for (int ii = 0; ii < size; ii++) { cell = (PdfCell) headercells[ii]; // calculation of the new cellpositions cell.Top = IndentTop - oldTop + cell.GetTop(0); cell.Bottom = IndentTop - oldTop + cell.GetBottom(0); ctx.pagetop = cell.Bottom; // we paint the borders of the cell ctx.cellGraphics.Rectangle(cell.Rectangle(IndentTop, IndentBottom)); // we write the text of the cell ArrayList images = cell.GetImages(IndentTop, IndentBottom); foreach (Image image in images) { cellsShown = true; graphics.AddImage(image); } lines = cell.GetLines(IndentTop, IndentBottom); float cellTop = cell.GetTop(IndentTop); text.MoveText(0, cellTop-heightCorrection); float cellDisplacement = FlushLines() - cellTop+heightCorrection; text.MoveText(0, cellDisplacement); } currentHeight = IndentTop - ctx.pagetop + table.Cellspacing; text.MoveText(0, ctx.pagetop - IndentTop - currentHeight); } else { if (somethingAdded) { ctx.pagetop = IndentTop; text.MoveText(0, -table.Cellspacing); } } ctx.oldHeight = currentHeight - heightCorrection; // calculating the new positions of the table and the cells size = Math.Min(cells.Count, table.Columns); int i = 0; while (i < size) { cell = (PdfCell) cells[i]; if (cell.GetTop(-table.Cellspacing) > ctx.lostTableBottom) { float newBottom = ctx.pagetop - difference + cell.Bottom; float neededHeight = cell.RemainingHeight; if (newBottom > ctx.pagetop - neededHeight) { difference += newBottom - (ctx.pagetop - neededHeight); } } i++; } size = cells.Count; table.Top = IndentTop; table.Bottom = ctx.pagetop - difference + table.GetBottom(table.Cellspacing); for (i = 0; i < size; i++) { cell = (PdfCell) cells[i]; float newBottom = ctx.pagetop - difference + cell.Bottom; float newTop = ctx.pagetop - difference + cell.GetTop(-table.Cellspacing); if (newTop > IndentTop - currentHeight) { newTop = IndentTop - currentHeight; } cell.Top = newTop ; cell.Bottom = newBottom ; } } } float tableHeight = table.Top - table.Bottom; // bugfix by Adauto Martins when have more than two tables and more than one page // If continuation of table in other page (bug report #1460051) if (isContinue) { currentHeight = tableHeight; text.MoveText(0, -(tableHeight - (ctx.oldHeight * 2))); } else { currentHeight = ctx.oldHeight + tableHeight; text.MoveText(0, -tableHeight); } pageEmpty = false; }