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;
PdfLine line;
float x1;
int status = 0;
if (rectangularMode) {
for (;;) {
firstIndent = (lastWasNewline ? indent : followingIndent);
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)) {
float[] maxSize = line.GetMaxSize();
if (UseAscender && float.IsNaN(firstLineY))
currentLeading = line.Ascender;
}
else {
currentLeading = fixedLeading + maxSize * multipliedLeading;
}
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)) {
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;
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);
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) {
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);
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
}
}
}
}

View File

@ -1,8 +1,8 @@
using System;
using iTextSharp.text;
/*
* $Id: PdfPRow.java 3913 2009-04-26 08:51:11Z blowagie $
*
* Copyright 2001, 2002 Paulo Soares
*
* The contents of this file are subject to the Mozilla Public License Version 1.1
@ -56,16 +56,26 @@ namespace iTextSharp.text.pdf {
*
* @author Paulo Soares (psoares@consiste.pt)
*/
public class PdfPRow {
/** the bottom limit (bottom right y) */
public const float BOTTOM_LIMIT = -(1 << 30);
/**
* the right limit
* @since 2.1.5
*/
public const float RIGHT_LIMIT = 20000;
protected PdfPCell[] cells;
protected float[] widths;
/**
* extra heights that needs to be added to a cell because of rowspans.
* @since 2.1.6
*/
protected float[] extraHeights;
protected float maxHeight = 0;
protected bool calculated = false;
@ -73,16 +83,20 @@ namespace iTextSharp.text.pdf {
private int[] canvasesPos;
/**
* Constructs a new PdfPRow with the cells in the array that was passed as a parameter.
* Constructs a new PdfPRow with the cells in the array that was passed
* as a parameter.
*
* @param cells
*/
public PdfPRow(PdfPCell[] cells) {
this.cells = cells;
widths = new float[cells.Length];
InitExtraHeights();
}
/**
* Makes a copy of an existing row.
*
* @param row
*/
public PdfPRow(PdfPRow row) {
@ -94,22 +108,30 @@ namespace iTextSharp.text.pdf {
cells[k] = new PdfPCell(row.cells[k]);
}
widths = new float[cells.Length];
Array.Copy(row.widths, 0, widths, 0, cells.Length);
System.Array.Copy(row.widths, 0, widths, 0, cells.Length);
InitExtraHeights();
}
/**
* Sets the widths of the columns in the row.
*
* @param widths
* @return true if everything went right
*/
public bool SetWidths(float[] widths) {
if (widths.Length != cells.Length)
return false;
Array.Copy(widths, 0, this.widths, 0, cells.Length);
System.Array.Copy(widths, 0, this.widths, 0, cells.Length);
float total = 0;
calculated = false;
for (int k = 0; k < widths.Length; ++k) {
PdfPCell cell = cells[k];
if (cell == null) {
total += widths[k];
continue;
}
cell.Left = total;
int last = k + cell.Colspan;
for (; k < last; ++k)
@ -121,75 +143,95 @@ namespace iTextSharp.text.pdf {
return true;
}
/**
* Initializes the extra heights array.
* @since 2.1.6
*/
public void InitExtraHeights() {
extraHeights = new float[cells.Length];
for (int i = 0; i < extraHeights.Length; i++) {
extraHeights[i] = 0;
}
}
/**
* Sets an extra height for a cell.
* @param cell the index of the cell that needs an extra height
* @param height the extra height
* @since 2.1.6
*/
public void SetExtraHeight(int cell, float height) {
if (cell < 0 || cell >= cells.Length)
return;
extraHeights[cell] = height;
}
/**
* Calculates the heights of each cell in the row.
*
* @return the maximum height of the row.
*/
public float CalculateHeights() {
maxHeight = 0;
for (int k = 0; k < cells.Length; ++k) {
PdfPCell cell = cells[k];
if (cell == null)
float height = 0;
if (cell == null) {
continue;
Image img = cell.Image;
if (img != null) {
img.ScalePercent(100);
float refWidth = img.ScaledWidth;
if (cell.Rotation == 90 || cell.Rotation == 270) {
refWidth = img.ScaledHeight;
}
float scale = (cell.Right - cell.EffectivePaddingRight
- cell.EffectivePaddingLeft - cell.Left)
/ refWidth;
img.ScalePercent(scale * 100);
float refHeight = img.ScaledHeight;
if (cell.Rotation == 90 || cell.Rotation == 270) {
refHeight = img.ScaledWidth;
}
cell.Bottom = cell.Top - cell.EffectivePaddingTop
- cell.EffectivePaddingBottom
- refHeight;
} else {
if (cell.Rotation == 0 || cell.Rotation == 180) {
float rightLimit = cell.NoWrap ? 20000 : cell.Right
- cell.EffectivePaddingRight;
float bry = (cell.FixedHeight > 0) ? cell.Top
- cell.EffectivePaddingTop
+ cell.EffectivePaddingBottom
- cell.FixedHeight : BOTTOM_LIMIT;
ColumnText ct = ColumnText.Duplicate(cell.Column);
SetColumn(ct,
cell.Left + cell.EffectivePaddingLeft, bry,
rightLimit, cell.Top - cell.EffectivePaddingTop);
ct.Go(true);
float yLine = ct.YLine;
if (cell.UseDescender)
yLine += ct.Descender;
cell.Bottom = yLine - cell.EffectivePaddingBottom;
}
else {
bool pivoted = (cell.Rotation == 90 || cell.Rotation == 270);
Image img = cell.Image;
if (img != null) {
img.ScalePercent(100);
float refWidth = pivoted ? img.ScaledHeight : img.ScaledWidth;
float scale = (cell.Right - cell.EffectivePaddingRight
- cell.EffectivePaddingLeft - cell.Left) / refWidth;
img.ScalePercent(scale * 100);
float refHeight = pivoted ? img.ScaledWidth : img.ScaledHeight;
cell.Bottom = cell.Top - cell.EffectivePaddingTop
- cell.EffectivePaddingBottom - refHeight;
}
else {
if (cell.FixedHeight > 0) {
if (pivoted && cell.HasFixedHeight())
cell.Bottom = cell.Top - cell.FixedHeight;
}
else {
ColumnText ct = ColumnText.Duplicate(cell.Column);
SetColumn(ct, 0, cell.Left + cell.EffectivePaddingLeft,
20000, cell.Right - cell.EffectivePaddingRight);
float right, top, left, bottom;
if (pivoted) {
right = RIGHT_LIMIT;
top = cell.Right - cell.EffectivePaddingRight;
left = 0;
bottom = cell.Left + cell.EffectivePaddingLeft;
}
else {
right = cell.NoWrap ? RIGHT_LIMIT : cell.Right - cell.EffectivePaddingRight;
top = cell.Top - cell.EffectivePaddingTop;
left = cell.Left + cell.EffectivePaddingLeft;
bottom = cell.HasFixedHeight() ? top + cell.EffectivePaddingBottom - cell.FixedHeight : BOTTOM_LIMIT;
}
SetColumn(ct, left, bottom, right, top);
ct.Go(true);
cell.Bottom = cell.Top - cell.EffectivePaddingTop
- cell.EffectivePaddingBottom - ct.FilledWidth;
if (pivoted)
cell.Bottom = cell.Top - cell.EffectivePaddingTop - cell.EffectivePaddingBottom - ct.FilledWidth;
else {
float yLine = ct.YLine;
if (cell.UseDescender)
yLine += ct.Descender;
cell.Bottom = yLine - cell.EffectivePaddingBottom;
}
}
}
}
float height = cell.FixedHeight;
if (height <= 0)
height = cell.Height;
if (height < cell.FixedHeight)
height = cell.FixedHeight;
else if (height < cell.MinimumHeight)
height = cell.MinimumHeight;
if (height > maxHeight)
maxHeight = height;
if (height <= 0)
height = cell.Height;
if (height < cell.FixedHeight)
height = cell.FixedHeight;
else if (height < cell.MinimumHeight)
height = cell.MinimumHeight;
if ((height > maxHeight) && (cell.Rowspan == 1))
maxHeight = height;
}
}
calculated = true;
return maxHeight;
@ -197,85 +239,48 @@ namespace iTextSharp.text.pdf {
/**
* Writes the border and background of one cell in the row.
* @param xPos
* @param yPos
*
* @param xPos The x-coordinate where the table starts on the canvas
* @param yPos The y-coordinate where the table starts on the canvas
* @param currentMaxHeight The height of the cell to be drawn.
* @param cell
* @param canvases
* @since 2.1.6 extra parameter currentMaxHeight
*/
public void WriteBorderAndBackground(float xPos, float yPos, PdfPCell cell,
PdfContentByte[] canvases) {
PdfContentByte lines = canvases[PdfPTable.LINECANVAS];
PdfContentByte backgr = canvases[PdfPTable.BACKGROUNDCANVAS];
// the coordinates of the border are retrieved
float x1 = cell.Left + xPos;
float y2 = cell.Top + yPos;
float x2 = cell.Right + xPos;
float y1 = y2 - maxHeight;
// the backgroundcolor is set
public void WriteBorderAndBackground(float xPos, float yPos, float currentMaxHeight, PdfPCell cell, PdfContentByte[] canvases) {
Color background = cell.BackgroundColor;
if (background != null) {
backgr.SetColorFill(background);
backgr.Rectangle(x1, y1, x2 - x1, y2 - y1);
backgr.Fill();
}
// if the element hasn't got any borders, nothing is added
if (cell.HasBorders()) {
if (cell.UseVariableBorders) {
Rectangle borderRect = new Rectangle(cell.Left + xPos, cell.Top
- maxHeight + yPos, cell.Right + xPos, cell.Top
+ yPos);
borderRect.CloneNonPositionParameters(cell);
borderRect.BackgroundColor = null;
lines.Rectangle(borderRect);
} else {
// the width is set to the width of the element
if (cell.BorderWidth != Rectangle.UNDEFINED) {
lines.SetLineWidth(cell.BorderWidth);
}
// the color is set to the color of the element
Color color = cell.BorderColor;
if (color != null) {
lines.SetColorStroke(color);
}
if (background != null || cell.HasBorders()) {
// Add xPos resp. yPos to the cell's coordinates for absolute coordinates
float right = cell.Right + xPos;
float top = cell.Top + yPos;
float left = cell.Left + xPos;
float bottom = top - currentMaxHeight;
// if the box is a rectangle, it is added as a rectangle
if (cell.HasBorder(Rectangle.BOX)) {
lines.Rectangle(x1, y1, x2 - x1, y2 - y1);
}
// if the border isn't a rectangle, the different sides are
// added apart
else {
if (cell.HasBorder(Rectangle.RIGHT_BORDER)) {
lines.MoveTo(x2, y1);
lines.LineTo(x2, y2);
}
if (cell.HasBorder(Rectangle.LEFT_BORDER)) {
lines.MoveTo(x1, y1);
lines.LineTo(x1, y2);
}
if (cell.HasBorder(Rectangle.BOTTOM_BORDER)) {
lines.MoveTo(x1, y1);
lines.LineTo(x2, y1);
}
if (cell.HasBorder(Rectangle.TOP_BORDER)) {
lines.MoveTo(x1, y2);
lines.LineTo(x2, y2);
}
}
lines.Stroke();
if (color != null) {
lines.ResetRGBColorStroke();
}
if (background != null) {
PdfContentByte backgr = canvases[PdfPTable.BACKGROUNDCANVAS];
backgr.SetColorFill(background);
backgr.Rectangle(left, bottom, right - left, top - bottom);
backgr.Fill();
}
if (cell.HasBorders()) {
Rectangle newRect = new Rectangle(left, bottom, right, top);
// Clone non-position parameters except for the background color
newRect.CloneNonPositionParameters(cell);
newRect.BackgroundColor = null;
// Write the borders on the line canvas
PdfContentByte lineCanvas = canvases[PdfPTable.LINECANVAS];
lineCanvas.Rectangle(newRect);
}
}
}
private void SaveAndRotateCanvases(PdfContentByte[] canvases, float a, float b, float c, float d, float e, float f) {
/**
* @since 2.1.6 private is now protected
*/
protected void SaveAndRotateCanvases(PdfContentByte[] canvases, float a, float b, float c, float d, float e, float f) {
int last = PdfPTable.TEXTCANVAS + 1;
if (canvasesPos == null) {
if (canvasesPos == null)
canvasesPos = new int[last * 2];
}
for (int k = 0; k < last; ++k) {
ByteBuffer bb = canvases[k].InternalBuffer;
canvasesPos[k * 2] = bb.Size;
@ -285,7 +290,10 @@ namespace iTextSharp.text.pdf {
}
}
private void RestoreCanvases(PdfContentByte[] canvases) {
/**
* @since 2.1.6 private is now protected
*/
protected void RestoreCanvases(PdfContentByte[] canvases) {
int last = PdfPTable.TEXTCANVAS + 1;
for (int k = 0; k < last; ++k) {
ByteBuffer bb = canvases[k].InternalBuffer;
@ -296,60 +304,78 @@ namespace iTextSharp.text.pdf {
}
}
private float SetColumn(ColumnText ct, float llx, float lly, float urx, float ury) {
if (llx > urx)
urx = llx;
if (lly > ury)
ury = lly;
ct.SetSimpleColumn(llx, lly, urx, ury);
return ury;
/**
* @since 2.1.6 private is now protected
*/
protected internal float SetColumn(ColumnText ct, float left, float bottom, float right, float top) {
if (left > right)
right = left;
if (bottom > top)
top = bottom;
ct.SetSimpleColumn(left, bottom, right, top);
return top;
}
/**
* Writes a number of cells (not necessarily all cells).
* @param colStart
* @param colEnd
* @param xPos
* @param yPos
* @param canvases
*
* @param colStart The first column to be written.
* Remember that the column index starts with 0.
* @param colEnd The last column to be written.
* Remember that the column index starts with 0.
* If -1, all the columns to the end are written.
* @param xPos The x-coordinate where the table starts on the canvas
* @param yPos The y-coordinate where the table starts on the canvas
*/
public void WriteCells(int colStart, int colEnd, float xPos, float yPos,
PdfContentByte[] canvases) {
public void WriteCells(int colStart, int colEnd, float xPos, float yPos, PdfContentByte[] canvases) {
if (!calculated)
CalculateHeights();
if (colEnd < 0)
colEnd = cells.Length;
colEnd = Math.Min(colEnd, cells.Length);
else
colEnd = Math.Min(colEnd, cells.Length);
if (colStart < 0)
colStart = 0;
if (colStart >= colEnd)
return;
int newStart;
for (newStart = colStart; newStart >= 0; --newStart) {
if (cells[newStart] != null)
break;
xPos -= widths[newStart - 1];
if (newStart > 0)
xPos -= widths[newStart - 1];
}
xPos -= cells[newStart].Left;
if (newStart < 0)
newStart = 0;
if (cells[newStart] != null)
xPos -= cells[newStart].Left;
for (int k = newStart; k < colEnd; ++k) {
PdfPCell cell = cells[k];
if (cell == null)
continue;
WriteBorderAndBackground(xPos, yPos, cell, canvases);
float currentMaxHeight = maxHeight + extraHeights[k];
WriteBorderAndBackground(xPos, yPos, currentMaxHeight, cell, canvases);
Image img = cell.Image;
float tly = 0;
switch (cell.VerticalAlignment) {
case Element.ALIGN_BOTTOM:
tly = cell.Top + yPos - maxHeight + cell.Height
- cell.EffectivePaddingTop;
break;
case Element.ALIGN_MIDDLE:
tly = cell.Top + yPos + (cell.Height - maxHeight) / 2
- cell.EffectivePaddingTop;
break;
default:
tly = cell.Top + yPos - cell.EffectivePaddingTop;
break;
float tly = cell.Top + yPos - cell.EffectivePaddingTop;
if (cell.Height <= currentMaxHeight) {
switch (cell.VerticalAlignment) {
case Element.ALIGN_BOTTOM:
tly = cell.Top + yPos - currentMaxHeight + cell.Height
- cell.EffectivePaddingTop;
break;
case Element.ALIGN_MIDDLE:
tly = cell.Top + yPos + (cell.Height - currentMaxHeight) / 2
- cell.EffectivePaddingTop;
break;
default:
break;
}
}
if (img != null) {
if (cell.Rotation != 0) {
@ -357,9 +383,9 @@ namespace iTextSharp.text.pdf {
img.Rotation = img.GetImageRotation() + (float)(cell.Rotation * Math.PI / 180.0);
}
bool vf = false;
if (cell.Height > maxHeight) {
if (cell.Height > currentMaxHeight) {
img.ScalePercent(100);
float scale = (maxHeight - cell.EffectivePaddingTop - cell
float scale = (currentMaxHeight - cell.EffectivePaddingTop - cell
.EffectivePaddingBottom)
/ img.ScaledHeight;
img.ScalePercent(scale * 100);
@ -389,8 +415,9 @@ namespace iTextSharp.text.pdf {
img.SetAbsolutePosition(left, tly - img.ScaledHeight);
canvases[PdfPTable.TEXTCANVAS].AddImage(img);
} else {
// rotation sponsored by Connection GmbH
if (cell.Rotation == 90 || cell.Rotation == 270) {
float netWidth = maxHeight - cell.EffectivePaddingTop - cell.EffectivePaddingBottom;
float netWidth = currentMaxHeight - cell.EffectivePaddingTop - cell.EffectivePaddingBottom;
float netHeight = cell.Width - cell.EffectivePaddingLeft - cell.EffectivePaddingRight;
ColumnText ct = ColumnText.Duplicate(cell.Column);
ct.Canvases = canvases;
@ -404,11 +431,11 @@ namespace iTextSharp.text.pdf {
calcHeight -= ct.Descender;
ct = ColumnText.Duplicate(cell.Column);
ct.Canvases = canvases;
ct.SetSimpleColumn(0, -0.001f, netWidth + 0.001f, calcHeight);
ct.SetSimpleColumn(-0.001f, -0.001f, netWidth + 0.001f, calcHeight);
float pivotX;
float pivotY;
if (cell.Rotation == 90) {
pivotY = cell.Top + yPos - maxHeight + cell.EffectivePaddingBottom;
pivotY = cell.Top + yPos - currentMaxHeight + cell.EffectivePaddingBottom;
switch (cell.VerticalAlignment) {
case Element.ALIGN_BOTTOM:
pivotX = cell.Left + xPos + cell.Width - cell.EffectivePaddingRight;
@ -452,46 +479,44 @@ namespace iTextSharp.text.pdf {
+ cell.EffectivePaddingLeft;
if (cell.NoWrap) {
switch (cell.HorizontalAlignment) {
case Element.ALIGN_CENTER:
rightLimit += 10000;
leftLimit -= 10000;
break;
case Element.ALIGN_RIGHT:
if (cell.Rotation == 180) {
rightLimit += 20000;
}
else {
leftLimit -= 20000;
}
break;
default:
if (cell.Rotation == 180) {
leftLimit -= 20000;
}
else {
rightLimit += 20000;
}
break;
case Element.ALIGN_CENTER:
rightLimit += 10000;
leftLimit -= 10000;
break;
case Element.ALIGN_RIGHT:
if (cell.Rotation == 180) {
rightLimit += RIGHT_LIMIT;
}
else {
leftLimit -= RIGHT_LIMIT;
}
break;
default:
if (cell.Rotation == 180) {
leftLimit -= RIGHT_LIMIT;
}
else {
rightLimit += RIGHT_LIMIT;
}
break;
}
}
ColumnText ct = ColumnText.Duplicate(cell.Column);
ct.Canvases = canvases;
float bry = tly
- (maxHeight /* cell.Height */
- cell.EffectivePaddingTop - cell
.EffectivePaddingBottom);
- (currentMaxHeight
- cell.EffectivePaddingTop - cell.EffectivePaddingBottom);
if (fixedHeight > 0) {
if (cell.Height > maxHeight) {
if (cell.Height > currentMaxHeight) {
tly = cell.Top + yPos - cell.EffectivePaddingTop;
bry = cell.Top + yPos - maxHeight
+ cell.EffectivePaddingBottom;
bry = cell.Top + yPos - currentMaxHeight + cell.EffectivePaddingBottom;
}
}
if ((tly > bry || ct.ZeroHeightElement()) && leftLimit < rightLimit) {
ct.SetSimpleColumn(leftLimit, bry - 0.001f, rightLimit, tly);
if (cell.Rotation == 180) {
float shx = leftLimit + rightLimit;
float shy = yPos + yPos - maxHeight + cell.EffectivePaddingBottom - cell.EffectivePaddingTop;
float shy = yPos + yPos - currentMaxHeight + cell.EffectivePaddingBottom - cell.EffectivePaddingTop;
SaveAndRotateCanvases(canvases, -1,0,0,-1,shx,shy);
}
try {
@ -507,7 +532,7 @@ namespace iTextSharp.text.pdf {
IPdfPCellEvent evt = cell.CellEvent;
if (evt != null) {
Rectangle rect = new Rectangle(cell.Left + xPos, cell.Top
+ yPos - maxHeight, cell.Right + xPos, cell.Top
+ yPos - currentMaxHeight, cell.Right + xPos, cell.Top
+ yPos);
evt.CellLayout(cell, rect, canvases);
}
@ -516,6 +541,7 @@ namespace iTextSharp.text.pdf {
/**
* Checks if the dimensions of the columns were calculated.
*
* @return true if the dimensions of the columns were calculated
*/
public bool IsCalculated() {
@ -538,6 +564,7 @@ namespace iTextSharp.text.pdf {
}
}
//end add
internal float[] GetEventWidth(float xPos) {
int n = 0;
@ -558,68 +585,81 @@ namespace iTextSharp.text.pdf {
}
/**
* Splits a row to newHeight. The returned row is the remainder. It will
* return null if the newHeight was so small that only an empty row would
* result.
* Splits a row to newHeight.
* The returned row is the remainder. It will return null if the newHeight
* was so small that only an empty row would result.
*
* @param newHeight
* the new height
* @param new_height the new height
* @return the remainder row or null if the newHeight was so small that only
* an empty row would result
* an empty row would result
*/
public PdfPRow SplitRow(float newHeight) {
public PdfPRow SplitRow(PdfPTable table, int rowIndex, float new_height) {
PdfPCell[] newCells = new PdfPCell[cells.Length];
float[] fh = new float[cells.Length * 2];
float[] fixHs = new float[cells.Length];
float[] minHs = new float[cells.Length];
bool allEmpty = true;
for (int k = 0; k < cells.Length; ++k) {
float newHeight = new_height;
PdfPCell cell = cells[k];
if (cell == null)
if (cell == null) {
int index = rowIndex;
if (table.RowSpanAbove(index, k)) {
newHeight += table.GetRowHeight(index);
while (table.RowSpanAbove(--index, k)) {
newHeight += table.GetRowHeight(index);
}
PdfPRow row = table.GetRow(index);
if (row != null && row.GetCells()[k] != null) {
newCells[k] = new PdfPCell(row.GetCells()[k]);
newCells[k].ConsumeHeight(newHeight);
newCells[k].Rowspan = row.GetCells()[k].Rowspan - rowIndex + index;
allEmpty = false;
}
}
continue;
fh[k * 2] = cell.FixedHeight;
fh[k * 2 + 1] = cell.MinimumHeight;
}
fixHs[k] = cell.FixedHeight;
minHs[k] = cell.MinimumHeight;
Image img = cell.Image;
PdfPCell c2 = new PdfPCell(cell);
PdfPCell newCell = new PdfPCell(cell);
if (img != null) {
if (newHeight > cell.EffectivePaddingBottom
+ cell.EffectivePaddingTop + 2) {
c2.Phrase = null;
if (newHeight > cell.EffectivePaddingBottom + cell.EffectivePaddingTop + 2) {
newCell.Phrase = null;
allEmpty = false;
}
} else {
int status;
}
else {
float y;
ColumnText ct = ColumnText.Duplicate(cell.Column);
if (cell.Rotation == 90 || cell.Rotation == 270) {
y = SetColumn(ct,
cell.Top - newHeight + cell.EffectivePaddingBottom,
cell.Left + cell.EffectivePaddingLeft,
cell.Top - cell.EffectivePaddingTop,
cell.Right - cell.EffectivePaddingRight);
}
else {
float rightLimit = cell.NoWrap ? 20000 : cell.Right
- cell.EffectivePaddingRight;
float y1 = cell.Top - newHeight
+ cell.EffectivePaddingBottom;
float y2 = cell.Top - cell.EffectivePaddingTop;
y = Math.Max(y1, y2);
y = SetColumn(ct,
cell.Left + cell.EffectivePaddingLeft, y1,
rightLimit, y2);
float left = cell.Left + cell.EffectivePaddingLeft;
float bottom = cell.Top + cell.EffectivePaddingBottom - newHeight;
float right = cell.Right - cell.EffectivePaddingRight;
float top = cell.Top - cell.EffectivePaddingTop;
switch (cell.Rotation) {
case 90:
case 270:
y = SetColumn(ct, bottom, left, top, right);
break;
default:
y = SetColumn(ct, left, bottom, cell.NoWrap ? RIGHT_LIMIT : right, top);
break;
}
int status;
status = ct.Go(true);
bool thisEmpty = (ct.YLine == y);
if (thisEmpty)
ct = ColumnText.Duplicate(cell.Column);
allEmpty = (allEmpty && thisEmpty);
if ((status & ColumnText.NO_MORE_TEXT) == 0 || thisEmpty) {
c2.Column = ct;
if (thisEmpty) {
newCell.Column = ColumnText.Duplicate(cell.Column);
ct.FilledWidth = 0;
} else {
c2.Phrase = null;
}
else if ((status & ColumnText.NO_MORE_TEXT) == 0) {
newCell.Column = ct;
ct.FilledWidth = 0;
}
else
newCell.Phrase = null;
allEmpty = (allEmpty && thisEmpty);
}
newCells[k] = c2;
newCells[k] = newCell;
cell.FixedHeight = newHeight;
}
if (allEmpty) {
@ -627,12 +667,10 @@ namespace iTextSharp.text.pdf {
PdfPCell cell = cells[k];
if (cell == null)
continue;
float f = fh[k * 2];
float m = fh[k * 2 + 1];
if (f <= 0)
cell.MinimumHeight = m;
if (fixHs[k] > 0)
cell.FixedHeight = fixHs[k];
else
cell.FixedHeight = f;
cell.MinimumHeight = minHs[k];
}
return null;
}
@ -647,13 +685,12 @@ namespace iTextSharp.text.pdf {
* Returns the array of cells in the row.
* Please be extremely careful with this method.
* Use the cells as read only objects.
* @return an array of cells
* @since 2.1.1
*
* @return an array of cells
* @since 2.1.1
*/
public PdfPCell[] Cells {
get {
return cells;
}
public PdfPCell[] GetCells() {
return cells;
}
}
}

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;