/** Gets the width that the line will occupy after writing. * Only the width of the first line is returned. * @param phrase the <CODE>Phrase</CODE> containing the line * @param runDirection the run direction * @param arabicOptions the options for the arabic shaping * @return the width of the line */ public static float GetWidth(Phrase phrase, int runDirection, int arabicOptions) { ColumnText ct = new ColumnText(null); ct.AddText(phrase); ct.AddWaitingPhrase(); PdfLine line = ct.bidiLine.ProcessLine(0, 20000, Element.ALIGN_LEFT, runDirection, arabicOptions); if (line == null) return 0; else return 20000 - line.WidthLeft; }
protected int GoComposite(bool simulate) { if (!rectangularMode) throw new DocumentException("Irregular columns are not supported in composite mode."); linesWritten = 0; descender = 0; bool firstPass = adjustFirstLine; main_loop: while (true) { if (compositeElements.Count == 0) return NO_MORE_TEXT; IElement element = (IElement)compositeElements[0]; if (element.Type == Element.PARAGRAPH) { Paragraph para = (Paragraph)element; int status = 0; for (int keep = 0; keep < 2; ++keep) { float lastY = yLine; bool createHere = false; if (compositeColumn == null) { compositeColumn = new ColumnText(canvas); compositeColumn.UseAscender = (firstPass ? useAscender : false); compositeColumn.Alignment = para.Alignment; compositeColumn.Indent = para.IndentationLeft + para.FirstLineIndent; compositeColumn.ExtraParagraphSpace = para.ExtraParagraphSpace; compositeColumn.FollowingIndent = para.IndentationLeft; compositeColumn.RightIndent = para.IndentationRight; compositeColumn.SetLeading(para.Leading, para.MultipliedLeading); compositeColumn.RunDirection = runDirection; compositeColumn.ArabicOptions = arabicOptions; compositeColumn.SpaceCharRatio = spaceCharRatio; compositeColumn.AddText(para); if (!firstPass) { yLine -= para.SpacingBefore; } createHere = true; } compositeColumn.leftX = leftX; compositeColumn.rightX = rightX; compositeColumn.yLine = yLine; compositeColumn.rectangularWidth = rectangularWidth; compositeColumn.rectangularMode = rectangularMode; compositeColumn.minY = minY; compositeColumn.maxY = maxY; bool keepCandidate = (para.KeepTogether && createHere && !firstPass); status = compositeColumn.Go(simulate || (keepCandidate && keep == 0)); UpdateFilledWidth(compositeColumn.filledWidth); if ((status & NO_MORE_TEXT) == 0 && keepCandidate) { compositeColumn = null; yLine = lastY; return NO_MORE_COLUMN; } if (simulate || !keepCandidate) break; if (keep == 0) { compositeColumn = null; yLine = lastY; } } firstPass = false; yLine = compositeColumn.yLine; linesWritten += compositeColumn.linesWritten; descender = compositeColumn.descender; if ((status & NO_MORE_TEXT) != 0) { compositeColumn = null; compositeElements.RemoveAt(0); yLine -= para.SpacingAfter; } if ((status & NO_MORE_COLUMN) != 0) { return NO_MORE_COLUMN; } } else if (element.Type == Element.LIST) { List list = (List)element; ArrayList items = list.Items; ListItem item = null; float listIndentation = list.IndentationLeft; int count = 0; Stack stack = new Stack(); for (int k = 0; k < items.Count; ++k) { Object obj = items[k]; if (obj is ListItem) { if (count == listIdx) { item = (ListItem)obj; break; } else ++count; } else if (obj is List) { stack.Push(new Object[]{list, k, listIndentation}); list = (List)obj; items = list.Items; listIndentation += list.IndentationLeft; k = -1; continue; } if (k == items.Count - 1) { if (stack.Count > 0) { Object[] objs = (Object[])stack.Pop(); list = (List)objs[0]; items = list.Items; k = (int)objs[1]; listIndentation = (float)objs[2]; } } } int status = 0; for (int keep = 0; keep < 2; ++keep) { float lastY = yLine; bool createHere = false; if (compositeColumn == null) { if (item == null) { listIdx = 0; compositeElements.RemoveAt(0); goto main_loop; } compositeColumn = new ColumnText(canvas); compositeColumn.UseAscender = (firstPass ? useAscender : false); compositeColumn.Alignment = item.Alignment; compositeColumn.Indent = item.IndentationLeft + listIndentation + item.FirstLineIndent; compositeColumn.ExtraParagraphSpace = item.ExtraParagraphSpace; compositeColumn.FollowingIndent = compositeColumn.Indent; compositeColumn.RightIndent = item.IndentationRight + list.IndentationRight; compositeColumn.SetLeading(item.Leading, item.MultipliedLeading); compositeColumn.RunDirection = runDirection; compositeColumn.ArabicOptions = arabicOptions; compositeColumn.SpaceCharRatio = spaceCharRatio; compositeColumn.AddText(item); if (!firstPass) { yLine -= item.SpacingBefore; } createHere = true; } compositeColumn.leftX = leftX; compositeColumn.rightX = rightX; compositeColumn.yLine = yLine; compositeColumn.rectangularWidth = rectangularWidth; compositeColumn.rectangularMode = rectangularMode; compositeColumn.minY = minY; compositeColumn.maxY = maxY; bool keepCandidate = (item.KeepTogether && createHere && !firstPass); status = compositeColumn.Go(simulate || (keepCandidate && keep == 0)); UpdateFilledWidth(compositeColumn.filledWidth); if ((status & NO_MORE_TEXT) == 0 && keepCandidate) { compositeColumn = null; yLine = lastY; return NO_MORE_COLUMN; } if (simulate || !keepCandidate) break; if (keep == 0) { compositeColumn = null; yLine = lastY; } } firstPass = false; yLine = compositeColumn.yLine; linesWritten += compositeColumn.linesWritten; descender = compositeColumn.descender; if (!float.IsNaN(compositeColumn.firstLineY) && !compositeColumn.firstLineYDone) { if (!simulate) ShowTextAligned(canvas, Element.ALIGN_LEFT, new Phrase(item.ListSymbol), compositeColumn.leftX + listIndentation, compositeColumn.firstLineY, 0); compositeColumn.firstLineYDone = true; } if ((status & NO_MORE_TEXT) != 0) { compositeColumn = null; ++listIdx; yLine -= item.SpacingAfter; } if ((status & NO_MORE_COLUMN) != 0) { return NO_MORE_COLUMN; } } else if (element.Type == Element.PTABLE) { // don't write anything in the current column if there's no more space available if (yLine < minY || yLine > maxY) return NO_MORE_COLUMN; // get the PdfPTable element PdfPTable table = (PdfPTable)element; // we ignore tables without a body if (table.Size <= table.HeaderRows) { compositeElements.RemoveAt(0); continue; } // offsets float yTemp = yLine; if (!firstPass && listIdx == 0) { yTemp -= table.SpacingBefore; } float yLineWrite = yTemp; // don't write anything in the current column if there's no more space available if (yTemp < minY || yTemp > maxY) { return NO_MORE_COLUMN; } // coordinates currentLeading = 0; float x1 = leftX; float tableWidth; if (table.LockedWidth) { tableWidth = table.TotalWidth; UpdateFilledWidth(tableWidth); } else { tableWidth = rectangularWidth * table.WidthPercentage / 100f; table.TotalWidth = tableWidth; } // how many header rows are real header rows; how many are footer rows? int headerRows = table.HeaderRows; int footerRows = table.FooterRows; if (footerRows > headerRows) footerRows = headerRows; int realHeaderRows = headerRows - footerRows; float headerHeight = table.HeaderHeight; float footerHeight = table.FooterHeight; // make sure the header and footer fit on the page bool skipHeader = (!firstPass && table.SkipFirstHeader && listIdx <= headerRows); if (!skipHeader) { yTemp -= headerHeight; if (yTemp < minY || yTemp > maxY) { if (firstPass) { compositeElements.RemoveAt(0); continue; } return NO_MORE_COLUMN; } } // how many real rows (not header or footer rows) fit on a page? int k; if (listIdx < headerRows) { listIdx = headerRows; } if (!table.ElementComplete) { yTemp -= footerHeight; } for (k = listIdx; k < table.Size; ++k) { float rowHeight = table.GetRowHeight(k); if (yTemp - rowHeight < minY) break; yTemp -= rowHeight; } if (!table.ElementComplete) { yTemp += footerHeight; } // either k is the first row that doesn't fit on the page (break); if (k < table.Size) { if (table.SplitRows && (!table.SplitLate || (k == listIdx && firstPass))) { if (!splittedRow) { splittedRow = true; table = new PdfPTable(table); compositeElements[0] = table; ArrayList rows = table.Rows; for (int i = headerRows; i < listIdx; ++i) rows[i] = null; } float h = yTemp - minY; PdfPRow newRow = table.GetRow(k).SplitRow(table, k, h); if (newRow == null) { if (k == listIdx) { return NO_MORE_COLUMN; } } else { yTemp = minY; table.Rows.Insert(++k, newRow); } } else if (!table.SplitRows && k == listIdx && firstPass) { compositeElements.RemoveAt(0); splittedRow = false; continue; } else if (k == listIdx && !firstPass && (!table.SplitRows || table.SplitLate) && (table.FooterRows == 0 || table.ElementComplete)) { return NO_MORE_COLUMN; } } // or k is the number of rows in the table (for loop was done). firstPass = false; // we draw the table (for real now) if (!simulate) { // set the alignment switch (table.HorizontalAlignment) { case Element.ALIGN_LEFT: break; case Element.ALIGN_RIGHT: x1 += rectangularWidth - tableWidth; break; default: x1 += (rectangularWidth - tableWidth) / 2f; break; } // copy the rows that fit on the page in a new table nt PdfPTable nt = PdfPTable.ShallowCopy(table); ArrayList sub = nt.Rows; // first we add the real header rows (if necessary) if (!skipHeader) { for (int j = 0; j < realHeaderRows; ++j) { PdfPRow headerRow = table.GetRow(j); sub.Add(headerRow); } } else { nt.HeaderRows = footerRows; } // then we add the real content sub.AddRange(table.GetRows(listIdx, k)); // if k < table.size(), we must indicate that the new table is complete; // otherwise no footers will be added (because iText thinks the table continues on the same page) bool showFooter = !table.SkipLastFooter; if (k < table.Size) { nt.ElementComplete = true; showFooter = true; } // we add the footer rows if necessary (not for incomplete tables) for (int j = 0; j < footerRows && nt.ElementComplete && showFooter; ++j) { sub.Add(table.GetRow(j + realHeaderRows)); } // we need a correction if the last row needs to be extended float rowHeight = 0; PdfPRow last = (PdfPRow)sub[sub.Count - 1 - footerRows]; if (table.ExtendLastRow) { rowHeight = last.MaxHeights; last.MaxHeights = yTemp - minY + rowHeight; yTemp = minY; } // now we render the rows of the new table if (canvases != null) nt.WriteSelectedRows(0, -1, x1, yLineWrite, canvases); else nt.WriteSelectedRows(0, -1, x1, yLineWrite, canvas); if (table.ExtendLastRow) { last.MaxHeights = rowHeight; } } else if (table.ExtendLastRow && minY > PdfPRow.BOTTOM_LIMIT) { yTemp = minY; } yLine = yTemp; if (!(skipHeader || table.ElementComplete)) { yLine += footerHeight; } if (k >= table.Size) { yLine -= table.SpacingAfter; compositeElements.RemoveAt(0); splittedRow = false; listIdx = 0; } else { if (splittedRow) { ArrayList rows = table.Rows; for (int i = listIdx; i < k; ++i) rows[i] = null; } listIdx = k; return NO_MORE_COLUMN; } } else if (element.Type == Element.YMARK) { if (!simulate) { IDrawInterface zh = (IDrawInterface)element; zh.Draw(canvas, leftX, minY, rightX, maxY, yLine); } compositeElements.RemoveAt(0); } else compositeElements.RemoveAt(0); } }