diff --git a/src/core/iTextSharp/text/pdf/PdfPRow.cs b/src/core/iTextSharp/text/pdf/PdfPRow.cs index 676a16c..7d69021 100644 --- a/src/core/iTextSharp/text/pdf/PdfPRow.cs +++ b/src/core/iTextSharp/text/pdf/PdfPRow.cs @@ -1,638 +1,648 @@ -using System; - -using iTextSharp.text; - -/* - * Copyright 2001, 2002 Paulo Soares - * - * The contents of this file are subject to the Mozilla Public License Version 1.1 - * (the "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the License. - * - * The Original Code is 'iText, a free JAVA-PDF library'. - * - * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by - * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie. - * All Rights Reserved. - * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer - * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved. - * - * Contributor(s): all the names of the contributors are added in the source code - * where applicable. - * - * Alternatively, the contents of this file may be used under the terms of the - * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the - * provisions of LGPL are applicable instead of those above. If you wish to - * allow use of your version of this file only under the terms of the LGPL - * License and not to allow others to use your version of this file under - * the MPL, indicate your decision by deleting the provisions above and - * replace them with the notice and other provisions required by the LGPL. - * If you do not delete the provisions above, a recipient may use your version - * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the MPL as stated above or under the terms of the GNU - * Library General Public License as published by the Free Software Foundation; - * either version 2 of the License, or any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more - * details. - * - * If you didn't download this code from the following link, you should check if - * you aren't using an obsolete version: - * http://www.lowagie.com/iText/ - */ - -namespace iTextSharp.text.pdf { - - /** - * A row in a PdfPTable. - * - * @author Paulo Soares (psoares@consiste.pt) - */ - - public class PdfPRow { - - /** the bottom limit (bottom right y) */ - public const float BOTTOM_LIMIT = -(1 << 30); - - protected PdfPCell[] cells; - - protected float[] widths; - - protected float maxHeight = 0; - - protected bool calculated = false; - - private int[] canvasesPos; - - /** - * 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]; - } - - /** - * Makes a copy of an existing row. - * @param row - */ - public PdfPRow(PdfPRow row) { - maxHeight = row.maxHeight; - calculated = row.calculated; - cells = new PdfPCell[row.cells.Length]; - for (int k = 0; k < cells.Length; ++k) { - if (row.cells[k] != null) - cells[k] = new PdfPCell(row.cells[k]); - } - widths = new float[cells.Length]; - Array.Copy(row.widths, 0, widths, 0, cells.Length); - } - - /** - * 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); - float total = 0; - calculated = false; - for (int k = 0; k < widths.Length; ++k) { - PdfPCell cell = cells[k]; - cell.Left = total; - int last = k + cell.Colspan; - for (; k < last; ++k) - total += widths[k]; - --k; - cell.Right = total; - cell.Top = 0; - } - return true; - } - - /** - * 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) - 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 { - if (cell.FixedHeight > 0) { - 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); - ct.Go(true); - cell.Bottom = cell.Top - cell.EffectivePaddingTop - - cell.EffectivePaddingBottom - ct.FilledWidth; - } - } - } - 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; - } - calculated = true; - return maxHeight; - } - - /** - * Writes the border and background of one cell in the row. - * @param xPos - * @param yPos - * @param cell - * @param canvases - */ - 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 - 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 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(); - } - } - } - } - - private void SaveAndRotateCanvases(PdfContentByte[] canvases, float a, float b, float c, float d, float e, float f) { - int last = PdfPTable.TEXTCANVAS + 1; - 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; - canvases[k].SaveState(); - canvases[k].ConcatCTM(a, b, c, d, e, f); - canvasesPos[k * 2 + 1] = bb.Size; - } - } - - private void RestoreCanvases(PdfContentByte[] canvases) { - int last = PdfPTable.TEXTCANVAS + 1; - for (int k = 0; k < last; ++k) { - ByteBuffer bb = canvases[k].InternalBuffer; - int p1 = bb.Size; - canvases[k].RestoreState(); - if (p1 == canvasesPos[k * 2 + 1]) - bb.Size = canvasesPos[k * 2]; - } - } - - 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; - } - - /** - * Writes a number of cells (not necessarily all cells). - * @param colStart - * @param colEnd - * @param xPos - * @param yPos - * @param 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); - 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]; - } - xPos -= cells[newStart].Left; - for (int k = newStart; k < colEnd; ++k) { - PdfPCell cell = cells[k]; - if (cell == null) - continue; - WriteBorderAndBackground(xPos, yPos, 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; - } - if (img != null) { - if (cell.Rotation != 0) { - img = Image.GetInstance(img); - img.Rotation = img.GetImageRotation() + (float)(cell.Rotation * Math.PI / 180.0); - } - bool vf = false; - if (cell.Height > maxHeight) { - img.ScalePercent(100); - float scale = (maxHeight - cell.EffectivePaddingTop - cell - .EffectivePaddingBottom) - / img.ScaledHeight; - img.ScalePercent(scale * 100); - vf = true; - } - float left = cell.Left + xPos - + cell.EffectivePaddingLeft; - if (vf) { - switch (cell.HorizontalAlignment) { - case Element.ALIGN_CENTER: - left = xPos - + (cell.Left + cell.EffectivePaddingLeft - + cell.Right - - cell.EffectivePaddingRight - img - .ScaledWidth) / 2; - break; - case Element.ALIGN_RIGHT: - left = xPos + cell.Right - - cell.EffectivePaddingRight - - img.ScaledWidth; - break; - default: - break; - } - tly = cell.Top + yPos - cell.EffectivePaddingTop; - } - img.SetAbsolutePosition(left, tly - img.ScaledHeight); - canvases[PdfPTable.TEXTCANVAS].AddImage(img); - } else { - if (cell.Rotation == 90 || cell.Rotation == 270) { - float netWidth = maxHeight - cell.EffectivePaddingTop - cell.EffectivePaddingBottom; - float netHeight = cell.Width - cell.EffectivePaddingLeft - cell.EffectivePaddingRight; - ColumnText ct = ColumnText.Duplicate(cell.Column); - ct.Canvases = canvases; - ct.SetSimpleColumn(0, 0, netWidth + 0.001f, -netHeight); - ct.Go(true); - float calcHeight = -ct.YLine; - if (netWidth <= 0 || netHeight <= 0) - calcHeight = 0; - if (calcHeight > 0) { - if (cell.UseDescender) - calcHeight -= ct.Descender; - ct = ColumnText.Duplicate(cell.Column); - ct.Canvases = canvases; - ct.SetSimpleColumn(0, -0.001f, netWidth + 0.001f, calcHeight); - float pivotX; - float pivotY; - if (cell.Rotation == 90) { - pivotY = cell.Top + yPos - maxHeight + cell.EffectivePaddingBottom; - switch (cell.VerticalAlignment) { - case Element.ALIGN_BOTTOM: - pivotX = cell.Left + xPos + cell.Width - cell.EffectivePaddingRight; - break; - case Element.ALIGN_MIDDLE: - pivotX = cell.Left + xPos + (cell.Width + cell.EffectivePaddingLeft - cell.EffectivePaddingRight + calcHeight) / 2; - break; - default: //top - pivotX = cell.Left + xPos + cell.EffectivePaddingLeft + calcHeight; - break; +using System; + +using iTextSharp.text; + +/* + * Copyright 2001, 2002 Paulo Soares + * + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the License. + * + * The Original Code is 'iText, a free JAVA-PDF library'. + * + * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by + * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie. + * All Rights Reserved. + * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer + * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved. + * + * Contributor(s): all the names of the contributors are added in the source code + * where applicable. + * + * Alternatively, the contents of this file may be used under the terms of the + * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the + * provisions of LGPL are applicable instead of those above. If you wish to + * allow use of your version of this file only under the terms of the LGPL + * License and not to allow others to use your version of this file under + * the MPL, indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by the LGPL. + * If you do not delete the provisions above, a recipient may use your version + * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the MPL as stated above or under the terms of the GNU + * Library General Public License as published by the Free Software Foundation; + * either version 2 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more + * details. + * + * If you didn't download this code from the following link, you should check if + * you aren't using an obsolete version: + * http://www.lowagie.com/iText/ + */ + +namespace iTextSharp.text.pdf { + + /** + * A row in a PdfPTable. + * + * @author Paulo Soares (psoares@consiste.pt) + */ + + public class PdfPRow { + + /** the bottom limit (bottom right y) */ + public const float BOTTOM_LIMIT = -(1 << 30); + + protected PdfPCell[] cells; + + protected float[] widths; + + protected float maxHeight = 0; + + protected bool calculated = false; + + private int[] canvasesPos; + + /** + * 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]; + } + + /** + * Makes a copy of an existing row. + * @param row + */ + public PdfPRow(PdfPRow row) { + maxHeight = row.maxHeight; + calculated = row.calculated; + cells = new PdfPCell[row.cells.Length]; + for (int k = 0; k < cells.Length; ++k) { + if (row.cells[k] != null) + cells[k] = new PdfPCell(row.cells[k]); + } + widths = new float[cells.Length]; + Array.Copy(row.widths, 0, widths, 0, cells.Length); + } + + /** + * 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); + float total = 0; + calculated = false; + for (int k = 0; k < widths.Length; ++k) { + PdfPCell cell = cells[k]; + cell.Left = total; + int last = k + cell.Colspan; + for (; k < last; ++k) + total += widths[k]; + --k; + cell.Right = total; + cell.Top = 0; + } + return true; + } + + /** + * 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) + 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 { + if (cell.FixedHeight > 0) { + 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); + ct.Go(true); + cell.Bottom = cell.Top - cell.EffectivePaddingTop + - cell.EffectivePaddingBottom - ct.FilledWidth; + } + } + } + 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; + } + calculated = true; + return maxHeight; + } + + /** + * Writes the border and background of one cell in the row. + * @param xPos + * @param yPos + * @param cell + * @param canvases + */ + 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 + 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 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(); + } + } + } + } + + private void SaveAndRotateCanvases(PdfContentByte[] canvases, float a, float b, float c, float d, float e, float f) { + int last = PdfPTable.TEXTCANVAS + 1; + 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; + canvases[k].SaveState(); + canvases[k].ConcatCTM(a, b, c, d, e, f); + canvasesPos[k * 2 + 1] = bb.Size; + } + } + + private void RestoreCanvases(PdfContentByte[] canvases) { + int last = PdfPTable.TEXTCANVAS + 1; + for (int k = 0; k < last; ++k) { + ByteBuffer bb = canvases[k].InternalBuffer; + int p1 = bb.Size; + canvases[k].RestoreState(); + if (p1 == canvasesPos[k * 2 + 1]) + bb.Size = canvasesPos[k * 2]; + } + } + + 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; + } + + /** + * Writes a number of cells (not necessarily all cells). + * @param colStart + * @param colEnd + * @param xPos + * @param yPos + * @param 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); + 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]; + } + xPos -= cells[newStart].Left; + for (int k = newStart; k < colEnd; ++k) { + PdfPCell cell = cells[k]; + if (cell == null) + continue; + WriteBorderAndBackground(xPos, yPos, 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; + } + if (img != null) { + if (cell.Rotation != 0) { + img = Image.GetInstance(img); + img.Rotation = img.GetImageRotation() + (float)(cell.Rotation * Math.PI / 180.0); + } + bool vf = false; + if (cell.Height > maxHeight) { + img.ScalePercent(100); + float scale = (maxHeight - cell.EffectivePaddingTop - cell + .EffectivePaddingBottom) + / img.ScaledHeight; + img.ScalePercent(scale * 100); + vf = true; + } + float left = cell.Left + xPos + + cell.EffectivePaddingLeft; + if (vf) { + switch (cell.HorizontalAlignment) { + case Element.ALIGN_CENTER: + left = xPos + + (cell.Left + cell.EffectivePaddingLeft + + cell.Right + - cell.EffectivePaddingRight - img + .ScaledWidth) / 2; + break; + case Element.ALIGN_RIGHT: + left = xPos + cell.Right + - cell.EffectivePaddingRight + - img.ScaledWidth; + break; + default: + break; + } + tly = cell.Top + yPos - cell.EffectivePaddingTop; + } + img.SetAbsolutePosition(left, tly - img.ScaledHeight); + canvases[PdfPTable.TEXTCANVAS].AddImage(img); + } else { + if (cell.Rotation == 90 || cell.Rotation == 270) { + float netWidth = maxHeight - cell.EffectivePaddingTop - cell.EffectivePaddingBottom; + float netHeight = cell.Width - cell.EffectivePaddingLeft - cell.EffectivePaddingRight; + ColumnText ct = ColumnText.Duplicate(cell.Column); + ct.Canvases = canvases; + ct.SetSimpleColumn(0, 0, netWidth + 0.001f, -netHeight); + ct.Go(true); + float calcHeight = -ct.YLine; + if (netWidth <= 0 || netHeight <= 0) + calcHeight = 0; + if (calcHeight > 0) { + if (cell.UseDescender) + calcHeight -= ct.Descender; + ct = ColumnText.Duplicate(cell.Column); + ct.Canvases = canvases; + ct.SetSimpleColumn(0, -0.001f, netWidth + 0.001f, calcHeight); + float pivotX; + float pivotY; + if (cell.Rotation == 90) { + pivotY = cell.Top + yPos - maxHeight + cell.EffectivePaddingBottom; + switch (cell.VerticalAlignment) { + case Element.ALIGN_BOTTOM: + pivotX = cell.Left + xPos + cell.Width - cell.EffectivePaddingRight; + break; + case Element.ALIGN_MIDDLE: + pivotX = cell.Left + xPos + (cell.Width + cell.EffectivePaddingLeft - cell.EffectivePaddingRight + calcHeight) / 2; + break; + default: //top + pivotX = cell.Left + xPos + cell.EffectivePaddingLeft + calcHeight; + break; + } + SaveAndRotateCanvases(canvases, 0,1,-1,0,pivotX,pivotY); + } + else { + pivotY = cell.Top + yPos - cell.EffectivePaddingTop; + switch (cell.VerticalAlignment) { + case Element.ALIGN_BOTTOM: + pivotX = cell.Left + xPos + cell.EffectivePaddingLeft; + break; + case Element.ALIGN_MIDDLE: + pivotX = cell.Left + xPos + (cell.Width + cell.EffectivePaddingLeft - cell.EffectivePaddingRight - calcHeight) / 2; + break; + default: //top + pivotX = cell.Left + xPos + cell.Width - cell.EffectivePaddingRight - calcHeight; + break; + } + SaveAndRotateCanvases(canvases, 0,-1,1,0,pivotX,pivotY); + } + try { + ct.Go(); + } finally { + RestoreCanvases(canvases); + } + } + } + else { + float fixedHeight = cell.FixedHeight; + float rightLimit = cell.Right + xPos + - cell.EffectivePaddingRight; + float leftLimit = cell.Left + xPos + + 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; } - SaveAndRotateCanvases(canvases, 0,1,-1,0,pivotX,pivotY); - } - else { - pivotY = cell.Top + yPos - cell.EffectivePaddingTop; - switch (cell.VerticalAlignment) { - case Element.ALIGN_BOTTOM: - pivotX = cell.Left + xPos + cell.EffectivePaddingLeft; - break; - case Element.ALIGN_MIDDLE: - pivotX = cell.Left + xPos + (cell.Width + cell.EffectivePaddingLeft - cell.EffectivePaddingRight - calcHeight) / 2; - break; - default: //top - pivotX = cell.Left + xPos + cell.Width - cell.EffectivePaddingRight - calcHeight; - break; + else { + leftLimit -= 20000; } - SaveAndRotateCanvases(canvases, 0,-1,1,0,pivotX,pivotY); - } - try { - ct.Go(); - } finally { - RestoreCanvases(canvases); - } - } - } - else { - float fixedHeight = cell.FixedHeight; - float rightLimit = cell.Right + xPos - - cell.EffectivePaddingRight; - float leftLimit = cell.Left + xPos - + cell.EffectivePaddingLeft; - if (cell.NoWrap) { - switch (cell.HorizontalAlignment) { - case Element.ALIGN_CENTER: - rightLimit += 10000; - leftLimit -= 10000; - break; - case Element.ALIGN_RIGHT: - leftLimit -= 20000; break; default: - rightLimit += 20000; - break; - } - } - ColumnText ct = ColumnText.Duplicate(cell.Column); - ct.Canvases = canvases; - float bry = tly - - (maxHeight /* cell.Height */ - - cell.EffectivePaddingTop - cell - .EffectivePaddingBottom); - if (fixedHeight > 0) { - if (cell.Height > maxHeight) { - tly = cell.Top + yPos - cell.EffectivePaddingTop; - bry = cell.Top + yPos - maxHeight - + 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; - SaveAndRotateCanvases(canvases, -1,0,0,-1,shx,shy); - } - try { - ct.Go(); - } finally { if (cell.Rotation == 180) { - RestoreCanvases(canvases); + leftLimit -= 20000; } - } - } - } - } - IPdfPCellEvent evt = cell.CellEvent; - if (evt != null) { - Rectangle rect = new Rectangle(cell.Left + xPos, cell.Top - + yPos - maxHeight, cell.Right + xPos, cell.Top - + yPos); - evt.CellLayout(cell, rect, canvases); - } - } - } - - /** - * Checks if the dimensions of the columns were calculated. - * @return true if the dimensions of the columns were calculated - */ - public bool IsCalculated() { - return calculated; - } - - /** - * Gets the maximum height of the row (i.e. of the 'highest' cell). - * @return the maximum height of the row - */ - public float MaxHeights { - get { - if (calculated) - return maxHeight; - else - return CalculateHeights(); - } - set { - this.maxHeight = value; - } - } - - - internal float[] GetEventWidth(float xPos) { - int n = 0; - for (int k = 0; k < cells.Length; ++k) { - if (cells[k] != null) - ++n; - } - float[] width = new float[n + 1]; - n = 0; - width[n++] = xPos; - for (int k = 0; k < cells.Length; ++k) { - if (cells[k] != null) { - width[n] = width[n - 1] + cells[k].Width; - ++n; - } - } - return width; - } - - /** - * 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 - * @return the remainder row or null if the newHeight was so small that only - * an empty row would result - */ - public PdfPRow SplitRow(float newHeight) { - PdfPCell[] newCells = new PdfPCell[cells.Length]; - float[] fh = new float[cells.Length * 2]; - bool allEmpty = true; - for (int k = 0; k < cells.Length; ++k) { - PdfPCell cell = cells[k]; - if (cell == null) - continue; - fh[k * 2] = cell.FixedHeight; - fh[k * 2 + 1] = cell.MinimumHeight; - Image img = cell.Image; - PdfPCell c2 = new PdfPCell(cell); - if (img != null) { - if (newHeight > cell.EffectivePaddingBottom - + cell.EffectivePaddingTop + 2) { - c2.Phrase = null; - allEmpty = false; - } - } else { - int status; - 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); - } - 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; - ct.FilledWidth = 0; - } else { - c2.Phrase = null; - } - } - newCells[k] = c2; - cell.FixedHeight = newHeight; - } - if (allEmpty) { - for (int k = 0; k < cells.Length; ++k) { - 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; - else - cell.FixedHeight = f; - } - return null; - } - CalculateHeights(); - PdfPRow split = new PdfPRow(newCells); - split.widths = (float[]) widths.Clone(); - split.CalculateHeights(); - return split; - } - + else { + rightLimit += 20000; + } + break; + } + } + ColumnText ct = ColumnText.Duplicate(cell.Column); + ct.Canvases = canvases; + float bry = tly + - (maxHeight /* cell.Height */ + - cell.EffectivePaddingTop - cell + .EffectivePaddingBottom); + if (fixedHeight > 0) { + if (cell.Height > maxHeight) { + tly = cell.Top + yPos - cell.EffectivePaddingTop; + bry = cell.Top + yPos - maxHeight + + 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; + SaveAndRotateCanvases(canvases, -1,0,0,-1,shx,shy); + } + try { + ct.Go(); + } finally { + if (cell.Rotation == 180) { + RestoreCanvases(canvases); + } + } + } + } + } + IPdfPCellEvent evt = cell.CellEvent; + if (evt != null) { + Rectangle rect = new Rectangle(cell.Left + xPos, cell.Top + + yPos - maxHeight, cell.Right + xPos, cell.Top + + yPos); + evt.CellLayout(cell, rect, canvases); + } + } + } + + /** + * Checks if the dimensions of the columns were calculated. + * @return true if the dimensions of the columns were calculated + */ + public bool IsCalculated() { + return calculated; + } + + /** + * Gets the maximum height of the row (i.e. of the 'highest' cell). + * @return the maximum height of the row + */ + public float MaxHeights { + get { + if (calculated) + return maxHeight; + else + return CalculateHeights(); + } + set { + this.maxHeight = value; + } + } + + + internal float[] GetEventWidth(float xPos) { + int n = 0; + for (int k = 0; k < cells.Length; ++k) { + if (cells[k] != null) + ++n; + } + float[] width = new float[n + 1]; + n = 0; + width[n++] = xPos; + for (int k = 0; k < cells.Length; ++k) { + if (cells[k] != null) { + width[n] = width[n - 1] + cells[k].Width; + ++n; + } + } + return width; + } + + /** + * 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 + * @return the remainder row or null if the newHeight was so small that only + * an empty row would result + */ + public PdfPRow SplitRow(float newHeight) { + PdfPCell[] newCells = new PdfPCell[cells.Length]; + float[] fh = new float[cells.Length * 2]; + bool allEmpty = true; + for (int k = 0; k < cells.Length; ++k) { + PdfPCell cell = cells[k]; + if (cell == null) + continue; + fh[k * 2] = cell.FixedHeight; + fh[k * 2 + 1] = cell.MinimumHeight; + Image img = cell.Image; + PdfPCell c2 = new PdfPCell(cell); + if (img != null) { + if (newHeight > cell.EffectivePaddingBottom + + cell.EffectivePaddingTop + 2) { + c2.Phrase = null; + allEmpty = false; + } + } else { + int status; + 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); + } + 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; + ct.FilledWidth = 0; + } else { + c2.Phrase = null; + } + } + newCells[k] = c2; + cell.FixedHeight = newHeight; + } + if (allEmpty) { + for (int k = 0; k < cells.Length; ++k) { + 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; + else + cell.FixedHeight = f; + } + return null; + } + CalculateHeights(); + PdfPRow split = new PdfPRow(newCells); + split.widths = (float[]) widths.Clone(); + split.CalculateHeights(); + return split; + } + /** * Returns the array of cells in the row. * Please be extremely careful with this method. @@ -645,5 +655,5 @@ namespace iTextSharp.text.pdf { return cells; } } - } + } } \ No newline at end of file