Example #1
0
 /** 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;
 }
Example #2
0
        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);
            }
        }