📄 pdfoutputtarget.java
字号:
/**
* ========================================
* JFreeReport : a free Java report library
* ========================================
*
* Project Info: http://www.jfree.org/jfreereport/index.html
* Project Lead: Thomas Morgner;
*
* (C) Copyright 2000-2003, by Thomas Morgner, Object Refinery Limited and Contributors.
*
* 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.
*
* --------------------
* PDFOutputTarget.java
* --------------------
* (C)opyright 2002, 2003, by Object Refinery Limited.and Contributors;
*
* Original Author: David Gilbert (for Object Refinery Limited);
* Contributor(s): Thomas Morgner;
*
* $Id: PDFOutputTarget.java,v 1.15.2.1 2003/12/21 23:28:45 taqua Exp $
*
* Changes
* -------
* 21-Feb-2002 : Version 1 (DG);
* 24-Apr-2002 : Support for Images and MultiLineElements.
* 07-May-2002 : Small change for source of JFreeReport info to set creator of PDF document (DG);
* 16-May-2002 : Interface of drawShape changhed so we can draw different line width (JS)
* 27-May-2002 : Fonts are embedded now, TrueType fonts are loaded directly into the pdf.
* See report4.xml for a demo. An encoding property is added to support unicode.
* 08-Jun-2002 : Documentation.
* 10-Jun-2002 : Fixed a bug in FontFactory which caused the class to crash in Linux
* 17-Jul-2002 : Fixed a nullpointer when an ImageReference did not contain a graphics
* 13-Sep-2002 : Removed caching of fonts for FontFactory as it causes OutOfMemoryErrors when a huge
* font collection is used
* 04-Nov-2002 : BugFix: PDFFonts need caching on setFont() or OutOfMemoryErrors occur
* 29-May-2003 : Turned off alpha encoding for PNG images, see bug ID 744941 (DG);
*/
package org.jfree.report.modules.output.pageable.pdf;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.Dimension2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Rectangle2D;
import java.awt.print.PageFormat;
import java.io.IOException;
import java.io.OutputStream;
import java.net.MalformedURLException;
import com.keypoint.PngEncoder;
import com.lowagie.text.BadElementException;
import com.lowagie.text.DocWriter;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Image;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfWriter;
import org.jfree.report.DrawableContainer;
import org.jfree.report.ImageReference;
import org.jfree.report.JFreeReport;
import org.jfree.report.ShapeElement;
import org.jfree.report.layout.SizeCalculator;
import org.jfree.report.modules.output.pageable.base.LogicalPage;
import org.jfree.report.modules.output.pageable.base.OutputTarget;
import org.jfree.report.modules.output.pageable.base.OutputTargetException;
import org.jfree.report.modules.output.pageable.base.output.AbstractOutputTarget;
import org.jfree.report.modules.output.pageable.base.output.DummyOutputTarget;
import org.jfree.report.modules.output.pageable.base.physicals.LogicalPageImpl;
import org.jfree.report.modules.output.pageable.base.physicals.PhysicalPage;
import org.jfree.report.modules.output.support.itext.BaseFontCreateException;
import org.jfree.report.modules.output.support.itext.BaseFontFactory;
import org.jfree.report.modules.output.support.itext.BaseFontRecord;
import org.jfree.report.modules.output.support.itext.BaseFontSupport;
import org.jfree.report.style.ElementDefaultStyleSheet;
import org.jfree.report.style.FontDefinition;
import org.jfree.report.util.Log;
import org.jfree.report.util.ReportConfiguration;
import org.jfree.report.util.WaitingImageObserver;
/**
* An output target for the report engine that generates a PDF file using the iText class library
* (see <code>http://www.lowagie.com/iText</code>, note that the URL is case-sensitive!).
* <p>
* If the system property "org.jfree.report.modules.output.pageable.pdf.PDFOutputTarget.AUTOINIT"
* is set to "true",
* the PDF-FontFactory is automatically initialized when this class is loaded. Be aware that
* embedding many fonts will result in larger files.
* <p>
* When using Unicode characters, you will have to adjust the encoding of this target to
* "Identity-H", to enable horizontal unicode printing. This will result in larger files.
* <p>
* The Encoding property is now a string with one of the values of "none" "40bit" or "128bit".
*
* @author David Gilbert
* @author Thomas Morgner
*/
public strictfp class PDFOutputTarget extends AbstractOutputTarget
{
/**
* A PDF size calculator.
*/
private static final strictfp class PDFSizeCalculator implements SizeCalculator
{
/** The base font. */
private final BaseFont baseFont;
/** The font size. */
private final float fontSize;
/**
* Creates a new size calculator.
*
* @param font the font.
* @param fontSize the font size.
*/
private PDFSizeCalculator(final BaseFont font, final float fontSize)
{
this.baseFont = font;
this.fontSize = fontSize;
}
/**
* Calculates the width of the specified String in the current Graphics context.
*
* @param text the text to be weighted.
* @param lineStartPos the start position of the substring to be weighted.
* @param endPos the position of the last characterto be included in the weightening process.
*
* @return the width of the given string in 1/72" dpi.
*/
public float getStringWidth(final String text, final int lineStartPos, final int endPos)
{
return baseFont.getWidthPoint(text.substring(lineStartPos, endPos), fontSize);
}
/**
* Returns the height of the current font. The font height specifies the distance between
* 2 base lines.
*
* @return the font height.
*/
public float getLineHeight()
{
return fontSize;
}
}
/** The configuration prefix. */
public static final String CONFIGURATION_PREFIX
= "org.jfree.report.modules.output.pageable.pdf.";
/** Literal text for the 'EmbedFonts' property name. */
public static final String EMBED_FONTS = "EmbedFonts";
/** Literal text for the 'AllowPrinting' property name. */
public static final String SECURITY_ALLOW_PRINTING = "AllowPrinting";
/** Literal text for the 'AllowModifyContents' property name. */
public static final String SECURITY_ALLOW_MODIFY_CONTENTS = "AllowModifyContents";
/** Literal text for the 'AllowCopy' property name. */
public static final String SECURITY_ALLOW_COPY = "AllowCopy";
/** Literal text for the 'AllowModifyAnnotations' property name. */
public static final String SECURITY_ALLOW_MODIFY_ANNOTATIONS = "AllowModifyAnnotations";
/** Literal text for the 'AllowFillIn' property name. */
public static final String SECURITY_ALLOW_FILLIN = "AllowFillIn";
/** Literal text for the 'AllowScreenReaders' property name. */
public static final String SECURITY_ALLOW_SCREENREADERS = "AllowScreenReaders";
/** Literal text for the 'AllowAssembly' property name. */
public static final String SECURITY_ALLOW_ASSEMBLY = "AllowAssembly";
/** Literal text for the 'AllowDegradedPrinting' property name. */
public static final String SECURITY_ALLOW_DEGRADED_PRINTING = "AllowDegradedPrinting";
/** Literal text for the 'Encryption' property name. */
public static final String SECURITY_ENCRYPTION = "Encryption";
/** A constant for the encryption type (40 bit). */
public static final String SECURITY_ENCRYPTION_NONE = "none";
/** A constant for the encryption type (40 bit). */
public static final String SECURITY_ENCRYPTION_40BIT = "40bit";
/** A constant for the encryption type (128 bit). */
public static final String SECURITY_ENCRYPTION_128BIT = "128bit";
/** Literal text for the 'userpassword' property name. */
public static final String SECURITY_USERPASSWORD = "UserPassword";
/** Literal text for the 'ownerpassword' property name. */
public static final String SECURITY_OWNERPASSWORD = "OwnerPassword";
/** A useful constant for specifying the PDF creator. */
private static final String CREATOR = JFreeReport.getInfo().getName() + " version "
+ JFreeReport.getInfo().getVersion();
/** The encoding key. */
public static final String ENCODING = "Encoding";
/** The 'PDF embed fonts' property key. */
public static final String PDFTARGET_EMBED_FONTS
= CONFIGURATION_PREFIX + EMBED_FONTS;
/** The default 'PDF embed fonts' property value. */
public static final String PDFTARGET_EMBED_FONTS_DEFAULT = "true";
/** The 'PDF encoding' property key. */
public static final String PDFTARGET_ENCODING
= CONFIGURATION_PREFIX + ENCODING;
/** The default 'PDF encoding' property value. */
public static final String PDFTARGET_ENCODING_DEFAULT = "Cp1252";
/** The pdf specification version that should be created. */
public static final String PDF_VERSION = "Version";
/** The global key name for the pdf specification version that should be created. */
public static final String PDFTARGET_PDF_VERSION =
CONFIGURATION_PREFIX + PDF_VERSION;
/** The default version number for the PDF specification version. */
public static final String PDF_VERSION_DEFAULT = "1.4";
/** The output stream. */
private final OutputStream out;
/** The document. */
private Document pdfDocument;
/** The document writer. */
private PdfWriter writer;
/** The current base font. */
private BaseFont baseFont;
/** The AWT font. */
private FontDefinition fontDefinition;
/** The stroke used for shapes. */
private Stroke awtStroke;
/** The current Paint as used in the AWT. */
private Paint awtPaint;
/** The PDF font support. */
private final BaseFontSupport fontSupport;
/**
* A bytearray containing an empty password. iText replaces the owner password with random
* values, but Adobe allows to have encryption without an owner password set.
* Copied from iText
*/
private static final byte PDF_PASSWORD_PAD[] = {
(byte) 0x28, (byte) 0xBF, (byte) 0x4E, (byte) 0x5E, (byte) 0x4E, (byte) 0x75,
(byte) 0x8A, (byte) 0x41, (byte) 0x64, (byte) 0x00, (byte) 0x4E, (byte) 0x56,
(byte) 0xFF, (byte) 0xFA, (byte) 0x01, (byte) 0x08, (byte) 0x2E, (byte) 0x2E,
(byte) 0x00, (byte) 0xB6, (byte) 0xD0, (byte) 0x68, (byte) 0x3E, (byte) 0x80,
(byte) 0x2F, (byte) 0x0C, (byte) 0xA9, (byte) 0xFE, (byte) 0x64, (byte) 0x53,
(byte) 0x69, (byte) 0x7A};
/**
* Constructs a PDFOutputTarget.
*
* @param out the output stream.
* @param pageFormat the page format.
* @param embedFonts embed fonts?
*/
public PDFOutputTarget(final OutputStream out, final PageFormat pageFormat,
final boolean embedFonts)
{
this(out, pageFormat, pageFormat, embedFonts);
}
/**
* Creates a new PDFOutputTarget.
*
* @param out the output stream.
* @param logPage the logical page.
* @param embedFonts embed the fonts?
*/
public PDFOutputTarget(final OutputStream out, final LogicalPage logPage,
final boolean embedFonts)
{
super(logPage);
this.out = out;
this.fontSupport = new BaseFontSupport();
setEmbedFonts(embedFonts);
}
/**
* Creates a new PDFOutputTarget.
*
* @param out the output stream.
* @param logPageFormat the logical page format.
* @param physPageFormat the physical page format.
* @param embedFonts embed the fonts?
*/
public PDFOutputTarget(final OutputStream out, final PageFormat logPageFormat,
final PageFormat physPageFormat, final boolean embedFonts)
{
this(out, new LogicalPageImpl(logPageFormat, physPageFormat), embedFonts);
}
/**
* Returns the default font encoding.
*
* @return the default font encoding.
*/
private static final String getDefaultFontEncoding()
{
return BaseFontFactory.getDefaultFontEncoding();
}
/**
* Returns the page height in points (1/72 inch).
*
* @return the page height.
*/
private float getPageHeight()
{
return this.getDocument().getPageSize().height();
}
/**
* Returns the currently active AWT-Font.
*
* @return the current font.
*/
public FontDefinition getFont()
{
return fontDefinition;
}
/**
* Returns the iText BaseFont.
*
* @return the iText BaseFont.
*/
public BaseFont getBaseFont()
{
return baseFont;
}
/**
* Sets the current font. The font is mapped to pdf specific fonts if possible.
* If no basefont could be created, an OutputTargetException is thrown.
*
* @param font the new font (null not permitted).
*
* @throws OutputTargetException if there was a problem setting the font for the target.
*/
public void setFont(final FontDefinition font) throws OutputTargetException
{
if (font == null)
{
throw new NullPointerException();
}
// do nothing if this font is already set
if (baseFont != null && fontDefinition != null && fontDefinition.equals(font))
{
return; // no need to do anything ...
}
this.fontDefinition = font;
try
{
this.baseFont = fontSupport.createBaseFont(font, font.getFontEncoding(getFontEncoding()),
(isEmbedFonts() || font.isEmbeddedFont())).getBaseFont();
if (baseFont == null)
{
throw new OutputTargetException("The font definition was not successfull.");
}
}
catch (BaseFontCreateException bfce)
{
throw new OutputTargetException("The font definition was not successfull.", bfce);
}
}
/**
* Draws an image from this {@link ImageReference}. The image is directly embedded into the
* pdf file to provide the best scaling support.
*
* @param imageRef the image reference.
*
* @throws OutputTargetException if there was a problem drawing the image to the target.
*/
public void drawImage(final ImageReference imageRef) throws OutputTargetException
{
try
{
final Rectangle2D bounds = getInternalOperationBounds();
final Rectangle2D imageBounds = imageRef.getBoundsScaled();
final float x = (float) (bounds.getX());
final float y = (float) (bounds.getY());
final Image image = getImage(imageRef);
image.setAbsolutePosition(x, (float) (getPageHeight() - y - bounds.getHeight()));
image.scaleAbsolute((float) imageBounds.getWidth(),
(float) imageBounds.getHeight());
final PdfContentByte cb = this.writer.getDirectContent();
cb.rectangle((float) (imageBounds.getX() + x),
(float) (getPageHeight() - imageBounds.getY() - y - bounds.getHeight()),
(float) imageBounds.getWidth(),
(float) imageBounds.getHeight());
cb.clip();
cb.newPath();
cb.addImage(image);
cb.restoreState();
cb.saveState();
}
catch (BadElementException be)
{
throw new OutputTargetException("BadElementException", be);
}
catch (DocumentException de)
{
throw new OutputTargetException("DocumentException", de);
}
catch (MalformedURLException mf)
{
throw new OutputTargetException("Invalid URL in ImageReference", mf);
}
catch (IOException mf)
{
throw new OutputTargetException("URL Content could not be read", mf);
}
}
/**
* Helperfunction to extract an image from an imagereference. If the image is contained as
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -