Porting update.

git-svn-id: svn://svn.code.sf.net/p/itextsharp/code/trunk@31 820d3149-562b-4f88-9aa4-a8e61a3485cf
master
psoares33 2009-06-15 07:17:13 +00:00
parent 167fa81408
commit ac378f9583
6 changed files with 1191 additions and 827 deletions

View File

@ -771,11 +771,12 @@ public class ColumnText {
ratio = 0.001f;
}
float firstIndent = 0;
int status = 0;
if (rectangularMode) {
for (;;) {
firstIndent = (lastWasNewline ? indent : followingIndent);
PdfLine line;
float x1;
int status = 0;
while(true) {
firstIndent = (lastWasNewline ? indent : followingIndent); //
if (rectangularMode) {
if (rectangularWidth <= firstIndent + rightIndent) {
status = NO_MORE_COLUMN;
if (bidiLine.IsEmpty())
@ -786,18 +787,16 @@ public class ColumnText {
status = NO_MORE_TEXT;
break;
}
PdfLine line = bidiLine.ProcessLine(leftX, rectangularWidth - firstIndent - rightIndent, alignment, localRunDirection, arabicOptions);
line = bidiLine.ProcessLine(leftX, rectangularWidth - firstIndent - rightIndent, alignment, localRunDirection, arabicOptions);
if (line == null) {
status = NO_MORE_TEXT;
break;
}
float maxSize = line.MaxSizeSimple;
if (UseAscender && float.IsNaN(firstLineY)) {
currentLeading = line.Ascender;
}
else {
currentLeading = fixedLeading + maxSize * multipliedLeading;
}
float[] maxSize = line.GetMaxSize();
if (UseAscender && float.IsNaN(firstLineY))
currentLeading = line.Ascender;
else
currentLeading = Math.Max(fixedLeading + maxSize[0] * multipliedLeading, maxSize[1]);
if (yLine > maxY || yLine - currentLeading < minY ) {
status = NO_MORE_COLUMN;
bidiLine.Restore();
@ -808,26 +807,12 @@ public class ColumnText {
text.BeginText();
dirty = true;
}
if (float.IsNaN(firstLineY)) {
firstLineY = yLine;
}
UpdateFilledWidth(rectangularWidth - line.WidthLeft);
if (!simulate) {
currentValues[0] = currentFont;
text.SetTextMatrix(leftX + (line.RTL ? rightIndent : firstIndent) + line.IndentLeft, yLine);
pdf.WriteLineToContent(line, text, graphics, currentValues, ratio);
currentFont = (PdfFont)currentValues[0];
}
lastWasNewline = line.NewlineSplit;
yLine -= line.NewlineSplit ? extraParagraphSpace : 0;
++linesWritten;
descender = line.Descender;
if (float.IsNaN(firstLineY))
firstLineY = yLine;
UpdateFilledWidth(rectangularWidth - line.WidthLeft);
x1 = leftX;
}
}
else {
currentLeading = fixedLeading;
for (;;) {
firstIndent = (lastWasNewline ? indent : followingIndent);
else {
float yTemp = yLine;
float[] xx = FindLimitsTwoLines();
if (xx == null) {
@ -842,7 +827,7 @@ public class ColumnText {
yLine = yTemp;
break;
}
float x1 = Math.Max(xx[0], xx[2]);
x1 = Math.Max(xx[0], xx[2]);
float x2 = Math.Min(xx[1], xx[3]);
if (x2 - x1 <= firstIndent + rightIndent)
continue;
@ -850,23 +835,23 @@ public class ColumnText {
text.BeginText();
dirty = true;
}
PdfLine line = bidiLine.ProcessLine(x1, x2 - x1 - firstIndent - rightIndent, alignment, localRunDirection, arabicOptions);
line = bidiLine.ProcessLine(x1, x2 - x1 - firstIndent - rightIndent, alignment, localRunDirection, arabicOptions);
if (line == null) {
status = NO_MORE_TEXT;
yLine = yTemp;
break;
}
if (!simulate) {
currentValues[0] = currentFont;
text.SetTextMatrix(x1 + (line.RTL ? rightIndent : firstIndent) + line.IndentLeft, yLine);
pdf.WriteLineToContent(line, text, graphics, currentValues, ratio);
currentFont = (PdfFont)currentValues[0];
}
lastWasNewline = line.NewlineSplit;
yLine -= line.NewlineSplit ? extraParagraphSpace : 0;
++linesWritten;
descender = line.Descender;
}
if (!simulate) {
currentValues[0] = currentFont;
text.SetTextMatrix(x1 + (line.RTL ? rightIndent : firstIndent) + line.IndentLeft, yLine);
pdf.WriteLineToContent(line, text, graphics, currentValues, ratio);
currentFont = (PdfFont)currentValues[0];
}
lastWasNewline = line.NewlineSplit;
yLine -= line.NewlineSplit ? extraParagraphSpace : 0;
++linesWritten;
descender = line.Descender;
}
if (dirty) {
text.EndText();
@ -1001,26 +986,37 @@ public class ColumnText {
alignment = Element.ALIGN_LEFT;
canvas.SaveState();
ColumnText ct = new ColumnText(canvas);
if (rotation == 0) {
if (alignment == Element.ALIGN_LEFT)
ct.SetSimpleColumn(phrase, x, y - 1, 20000 + x, y + 2, 2, alignment);
else if (alignment == Element.ALIGN_RIGHT)
ct.SetSimpleColumn(phrase, x-20000, y-1, x, y+2, 2, alignment);
else
ct.SetSimpleColumn(phrase, x-20000, y-1, x+20000, y+2, 2, alignment);
float lly = -1;
float ury = 2;
float llx;
float urx;
switch (alignment) {
case Element.ALIGN_LEFT:
llx = 0;
urx = 20000;
break;
case Element.ALIGN_RIGHT:
llx = -20000;
urx = 0;
break;
default:
llx = -20000;
urx = 20000;
break;
}
if (rotation == 0) {
llx += x;
lly += y;
urx += x;
ury += y;
}
else {
double alpha = rotation * Math.PI / 180.0;
float cos = (float)Math.Cos(alpha);
float sin = (float)Math.Sin(alpha);
canvas.ConcatCTM(cos, sin, -sin, cos, x, y);
if (alignment == Element.ALIGN_LEFT)
ct.SetSimpleColumn(phrase, 0, -1, 20000, 2, 2, alignment);
else if (alignment == Element.ALIGN_RIGHT)
ct.SetSimpleColumn(phrase, -20000, -1, 0, 2, 2, alignment);
else
ct.SetSimpleColumn(phrase, -20000, -1, 20000, 2, 2, alignment);
}
ct.SetSimpleColumn(phrase, llx, lly, urx, ury, 2, alignment);
if (runDirection == PdfWriter.RUN_DIRECTION_RTL) {
if (alignment == Element.ALIGN_LEFT)
alignment = Element.ALIGN_RIGHT;
@ -1308,7 +1304,7 @@ public class ColumnText {
rows[i] = null;
}
float h = yTemp - minY;
PdfPRow newRow = table.GetRow(k).SplitRow(h);
PdfPRow newRow = table.GetRow(k).SplitRow(table, k, h);
if (newRow == null) {
if (k == listIdx) {
return NO_MORE_COLUMN;
@ -1345,13 +1341,12 @@ public class ColumnText {
}
// copy the rows that fit on the page in a new table nt
PdfPTable nt = PdfPTable.ShallowCopy(table);
ArrayList rows = table.Rows;
ArrayList sub = nt.Rows;
// first we add the real header rows (if necessary)
if (!skipHeader) {
for (int j = 0; j < realHeaderRows; ++j) {
PdfPRow headerRow = (PdfPRow)rows[j];
PdfPRow headerRow = table.GetRow(j);
sub.Add(headerRow);
}
}
@ -1359,23 +1354,23 @@ public class ColumnText {
nt.HeaderRows = footerRows;
}
// then we add the real content
for (int j = listIdx; j < k; ++j) {
sub.Add(rows[j]);
}
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; ++j) {
sub.Add(rows[j + realHeaderRows]);
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) {
PdfPRow last = (PdfPRow)sub[sub.Count - 1 - footerRows];
rowHeight = last.MaxHeights;
last.MaxHeights = yTemp - minY + rowHeight;
yTemp = minY;
@ -1387,7 +1382,6 @@ public class ColumnText {
else
nt.WriteSelectedRows(0, -1, x1, yLineWrite, canvas);
if (table.ExtendLastRow) {
PdfPRow last = (PdfPRow)sub[sub.Count - 1 - footerRows];
last.MaxHeights = rowHeight;
}
}

View File

@ -168,7 +168,7 @@ namespace iTextSharp.text.pdf {
AddToLine(chunk);
}
// if the length of the chunk > 0 we add it to the line
else if (chunk.Length > 0) {
else if (chunk.Length > 0 || chunk.IsImage()) {
if (overflow != null)
chunk.TrimLastSpace();
width -= chunk.Width;
@ -260,16 +260,15 @@ namespace iTextSharp.text.pdf {
return left;
}
}
else {
else if (this.GetSeparatorCount() == 0) {
switch (alignment) {
case Element.ALIGN_RIGHT:
return left + width;
case Element.ALIGN_CENTER:
return left + (width / 2f);
default:
return left;
}
}
return left;
}
}
@ -443,24 +442,25 @@ namespace iTextSharp.text.pdf {
}
/**
* Gets the maximum size of all the fonts used in this line
* including images.
* @return maximum size of all the fonts used in this line
*/
internal float MaxSizeSimple {
get {
float maxSize = 0;
for (int k = 0; k < line.Count; ++k) {
PdfChunk chunk = (PdfChunk)line[k];
if (!chunk.IsImage()) {
maxSize = Math.Max(chunk.Font.Size, maxSize);
}
else {
maxSize = Math.Max(chunk.Image.ScaledHeight + chunk.ImageOffsetY , maxSize);
}
* Gets the difference between the "normal" leading and the maximum
* size (for instance when there are images in the chunk).
* @return an extra leading for images
* @since 2.1.5
*/
internal float[] GetMaxSize() {
float normal_leading = 0;
float image_leading = -10000;
PdfChunk chunk;
for (int k = 0; k < line.Count; ++k) {
chunk = (PdfChunk)line[k];
if (!chunk.IsImage()) {
normal_leading = Math.Max(chunk.Font.Size, normal_leading);
}
else {
image_leading = Math.Max(chunk.Image.ScaledHeight + chunk.ImageOffsetY, image_leading);
}
return maxSize;
}
return new float[]{normal_leading, image_leading};
}
internal bool RTL {

View File

@ -89,6 +89,12 @@ namespace iTextSharp.text.pdf {
/** Holds value of property colspan. */
private int colspan = 1;
/**
* Holds value of property rowspan.
* @since 2.1.6
*/
private int rowspan = 1;
/** Holds value of property image. */
private Image image;
@ -105,6 +111,12 @@ namespace iTextSharp.text.pdf {
/** The text in the cell. */
protected Phrase phrase;
/**
* The rotation of the cell. Possible values are
* 0, 90, 180 and 270.
*/
private new int rotation;
/** Constructs an empty <CODE>PdfPCell</CODE>.
* The default padding is 2.
*/
@ -138,16 +150,14 @@ namespace iTextSharp.text.pdf {
* @param fit <CODE>true</CODE> to fit the image to the cell
*/
public PdfPCell(Image image, bool fit) : base(0, 0, 0, 0) {
borderWidth = 0.5f;
border = BOX;
if (fit) {
borderWidth = 0.5f;
border = BOX;
this.image = image;
column.SetLeading(0, 1);
Padding = borderWidth / 2;
}
else {
borderWidth = 0.5f;
border = BOX;
column.AddText(this.phrase = new Phrase(new Chunk(image, 0, 0)));
column.SetLeading(0, 1);
Padding = 0;
@ -185,6 +195,7 @@ namespace iTextSharp.text.pdf {
paddingTop = style.paddingTop;
paddingBottom = style.paddingBottom;
colspan = style.colspan;
rowspan = style.rowspan;
cellEvent = style.cellEvent;
useDescender = style.useDescender;
useBorderPadding = style.useBorderPadding;
@ -210,6 +221,7 @@ namespace iTextSharp.text.pdf {
minimumHeight = cell.minimumHeight;
noWrap = cell.noWrap;
colspan = cell.colspan;
rowspan = cell.rowspan;
if (cell.table != null)
table = new PdfPTable(cell.table);
image = Image.GetInstance(cell.image);
@ -278,7 +290,11 @@ namespace iTextSharp.text.pdf {
*/
public float EffectivePaddingLeft {
get {
return paddingLeft + (UseBorderPadding ? (BorderWidthLeft/(UseVariableBorders?1f:2f)) : 0);
if (UseBorderPadding) {
float border = BorderWidthLeft / (UseVariableBorders ? 1f : 2f);
return paddingLeft + border;
}
return paddingLeft;
}
}
@ -300,7 +316,11 @@ namespace iTextSharp.text.pdf {
*/
public float EffectivePaddingRight {
get {
return paddingRight + (UseBorderPadding ? (BorderWidthRight/(UseVariableBorders?1f:2f)) : 0);
if (UseBorderPadding) {
float border = BorderWidthRight / (UseVariableBorders ? 1f : 2f);
return paddingRight + border;
}
return paddingRight;
}
}
@ -323,7 +343,11 @@ namespace iTextSharp.text.pdf {
*/
public float EffectivePaddingTop {
get {
return paddingTop + (UseBorderPadding ? (BorderWidthTop/(UseVariableBorders?1f:2f)) : 0);
if (UseBorderPadding) {
float border = BorderWidthTop/(UseVariableBorders?1f:2f);
return paddingTop + border;
}
return paddingTop;
}
}
@ -347,7 +371,11 @@ namespace iTextSharp.text.pdf {
*/
public float EffectivePaddingBottom {
get {
return paddingBottom + (UseBorderPadding ? (BorderWidthBottom/(UseVariableBorders?1f:2f)) : 0);
if (UseBorderPadding) {
float border = BorderWidthBottom/(UseVariableBorders?1f:2f);
return paddingBottom + border;
}
return paddingBottom;
}
}
@ -461,6 +489,16 @@ namespace iTextSharp.text.pdf {
}
}
/**
* Tells you whether the cell has a fixed height.
*
* @return true is a fixed height was set.
* @since 2.1.5
*/
public bool HasFixedHeight() {
return FixedHeight > 0;
}
/**
* Setter for property noWrap.
* @param noWrap New value of property noWrap.
@ -507,6 +545,16 @@ namespace iTextSharp.text.pdf {
}
}
/**
* Tells you whether the cell has a minimum height.
*
* @return true if a minimum height was set.
* @since 2.1.5
*/
public bool HasMinimumHeight() {
return MinimumHeight > 0;
}
/** Getter for property colspan.
* @return Value of property colspan.
*/
@ -519,6 +567,18 @@ namespace iTextSharp.text.pdf {
}
}
/** Getter for property rowspan.
* @return Value of property rowspan.
*/
public int Rowspan {
get {
return rowspan;
}
set {
rowspan = value;
}
}
/**
* Gets the following paragraph lines indent.
* @return the indent
@ -668,12 +728,6 @@ namespace iTextSharp.text.pdf {
}
}
/**
* The rotation of the cell. Possible values are
* 0, 90, 180 and 270.
*/
private new int rotation;
/**
* Sets the rotation of the cell. Possible values are
* 0, 90, 180 and 270.
@ -692,5 +746,27 @@ namespace iTextSharp.text.pdf {
return rotation;
}
}
/**
* Consumes part of the content of the cell.
* @param height the hight of the part that has to be consumed
* @since 2.1.6
*/
internal void ConsumeHeight(float height) {
float rightLimit = Right - EffectivePaddingRight;
float leftLimit = Left + EffectivePaddingLeft;
float bry = height - EffectivePaddingTop - EffectivePaddingBottom;
if (Rotation != 90 && Rotation != 270) {
column.SetSimpleColumn(leftLimit, bry + 0.001f, rightLimit, 0);
}
else {
column.SetSimpleColumn(0, leftLimit, bry + 0.001f, rightLimit);
}
try {
column.Go(true);
} catch (DocumentException) {
// do nothing
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -99,6 +99,12 @@ namespace iTextSharp.text.pdf {
/** Holds value of property skipFirstHeader. */
private bool skipFirstHeader = false;
/**
* Holds value of property skipLastFooter.
* @since 2.1.6
*/
private bool skipLastFooter = false;
protected bool isColspan = false;
protected int runDirection = PdfWriter.RUN_DIRECTION_DEFAULT;
@ -148,6 +154,12 @@ namespace iTextSharp.text.pdf {
private int footerRows;
/**
* Keeps track of the completeness of the current row.
* @since 2.1.6
*/
protected bool rowCompleted = true;
protected PdfPTable() {
}
@ -215,11 +227,11 @@ namespace iTextSharp.text.pdf {
* Copies the format of the sourceTable without copying the content.
* @param sourceTable
*/
private void CopyFormat(PdfPTable sourceTable) {
relativeWidths = new float[sourceTable.relativeWidths.Length];
absoluteWidths = new float[sourceTable.relativeWidths.Length];
Array.Copy(sourceTable.relativeWidths, 0, relativeWidths, 0, relativeWidths.Length);
Array.Copy(sourceTable.absoluteWidths, 0, absoluteWidths, 0, relativeWidths.Length);
protected internal void CopyFormat(PdfPTable sourceTable) {
relativeWidths = new float[sourceTable.NumberOfColumns];
absoluteWidths = new float[sourceTable.NumberOfColumns];
System.Array.Copy(sourceTable.relativeWidths, 0, relativeWidths, 0, NumberOfColumns);
System.Array.Copy(sourceTable.absoluteWidths, 0, absoluteWidths, 0, NumberOfColumns);
totalWidth = sourceTable.totalWidth;
totalHeight = sourceTable.totalHeight;
currentRowIdx = 0;
@ -239,6 +251,7 @@ namespace iTextSharp.text.pdf {
widthPercentage = sourceTable.widthPercentage;
splitLate = sourceTable.splitLate;
skipFirstHeader = sourceTable.skipFirstHeader;
skipLastFooter = sourceTable.skipLastFooter;
horizontalAlignment = sourceTable.horizontalAlignment;
keepTogether = sourceTable.keepTogether;
complete = sourceTable.complete;
@ -250,14 +263,14 @@ namespace iTextSharp.text.pdf {
* of columns
*/
public void SetWidths(float[] relativeWidths) {
if (relativeWidths.Length != this.relativeWidths.Length)
if (relativeWidths.Length != NumberOfColumns)
throw new DocumentException("Wrong number of columns.");
this.relativeWidths = new float[relativeWidths.Length];
Array.Copy(relativeWidths, 0, this.relativeWidths, 0, relativeWidths.Length);
absoluteWidths = new float[relativeWidths.Length];
totalHeight = 0;
CalculateWidths();
CalculateHeights();
CalculateHeights(true);
}
/** Sets the relative widths of the table.
@ -272,16 +285,15 @@ namespace iTextSharp.text.pdf {
SetWidths(tb);
}
private void CalculateWidths() {
protected internal void CalculateWidths() {
if (totalWidth <= 0)
return;
float total = 0;
for (int k = 0; k < absoluteWidths.Length; ++k) {
int numCols = NumberOfColumns;
for (int k = 0; k < numCols; ++k)
total += relativeWidths[k];
}
for (int k = 0; k < absoluteWidths.Length; ++k) {
for (int k = 0; k < numCols; ++k)
absoluteWidths[k] = totalWidth * relativeWidths[k] / total;
}
}
/** Sets the full width of the table from the absolute column width.
@ -290,7 +302,7 @@ namespace iTextSharp.text.pdf {
* of columns
*/
public void SetTotalWidth(float[] columnWidth) {
if (columnWidth.Length != this.relativeWidths.Length)
if (columnWidth.Length != NumberOfColumns)
throw new DocumentException("Wrong number of columns.");
totalWidth = 0;
for (int k = 0; k < columnWidth.Length; ++k)
@ -304,7 +316,7 @@ namespace iTextSharp.text.pdf {
* @throws DocumentException
*/
public void SetWidthPercentage(float[] columnWidth, Rectangle pageSize) {
if (columnWidth.Length != this.relativeWidths.Length)
if (columnWidth.Length != NumberOfColumns)
throw new ArgumentException("Wrong number of columns.");
float totalWidth = 0;
for (int k = 0; k < columnWidth.Length; ++k)
@ -326,35 +338,41 @@ namespace iTextSharp.text.pdf {
this.totalWidth = value;
totalHeight = 0;
CalculateWidths();
CalculateHeights();
CalculateHeights(true);
}
}
internal void CalculateHeights() {
/**
* Calculates the heights of the table.
*
* @param firsttime if true, the heights of the rows will be recalculated.
* This takes time; normally the heights of the rows are already calcultated,
* so in most cases, it's save to use false as parameter.
* @return the total height of the table. Note that it will be 0 if you didn't
* specify the width of the table with SetTotalWidth().
* @since 2.1.5 added a parameter and a return type to an existing method,
* and made it public
*/
public float CalculateHeights(bool firsttime) {
if (totalWidth <= 0)
return;
return 0;
totalHeight = 0;
for (int k = 0; k < rows.Count; ++k) {
PdfPRow row = (PdfPRow)rows[k];
if (row != null) {
row.SetWidths(absoluteWidths);
if (firsttime)
row.SetWidths(absoluteWidths);
totalHeight += row.MaxHeights;
}
}
return totalHeight;
}
/**
* Calculates the heights of the table.
*/
public void CalculateHeightsFast() {
if (totalWidth <= 0)
return;
totalHeight = 0;
for (int k = 0; k < rows.Count; ++k) {
PdfPRow row = (PdfPRow)rows[k];
if (row != null)
totalHeight += row.MaxHeights;
}
CalculateHeights(false);
}
/** Gets the default <CODE>PdfPCell</CODE> that will be used as
@ -368,25 +386,41 @@ namespace iTextSharp.text.pdf {
}
}
/** Adds a cell element.
/**
* Adds a cell element.
*
* @param cell the cell element
*/
public void AddCell(PdfPCell cell) {
rowCompleted = false;
PdfPCell ncell = new PdfPCell(cell);
int colspan = ncell.Colspan;
colspan = Math.Max(colspan, 1);
colspan = Math.Min(colspan, currentRow.Length - currentRowIdx);
ncell.Colspan = colspan;
if (colspan != 1)
isColspan = true;
int rdir = ncell.RunDirection;
if (rdir == PdfWriter.RUN_DIRECTION_DEFAULT)
ncell.RunDirection = runDirection;
currentRow[currentRowIdx] = ncell;
currentRowIdx += colspan;
SkipColsWithRowspanAbove();
bool cellAdded = false;
if (currentRowIdx < currentRow.Length) {
currentRow[currentRowIdx] = ncell;
currentRowIdx += colspan;
cellAdded = true;
}
SkipColsWithRowspanAbove();
if (currentRowIdx >= currentRow.Length) {
int numCols = NumberOfColumns;
if (runDirection == PdfWriter.RUN_DIRECTION_RTL) {
PdfPCell[] rtlRow = new PdfPCell[absoluteWidths.Length];
PdfPCell[] rtlRow = new PdfPCell[numCols];
int rev = currentRow.Length;
for (int k = 0; k < currentRow.Length; ++k) {
PdfPCell rcell = currentRow[k];
@ -403,9 +437,74 @@ namespace iTextSharp.text.pdf {
totalHeight += row.MaxHeights;
}
rows.Add(row);
currentRow = new PdfPCell[absoluteWidths.Length];
currentRow = new PdfPCell[numCols];
currentRowIdx = 0;
rowCompleted = true;
}
if (!cellAdded) {
currentRow[currentRowIdx] = ncell;
currentRowIdx += colspan;
}
}
/**
* When updating the row index, cells with rowspan should be taken into account.
* This is what happens in this method.
* @since 2.1.6
*/
private void SkipColsWithRowspanAbove() {
int direction = 1;
if (runDirection == PdfWriter.RUN_DIRECTION_RTL)
direction = -1;
while (RowSpanAbove(rows.Count, currentRowIdx))
currentRowIdx += direction;
}
/**
* Checks if there are rows above belonging to a rowspan.
* @param currRow the current row to check
* @param currCol the current column to check
* @return true if there's a cell above that belongs to a rowspan
* @since 2.1.6
*/
internal bool RowSpanAbove(int currRow, int currCol) {
if ((currCol >= NumberOfColumns)
|| (currCol < 0)
|| (currRow == 0))
return false;
int row = currRow - 1;
PdfPRow aboveRow = (PdfPRow)rows[row];
if (aboveRow == null)
return false;
PdfPCell aboveCell = (PdfPCell)aboveRow.GetCells()[currCol];
while ((aboveCell == null) && (row > 0)) {
aboveRow = (PdfPRow)rows[--row];
aboveCell = (PdfPCell)aboveRow.GetCells()[currCol];
}
int distance = currRow - row;
if (aboveCell == null) {
int col = currCol - 1;
aboveCell = (PdfPCell)aboveRow.GetCells()[col];
while ((aboveCell == null) && (row > 0))
aboveCell = (PdfPCell)aboveRow.GetCells()[--col];
return aboveCell != null && aboveCell.Rowspan > distance;
}
if ((aboveCell.Rowspan == 1) && (distance > 1)) {
int col = currCol - 1;
aboveRow = (PdfPRow)rows[row + 1];
distance--;
aboveCell = (PdfPCell)aboveRow.GetCells()[col];
while ((aboveCell == null) && (col > 0))
aboveCell = (PdfPCell)aboveRow.GetCells()[--col];
}
return aboveCell != null && aboveCell.Rowspan > distance;
}
/** Adds a cell element.
@ -486,20 +585,25 @@ namespace iTextSharp.text.pdf {
public float WriteSelectedRows(int colStart, int colEnd, int rowStart, int rowEnd, float xPos, float yPos, PdfContentByte[] canvases) {
if (totalWidth <= 0)
throw new ArgumentException("The table width must be greater than zero.");
int size = rows.Count;
if (rowEnd < 0)
rowEnd = size;
rowEnd = Math.Min(rowEnd, size);
int totalRows = rows.Count;
if (rowStart < 0)
rowStart = 0;
if (rowEnd < 0)
rowEnd = totalRows;
else
rowEnd = Math.Min(rowEnd, totalRows);
if (rowStart >= rowEnd)
return yPos;
if (colEnd < 0)
colEnd = absoluteWidths.Length;
colEnd = Math.Min(colEnd, absoluteWidths.Length);
int totalCols = NumberOfColumns;
if (colStart < 0)
colStart = 0;
colStart = Math.Min(colStart, absoluteWidths.Length);
else
colStart = Math.Min(colStart, totalCols);
if (colEnd < 0)
colEnd = totalCols;
else
colEnd = Math.Min(colEnd, totalCols);
float yPosStart = yPos;
for (int k = rowStart; k < rowEnd; ++k) {
PdfPRow row = (PdfPRow)rows[k];
@ -508,7 +612,7 @@ namespace iTextSharp.text.pdf {
yPos -= row.MaxHeights;
}
}
if (tableEvent != null && colStart == 0 && colEnd == absoluteWidths.Length) {
if (tableEvent != null && colStart == 0 && colEnd == totalCols) {
float[] heights = new float[rowEnd - rowStart + 1];
heights[0] = yPosStart;
for (int k = rowStart; k < rowEnd; ++k) {
@ -558,32 +662,38 @@ namespace iTextSharp.text.pdf {
* @return the y coordinate position of the bottom of the last row
*/
public float WriteSelectedRows(int colStart, int colEnd, int rowStart, int rowEnd, float xPos, float yPos, PdfContentByte canvas) {
if (colEnd < 0)
colEnd = absoluteWidths.Length;
colEnd = Math.Min(colEnd, absoluteWidths.Length);
int totalCols = NumberOfColumns;
if (colStart < 0)
colStart = 0;
colStart = Math.Min(colStart, absoluteWidths.Length);
if (colStart != 0 || colEnd != absoluteWidths.Length) {
else
colStart = Math.Min(colStart, totalCols);
if (colEnd < 0)
colEnd = totalCols;
else
colEnd = Math.Min(colEnd, totalCols);
bool clip = (colStart != 0 || colEnd != totalCols);
if (clip) {
float w = 0;
for (int k = colStart; k < colEnd; ++k)
w += absoluteWidths[k];
canvas.SaveState();
float lx = 0;
float rx = 0;
if (colStart == 0)
lx = 10000;
if (colEnd == absoluteWidths.Length)
rx = 10000;
canvas.Rectangle(xPos - lx, -10000, w + lx + rx, 20000);
float lx = (colStart == 0) ? 10000 : 0;
float rx = (colEnd == totalCols) ? 10000 : 0;
canvas.Rectangle(xPos - lx, -10000, w + lx + rx, PdfPRow.RIGHT_LIMIT);
canvas.Clip();
canvas.NewPath();
}
PdfContentByte[] canvases = BeginWritingRows(canvas);
float y = WriteSelectedRows(colStart, colEnd, rowStart, rowEnd, xPos, yPos, canvases);
EndWritingRows(canvases);
if (colStart != 0 || colEnd != absoluteWidths.Length)
if (clip)
canvas.RestoreState();
return y;
}
@ -659,6 +769,31 @@ namespace iTextSharp.text.pdf {
return row.MaxHeights;
}
/**
* Gets the maximum height of a cell in a particular row (will only be different
* from getRowHeight is one of the cells in the row has a rowspan > 1).
*
* @param rowIndex the row index
* @param cellIndex the cell index
* @return the height of a particular row including rowspan
* @since 2.1.6
*/
public float GetRowspanHeight(int rowIndex, int cellIndex) {
if (totalWidth <= 0 || rowIndex < 0 || rowIndex >= rows.Count)
return 0;
PdfPRow row = (PdfPRow)rows[rowIndex];
if (row == null || cellIndex >= row.GetCells().Length)
return 0;
PdfPCell cell = row.GetCells()[cellIndex];
if (cell == null)
return 0;
float rowspanHeight = 0;
for (int j = 0; j < cell.Rowspan; j++) {
rowspanHeight += GetRowHeight(rowIndex + j);
}
return rowspanHeight;
}
/** Gets the height of the rows that constitute the header as defined by
* <CODE>setHeaderRows()</CODE>.
* @return the height of the rows that constitute the header and footer
@ -684,8 +819,8 @@ namespace iTextSharp.text.pdf {
public float FooterHeight {
get {
float total = 0;
int start = Math.Min(0, headerRows - footerRows);
int size = Math.Min(rows.Count, footerRows);
int start = Math.Max(0, headerRows - footerRows);
int size = Math.Min(rows.Count, headerRows);
for (int k = start; k < size; ++k) {
PdfPRow row = (PdfPRow)rows[k];
if (row != null)
@ -709,6 +844,11 @@ namespace iTextSharp.text.pdf {
totalHeight -= row.MaxHeights;
}
rows.RemoveAt(rowNumber);
if (rowNumber < headerRows) {
--headerRows;
if (rowNumber >= (headerRows - footerRows))
--footerRows;
}
return true;
}
@ -855,6 +995,79 @@ namespace iTextSharp.text.pdf {
}
}
/**
* Gets an arraylist with a selection of rows.
* @param start the first row in the selection
* @param end the first row that isn't part of the selection
* @return a selection of rows
* @since 2.1.6
*/
public ArrayList GetRows(int start, int end) {
ArrayList list = new ArrayList();
if (start < 0 || end > Size) {
return list;
}
PdfPRow firstRow = AdjustCellsInRow(start, end);
int colIndex = 0;
PdfPCell cell;
while (colIndex < NumberOfColumns) {
int rowIndex = start;
while (RowSpanAbove(rowIndex--, colIndex)) {
PdfPRow row = GetRow(rowIndex);
if (row != null) {
PdfPCell replaceCell = row.GetCells()[colIndex];
if (replaceCell != null) {
firstRow.GetCells()[colIndex] = new PdfPCell(replaceCell);
float extra = 0;
int stop = Math.Min(rowIndex + replaceCell.Rowspan, end);
for (int j = start + 1; j < stop; j++) {
extra += GetRowHeight(j);
}
firstRow.SetExtraHeight(colIndex, extra);
float diff = GetRowspanHeight(rowIndex, colIndex)
- GetRowHeight(start) - extra;
firstRow.GetCells()[colIndex].ConsumeHeight(diff);
}
}
}
cell = firstRow.GetCells()[colIndex];
if (cell == null)
colIndex++;
else
colIndex += cell.Colspan;
}
list.Add(firstRow);
for (int i = start + 1; i < end; i++) {
list.Add(AdjustCellsInRow(i, end));
}
return list;
}
/**
* Calculates the extra height needed in a row because of rowspans.
* @param start the index of the start row (the one to adjust)
* @param end the index of the end row on the page
* @since 2.1.6
*/
protected PdfPRow AdjustCellsInRow(int start, int end) {
PdfPRow row = new PdfPRow(GetRow(start));
row.InitExtraHeights();
PdfPCell cell;
PdfPCell[] cells = row.GetCells();
for (int i = 0; i < cells.Length; i++) {
cell = cells[i];
if (cell == null || cell.Rowspan == 1)
continue;
int stop = Math.Min(end, start + cell.Rowspan);
float extra = 0;
for (int k = start + 1; k < stop; k++) {
extra += GetRowHeight(k);
}
row.SetExtraHeight(i, extra);
}
return row;
}
public IPdfPTableEvent TableEvent {
get {
return tableEvent;
@ -907,9 +1120,10 @@ namespace iTextSharp.text.pdf {
}
}
else {
float[] width = new float[absoluteWidths.Length + 1];
int numCols = NumberOfColumns;
float[] width = new float[numCols + 1];
width[0] = xPos;
for (int k = 0; k < absoluteWidths.Length; ++k)
for (int k = 0; k < numCols; ++k)
width[k + 1] = width[k] + absoluteWidths[k];
for (int k = 0; k < widths.Length; ++k)
widths[k] = width;
@ -926,14 +1140,37 @@ namespace iTextSharp.text.pdf {
}
}
/**
* Tells you if the last footer needs to be skipped
* (for instance if the footer says "continued on the next page")
*
* @return Value of property skipLastFooter.
* @since 2.1.6
*/
public bool SkipLastFooter {
get {
return skipLastFooter;
}
set {
skipLastFooter = value;
}
}
public int RunDirection {
get {
return runDirection;
}
set {
if (value < PdfWriter.RUN_DIRECTION_DEFAULT || value > PdfWriter.RUN_DIRECTION_RTL)
throw new ArgumentException("Invalid run direction: " + value);
runDirection = value;
switch (runDirection) {
case PdfWriter.RUN_DIRECTION_DEFAULT:
case PdfWriter.RUN_DIRECTION_NO_BIDI:
case PdfWriter.RUN_DIRECTION_LTR:
case PdfWriter.RUN_DIRECTION_RTL:
this.runDirection = runDirection;
break;
default:
throw new ArgumentException("Invalid run direction: " + runDirection);
}
}
}
@ -1020,7 +1257,7 @@ namespace iTextSharp.text.pdf {
* but calling this method will make sure that it will be present in the table.
*/
public void CompleteRow() {
while (currentRowIdx > 0) {
while (!rowCompleted) {
AddCell(defaultCell);
}
}

View File

@ -118,7 +118,7 @@ namespace iTextSharp.text.pdf {
return phrase;
}
private static String RemoveCRLF(String text) {
public static String RemoveCRLF(String text) {
if (text.IndexOf('\n') >= 0 || text.IndexOf('\r') >= 0) {
char[] p = text.ToCharArray();
StringBuilder sb = new StringBuilder(p.Length);
@ -140,10 +140,22 @@ namespace iTextSharp.text.pdf {
}
/**
* Gets the appearance for this TextField.
* @return the appearance object for this TextField
* @throws IOException
* @throws DocumentException
* Obfuscates a password <code>String</code>.
* Every character is replaced by an asterisk (*).
*
* @param text
* @return String
* @since 2.1.5
*/
public static String ObfuscatePassword(String text) {
return new string('*', text.Length);
}
/**
* Get the <code>PdfAppearance</code> of a text or combo field
* @throws IOException on error
* @throws DocumentException on error
* @return A <code>PdfAppearance</code>
*/
public PdfAppearance GetAppearance() {
PdfAppearance app = GetBorderAppearance();
@ -152,34 +164,32 @@ namespace iTextSharp.text.pdf {
app.EndVariableText();
return app;
}
BaseFont ufont = RealFont;
bool borderExtra = borderStyle == PdfBorderDictionary.STYLE_BEVELED || borderStyle == PdfBorderDictionary.STYLE_INSET;
float h = box.Height - borderWidth * 2;
float h = box.Height - borderWidth * 2 - extraMarginTop;
float bw2 = borderWidth;
if (borderExtra) {
h -= borderWidth * 2;
bw2 *= 2;
}
h -= extraMarginTop;
float offsetX = (borderExtra ? 2 * borderWidth : borderWidth);
offsetX = Math.Max(offsetX, 1);
float offsetX = Math.Max(bw2, 1);
float offX = Math.Min(bw2, offsetX);
app.SaveState();
app.Rectangle(offX, offX, box.Width - 2 * offX, box.Height - 2 * offX);
app.Clip();
app.NewPath();
Color fcolor = (textColor == null) ? GrayColor.GRAYBLACK : textColor;
String ptext = text; //fixed by Kazuya Ujihara (ujihara.jp)
if ((options & PASSWORD) != 0) {
ptext = new String('*', ptext.Length);
}
int rtl = CheckRTL(ptext) ? PdfWriter.RUN_DIRECTION_LTR : PdfWriter.RUN_DIRECTION_NO_BIDI;
if ((options & MULTILINE) == 0) {
String ptext;
if ((options & PASSWORD) != 0)
ptext = ObfuscatePassword(text);
else if ((options & MULTILINE) == 0)
ptext = RemoveCRLF(text);
}
Phrase phrase = ComposePhrase(ptext, ufont, fcolor, fontSize);
else
ptext = text; //fixed by Kazuya Ujihara (ujihara.jp)
BaseFont ufont = RealFont;
Color fcolor = (textColor == null) ? GrayColor.GRAYBLACK : textColor;
int rtl = CheckRTL(ptext) ? PdfWriter.RUN_DIRECTION_LTR : PdfWriter.RUN_DIRECTION_NO_BIDI;
float usize = fontSize;
Phrase phrase = ComposePhrase(ptext, ufont, fcolor, usize);
if ((options & MULTILINE) != 0) {
float usize = fontSize;
float width = box.Width - 4 * offsetX - extraMarginLeft;
float factor = ufont.GetFontDescriptor(BaseFont.BBOXURY, 1) - ufont.GetFontDescriptor(BaseFont.BBOXLLY, 1);
ColumnText ct = new ColumnText(null);
@ -218,7 +228,6 @@ namespace iTextSharp.text.pdf {
ct.Go();
}
else {
float usize = fontSize;
if (usize == 0) {
float maxCalculatedSize = h / (ufont.GetFontDescriptor(BaseFont.BBOXURX, 1) - ufont.GetFontDescriptor(BaseFont.BBOXLLY, 1));
ChangeFontSize(phrase, 1);
@ -226,9 +235,7 @@ namespace iTextSharp.text.pdf {
if (wd == 0)
usize = maxCalculatedSize;
else
usize = (box.Width - extraMarginLeft - 4 * offsetX) / wd;
if (usize > maxCalculatedSize)
usize = maxCalculatedSize;
usize = Math.Min(maxCalculatedSize, (box.Width - extraMarginLeft - 4 * offsetX) / wd);
if (usize < 4)
usize = 4;
}
@ -272,14 +279,19 @@ namespace iTextSharp.text.pdf {
app.EndText();
}
else {
if (alignment == Element.ALIGN_RIGHT) {
ColumnText.ShowTextAligned(app, Element.ALIGN_RIGHT, phrase, extraMarginLeft + box.Width - 2 * offsetX, offsetY - extraMarginTop, 0, rtl, 0);
float x;
switch (alignment) {
case Element.ALIGN_RIGHT:
x = extraMarginLeft + box.Width - (2 * offsetX);
break;
case Element.ALIGN_CENTER:
x = extraMarginLeft + (box.Width / 2);
break;
default:
x = extraMarginLeft + (2 * offsetX);
break;
}
else if (alignment == Element.ALIGN_CENTER) {
ColumnText.ShowTextAligned(app, Element.ALIGN_CENTER, phrase, extraMarginLeft + box.Width / 2, offsetY - extraMarginTop, 0, rtl, 0);
}
else
ColumnText.ShowTextAligned(app, Element.ALIGN_LEFT, phrase, extraMarginLeft + 2 * offsetX, offsetY - extraMarginTop, 0, rtl, 0);
ColumnText.ShowTextAligned(app, alignment, phrase, x, offsetY - extraMarginTop, 0, rtl, 0);
}
}
app.RestoreState();
@ -287,6 +299,12 @@ namespace iTextSharp.text.pdf {
return app;
}
/**
* Get the <code>PdfAppearance</code> of a list field
* @throws IOException on error
* @throws DocumentException on error
* @return A <code>PdfAppearance</code>
*/
internal PdfAppearance GetListAppearance() {
PdfAppearance app = GetBorderAppearance();
app.BeginVariableText();
@ -306,9 +324,11 @@ namespace iTextSharp.text.pdf {
usize = 12;
bool borderExtra = borderStyle == PdfBorderDictionary.STYLE_BEVELED || borderStyle == PdfBorderDictionary.STYLE_INSET;
float h = box.Height - borderWidth * 2;
if (borderExtra)
float offsetX = borderWidth;
if (borderExtra) {
h -= borderWidth * 2;
float offsetX = (borderExtra ? 2 * borderWidth : borderWidth);
offsetX *= 2;
}
float leading = ufont.GetFontDescriptor(BaseFont.BBOXURY, usize) - ufont.GetFontDescriptor(BaseFont.BBOXLLY, usize);
int maxFit = (int)(h / leading) + 1;
int first = 0;