Java tutorial
/* * ============================================================================ * GNU Lesser General Public License * ============================================================================ * * JasperReports - Free Java report-generating library. * Copyright (C) 2001-2006 JasperSoft Corporation http://www.jaspersoft.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. * * JasperSoft Corporation * 303 Second Street, Suite 450 North * San Francisco, CA 94107 * http://www.jaspersoft.com */ /* * Contributors: * Adrian Jackson - iapetus@users.sourceforge.net * David Taylor - exodussystems@users.sourceforge.net * Lars Kristensen - llk@users.sourceforge.net * Ling Li - lonecatz@users.sourceforge.net * Martin Clough - mtclough@users.sourceforge.net */ package net.sf.jasperreports.engine.export; import java.awt.Color; import java.awt.Graphics2D; import java.awt.font.TextAttribute; import java.awt.geom.AffineTransform; import java.awt.geom.Dimension2D; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.text.AttributedCharacterIterator; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import net.sf.jasperreports.engine.JRAbstractExporter; import net.sf.jasperreports.engine.JRAlignment; import net.sf.jasperreports.engine.JRAnchor; import net.sf.jasperreports.engine.JRElement; import net.sf.jasperreports.engine.JRException; import net.sf.jasperreports.engine.JRExporterParameter; import net.sf.jasperreports.engine.JRFont; import net.sf.jasperreports.engine.JRHyperlink; import net.sf.jasperreports.engine.JRImage; import net.sf.jasperreports.engine.JRImageRenderer; import net.sf.jasperreports.engine.JRLine; import net.sf.jasperreports.engine.JRLineBox; import net.sf.jasperreports.engine.JRPen; import net.sf.jasperreports.engine.JRPrintAnchor; import net.sf.jasperreports.engine.JRPrintElement; import net.sf.jasperreports.engine.JRPrintEllipse; import net.sf.jasperreports.engine.JRPrintFrame; import net.sf.jasperreports.engine.JRPrintHyperlink; import net.sf.jasperreports.engine.JRPrintImage; import net.sf.jasperreports.engine.JRPrintLine; import net.sf.jasperreports.engine.JRPrintPage; import net.sf.jasperreports.engine.JRPrintRectangle; import net.sf.jasperreports.engine.JRPrintText; import net.sf.jasperreports.engine.JRRenderable; import net.sf.jasperreports.engine.JRReportFont; import net.sf.jasperreports.engine.JRRuntimeException; import net.sf.jasperreports.engine.JRStyle; import net.sf.jasperreports.engine.JRTextElement; import net.sf.jasperreports.engine.JasperPrint; import net.sf.jasperreports.engine.base.JRBaseFont; import net.sf.jasperreports.engine.export.legacy.BorderOffset; import net.sf.jasperreports.engine.util.BreakIteratorSplitCharacter; import net.sf.jasperreports.engine.util.JRLoader; import net.sf.jasperreports.engine.util.JRProperties; import net.sf.jasperreports.engine.util.JRStyledText; import net.sf.jasperreports.engine.util.JRTextAttribute; import com.lowagie.text.Chunk; import com.lowagie.text.Document; import com.lowagie.text.DocumentException; import com.lowagie.text.Element; import com.lowagie.text.Font; import com.lowagie.text.FontFactory; import com.lowagie.text.Image; import com.lowagie.text.Phrase; import com.lowagie.text.Rectangle; import com.lowagie.text.SplitCharacter; import com.lowagie.text.pdf.BaseFont; import com.lowagie.text.pdf.ColumnText; import com.lowagie.text.pdf.FontMapper; import com.lowagie.text.pdf.PdfAction; import com.lowagie.text.pdf.PdfContentByte; import com.lowagie.text.pdf.PdfDestination; import com.lowagie.text.pdf.PdfOutline; import com.lowagie.text.pdf.PdfTemplate; import com.lowagie.text.pdf.PdfWriter; /** * Exports a JasperReports document to PDF format. It has binary output type and exports the document to * a free-form layout. * <p> * Since classic AWT fonts can be sometimes very different from PDF fonts, a font mapping feature was added. * By using the {@link JRExporterParameter#FONT_MAP} parameter, a logical font like "sansserif" can be mapped * to a system specific font, like "Helvetica-BoldOblique". PDF font mapping is a little more complicated, because * for a logical font, PDF cand provide two or more fonts, from the same family but with different styles (like * "Helvetica", "Helvetica-Bold", "Helvetica-BoldOblique"). So every key in the map is a simple bean containing * font family, bold and italic flag, and every value is another bean containing the PDF font name, encoding and * embedding flag. * @see FontKey * @see PdfFont * @author Teodor Danciu (teodord@users.sourceforge.net) * @version $Id: JRPdfExporter.java 2195 2008-05-19 13:26:22Z teodord $ */ public class JRPdfExporter extends JRAbstractExporter { /** * @deprecated Replaced by {@link JRPdfExporterParameter#PROPERTY_FORCE_SVG_SHAPES}. */ public static final String PDF_FORCE_SVG_SHAPES = JRPdfExporterParameter.PROPERTY_FORCE_SVG_SHAPES; private static final String PDF_ORIGIN_EXPORTER_FILTER_PREFIX = JRProperties.PROPERTY_PREFIX + "export.pdf.exclude.origin."; private static final String EMPTY_BOOKMARK_TITLE = ""; /** * */ protected static final String JR_PAGE_ANCHOR_PREFIX = "JR_PAGE_ANCHOR_"; protected static boolean fontsRegistered = false; /** * */ protected Document document = null; protected PdfContentByte pdfContentByte = null; protected PdfWriter pdfWriter = null; protected Document imageTesterDocument = null; protected PdfContentByte imageTesterPdfContentByte = null; protected JRExportProgressMonitor progressMonitor = null; protected int reportIndex = 0; /** * */ protected boolean forceSvgShapes; protected boolean isCreatingBatchModeBookmarks; protected boolean isCompressed; protected boolean isEncrypted; protected boolean is128BitKey; protected String userPassword; protected String ownerPassword; protected int permissions = 0; protected Character pdfVersion; protected String pdfJavaScript; /** * */ protected Map loadedImagesMap = null; protected Image pxImage = null; private BookmarkStack bookmarkStack = null; private Map fontMap = null; private SplitCharacter splitCharacter; protected JRHyperlinkProducerFactory hyperlinkProducerFactory; /** * */ protected Image getPxImage() { if (pxImage == null) { try { pxImage = Image.getInstance( JRLoader.loadBytesFromLocation("net/sf/jasperreports/engine/images/pixel.GIF", null)); } catch (Exception e) { throw new JRRuntimeException(e); } } return pxImage; } /** * */ public void exportReport() throws JRException { registerFonts(); progressMonitor = (JRExportProgressMonitor) parameters.get(JRExporterParameter.PROGRESS_MONITOR); /* */ setOffset(); try { /* */ setExportContext(); /* */ setInput(); if (!parameters.containsKey(JRExporterParameter.FILTER)) { filter = JROriginExporterFilter.getFilter(jasperPrint.getPropertiesMap(), PDF_ORIGIN_EXPORTER_FILTER_PREFIX); } /* */ if (!isModeBatch) { setPageRange(); } isCreatingBatchModeBookmarks = getBooleanParameter( JRPdfExporterParameter.IS_CREATING_BATCH_MODE_BOOKMARKS, JRPdfExporterParameter.PROPERTY_CREATE_BATCH_MODE_BOOKMARKS, false); forceSvgShapes = //FIXME certain properties need to be read from each individual document in batch mode; check all exporters and all props getBooleanParameter(JRPdfExporterParameter.FORCE_SVG_SHAPES, JRPdfExporterParameter.PROPERTY_FORCE_SVG_SHAPES, false); isCompressed = getBooleanParameter(JRPdfExporterParameter.IS_COMPRESSED, JRPdfExporterParameter.PROPERTY_COMPRESSED, false); isEncrypted = getBooleanParameter(JRPdfExporterParameter.IS_ENCRYPTED, JRPdfExporterParameter.PROPERTY_ENCRYPTED, false); is128BitKey = getBooleanParameter(JRPdfExporterParameter.IS_128_BIT_KEY, JRPdfExporterParameter.PROPERTY_128_BIT_KEY, false); userPassword = getStringParameter(JRPdfExporterParameter.USER_PASSWORD, JRPdfExporterParameter.PROPERTY_USER_PASSWORD); ownerPassword = getStringParameter(JRPdfExporterParameter.OWNER_PASSWORD, JRPdfExporterParameter.PROPERTY_OWNER_PASSWORD); Integer permissionsParameter = (Integer) parameters.get(JRPdfExporterParameter.PERMISSIONS); if (permissionsParameter != null) { permissions = permissionsParameter.intValue(); } String strPdfVersion = getStringParameter(JRPdfExporterParameter.PDF_VERSION, JRPdfExporterParameter.PROPERTY_PDF_VERSION); pdfVersion = (strPdfVersion == null || strPdfVersion.length() == 0) ? null : new Character(strPdfVersion.charAt(0)); fontMap = (Map) parameters.get(JRExporterParameter.FONT_MAP); setSplitCharacter(); setHyperlinkProducerFactory(); pdfJavaScript = getStringParameter(JRPdfExporterParameter.PDF_JAVASCRIPT, JRPdfExporterParameter.PROPERTY_PDF_JAVASCRIPT); OutputStream os = (OutputStream) parameters.get(JRExporterParameter.OUTPUT_STREAM); if (os != null) { exportReportToStream(os); } else { File destFile = (File) parameters.get(JRExporterParameter.OUTPUT_FILE); if (destFile == null) { String fileName = (String) parameters.get(JRExporterParameter.OUTPUT_FILE_NAME); if (fileName != null) { destFile = new File(fileName); } else { throw new JRException("No output specified for the exporter."); } } try { os = new FileOutputStream(destFile); exportReportToStream(os); os.flush(); } catch (IOException e) { throw new JRException("Error trying to export to file : " + destFile, e); } finally { if (os != null) { try { os.close(); } catch (IOException e) { } } } } } finally { resetExportContext(); } } protected void setSplitCharacter() { boolean useFillSplitCharacter; Boolean useFillSplitCharacterParam = (Boolean) parameters .get(JRPdfExporterParameter.FORCE_LINEBREAK_POLICY); if (useFillSplitCharacterParam == null) { useFillSplitCharacter = JRProperties.getBooleanProperty(jasperPrint.getPropertiesMap(), JRPdfExporterParameter.PROPERTY_FORCE_LINEBREAK_POLICY, false); } else { useFillSplitCharacter = useFillSplitCharacterParam.booleanValue(); } if (useFillSplitCharacter) { splitCharacter = new BreakIteratorSplitCharacter(); } } protected void setHyperlinkProducerFactory() { hyperlinkProducerFactory = (JRHyperlinkProducerFactory) parameters .get(JRExporterParameter.HYPERLINK_PRODUCER_FACTORY); } /** * */ protected void exportReportToStream(OutputStream os) throws JRException { //ByteArrayOutputStream baos = new ByteArrayOutputStream(); document = new Document(new Rectangle(jasperPrint.getPageWidth(), jasperPrint.getPageHeight())); imageTesterDocument = new Document(new Rectangle(10, //jasperPrint.getPageWidth(), 10 //jasperPrint.getPageHeight() )); boolean closeDocuments = true; try { pdfWriter = PdfWriter.getInstance(document, os); pdfWriter.setCloseStream(false); if (pdfVersion != null) pdfWriter.setPdfVersion(pdfVersion.charValue()); if (isCompressed) pdfWriter.setFullCompression(); if (isEncrypted) { pdfWriter.setEncryption(is128BitKey, userPassword, ownerPassword, permissions); } // Add meta-data parameters to generated PDF document // mtclough@users.sourceforge.net 2005-12-05 String title = (String) parameters.get(JRPdfExporterParameter.METADATA_TITLE); if (title != null) document.addTitle(title); String author = (String) parameters.get(JRPdfExporterParameter.METADATA_AUTHOR); if (author != null) document.addAuthor(author); String subject = (String) parameters.get(JRPdfExporterParameter.METADATA_SUBJECT); if (subject != null) document.addSubject(subject); String keywords = (String) parameters.get(JRPdfExporterParameter.METADATA_KEYWORDS); if (keywords != null) document.addKeywords(keywords); String creator = (String) parameters.get(JRPdfExporterParameter.METADATA_CREATOR); if (creator != null) document.addCreator(creator); else document.addCreator("JasperReports (" + jasperPrint.getName() + ")"); document.open(); if (pdfJavaScript != null) pdfWriter.addJavaScript(pdfJavaScript); pdfContentByte = pdfWriter.getDirectContent(); initBookmarks(); PdfWriter imageTesterPdfWriter = PdfWriter.getInstance(imageTesterDocument, new NullOutputStream() // discard the output ); imageTesterDocument.open(); imageTesterDocument.newPage(); imageTesterPdfContentByte = imageTesterPdfWriter.getDirectContent(); imageTesterPdfContentByte.setLiteral("\n"); for (reportIndex = 0; reportIndex < jasperPrintList.size(); reportIndex++) { jasperPrint = (JasperPrint) jasperPrintList.get(reportIndex); loadedImagesMap = new HashMap(); document.setPageSize(new Rectangle(jasperPrint.getPageWidth(), jasperPrint.getPageHeight())); BorderOffset.setLegacy(JRProperties.getBooleanProperty(jasperPrint, BorderOffset.PROPERTY_LEGACY_BORDER_OFFSET, false)); List pages = jasperPrint.getPages(); if (pages != null && pages.size() > 0) { if (isModeBatch) { document.newPage(); if (isCreatingBatchModeBookmarks) { //add a new level to our outline for this report addBookmark(0, jasperPrint.getName(), 0, 0); } startPageIndex = 0; endPageIndex = pages.size() - 1; } for (int pageIndex = startPageIndex; pageIndex <= endPageIndex; pageIndex++) { if (Thread.currentThread().isInterrupted()) { throw new JRException("Current thread interrupted."); } JRPrintPage page = (JRPrintPage) pages.get(pageIndex); document.newPage(); pdfContentByte = pdfWriter.getDirectContent(); pdfContentByte.setLineCap(2);//PdfContentByte.LINE_CAP_PROJECTING_SQUARE since iText 1.02b writePageAnchor(pageIndex); /* */ exportPage(page); } } else { document.newPage(); pdfContentByte = pdfWriter.getDirectContent(); pdfContentByte.setLiteral("\n"); } } closeDocuments = false; document.close(); imageTesterDocument.close(); } catch (DocumentException e) { throw new JRException("PDF Document error : " + jasperPrint.getName(), e); } catch (IOException e) { throw new JRException("Error generating PDF report : " + jasperPrint.getName(), e); } finally { if (closeDocuments) //only on exception { try { document.close(); } catch (Throwable e) { // ignore, let the original exception propagate } try { imageTesterDocument.close(); } catch (Throwable e) { // ignore, let the original exception propagate } } } //return os.toByteArray(); } protected void writePageAnchor(int pageIndex) throws DocumentException { Map pdfFontAttrs = getDefaultPdfFontAttributes(); Chunk chunk; if (pdfFontAttrs == null) { chunk = new Chunk(" "); } else { Font pdfFont = getFont(pdfFontAttrs); chunk = new Chunk(" ", pdfFont); } chunk.setLocalDestination(JR_PAGE_ANCHOR_PREFIX + reportIndex + "_" + (pageIndex + 1)); ColumnText colText = new ColumnText(pdfContentByte); colText.setSimpleColumn(new Phrase(chunk), 0, jasperPrint.getPageHeight(), 1, 1, 0, Element.ALIGN_LEFT); colText.go(); } protected Map getDefaultPdfFontAttributes() { Map attrs; JRStyle style = jasperPrint.getDefaultStyle(); if (style != null) { attrs = new HashMap(); attrs.put(JRTextAttribute.PDF_FONT_NAME, style.getPdfFontName()); attrs.put(JRTextAttribute.PDF_ENCODING, style.getPdfEncoding()); attrs.put(JRTextAttribute.IS_PDF_EMBEDDED, style.isPdfEmbedded()); } else { JRReportFont font = jasperPrint.getDefaultFont(); if (font != null) { attrs = new HashMap(); attrs.put(JRTextAttribute.PDF_FONT_NAME, font.getPdfFontName()); attrs.put(JRTextAttribute.PDF_ENCODING, font.getPdfEncoding()); attrs.put(JRTextAttribute.IS_PDF_EMBEDDED, font.isPdfEmbedded() ? Boolean.TRUE : Boolean.FALSE); } else { attrs = null; } } return attrs; } /** * */ protected void exportPage(JRPrintPage page) throws JRException, DocumentException, IOException { Collection elements = page.getElements(); exportElements(elements); if (progressMonitor != null) { progressMonitor.afterPageExport(); } } protected void exportElements(Collection elements) throws DocumentException, IOException, JRException { if (elements != null && elements.size() > 0) { JRPrintElement element; for (Iterator it = elements.iterator(); it.hasNext();) { element = (JRPrintElement) it.next(); if (filter == null || filter.isToExport(element)) { if (element instanceof JRPrintLine) { exportLine((JRPrintLine) element); } else if (element instanceof JRPrintRectangle) { exportRectangle((JRPrintRectangle) element); } else if (element instanceof JRPrintEllipse) { exportEllipse((JRPrintEllipse) element); } else if (element instanceof JRPrintImage) { exportImage((JRPrintImage) element); } else if (element instanceof JRPrintText) { exportText((JRPrintText) element); } else if (element instanceof JRPrintFrame) { exportFrame((JRPrintFrame) element); } } } } } /** * */ protected void exportLine(JRPrintLine line) { float lineWidth = line.getLinePen().getLineWidth().floatValue(); if (lineWidth > 0f) { preparePen(pdfContentByte, line.getLinePen(), PdfContentByte.LINE_CAP_BUTT); if (line.getWidth() == 1) { if (line.getHeight() == 1) { //Nothing to draw } else { //Vertical line if (line.getLinePen().getLineStyle().byteValue() == JRPen.LINE_STYLE_DOUBLE) { pdfContentByte.moveTo(line.getX() + getOffsetX() + 0.5f - lineWidth / 3, jasperPrint.getPageHeight() - line.getY() - getOffsetY()); pdfContentByte.lineTo(line.getX() + getOffsetX() + 0.5f - lineWidth / 3, jasperPrint.getPageHeight() - line.getY() - getOffsetY() - line.getHeight()); pdfContentByte.stroke(); pdfContentByte.moveTo(line.getX() + getOffsetX() + 0.5f + lineWidth / 3, jasperPrint.getPageHeight() - line.getY() - getOffsetY()); pdfContentByte.lineTo(line.getX() + getOffsetX() + 0.5f + lineWidth / 3, jasperPrint.getPageHeight() - line.getY() - getOffsetY() - line.getHeight()); } else { pdfContentByte.moveTo(line.getX() + getOffsetX() + 0.5f, jasperPrint.getPageHeight() - line.getY() - getOffsetY()); pdfContentByte.lineTo(line.getX() + getOffsetX() + 0.5f, jasperPrint.getPageHeight() - line.getY() - getOffsetY() - line.getHeight()); } } } else { if (line.getHeight() == 1) { //Horizontal line if (line.getLinePen().getLineStyle().byteValue() == JRPen.LINE_STYLE_DOUBLE) { pdfContentByte.moveTo(line.getX() + getOffsetX(), jasperPrint.getPageHeight() - line.getY() - getOffsetY() - 0.5f + lineWidth / 3); pdfContentByte.lineTo(line.getX() + getOffsetX() + line.getWidth(), jasperPrint.getPageHeight() - line.getY() - getOffsetY() - 0.5f + lineWidth / 3); pdfContentByte.stroke(); pdfContentByte.moveTo(line.getX() + getOffsetX(), jasperPrint.getPageHeight() - line.getY() - getOffsetY() - 0.5f - lineWidth / 3); pdfContentByte.lineTo(line.getX() + getOffsetX() + line.getWidth(), jasperPrint.getPageHeight() - line.getY() - getOffsetY() - 0.5f - lineWidth / 3); } else { pdfContentByte.moveTo(line.getX() + getOffsetX(), jasperPrint.getPageHeight() - line.getY() - getOffsetY() - 0.5f); pdfContentByte.lineTo(line.getX() + getOffsetX() + line.getWidth(), jasperPrint.getPageHeight() - line.getY() - getOffsetY() - 0.5f); } } else { //Oblique line if (line.getDirection() == JRLine.DIRECTION_TOP_DOWN) { if (line.getLinePen().getLineStyle().byteValue() == JRPen.LINE_STYLE_DOUBLE) { double xtrans = lineWidth / (3 * Math.sqrt(1 + Math.pow(line.getWidth(), 2) / Math.pow(line.getHeight(), 2))); double ytrans = lineWidth / (3 * Math.sqrt(1 + Math.pow(line.getHeight(), 2) / Math.pow(line.getWidth(), 2))); pdfContentByte.moveTo(line.getX() + getOffsetX() + (float) xtrans, jasperPrint.getPageHeight() - line.getY() - getOffsetY() + (float) ytrans); pdfContentByte.lineTo(line.getX() + getOffsetX() + line.getWidth() + (float) xtrans, jasperPrint.getPageHeight() - line.getY() - getOffsetY() - line.getHeight() + (float) ytrans); pdfContentByte.stroke(); pdfContentByte.moveTo(line.getX() + getOffsetX() - (float) xtrans, jasperPrint.getPageHeight() - line.getY() - getOffsetY() - (float) ytrans); pdfContentByte.lineTo(line.getX() + getOffsetX() + line.getWidth() - (float) xtrans, jasperPrint.getPageHeight() - line.getY() - getOffsetY() - line.getHeight() - (float) ytrans); } else { pdfContentByte.moveTo(line.getX() + getOffsetX(), jasperPrint.getPageHeight() - line.getY() - getOffsetY()); pdfContentByte.lineTo(line.getX() + getOffsetX() + line.getWidth(), jasperPrint.getPageHeight() - line.getY() - getOffsetY() - line.getHeight()); } } else { if (line.getLinePen().getLineStyle().byteValue() == JRPen.LINE_STYLE_DOUBLE) { double xtrans = lineWidth / (3 * Math.sqrt(1 + Math.pow(line.getWidth(), 2) / Math.pow(line.getHeight(), 2))); double ytrans = lineWidth / (3 * Math.sqrt(1 + Math.pow(line.getHeight(), 2) / Math.pow(line.getWidth(), 2))); pdfContentByte.moveTo(line.getX() + getOffsetX() + (float) xtrans, jasperPrint.getPageHeight() - line.getY() - getOffsetY() - line.getHeight() - (float) ytrans); pdfContentByte.lineTo(line.getX() + getOffsetX() + line.getWidth() + (float) xtrans, jasperPrint.getPageHeight() - line.getY() - getOffsetY() - (float) ytrans); pdfContentByte.stroke(); pdfContentByte.moveTo(line.getX() + getOffsetX() - (float) xtrans, jasperPrint.getPageHeight() - line.getY() - getOffsetY() - line.getHeight() + (float) ytrans); pdfContentByte.lineTo(line.getX() + getOffsetX() + line.getWidth() - (float) xtrans, jasperPrint.getPageHeight() - line.getY() - getOffsetY() + (float) ytrans); } else { pdfContentByte.moveTo(line.getX() + getOffsetX(), jasperPrint.getPageHeight() - line.getY() - getOffsetY() - line.getHeight()); pdfContentByte.lineTo(line.getX() + getOffsetX() + line.getWidth(), jasperPrint.getPageHeight() - line.getY() - getOffsetY()); } } } } pdfContentByte.stroke(); pdfContentByte.setLineDash(0f); pdfContentByte.setLineCap(PdfContentByte.LINE_CAP_PROJECTING_SQUARE); } } /** * */ protected void exportRectangle(JRPrintRectangle rectangle) { pdfContentByte.setRGBColorFill(rectangle.getBackcolor().getRed(), rectangle.getBackcolor().getGreen(), rectangle.getBackcolor().getBlue()); preparePen(pdfContentByte, rectangle.getLinePen(), PdfContentByte.LINE_CAP_PROJECTING_SQUARE); float lineWidth = rectangle.getLinePen().getLineWidth().floatValue(); float lineOffset = BorderOffset.getOffset(rectangle.getLinePen()); if (rectangle.getMode() == JRElement.MODE_OPAQUE) { pdfContentByte.roundRectangle(rectangle.getX() + getOffsetX(), jasperPrint.getPageHeight() - rectangle.getY() - getOffsetY() - rectangle.getHeight(), rectangle.getWidth(), rectangle.getHeight(), rectangle.getRadius()); pdfContentByte.fill(); } if (lineWidth > 0f) { if (rectangle.getLinePen().getLineStyle().byteValue() == JRPen.LINE_STYLE_DOUBLE) { pdfContentByte.roundRectangle(rectangle.getX() + getOffsetX() - lineWidth / 3, jasperPrint.getPageHeight() - rectangle.getY() - getOffsetY() - rectangle.getHeight() - lineWidth / 3, rectangle.getWidth() + 2 * lineWidth / 3, rectangle.getHeight() + 2 * lineWidth / 3, rectangle.getRadius()); pdfContentByte.stroke(); pdfContentByte.roundRectangle(rectangle.getX() + getOffsetX() + lineWidth / 3, jasperPrint.getPageHeight() - rectangle.getY() - getOffsetY() - rectangle.getHeight() + lineWidth / 3, rectangle.getWidth() - 2 * lineWidth / 3, rectangle.getHeight() - 2 * lineWidth / 3, rectangle.getRadius()); pdfContentByte.stroke(); } else { pdfContentByte.roundRectangle(rectangle.getX() + getOffsetX() + lineOffset, jasperPrint.getPageHeight() - rectangle.getY() - getOffsetY() - rectangle.getHeight() + lineOffset, rectangle.getWidth() - 2 * lineOffset, rectangle.getHeight() - 2 * lineOffset, rectangle.getRadius()); pdfContentByte.stroke(); } } pdfContentByte.setLineDash(0f); } /** * */ protected void exportEllipse(JRPrintEllipse ellipse) { pdfContentByte.setRGBColorFill(ellipse.getBackcolor().getRed(), ellipse.getBackcolor().getGreen(), ellipse.getBackcolor().getBlue()); preparePen(pdfContentByte, ellipse.getLinePen(), PdfContentByte.LINE_CAP_PROJECTING_SQUARE); float lineWidth = ellipse.getLinePen().getLineWidth().floatValue(); float lineOffset = BorderOffset.getOffset(ellipse.getLinePen()); if (ellipse.getMode() == JRElement.MODE_OPAQUE) { pdfContentByte.ellipse(ellipse.getX() + getOffsetX(), jasperPrint.getPageHeight() - ellipse.getY() - getOffsetY() - ellipse.getHeight(), ellipse.getX() + getOffsetX() + ellipse.getWidth(), jasperPrint.getPageHeight() - ellipse.getY() - getOffsetY()); pdfContentByte.fill(); } if (lineWidth > 0f) { if (ellipse.getLinePen().getLineStyle().byteValue() == JRPen.LINE_STYLE_DOUBLE) { pdfContentByte.ellipse(ellipse.getX() + getOffsetX() - lineWidth / 3, jasperPrint.getPageHeight() - ellipse.getY() - getOffsetY() - ellipse.getHeight() - lineWidth / 3, ellipse.getX() + getOffsetX() + ellipse.getWidth() + lineWidth / 3, jasperPrint.getPageHeight() - ellipse.getY() - getOffsetY() + lineWidth / 3); pdfContentByte.stroke(); pdfContentByte.ellipse(ellipse.getX() + getOffsetX() + lineWidth / 3, jasperPrint.getPageHeight() - ellipse.getY() - getOffsetY() - ellipse.getHeight() + lineWidth / 3, ellipse.getX() + getOffsetX() + ellipse.getWidth() - lineWidth / 3, jasperPrint.getPageHeight() - ellipse.getY() - getOffsetY() - lineWidth / 3); pdfContentByte.stroke(); } else { pdfContentByte.ellipse(ellipse.getX() + getOffsetX() + lineOffset, jasperPrint.getPageHeight() - ellipse.getY() - getOffsetY() - ellipse.getHeight() + lineOffset, ellipse.getX() + getOffsetX() + ellipse.getWidth() - lineOffset, jasperPrint.getPageHeight() - ellipse.getY() - getOffsetY() - lineOffset); pdfContentByte.stroke(); } } pdfContentByte.setLineDash(0f); } /** * */ protected void exportImage(JRPrintImage printImage) throws DocumentException, IOException, JRException { if (printImage.getMode() == JRElement.MODE_OPAQUE) { pdfContentByte.setRGBColorFill(printImage.getBackcolor().getRed(), printImage.getBackcolor().getGreen(), printImage.getBackcolor().getBlue()); pdfContentByte.rectangle(printImage.getX() + getOffsetX(), jasperPrint.getPageHeight() - printImage.getY() - getOffsetY(), printImage.getWidth(), -printImage.getHeight()); pdfContentByte.fill(); } int topPadding = printImage.getLineBox().getTopPadding().intValue(); int leftPadding = printImage.getLineBox().getLeftPadding().intValue(); int bottomPadding = printImage.getLineBox().getBottomPadding().intValue(); int rightPadding = printImage.getLineBox().getRightPadding().intValue(); int availableImageWidth = printImage.getWidth() - leftPadding - rightPadding; availableImageWidth = (availableImageWidth < 0) ? 0 : availableImageWidth; int availableImageHeight = printImage.getHeight() - topPadding - bottomPadding; availableImageHeight = (availableImageHeight < 0) ? 0 : availableImageHeight; JRRenderable renderer = printImage.getRenderer(); if (renderer != null && availableImageWidth > 0 && availableImageHeight > 0) { if (renderer.getType() == JRRenderable.TYPE_IMAGE) { // Image renderers are all asked for their image data at some point. // Better to test and replace the renderer now, in case of lazy load error. renderer = JRImageRenderer.getOnErrorRendererForImageData(renderer, printImage.getOnErrorType()); } } else { renderer = null; } if (renderer != null) { int xoffset = 0; int yoffset = 0; Chunk chunk = null; float scaledWidth = availableImageWidth; float scaledHeight = availableImageHeight; if (renderer.getType() == JRRenderable.TYPE_IMAGE) { com.lowagie.text.Image image = null; float xalignFactor = getXAlignFactor(printImage); float yalignFactor = getYAlignFactor(printImage); switch (printImage.getScaleImage()) { case JRImage.SCALE_IMAGE_CLIP: { // Image load might fail, from given image data. // Better to test and replace the renderer now, in case of lazy load error. renderer = JRImageRenderer.getOnErrorRendererForDimension(renderer, printImage.getOnErrorType()); if (renderer == null) { break; } int normalWidth = availableImageWidth; int normalHeight = availableImageHeight; Dimension2D dimension = renderer.getDimension(); if (dimension != null) { normalWidth = (int) dimension.getWidth(); normalHeight = (int) dimension.getHeight(); } xoffset = (int) (xalignFactor * (availableImageWidth - normalWidth)); yoffset = (int) (yalignFactor * (availableImageHeight - normalHeight)); int minWidth = Math.min(normalWidth, availableImageWidth); int minHeight = Math.min(normalHeight, availableImageHeight); BufferedImage bi = new BufferedImage(minWidth, minHeight, BufferedImage.TYPE_INT_ARGB); Graphics2D g = bi.createGraphics(); if (printImage.getMode() == JRElement.MODE_OPAQUE) { g.setColor(printImage.getBackcolor()); g.fillRect(0, 0, minWidth, minHeight); } renderer.render(g, new java.awt.Rectangle((xoffset > 0 ? 0 : xoffset), (yoffset > 0 ? 0 : yoffset), normalWidth, normalHeight)); g.dispose(); xoffset = (xoffset < 0 ? 0 : xoffset); yoffset = (yoffset < 0 ? 0 : yoffset); //awtImage = bi.getSubimage(0, 0, minWidth, minHeight); //image = com.lowagie.text.Image.getInstance(awtImage, printImage.getBackcolor()); image = com.lowagie.text.Image.getInstance(bi, null); break; } case JRImage.SCALE_IMAGE_FILL_FRAME: { if (printImage.isUsingCache() && loadedImagesMap.containsKey(renderer)) { image = (com.lowagie.text.Image) loadedImagesMap.get(renderer); } else { try { image = com.lowagie.text.Image.getInstance(renderer.getImageData()); imageTesterPdfContentByte.addImage(image, 10, 0, 0, 10, 0, 0); } catch (Exception e) { JRImageRenderer tmpRenderer = JRImageRenderer.getOnErrorRendererForImage( JRImageRenderer.getInstance(renderer.getImageData()), printImage.getOnErrorType()); if (tmpRenderer == null) { break; } java.awt.Image awtImage = tmpRenderer.getImage(); image = com.lowagie.text.Image.getInstance(awtImage, null); } if (printImage.isUsingCache()) { loadedImagesMap.put(renderer, image); } } image.scaleAbsolute(availableImageWidth, availableImageHeight); break; } case JRImage.SCALE_IMAGE_RETAIN_SHAPE: default: { if (printImage.isUsingCache() && loadedImagesMap.containsKey(renderer)) { image = (com.lowagie.text.Image) loadedImagesMap.get(renderer); } else { try { image = com.lowagie.text.Image.getInstance(renderer.getImageData()); imageTesterPdfContentByte.addImage(image, 10, 0, 0, 10, 0, 0); } catch (Exception e) { JRImageRenderer tmpRenderer = JRImageRenderer.getOnErrorRendererForImage( JRImageRenderer.getInstance(renderer.getImageData()), printImage.getOnErrorType()); if (tmpRenderer == null) { break; } java.awt.Image awtImage = tmpRenderer.getImage(); image = com.lowagie.text.Image.getInstance(awtImage, null); } if (printImage.isUsingCache()) { loadedImagesMap.put(renderer, image); } } image.scaleToFit(availableImageWidth, availableImageHeight); xoffset = (int) (xalignFactor * (availableImageWidth - image.plainWidth())); yoffset = (int) (yalignFactor * (availableImageHeight - image.plainHeight())); xoffset = (xoffset < 0 ? 0 : xoffset); yoffset = (yoffset < 0 ? 0 : yoffset); break; } } if (image != null) { chunk = new Chunk(image, 0, 0); scaledWidth = image.scaledWidth(); scaledHeight = image.scaledHeight(); } } else { double normalWidth = availableImageWidth; double normalHeight = availableImageHeight; double displayWidth = availableImageWidth; double displayHeight = availableImageHeight; double ratioX = 1f; double ratioY = 1f; Rectangle2D clip = null; Dimension2D dimension = renderer.getDimension(); if (dimension != null) { normalWidth = dimension.getWidth(); normalHeight = dimension.getHeight(); displayWidth = normalWidth; displayHeight = normalHeight; float xalignFactor = getXAlignFactor(printImage); float yalignFactor = getYAlignFactor(printImage); switch (printImage.getScaleImage()) { case JRImage.SCALE_IMAGE_CLIP: { xoffset = (int) (xalignFactor * (availableImageWidth - normalWidth)); yoffset = (int) (yalignFactor * (availableImageHeight - normalHeight)); clip = new Rectangle2D.Double(-xoffset, -yoffset, availableImageWidth, availableImageHeight); break; } case JRImage.SCALE_IMAGE_FILL_FRAME: { ratioX = availableImageWidth / normalWidth; ratioY = availableImageHeight / normalHeight; normalWidth *= ratioX; normalHeight *= ratioY; xoffset = 0; yoffset = 0; break; } case JRImage.SCALE_IMAGE_RETAIN_SHAPE: default: { ratioX = availableImageWidth / normalWidth; ratioY = availableImageHeight / normalHeight; ratioX = ratioX < ratioY ? ratioX : ratioY; ratioY = ratioX; normalWidth *= ratioX; normalHeight *= ratioY; xoffset = (int) (xalignFactor * (availableImageWidth - normalWidth)); yoffset = (int) (yalignFactor * (availableImageHeight - normalHeight)); break; } } } PdfTemplate template = pdfContentByte.createTemplate((float) displayWidth, (float) displayHeight); Graphics2D g = forceSvgShapes ? template.createGraphicsShapes((float) displayWidth, (float) displayHeight) : template.createGraphics(availableImageWidth, availableImageHeight, new LocalFontMapper()); if (clip != null) { g.setClip(clip); } if (printImage.getMode() == JRElement.MODE_OPAQUE) { g.setColor(printImage.getBackcolor()); g.fillRect(0, 0, (int) displayWidth, (int) displayHeight); } Rectangle2D rectangle = new Rectangle2D.Double(0, 0, displayWidth, displayHeight); renderer.render(g, rectangle); g.dispose(); pdfContentByte.saveState(); pdfContentByte.addTemplate(template, (float) ratioX, 0f, 0f, (float) ratioY, printImage.getX() + getOffsetX() + xoffset, jasperPrint.getPageHeight() - printImage.getY() - getOffsetY() - (int) normalHeight - yoffset); pdfContentByte.restoreState(); Image image = getPxImage(); image.scaleAbsolute(availableImageWidth, availableImageHeight); chunk = new Chunk(image, 0, 0); } /* image.setAbsolutePosition( printImage.getX() + offsetX + borderOffset, jasperPrint.getPageHeight() - printImage.getY() - offsetY - image.scaledHeight() - borderOffset ); pdfContentByte.addImage(image); */ if (chunk != null) { setAnchor(chunk, printImage, printImage); setHyperlinkInfo(chunk, printImage); ColumnText colText = new ColumnText(pdfContentByte); int upperY = jasperPrint.getPageHeight() - printImage.getY() - topPadding - getOffsetY() - yoffset; int lowerX = printImage.getX() + leftPadding + getOffsetX() + xoffset; colText.setSimpleColumn(new Phrase(chunk), lowerX, upperY - scaledHeight, lowerX + scaledWidth, upperY, scaledHeight, Element.ALIGN_LEFT); colText.go(); } } if (printImage.getLineBox().getTopPen().getLineWidth().floatValue() <= 0f && printImage.getLineBox().getLeftPen().getLineWidth().floatValue() <= 0f && printImage.getLineBox().getBottomPen().getLineWidth().floatValue() <= 0f && printImage.getLineBox().getRightPen().getLineWidth().floatValue() <= 0f) { if (printImage.getLinePen().getLineWidth().floatValue() > 0f) { exportPen(printImage.getLinePen(), printImage); } } else { /* */ exportBox(printImage.getLineBox(), printImage); } } private float getXAlignFactor(JRPrintImage printImage) { float xalignFactor = 0f; switch (printImage.getHorizontalAlignment()) { case JRAlignment.HORIZONTAL_ALIGN_RIGHT: { xalignFactor = 1f; break; } case JRAlignment.HORIZONTAL_ALIGN_CENTER: { xalignFactor = 0.5f; break; } case JRAlignment.HORIZONTAL_ALIGN_LEFT: default: { xalignFactor = 0f; break; } } return xalignFactor; } private float getYAlignFactor(JRPrintImage printImage) { float yalignFactor = 0f; switch (printImage.getVerticalAlignment()) { case JRAlignment.VERTICAL_ALIGN_BOTTOM: { yalignFactor = 1f; break; } case JRAlignment.VERTICAL_ALIGN_MIDDLE: { yalignFactor = 0.5f; break; } case JRAlignment.VERTICAL_ALIGN_TOP: default: { yalignFactor = 0f; break; } } return yalignFactor; } /** * */ protected void setHyperlinkInfo(Chunk chunk, JRPrintHyperlink link) { switch (link.getHyperlinkType()) { case JRHyperlink.HYPERLINK_TYPE_REFERENCE: { if (link.getHyperlinkReference() != null) { switch (link.getHyperlinkTarget()) { case JRHyperlink.HYPERLINK_TARGET_BLANK: { chunk.setAction(PdfAction.javaScript("if (app.viewerVersion < 7)" + "{this.getURL(\"" + link.getHyperlinkReference() + "\");}" + "else {app.launchURL(\"" + link.getHyperlinkReference() + "\", true);};", pdfWriter)); break; } case JRHyperlink.HYPERLINK_TARGET_SELF: default: { chunk.setAnchor(link.getHyperlinkReference()); break; } } } break; } case JRHyperlink.HYPERLINK_TYPE_LOCAL_ANCHOR: { if (link.getHyperlinkAnchor() != null) { chunk.setLocalGoto(link.getHyperlinkAnchor()); } break; } case JRHyperlink.HYPERLINK_TYPE_LOCAL_PAGE: { if (link.getHyperlinkPage() != null) { chunk.setLocalGoto(JR_PAGE_ANCHOR_PREFIX + reportIndex + "_" + link.getHyperlinkPage().toString()); } break; } case JRHyperlink.HYPERLINK_TYPE_REMOTE_ANCHOR: { if (link.getHyperlinkReference() != null && link.getHyperlinkAnchor() != null) { chunk.setRemoteGoto(link.getHyperlinkReference(), link.getHyperlinkAnchor()); } break; } case JRHyperlink.HYPERLINK_TYPE_REMOTE_PAGE: { if (link.getHyperlinkReference() != null && link.getHyperlinkPage() != null) { chunk.setRemoteGoto(link.getHyperlinkReference(), link.getHyperlinkPage().intValue()); } break; } case JRHyperlink.HYPERLINK_TYPE_CUSTOM: { if (hyperlinkProducerFactory != null) { String hyperlink = hyperlinkProducerFactory.produceHyperlink(link); if (hyperlink != null) { switch (link.getHyperlinkTarget()) { case JRHyperlink.HYPERLINK_TARGET_BLANK: { chunk.setAction( PdfAction.javaScript( "if (app.viewerVersion < 7)" + "{this.getURL(\"" + hyperlink + "\");}" + "else {app.launchURL(\"" + hyperlink + "\", true);};", pdfWriter)); break; } case JRHyperlink.HYPERLINK_TARGET_SELF: default: { chunk.setAnchor(hyperlink); break; } } } } } case JRHyperlink.HYPERLINK_TYPE_NONE: default: { break; } } } /** * */ protected Phrase getPhrase(JRStyledText styledText, JRPrintText textElement) { Phrase phrase = new Phrase(); String text = styledText.getText(); int runLimit = 0; AttributedCharacterIterator iterator = styledText.getAttributedString().getIterator(); while (runLimit < styledText.length() && (runLimit = iterator.getRunLimit()) <= styledText.length()) { Chunk chunk = getChunk(iterator.getAttributes(), text.substring(iterator.getIndex(), runLimit)); setAnchor(chunk, textElement, textElement); setHyperlinkInfo(chunk, textElement); phrase.add(chunk); iterator.setIndex(runLimit); } return phrase; } /** * */ protected Chunk getChunk(Map attributes, String text) { Font font = getFont(attributes); Chunk chunk = new Chunk(text, font); Color backcolor = (Color) attributes.get(TextAttribute.BACKGROUND); if (backcolor != null) { chunk.setBackground(backcolor); } Object script = attributes.get(TextAttribute.SUPERSCRIPT); if (script != null) { if (TextAttribute.SUPERSCRIPT_SUPER.equals(script)) { chunk.setTextRise(font.leading(1f) / 2); } else if (script != null && TextAttribute.SUPERSCRIPT_SUB.equals(script)) { chunk.setTextRise(-font.leading(1f) / 2); } } if (splitCharacter != null) { chunk.setSplitCharacter(splitCharacter); } return chunk; } /** * */ protected Font getFont(Map attributes) { JRFont jrFont = new JRBaseFont(attributes); Exception initialException = null; Color forecolor = (Color) attributes.get(TextAttribute.FOREGROUND); Font font = null; PdfFont pdfFont = null; FontKey key = new FontKey(jrFont.getFontName(), jrFont.isBold(), jrFont.isItalic()); if (fontMap != null && fontMap.containsKey(key)) { pdfFont = (PdfFont) fontMap.get(key); } else { pdfFont = new PdfFont(jrFont.getPdfFontName(), jrFont.getPdfEncoding(), jrFont.isPdfEmbedded()); } try { font = FontFactory.getFont(pdfFont.getPdfFontName(), pdfFont.getPdfEncoding(), pdfFont.isPdfEmbedded(), jrFont.getFontSize(), (pdfFont.isPdfSimulatedBold() ? Font.BOLD : 0) | (pdfFont.isPdfSimulatedItalic() ? Font.ITALIC : 0) | (jrFont.isUnderline() ? Font.UNDERLINE : 0) | (jrFont.isStrikeThrough() ? Font.STRIKETHRU : 0), forecolor); // check if FontFactory didn't find the font if (font.getBaseFont() == null && font.family() == Font.UNDEFINED) { font = null; } } catch (Exception e) { initialException = e; } if (font == null) { byte[] bytes = null; try { bytes = JRLoader.loadBytesFromLocation(pdfFont.getPdfFontName(), classLoader, urlHandlerFactory, fileResolver); } catch (JRException e) { throw new JRRuntimeException("Could not load the following font : " + "\npdfFontName : " + pdfFont.getPdfFontName() + "\npdfEncoding : " + pdfFont.getPdfEncoding() + "\nisPdfEmbedded : " + pdfFont.isPdfEmbedded(), initialException); } BaseFont baseFont = null; try { baseFont = BaseFont.createFont(pdfFont.getPdfFontName(), pdfFont.getPdfEncoding(), pdfFont.isPdfEmbedded(), true, bytes, null); } catch (DocumentException e) { throw new JRRuntimeException(e); } catch (IOException e) { throw new JRRuntimeException(e); } font = new Font(baseFont, jrFont.getFontSize(), ((pdfFont.isPdfSimulatedBold()) ? Font.BOLD : 0) | ((pdfFont.isPdfSimulatedItalic()) ? Font.ITALIC : 0) | (jrFont.isUnderline() ? Font.UNDERLINE : 0) | (jrFont.isStrikeThrough() ? Font.STRIKETHRU : 0), forecolor); } return font; } /** * */ protected void exportText(JRPrintText text) throws DocumentException { JRStyledText styledText = getStyledText(text, false); if (styledText == null) { return; } int textLength = styledText.length(); int x = text.getX() + getOffsetX(); int y = text.getY() + getOffsetY(); int width = text.getWidth(); int height = text.getHeight(); int topPadding = text.getLineBox().getTopPadding().intValue(); int leftPadding = text.getLineBox().getLeftPadding().intValue(); int bottomPadding = text.getLineBox().getBottomPadding().intValue(); int rightPadding = text.getLineBox().getRightPadding().intValue(); int xFillCorrection = 0; int yFillCorrection = 0; double angle = 0; switch (text.getRotation()) { case JRTextElement.ROTATION_LEFT: { y = text.getY() + getOffsetY() + text.getHeight(); xFillCorrection = 1; width = text.getHeight(); height = text.getWidth(); int tmpPadding = topPadding; topPadding = leftPadding; leftPadding = bottomPadding; bottomPadding = rightPadding; rightPadding = tmpPadding; angle = Math.PI / 2; break; } case JRTextElement.ROTATION_RIGHT: { x = text.getX() + getOffsetX() + text.getWidth(); yFillCorrection = -1; width = text.getHeight(); height = text.getWidth(); int tmpPadding = topPadding; topPadding = rightPadding; rightPadding = bottomPadding; bottomPadding = leftPadding; leftPadding = tmpPadding; angle = -Math.PI / 2; break; } case JRTextElement.ROTATION_UPSIDE_DOWN: { x = text.getX() + getOffsetX() + text.getWidth(); y = text.getY() + getOffsetY() + text.getHeight(); int tmpPadding = topPadding; topPadding = bottomPadding; bottomPadding = tmpPadding; tmpPadding = leftPadding; leftPadding = rightPadding; rightPadding = tmpPadding; angle = Math.PI; break; } case JRTextElement.ROTATION_NONE: default: { } } AffineTransform atrans = new AffineTransform(); atrans.rotate(angle, x, jasperPrint.getPageHeight() - y); pdfContentByte.transform(atrans); if (text.getMode() == JRElement.MODE_OPAQUE) { Color backcolor = text.getBackcolor(); pdfContentByte.setRGBColorFill(backcolor.getRed(), backcolor.getGreen(), backcolor.getBlue()); pdfContentByte.rectangle(x + xFillCorrection, jasperPrint.getPageHeight() - y + yFillCorrection, width, -height); pdfContentByte.fill(); } if (textLength > 0) { int horizontalAlignment = Element.ALIGN_LEFT; switch (text.getHorizontalAlignment()) { case JRAlignment.HORIZONTAL_ALIGN_LEFT: { if (text.getRunDirection() == JRPrintText.RUN_DIRECTION_LTR) { horizontalAlignment = Element.ALIGN_LEFT; } else { horizontalAlignment = Element.ALIGN_RIGHT; } break; } case JRAlignment.HORIZONTAL_ALIGN_CENTER: { horizontalAlignment = Element.ALIGN_CENTER; break; } case JRAlignment.HORIZONTAL_ALIGN_RIGHT: { if (text.getRunDirection() == JRPrintText.RUN_DIRECTION_LTR) { horizontalAlignment = Element.ALIGN_RIGHT; } else { horizontalAlignment = Element.ALIGN_LEFT; } break; } case JRAlignment.HORIZONTAL_ALIGN_JUSTIFIED: { horizontalAlignment = Element.ALIGN_JUSTIFIED; break; } default: { horizontalAlignment = Element.ALIGN_LEFT; } } float verticalOffset = 0f; switch (text.getVerticalAlignment()) { case JRAlignment.VERTICAL_ALIGN_TOP: { verticalOffset = 0f; break; } case JRAlignment.VERTICAL_ALIGN_MIDDLE: { verticalOffset = (height - topPadding - bottomPadding - text.getTextHeight()) / 2f; break; } case JRAlignment.VERTICAL_ALIGN_BOTTOM: { verticalOffset = height - topPadding - bottomPadding - text.getTextHeight(); break; } default: { verticalOffset = 0f; } } ColumnText colText = new ColumnText(pdfContentByte); colText.setSimpleColumn(getPhrase(styledText, text), x + leftPadding, jasperPrint.getPageHeight() - y - topPadding - verticalOffset - text.getLeadingOffset(), //+ text.getLineSpacingFactor() * text.getFont().getSize(), x + width - rightPadding, jasperPrint.getPageHeight() - y - height + bottomPadding, 0, //text.getLineSpacingFactor(),// * text.getFont().getSize(), horizontalAlignment); colText.setLeading(0, text.getLineSpacingFactor());// * text.getFont().getSize()); colText.setRunDirection( text.getRunDirection() == JRPrintText.RUN_DIRECTION_LTR ? PdfWriter.RUN_DIRECTION_LTR : PdfWriter.RUN_DIRECTION_RTL); colText.go(); } atrans = new AffineTransform(); atrans.rotate(-angle, x, jasperPrint.getPageHeight() - y); pdfContentByte.transform(atrans); /* */ exportBox(text.getLineBox(), text); } /** * */ protected void exportBox(JRLineBox box, JRPrintElement element) { exportTopPen(box.getTopPen(), box.getLeftPen(), box.getRightPen(), element); exportLeftPen(box.getTopPen(), box.getLeftPen(), box.getBottomPen(), element); exportBottomPen(box.getLeftPen(), box.getBottomPen(), box.getRightPen(), element); exportRightPen(box.getTopPen(), box.getBottomPen(), box.getRightPen(), element); pdfContentByte.setLineDash(0f); pdfContentByte.setLineCap(PdfContentByte.LINE_CAP_PROJECTING_SQUARE); } /** * */ protected void exportPen(JRPen pen, JRPrintElement element) { exportTopPen(pen, pen, pen, element); exportLeftPen(pen, pen, pen, element); exportBottomPen(pen, pen, pen, element); exportRightPen(pen, pen, pen, element); pdfContentByte.setLineDash(0f); pdfContentByte.setLineCap(PdfContentByte.LINE_CAP_PROJECTING_SQUARE); } /** * */ protected void exportTopPen(JRPen topPen, JRPen leftPen, JRPen rightPen, JRPrintElement element) { if (topPen.getLineWidth().floatValue() > 0f) { float leftOffset = leftPen.getLineWidth().floatValue() / 2 - BorderOffset.getOffset(leftPen); float rightOffset = rightPen.getLineWidth().floatValue() / 2 - BorderOffset.getOffset(rightPen); preparePen(pdfContentByte, topPen, PdfContentByte.LINE_CAP_BUTT); if (topPen.getLineStyle().byteValue() == JRPen.LINE_STYLE_DOUBLE) { float topOffset = topPen.getLineWidth().floatValue(); pdfContentByte.moveTo(element.getX() + getOffsetX() - leftOffset, jasperPrint.getPageHeight() - element.getY() - getOffsetY() + topOffset / 3); pdfContentByte.lineTo(element.getX() + getOffsetX() + element.getWidth() + rightOffset, jasperPrint.getPageHeight() - element.getY() - getOffsetY() + topOffset / 3); pdfContentByte.stroke(); pdfContentByte.moveTo(element.getX() + getOffsetX() + leftOffset / 3, jasperPrint.getPageHeight() - element.getY() - getOffsetY() - topOffset / 3); pdfContentByte.lineTo(element.getX() + getOffsetX() + element.getWidth() - rightOffset / 3, jasperPrint.getPageHeight() - element.getY() - getOffsetY() - topOffset / 3); pdfContentByte.stroke(); } else { float topOffset = BorderOffset.getOffset(topPen); pdfContentByte.moveTo(element.getX() + getOffsetX() - leftOffset, jasperPrint.getPageHeight() - element.getY() - getOffsetY() - topOffset); pdfContentByte.lineTo(element.getX() + getOffsetX() + element.getWidth() + rightOffset, jasperPrint.getPageHeight() - element.getY() - getOffsetY() - topOffset); pdfContentByte.stroke(); } } } /** * */ protected void exportLeftPen(JRPen topPen, JRPen leftPen, JRPen bottomPen, JRPrintElement element) { if (leftPen.getLineWidth().floatValue() > 0f) { float topOffset = topPen.getLineWidth().floatValue() / 2 - BorderOffset.getOffset(topPen); float bottomOffset = bottomPen.getLineWidth().floatValue() / 2 - BorderOffset.getOffset(bottomPen); preparePen(pdfContentByte, leftPen, PdfContentByte.LINE_CAP_BUTT); if (leftPen.getLineStyle().byteValue() == JRPen.LINE_STYLE_DOUBLE) { float leftOffset = leftPen.getLineWidth().floatValue(); pdfContentByte.moveTo(element.getX() + getOffsetX() - leftOffset / 3, jasperPrint.getPageHeight() - element.getY() - getOffsetY() + topOffset); pdfContentByte.lineTo(element.getX() + getOffsetX() - leftOffset / 3, jasperPrint.getPageHeight() - element.getY() - getOffsetY() - element.getHeight() - bottomOffset); pdfContentByte.stroke(); pdfContentByte.moveTo(element.getX() + getOffsetX() + leftOffset / 3, jasperPrint.getPageHeight() - element.getY() - getOffsetY() - topOffset / 3); pdfContentByte.lineTo(element.getX() + getOffsetX() + leftOffset / 3, jasperPrint.getPageHeight() - element.getY() - getOffsetY() - element.getHeight() + bottomOffset / 3); pdfContentByte.stroke(); } else { float leftOffset = BorderOffset.getOffset(leftPen); pdfContentByte.moveTo(element.getX() + getOffsetX() + leftOffset, jasperPrint.getPageHeight() - element.getY() - getOffsetY() + topOffset); pdfContentByte.lineTo(element.getX() + getOffsetX() + leftOffset, jasperPrint.getPageHeight() - element.getY() - getOffsetY() - element.getHeight() - bottomOffset); pdfContentByte.stroke(); } } } /** * */ protected void exportBottomPen(JRPen leftPen, JRPen bottomPen, JRPen rightPen, JRPrintElement element) { if (bottomPen.getLineWidth().floatValue() > 0f) { float leftOffset = leftPen.getLineWidth().floatValue() / 2 - BorderOffset.getOffset(leftPen); float rightOffset = rightPen.getLineWidth().floatValue() / 2 - BorderOffset.getOffset(rightPen); preparePen(pdfContentByte, bottomPen, PdfContentByte.LINE_CAP_BUTT); if (bottomPen.getLineStyle().byteValue() == JRPen.LINE_STYLE_DOUBLE) { float bottomOffset = bottomPen.getLineWidth().floatValue(); pdfContentByte.moveTo(element.getX() + getOffsetX() - leftOffset, jasperPrint.getPageHeight() - element.getY() - getOffsetY() - element.getHeight() - bottomOffset / 3); pdfContentByte.lineTo(element.getX() + getOffsetX() + element.getWidth() + rightOffset, jasperPrint.getPageHeight() - element.getY() - getOffsetY() - element.getHeight() - bottomOffset / 3); pdfContentByte.stroke(); pdfContentByte.moveTo(element.getX() + getOffsetX() + leftOffset / 3, jasperPrint.getPageHeight() - element.getY() - getOffsetY() - element.getHeight() + bottomOffset / 3); pdfContentByte.lineTo(element.getX() + getOffsetX() + element.getWidth() - rightOffset / 3, jasperPrint.getPageHeight() - element.getY() - getOffsetY() - element.getHeight() + bottomOffset / 3); pdfContentByte.stroke(); } else { float bottomOffset = BorderOffset.getOffset(bottomPen); pdfContentByte.moveTo(element.getX() + getOffsetX() - leftOffset, jasperPrint.getPageHeight() - element.getY() - getOffsetY() - element.getHeight() + bottomOffset); pdfContentByte.lineTo(element.getX() + getOffsetX() + element.getWidth() + rightOffset, jasperPrint.getPageHeight() - element.getY() - getOffsetY() - element.getHeight() + bottomOffset); pdfContentByte.stroke(); } } } /** * */ protected void exportRightPen(JRPen topPen, JRPen bottomPen, JRPen rightPen, JRPrintElement element) { if (rightPen.getLineWidth().floatValue() > 0f) { float topOffset = topPen.getLineWidth().floatValue() / 2 - BorderOffset.getOffset(topPen); float bottomOffset = bottomPen.getLineWidth().floatValue() / 2 - BorderOffset.getOffset(bottomPen); preparePen(pdfContentByte, rightPen, PdfContentByte.LINE_CAP_BUTT); if (rightPen.getLineStyle().byteValue() == JRPen.LINE_STYLE_DOUBLE) { float rightOffset = rightPen.getLineWidth().floatValue(); pdfContentByte.moveTo(element.getX() + getOffsetX() + element.getWidth() + rightOffset / 3, jasperPrint.getPageHeight() - element.getY() - getOffsetY() + topOffset); pdfContentByte.lineTo(element.getX() + getOffsetX() + element.getWidth() + rightOffset / 3, jasperPrint.getPageHeight() - element.getY() - getOffsetY() - element.getHeight() - bottomOffset); pdfContentByte.stroke(); pdfContentByte.moveTo(element.getX() + getOffsetX() + element.getWidth() - rightOffset / 3, jasperPrint.getPageHeight() - element.getY() - getOffsetY() - topOffset / 3); pdfContentByte.lineTo(element.getX() + getOffsetX() + element.getWidth() - rightOffset / 3, jasperPrint.getPageHeight() - element.getY() - getOffsetY() - element.getHeight() + bottomOffset / 3); pdfContentByte.stroke(); } else { float rightOffset = BorderOffset.getOffset(rightPen); pdfContentByte.moveTo(element.getX() + getOffsetX() + element.getWidth() - rightOffset, jasperPrint.getPageHeight() - element.getY() - getOffsetY() + topOffset); pdfContentByte.lineTo(element.getX() + getOffsetX() + element.getWidth() - rightOffset, jasperPrint.getPageHeight() - element.getY() - getOffsetY() - element.getHeight() - bottomOffset); pdfContentByte.stroke(); } } } /** * */ private static void preparePen(PdfContentByte pdfContentByte, JRPen pen, int lineCap) { float lineWidth = pen.getLineWidth().floatValue(); if (lineWidth <= 0) { return; } pdfContentByte.setLineWidth(lineWidth); pdfContentByte.setLineCap(lineCap); Color color = pen.getLineColor(); pdfContentByte.setRGBColorStroke(color.getRed(), color.getGreen(), color.getBlue()); switch (pen.getLineStyle().byteValue()) { case JRPen.LINE_STYLE_DOUBLE: { pdfContentByte.setLineWidth(lineWidth / 3); pdfContentByte.setLineDash(0f); break; } case JRPen.LINE_STYLE_DOTTED: { switch (lineCap) { case PdfContentByte.LINE_CAP_BUTT: { pdfContentByte.setLineDash(lineWidth, lineWidth, 0f); break; } case PdfContentByte.LINE_CAP_PROJECTING_SQUARE: { pdfContentByte.setLineDash(0, 2 * lineWidth, 0f); break; } } break; } case JRPen.LINE_STYLE_DASHED: { switch (lineCap) { case PdfContentByte.LINE_CAP_BUTT: { pdfContentByte.setLineDash(5 * lineWidth, 3 * lineWidth, 0f); break; } case PdfContentByte.LINE_CAP_PROJECTING_SQUARE: { pdfContentByte.setLineDash(4 * lineWidth, 4 * lineWidth, 0f); break; } } break; } case JRPen.LINE_STYLE_SOLID: default: { pdfContentByte.setLineDash(0f); break; } } } protected static synchronized void registerFonts() { if (!fontsRegistered) { List fontFiles = JRProperties.getProperties(JRProperties.PDF_FONT_FILES_PREFIX); if (!fontFiles.isEmpty()) { for (Iterator i = fontFiles.iterator(); i.hasNext();) { JRProperties.PropertySuffix font = (JRProperties.PropertySuffix) i.next(); String file = font.getValue(); if (file.toLowerCase().endsWith(".ttc")) { FontFactory.register(file); } else { String alias = font.getSuffix(); FontFactory.register(file, alias); } } } List fontDirs = JRProperties.getProperties(JRProperties.PDF_FONT_DIRS_PREFIX); if (!fontDirs.isEmpty()) { for (Iterator i = fontDirs.iterator(); i.hasNext();) { JRProperties.PropertySuffix dir = (JRProperties.PropertySuffix) i.next(); FontFactory.registerDirectory(dir.getValue()); } } fontsRegistered = true; } } static protected class Bookmark { final PdfOutline pdfOutline; final int level; Bookmark(Bookmark parent, int x, int top, String title) { this(parent, new PdfDestination(PdfDestination.XYZ, x, top, 0), title); } Bookmark(Bookmark parent, PdfDestination destination, String title) { this.pdfOutline = new PdfOutline(parent.pdfOutline, destination, title, false); this.level = parent.level + 1; } Bookmark(PdfOutline pdfOutline, int level) { this.pdfOutline = pdfOutline; this.level = level; } } static protected class BookmarkStack { LinkedList stack; BookmarkStack() { stack = new LinkedList(); } void push(Bookmark bookmark) { stack.add(bookmark); } Bookmark pop() { return (Bookmark) stack.removeLast(); } Bookmark peek() { return (Bookmark) stack.getLast(); } } protected void initBookmarks() { bookmarkStack = new BookmarkStack(); int rootLevel = isModeBatch && isCreatingBatchModeBookmarks ? -1 : 0; Bookmark bookmark = new Bookmark(pdfContentByte.getRootOutline(), rootLevel); bookmarkStack.push(bookmark); } protected void addBookmark(int level, String title, int x, int y) { Bookmark parent = bookmarkStack.peek(); while (parent.level > level - 1) { bookmarkStack.pop(); parent = bookmarkStack.peek(); } for (int i = parent.level + 1; i < level; ++i) { Bookmark emptyBookmark = new Bookmark(parent, parent.pdfOutline.getPdfDestination(), EMPTY_BOOKMARK_TITLE); bookmarkStack.push(emptyBookmark); parent = emptyBookmark; } Bookmark bookmark = new Bookmark(parent, x, jasperPrint.getPageHeight() - y, title); bookmarkStack.push(bookmark); } protected void setAnchor(Chunk chunk, JRPrintAnchor anchor, JRPrintElement element) { String anchorName = anchor.getAnchorName(); if (anchorName != null) { chunk.setLocalDestination(anchorName); if (anchor.getBookmarkLevel() != JRAnchor.NO_BOOKMARK) { addBookmark(anchor.getBookmarkLevel(), anchor.getAnchorName(), element.getX(), element.getY()); } } } protected void exportFrame(JRPrintFrame frame) throws DocumentException, IOException, JRException { if (frame.getMode() == JRElement.MODE_OPAQUE) { int x = frame.getX() + getOffsetX(); int y = frame.getY() + getOffsetY(); Color backcolor = frame.getBackcolor(); pdfContentByte.setRGBColorFill(backcolor.getRed(), backcolor.getGreen(), backcolor.getBlue()); pdfContentByte.rectangle(x, jasperPrint.getPageHeight() - y, frame.getWidth(), -frame.getHeight()); pdfContentByte.fill(); } setFrameElementsOffset(frame, false); try { exportElements(frame.getElements()); } finally { restoreElementOffsets(); } exportBox(frame.getLineBox(), frame); } /** * Output stream implementation that discards all the data. */ public static class NullOutputStream extends OutputStream { public NullOutputStream() { } public void write(int b) { // discard the data } public void write(byte[] b, int off, int len) { // discard the data } public void write(byte[] b) { // discard the data } } /** * */ class LocalFontMapper implements FontMapper { public LocalFontMapper() { } public BaseFont awtToPdf(java.awt.Font font) { return getFont(font.getAttributes()).getBaseFont(); } public java.awt.Font pdfToAwt(BaseFont font, int size) { return null; } } }