/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ro.nextreports.engine.exporter;
import com.itextpdf.text.*;
import com.itextpdf.text.Font;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.Image;
import com.itextpdf.text.html.simpleparser.HTMLWorker;
import com.itextpdf.text.html.simpleparser.StyleSheet;
import com.itextpdf.text.pdf.ArabicLigaturizer;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPRow;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfTemplate;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.PdfPTable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.Map;
import java.awt.*;
import java.io.IOException;
import java.io.StringReader;
import ro.nextreports.engine.ReleaseInfoAdapter;
import ro.nextreports.engine.Report;
import ro.nextreports.engine.ReportLayout;
import ro.nextreports.engine.band.Band;
import ro.nextreports.engine.band.BandElement;
import ro.nextreports.engine.band.Hyperlink;
import ro.nextreports.engine.band.HyperlinkBandElement;
import ro.nextreports.engine.band.ImageBandElement;
import ro.nextreports.engine.band.ImageColumnBandElement;
import ro.nextreports.engine.band.Padding;
import ro.nextreports.engine.band.PaperSize;
import ro.nextreports.engine.band.ReportBandElement;
import ro.nextreports.engine.band.VariableBandElement;
import ro.nextreports.engine.exporter.util.StyleFormatConstants;
import ro.nextreports.engine.exporter.util.variable.TotalPageNoVariable;
import ro.nextreports.engine.exporter.util.variable.VariableFactory;
import ro.nextreports.engine.queryexec.QueryException;
import ro.nextreports.engine.util.StringUtil;
/**
* Created by IntelliJ IDEA.
* User: mihai.panaitescu
* Date: Dec 5, 2008
* Time: 11:19:52 AM
*/
public class PdfExporter extends ResultExporter {
// total page no
// Templates are only written to the output when the document is closed permitting things like showing text in the first page
// that is only defined in the last page
private PdfTemplate total;
public PdfExporter(ExporterBean bean) {
super(bean);
}
protected void initExport() throws QueryException {
Padding margins = bean.getReportLayout().getPagePadding();
if (!bean.isSubreport()) {
float footerHeight = computeFooterHeight();
Rectangle rectangle;
if (ReportLayout.CUSTOM.equals(bean.getReportLayout().getPageFormat())) {
PaperSize customSize = bean.getReportLayout().getPaperSize();
rectangle = new Rectangle(customSize.getWidthPoints(), customSize.getHeightPoints());
} else {
rectangle = PageSize.getRectangle(bean.getReportLayout().getPageFormat());
}
document = new Document(rectangle, getPoints(margins.getLeft()),
getPoints(margins.getRight()), getPoints(margins.getTop()), getPoints(margins.getBottom()) + footerHeight);
if (bean.getReportLayout().getOrientation() == LANDSCAPE) {
document.setPageSize(rectangle.rotate());
}
}
PdfWriter wr = null;
try {
if (!bean.isSubreport()) {
wr = PdfWriter.getInstance(document, getOut());
wr.setPageEvent(new PdfPageEvent());
addMetaData();
document.open();
}
table = buildPdfTable(PRINT_DOCUMENT);
} catch (DocumentException e) {
e.printStackTrace();
throw new QueryException(e);
}
}
// Metadata methods must be called after establishing the document writer and prior
// to opening the document
private void addMetaData() {
document.addTitle(getDocumentTitle());
document.addAuthor(ReleaseInfoAdapter.getCompany());
document.addCreator("NextReports " + ReleaseInfoAdapter.getVersionNumber());
document.addSubject("Created by NextReports Designer" + ReleaseInfoAdapter.getVersionNumber());
document.addCreationDate();
document.addKeywords(ReleaseInfoAdapter.getHome());
}
protected void finishExport() {
if (!bean.isSubreport()) {
try {
// if nothing was added to report we must add an empty paragraph
// otheriwse a "This document has no pages" error will be given
// on document.close()
if (table != null) {
document.add(table);
} else {
document.add(new Paragraph(" "));
}
} catch (DocumentException e) {
e.printStackTrace();
} finally {
table = null;
document.close();
}
}
}
protected void close() {
if (!bean.isSubreport()) {
document.close();
}
}
protected void flush() {
if (!bean.isSubreport()) {
if (resultSetRow % fragmentsize == fragmentsize - 1) {
flushNow();
}
}
}
protected void flushNow() {
if (!bean.isSubreport()) {
try {
document.add(table);
table.deleteBodyRows();
table.setSkipFirstHeader(true);
} catch (DocumentException e) {
e.printStackTrace();
}
}
}
protected Set<CellElement> getIgnoredCells(Band band) {
return getIgnoredCellElements(band);
}
protected void exportCell(String bandName, BandElement bandElement, Object value, int gridRow, int row, int column,
int cols, int rowSpan, int colSpan, boolean isImage) {
if (!bean.isSubreport()) {
if (ReportLayout.PAGE_HEADER_BAND_NAME.equals(bandName)) {
header.addCell(renderPdfCell(bandElement, value, gridRow, rowSpan, colSpan, isImage, column));
} else if (ReportLayout.PAGE_FOOTER_BAND_NAME.equals(bandName)) {
footer.addCell(renderPdfCell(bandElement, value, gridRow, rowSpan, colSpan, isImage, column));
} else {
table.addCell(renderPdfCell(bandElement, value, gridRow, rowSpan, colSpan, isImage, column));
}
} else {
table.addCell(renderPdfCell(bandElement, value, gridRow, rowSpan, colSpan, isImage, column));
}
}
protected void afterRowExport() {
}
protected String getNullElement() {
return "";
}
public static final String PDF_ENCODING_PROPERTY = "nextreports.pdf.encoding";
public static final String PDF_FONT_PROPERTY = "nextreports.pdf.font";
public static final String PDF_DIRECTION = "nextreports.pdf.direction";
public static final String PDF_ARABIC_OPTIONS = "nextreports.pdf.arabicOptions";
// ANSI Encoding of the pdf document
// http://www.microsoft.com/globaldev/reference/WinCP.mspx
private final String encoding = System.getProperty(PDF_ENCODING_PROPERTY);
// Full path to an embedded tiff font (The outlines of the glyphs needed inside the text
// will be embedded in the pdf document) . Without such a font the glyphs for some
// alphabets (like greek, cyrillic, ..) will be overlapped one over the other in the document
// creating a not-readable string.
// This is used only if an encoding is present.
private final String embeddedFont = System.getProperty(PDF_FONT_PROPERTY);
// other writing properties
// PdfWriter.RUN_DIRECTION_DEFAULT, PdfWriter.RUN_DIRECTION_NO_BIDI, PdfWriter.RUN_DIRECTION_LTR, PdfWriter.RUN_DIRECTION_RTL
private final int textDirection = Integer.getInteger(PDF_DIRECTION, PdfWriter.RUN_DIRECTION_DEFAULT);
// ar_nothing, ar_novowel, ar_composedtashkeel, ar_lig
private final int arabicOptions = Integer.getInteger(PDF_ARABIC_OPTIONS, ArabicLigaturizer.ar_nothing);
// Pdf font name if no encoding or if no embedded font is used
private String fontName = FontFactory.TIMES;
private int fragmentsize = 15000;
private Document document;
private PdfPTable table;
private PdfPTable header;
private PdfPTable footer;
private float percentage = 100;
private int[] headerwidths;
private static final int MINIMUM_HEIGHT = 12;
private PdfPCell renderPdfCell(BandElement bandElement, Object value, int gridRow, int rowSpan, int colSpan, boolean image, int column) {
Map<String, Object> style = buildCellStyleMap(bandElement, value, gridRow, column, colSpan);
FontFactoryImp fact = new FontFactoryImp();
com.itextpdf.text.Font fnt;
if (bandElement != null) {
fontName = (String)style.get(StyleFormatConstants.FONT_NAME_KEY);
int size = ((Float)style.get(StyleFormatConstants.FONT_SIZE )).intValue();
fnt = getFont(size);
} else {
fnt = getFont(10);
}
PdfPCell cell;
if (image) {
if (value == null) {
cell = new PdfPCell(new Phrase(IMAGE_NOT_FOUND));
} else {
ImageBandElement ibe = (ImageBandElement)bandElement;
try {
byte[] imageBytes = getImage((String) value);
cell = getImageCell(ibe, imageBytes, column, colSpan);
} catch (Exception e) {
cell = new PdfPCell(new Phrase(IMAGE_NOT_LOADED));
}
}
} else if (bandElement instanceof HyperlinkBandElement) {
Hyperlink hyperlink = ((HyperlinkBandElement)bandElement).getHyperlink();
Anchor anchor = new Anchor(hyperlink.getText(), fnt);
anchor.setReference(hyperlink.getUrl());
Phrase ph = new Phrase();
ph.add(anchor);
cell = new PdfPCell(ph);
} else if (bandElement instanceof ReportBandElement) {
Report report = ((ReportBandElement)bandElement).getReport();
ExporterBean eb = null;
try {
eb = getSubreportExporterBean(report);
PdfExporter subExporter = new PdfExporter(eb);
subExporter.export();
PdfPTable innerTable = subExporter.getTable();
cell = new PdfPCell(innerTable);
} catch (Exception e) {
cell = new PdfPCell();
e.printStackTrace();
} finally {
if ((eb != null) && (eb.getResult() != null)) {
eb.getResult().close();
}
}
} else if ( (bandElement instanceof VariableBandElement) &&
(VariableFactory.getVariable(((VariableBandElement) bandElement).getVariable()) instanceof TotalPageNoVariable) ) {
try {
cell = new PdfPCell(Image.getInstance(total));
} catch (BadElementException e) {
cell = new PdfPCell(new Phrase("NA"));
}
} else if (bandElement instanceof ImageColumnBandElement) {
try {
String v = StringUtil.getValueAsString(value, null);
if(StringUtil.BLOB.equals(v)) {
cell = new PdfPCell(new Phrase(StringUtil.BLOB));
} else {
byte[] bytes = StringUtil.decodeImage(v);
cell = getImageCell(bandElement, bytes, column, colSpan);
}
} catch (Exception e) {
e.printStackTrace();
cell = new PdfPCell(new Phrase(IMAGE_NOT_LOADED));
}
} else {
String stringValue;
if (style.containsKey(StyleFormatConstants.PATTERN)) {
stringValue = StringUtil.getValueAsString(value, (String) style.get(StyleFormatConstants.PATTERN), getReportLanguage());
} else {
stringValue = StringUtil.getValueAsString(value, null, getReportLanguage());
}
if (stringValue == null) {
stringValue = "";
}
if (stringValue.startsWith("<html>")) {
StringReader reader = new StringReader(stringValue);
List<Element> elems = new ArrayList<Element>();
try {
elems = HTMLWorker.parseToList(reader, new StyleSheet());
Phrase ph = new Phrase();
for (int i = 0; i < elems.size(); i++){
Element elem = (Element)elems.get(i);
ph.add(elem);
}
cell = new PdfPCell(ph);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Phrase ph = new Phrase(stringValue, fnt);
cell = new PdfPCell(ph);
}
} else {
Phrase ph = new Phrase(stringValue, fnt);
cell = new PdfPCell(ph);
}
}
cell.setArabicOptions(arabicOptions);
cell.setRunDirection(textDirection);
cell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);
cell.setUseDescender(true); // needed for a cell without padding
cell.setMinimumHeight(MINIMUM_HEIGHT); // needed if there is a row in which all cells are empty
if (bandElement != null) {
cell.setRotation(bandElement.getTextRotation());
}
if (colSpan > 1) {
cell.setColspan(colSpan);
}
if (rowSpan > 1) {
cell.setRowspan(rowSpan);
}
if (style != null) {
updateFont(style, fnt);
if (style.containsKey(StyleFormatConstants.BACKGROUND_COLOR)) {
Color val = (Color) style.get(StyleFormatConstants.BACKGROUND_COLOR);
cell.setBackgroundColor(new BaseColor(val));
}
if (style.containsKey(StyleFormatConstants.HORIZONTAL_ALIGN_KEY)) {
if (StyleFormatConstants.HORIZONTAL_ALIGN_LEFT.equals(style.get(StyleFormatConstants.HORIZONTAL_ALIGN_KEY))) {
cell.setHorizontalAlignment(PdfPCell.ALIGN_LEFT);
}
if (StyleFormatConstants.HORIZONTAL_ALIGN_RIGHT.equals(style.get(StyleFormatConstants.HORIZONTAL_ALIGN_KEY))) {
cell.setHorizontalAlignment(PdfPCell.ALIGN_RIGHT);
}
if (StyleFormatConstants.HORIZONTAL_ALIGN_CENTER.equals(style.get(StyleFormatConstants.HORIZONTAL_ALIGN_KEY))) {
cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
}
}
if (style.containsKey(StyleFormatConstants.VERTICAL_ALIGN_KEY)) {
if (StyleFormatConstants.VERTICAL_ALIGN_TOP.equals(style.get(StyleFormatConstants.VERTICAL_ALIGN_KEY))) {
cell.setVerticalAlignment(Element.ALIGN_TOP);
}
if (StyleFormatConstants.VERTICAL_ALIGN_MIDDLE.equals(style.get(StyleFormatConstants.VERTICAL_ALIGN_KEY))) {
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
}
if (StyleFormatConstants.VERTICAL_ALIGN_BOTTOM.equals(style.get(StyleFormatConstants.VERTICAL_ALIGN_KEY))) {
cell.setVerticalAlignment(Element.ALIGN_BOTTOM);
}
}
if (style.containsKey(StyleFormatConstants.PADDING_LEFT)) {
Float val = (Float) style.get(StyleFormatConstants.PADDING_LEFT);
cell.setPaddingLeft(val);
}
if (style.containsKey(StyleFormatConstants.PADDING_RIGHT)) {
Float val = (Float) style.get(StyleFormatConstants.PADDING_RIGHT);
cell.setPaddingRight(val);
}
if (style.containsKey(StyleFormatConstants.PADDING_TOP)) {
Float val = (Float) style.get(StyleFormatConstants.PADDING_TOP);
cell.setPaddingTop(val);
}
if (style.containsKey(StyleFormatConstants.PADDING_BOTTOM)) {
Float val = (Float) style.get(StyleFormatConstants.PADDING_BOTTOM);
cell.setPaddingBottom(val);
}
cell.setBorderWidth(0);
if (style.containsKey(StyleFormatConstants.BORDER_LEFT)) {
Float val = (Float) style.get(StyleFormatConstants.BORDER_LEFT);
cell.setBorderWidthLeft(val / 2);
Color color = (Color) style.get(StyleFormatConstants.BORDER_LEFT_COLOR);
cell.setBorderColorLeft(new BaseColor(color));
}
if (style.containsKey(StyleFormatConstants.BORDER_RIGHT)) {
Float val = (Float) style.get(StyleFormatConstants.BORDER_RIGHT);
cell.setBorderWidthRight(val / 2);
Color color = (Color) style.get(StyleFormatConstants.BORDER_RIGHT_COLOR);
cell.setBorderColorRight(new BaseColor(color));
}
if (style.containsKey(StyleFormatConstants.BORDER_TOP)) {
Float val = (Float) style.get(StyleFormatConstants.BORDER_TOP);
cell.setBorderWidthTop(val / 2);
Color color = (Color) style.get(StyleFormatConstants.BORDER_TOP_COLOR);
cell.setBorderColorTop(new BaseColor(color));
}
if (style.containsKey(StyleFormatConstants.BORDER_BOTTOM)) {
Float val = (Float) style.get(StyleFormatConstants.BORDER_BOTTOM);
cell.setBorderWidthBottom(val / 2);
Color color = (Color) style.get(StyleFormatConstants.BORDER_BOTTOM_COLOR);
cell.setBorderColorBottom(new BaseColor(color));
}
// for subreports we use default no wrap
if (cell.getTable() == null) {
cell.setNoWrap(true);
if (bandElement != null) {
if (bandElement.isWrapText()) {
cell.setNoWrap(false);
cell.setLeading(0, (float)bandElement.getPercentLineSpacing()/100);
}
}
}
// to see a background image all cells must not have any background!
if (bean.getReportLayout().getBackgroundImage() != null) {
cell.setBackgroundColor(null);
}
}
return cell;
}
private void updateFont(Map<String, Object> style, Font fnt) {
if (style.containsKey(StyleFormatConstants.FONT_FAMILY_KEY)) {
String val = (String) style.get(StyleFormatConstants.FONT_FAMILY_KEY);
fnt.setFamily(val);
}
if (style.containsKey(StyleFormatConstants.FONT_SIZE)) {
Float val = (Float) style.get(StyleFormatConstants.FONT_SIZE);
fnt.setSize(val);
}
if (style.containsKey(StyleFormatConstants.FONT_COLOR)) {
Color val = (Color) style.get(StyleFormatConstants.FONT_COLOR);
fnt.setColor(new BaseColor(val));
}
if (style.containsKey(StyleFormatConstants.FONT_STYLE_KEY)) {
if (StyleFormatConstants.FONT_STYLE_NORMAL.equals(style.get(StyleFormatConstants.FONT_STYLE_KEY))) {
fnt.setStyle(Font.NORMAL);
}
if (StyleFormatConstants.FONT_STYLE_BOLD.equals(style.get(StyleFormatConstants.FONT_STYLE_KEY))) {
fnt.setStyle(Font.BOLD);
}
if (StyleFormatConstants.FONT_STYLE_ITALIC.equals(style.get(StyleFormatConstants.FONT_STYLE_KEY))) {
fnt.setStyle(Font.ITALIC);
}
if (StyleFormatConstants.FONT_STYLE_BOLDITALIC.equals(style.get(StyleFormatConstants.FONT_STYLE_KEY))) {
fnt.setStyle(Font.BOLDITALIC);
}
}
}
private Font getFont(int size) {
if (encoding == null) {
return FontFactory.getFont(fontName, size);
} else {
if (embeddedFont == null) {
return FontFactory.getFont(fontName, encoding, size);
} else {
return FontFactory.getFont(embeddedFont, encoding, true, size, Font.NORMAL);
}
}
}
private class PdfPageEvent extends PdfPageEventHelper {
@Override
public void onStartPage(PdfWriter writer, Document document) {
try {
header = buildPdfTable(PRINT_PAGE_HEADER);
if (header != null) {
printPageHeaderBand();
document.add(header);
}
} catch (Exception e) {
throw new ExceptionConverter(e);
}
}
@Override
public void onEndPage(PdfWriter writer, Document document) {
try {
footer = buildPdfTable(PRINT_PAGE_FOOTER);
if (footer != null) {
printPageFooterBand();
Rectangle page = document.getPageSize();
footer.setTotalWidth(page.getWidth() - document.leftMargin() - document.rightMargin());
footer.writeSelectedRows(0, -1, document.leftMargin(), document.bottomMargin(), writer.getDirectContent());
String image = bean.getReportLayout().getBackgroundImage();
if (image != null) {
byte[] imageBytes = getImage(image);
Image pdfImage = Image.getInstance(imageBytes);
pdfImage.setAbsolutePosition(0, 0);
writer.getDirectContentUnder().addImage(pdfImage);
}
}
} catch (Exception e) {
throw new ExceptionConverter(e);
} finally {
pageNo = writer.getPageNumber();
}
}
/**
* Creates the PdfTemplate that will hold the total number of pages.
*/
public void onOpenDocument(PdfWriter writer, Document document) {
int size = 10;
if (totalPageNoVbe != null) {
Map<String, Object> style = buildCellStyleMap(totalPageNoVbe);
size = ((Float) style.get(StyleFormatConstants.FONT_SIZE)).intValue();
}
total = writer.getDirectContent().createTemplate(30, size);
}
/**
* Fills out the total number of pages before the document is closed.
*/
public void onCloseDocument(PdfWriter writer, Document document) {
totalPageNo = writer.getPageNumber() - 1;
if (totalPageNoVbe != null) {
Map<String, Object> style = buildCellStyleMap(totalPageNoVbe);
fontName = (String) style.get(StyleFormatConstants.FONT_NAME_KEY);
int size = ((Float) style.get(StyleFormatConstants.FONT_SIZE)).intValue();
Font fnt = getFont(size);
updateFont(style, fnt);
ColumnText.showTextAligned(total, Element.ALIGN_LEFT, new Phrase(String.valueOf(totalPageNo), fnt), 0, 1, 0);
}
}
}
// type : PRINT_DOCUMENT, PRINT_PAGE_HEADER, PRINT_PAGE_FOOTER
private PdfPTable buildPdfTable(int type) throws QueryException {
List<Band> bands = new ArrayList<Band>();
if (type == PRINT_PAGE_HEADER) {
bands.add(getReportLayout().getPageHeaderBand());
} else if (type == PRINT_PAGE_FOOTER) {
bands.add(getReportLayout().getPageFooterBand());
} else {
bands = getReportLayout().getDocumentBands();
}
int totalRows = 0;
int totalColumns = 0;
for (Band band : bands) {
totalRows += band.getRowCount();
int cols = band.getColumnCount();
if (cols > totalColumns) {
totalColumns = cols;
}
}
// no page header or no page footer
if (totalColumns == 0) {
return null;
}
PdfPTable datatable = new PdfPTable(totalColumns);
// !Important: when a cell is bigger than a page it won't show
// we could use datatable.setSplitLate(false)and in this case we can see
// some content but it is very ugly.
headerwidths = new int[totalColumns]; // %
int size = 100 / totalColumns;
int totalWidth = 0;
for (int i = 0; i < totalColumns; i++) {
if (bean.getReportLayout().isUseSize()) {
headerwidths[i] = bean.getReportLayout().getColumnsWidth().get(i);
} else {
headerwidths[i] = size;
}
totalWidth += headerwidths[i];
}
try {
if (bean.getReportLayout().isUseSize()) {
float pixels = A4_PORTRAIT_PIXELS;
if (bean.getReportLayout().getOrientation() == LANDSCAPE) {
pixels = A4_LANDSCAPE_PIXELS;
}
percentage = totalWidth * 100 / pixels;
// do not allow to go outside an A4 frame
if (percentage > 100) {
percentage = 100;
}
if (!ReportLayout.CUSTOM.equals(bean.getReportLayout().getPageFormat())) {
datatable.setWidthPercentage(percentage);
}
datatable.setWidths(headerwidths);
} else {
datatable.setWidthPercentage(100);
}
} catch (DocumentException e) {
throw new QueryException(e);
}
if (type == PRINT_DOCUMENT) {
writeHeader(datatable);
}
// this is used in correlation with sepSplitRows(true) which is the default inside PdfPTable;
// by default splitLate is true and in case a subreport is bigger than a page, the subreport
// will be written starting from next page, leaving first page empty
datatable.setSplitLate(false);
return datatable;
}
private void writeHeader(PdfPTable datatable) {
if (bean.getReportLayout().isHeaderOnEveryPage()) {
int headerNo = bean.getReportLayout().getHeaderBand().getRowCount();
if (headerNo > 0) {
datatable.setHeaderRows(headerNo);
}
}
}
protected void newPage() {
if (!bean.isSubreport()) {
try {
document.add(table);
document.newPage();
table.deleteBodyRows();
} catch (Exception e) {
e.printStackTrace();
}
}
}
private float computeFooterHeight() throws QueryException {
footer = buildPdfTable(PRINT_PAGE_FOOTER);
if (footer == null) {
return 0;
}
printPageFooterBand();
float height = 0;
ArrayList<PdfPRow> rows = footer.getRows();
for (int k = 0; k < rows.size(); k++) {
PdfPRow row = rows.get(k);
PdfPCell[] cells = row.getCells();
float rowHeight = 0;
for (PdfPCell cell : cells) {
if (cell == null) {
rowHeight = Math.max(rowHeight, MINIMUM_HEIGHT);
} else {
rowHeight = Math.max(rowHeight, cell.getMaxHeight());
}
}
height += rowHeight;
}
return height;
}
public PdfPTable getTable() {
return table;
}
private PdfPCell getImageCell(BandElement bandElement, byte[] imageBytes, int column, int colSpan) {
PdfPCell cell;
try {
Image pdfImage = Image.getInstance(imageBytes);
Integer width = getImageWidth(bandElement);
Integer height = getImageHeight(bandElement);
if (isScaled(bandElement)) {
// scale image (is done in postscript points)
// if use size
// if width is less than the cell width (with span)
// the image is added with its size :
// new PdfPCell(pdfImage) -> no further scale
// if width is greater than cell width (with span)
// the image will fit the cell :
// cell.setImage(pdfImage); -> does a scale to fit cell
// if do not use size
// the image will be added with its size
float factor = 72f * percentage / (getDPI() * 100);
pdfImage.scaleAbsolute(width * factor, height * factor);
int cellWidth = 0;
for (int i = column; i < column + colSpan; i++) {
cellWidth += headerwidths[i];
}
if ((width.intValue() >= cellWidth) && bean.getReportLayout().isUseSize()) {
cell = new PdfPCell();
cell.setImage(pdfImage); // scale to fit cell
} else {
cell = new PdfPCell(pdfImage); // do not scale
}
} else {
cell = new PdfPCell(pdfImage);
}
} catch (Exception e) {
e.printStackTrace();
cell = new PdfPCell(new Phrase(IMAGE_NOT_LOADED));
}
return cell;
}
private int getImageWidth(BandElement be) {
Integer width = null;
if (be instanceof ImageBandElement) {
width = ((ImageBandElement)be).getWidth();
} else {
width = ((ImageColumnBandElement)be).getWidth();
}
if (width == null) {
width = 0;
}
return width;
}
private int getImageHeight(BandElement be) {
Integer height = null;
if (be instanceof ImageBandElement) {
height = ((ImageBandElement)be).getHeight();
} else {
height = ((ImageColumnBandElement)be).getHeight();
}
if (height == null) {
height = 0;
}
return height;
}
private boolean isScaled(BandElement be) {
if (be instanceof ImageBandElement) {
return ((ImageBandElement)be).isScaled();
} else {
return ((ImageColumnBandElement)be).isScaled();
}
}
}