protected int GoComposite(bool simulate) {
if (!rectangularMode)
throw new DocumentException(MessageLocalization.GetComposedMessage("irregular.columns.are.not.supported.in.composite.mode"));
linesWritten = 0;
descender = 0;
bool firstPass = true;
main_loop:
while (true) {
if (compositeElements.Count == 0)
return NO_MORE_TEXT;
IElement element = 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.Alignment = para.Alignment;
compositeColumn.SetIndent(para.IndentationLeft + para.FirstLineIndent, false);
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 && adjustFirstLine)) {
yLine -= para.SpacingBefore;
}
createHere = true;
}
compositeColumn.UseAscender = ((firstPass || descender == 0) && adjustFirstLine ? useAscender : false);
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 && adjustFirstLine));
status = compositeColumn.Go(simulate || (keepCandidate && keep == 0));
lastX = compositeColumn.LastX;
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;
if (compositeColumn.linesWritten > 0) {
yLine = compositeColumn.yLine;
linesWritten += compositeColumn.linesWritten;
descender = compositeColumn.descender;
}
currentLeading = compositeColumn.currentLeading;
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;
List<IElement> items = list.Items;
ListItem item = null;
float listIndentation = list.IndentationLeft;
int count = 0;
Stack<Object[]> stack = new Stack<Object[]>();
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 = 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 || descender == 0) && adjustFirstLine ? useAscender : false);
compositeColumn.Alignment = item.Alignment;
compositeColumn.SetIndent(item.IndentationLeft + listIndentation + item.FirstLineIndent, false);
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 && adjustFirstLine)) {
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 && adjustFirstLine));
status = compositeColumn.Go(simulate || (keepCandidate && keep == 0));
lastX = compositeColumn.LastX;
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;
currentLeading = compositeColumn.currentLeading;
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) {
// INITIALISATIONS
// get the PdfPTable element
PdfPTable table = (PdfPTable)element;
// tables without a body are dismissed
if (table.Size <= table.HeaderRows) {
compositeElements.RemoveAt(0);
continue;
}
// Y-offset
float yTemp = yLine;
yTemp += descender;
if (rowIdx == 0 && adjustFirstLine)
yTemp -= table.SpacingBefore;
// if there's no space left, ask for new column
if (yTemp < minY || yTemp > maxY) {
return NO_MORE_COLUMN;
}
// coordinates
float yLineWrite = yTemp;
float x1 = leftX;
currentLeading = 0;
// get the width of the table
float tableWidth;
if (table.LockedWidth) {
tableWidth = table.TotalWidth;
UpdateFilledWidth(tableWidth);
}
else {
tableWidth = rectangularWidth * table.WidthPercentage / 100f;
table.TotalWidth = tableWidth;
}
// HEADERS / FOOTERS
// how many header rows are real header rows; how many are footer rows?
table.NormalizeHeadersFooters();
int headerRows = table.HeaderRows;
int footerRows = table.FooterRows;
int realHeaderRows = headerRows - footerRows;
float headerHeight = table.HeaderHeight;
float footerHeight = table.FooterHeight;
// do we need to skip the header?
bool skipHeader = table.SkipFirstHeader && rowIdx <= realHeaderRows;
// if not, we wan't to be able to add more than just a header and a footer
if (!skipHeader) {
yTemp -= headerHeight;
if (yTemp < minY || yTemp > maxY) {
return NO_MORE_COLUMN;
}
}
// MEASURE NECESSARY SPACE
// how many real rows (not header or footer rows) fit on a page?
int k = 0;
if (rowIdx < headerRows)
rowIdx = headerRows;
// if the table isn't complete, we need to be able to add a footer
if (!table.ElementComplete) {
yTemp -= footerHeight;
}
// k will be the first row that doesn't fit
for (k = rowIdx; k < table.Size; ++k) {
float rowHeight = table.GetRowHeight(k);
if (yTemp - rowHeight < minY)
break;
yTemp -= rowHeight;
}
// only for incomplete tables:
if (!table.ElementComplete) {
yTemp += footerHeight;
}
// IF ROWS MAY NOT BE SPLIT
if (!table.SplitRows) {
splittedRow = -1;
if (k == rowIdx) {
// drop the whole table
if (k == table.Size) {
compositeElements.RemoveAt(0);
continue;
}
// or drop the row
else {
table.Rows.RemoveAt(k);
return NO_MORE_COLUMN;
}
}
}
// IF ROWS SHOULD NOT BE SPLIT
else if (table.SplitLate && !table.HasRowspan(k) && rowIdx < k) {
splittedRow = -1;
}
// SPLIT ROWS (IF WANTED AND NECESSARY)
else if (k < table.Size) {
// if the row hasn't been split before, we duplicate (part of) the table
if (k != splittedRow) {
splittedRow = k + 1;
table = new PdfPTable(table);
compositeElements[0] = table;
List<PdfPRow> rows = table.Rows;
for (int i = headerRows; i < rowIdx; ++i)
rows[i] = null;
}
// we calculate the remaining vertical space
float h = yTemp - minY;
// we create a new row with the remaining content
PdfPRow newRow = table.GetRow(k).SplitRow(table, k, h);
// if the row isn't null add it as an extra row
if (newRow == null) {
splittedRow = -1;
if (rowIdx == k)
return NO_MORE_COLUMN;
}
else {
yTemp = minY;
table.Rows.Insert(++k, newRow);
}
}
// We're no longer in the first pass
firstPass = false;
// if not in simulation mode, draw the table
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);
List<PdfPRow> sub = nt.Rows;
// first we add the real header rows (if necessary)
if (!skipHeader && realHeaderRows > 0) {
sub.AddRange(table.GetRows(0, realHeaderRows));
}
else {
nt.HeaderRows = footerRows;
}
// then we add the real content
sub.AddRange(table.GetRows(rowIdx, k));
// do we need to show a footer?
bool showFooter = !table.SkipLastFooter;
bool newPageFollows = false;
if (k < table.Size) {
nt.ElementComplete = true;
showFooter = true;
newPageFollows = true;
}
// we add the footer rows if necessary (not for incomplete tables)
if (footerRows > 0 && nt.ElementComplete && showFooter) {
sub.AddRange(table.GetRows(realHeaderRows, realHeaderRows + footerRows));
}
else {
footerRows = 0;
}
// we need a correction if the last row needs to be extended
float rowHeight = 0;
int lastIdx = sub.Count - 1 - footerRows;
PdfPRow last = sub[lastIdx];
if (table.IsExtendLastRow(newPageFollows)) {
rowHeight = last.MaxHeights;
last.MaxHeights = yTemp - minY + rowHeight;
yTemp = minY;
}
// newPageFollows indicates that this table is being split
if (newPageFollows) {
IPdfPTableEvent tableEvent = table.TableEvent;
if (tableEvent is IPdfPTableEventSplit) {
((IPdfPTableEventSplit)tableEvent).SplitTable(table);
}
}
// now we render the rows of the new table
if (canvases != null)
nt.WriteSelectedRows(0, -1, 0, -1, x1, yLineWrite, canvases, false);
else
nt.WriteSelectedRows(0, -1, 0, -1, x1, yLineWrite, canvas, false);
// if the row was split, we copy the content of the last row
// that was consumed into the first row shown on the next page
if (splittedRow == k && k < table.Size) {
PdfPRow splitted = table.Rows[k];
splitted.CopyRowContent(nt, lastIdx);
}
// reset the row height of the last row
if (table.IsExtendLastRow(newPageFollows)) {
last.MaxHeights = rowHeight;
}
}
// in simulation mode, we need to take extendLastRow into account
else if (table.ExtendLastRow && minY > PdfPRow.BOTTOM_LIMIT) {
yTemp = minY;
}
yLine = yTemp;
descender = 0;
currentLeading = 0;
if (!(skipHeader || table.ElementComplete)) {
yLine += footerHeight;
}
if (k >= table.Size) {
// Use up space no more than left
if (yLine - table.SpacingAfter < minY) {
yLine = minY;
}
else {
yLine -= table.SpacingAfter;
}
compositeElements.RemoveAt(0);
splittedRow = -1;
rowIdx = 0;
}
else {
if (splittedRow != -1) {
List<PdfPRow> rows = table.Rows;
for (int i = rowIdx; i < k; ++i)
rows[i] = null;
}
rowIdx = 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 if (element.Type == Element.DIV) {
List<IElement> floatingElements = new List<IElement>();
do {
floatingElements.Add(element);
compositeElements.RemoveAt(0);
element = compositeElements.Count > 0 ? compositeElements[0] : null;
} while (element != null && element.Type == Element.DIV);
compositeColumn = new ColumnText(canvas);
compositeColumn.UseAscender = (firstPass || descender == 0) && adjustFirstLine ? useAscender : false;
//compositeColumn.setAlignment(div.getTextAlignment());
//compositeColumn.setIndent(para.getIndentationLeft() + para.getFirstLineIndent());
compositeColumn.RunDirection = runDirection;
compositeColumn.ArabicOptions = arabicOptions;
compositeColumn.SpaceCharRatio = spaceCharRatio;
FloatLayout fl = new FloatLayout(compositeColumn, floatingElements);
fl.SetSimpleColumn(leftX, minY, rightX, yLine);
int status = fl.layout(simulate);
//firstPass = false;
yLine = fl.getYLine();
descender = 0;
compositeColumn = null;
if ((status & NO_MORE_TEXT) == 0) {
foreach (IElement floatingElement in floatingElements) {
compositeElements.Add(floatingElement);
}
return status;
}
} else
compositeElements.RemoveAt(0);
}
}