net.sf.jasperreports.engine.export.JRGraphics2DExporter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jasperreports Show documentation
Show all versions of jasperreports Show documentation
Free Java Reporting Library
/*
* JasperReports - Free Java Reporting Library.
* Copyright (C) 2001 - 2019 TIBCO Software Inc. All rights reserved.
* http://www.jaspersoft.com
*
* Unless you have purchased a commercial license agreement from Jaspersoft,
* the following license terms apply:
*
* This program is part of JasperReports.
*
* JasperReports 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 3 of the License, or
* (at your option) any later version.
*
* JasperReports 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 JasperReports. If not, see .
*/
/*
* Contributors:
* Eugene D - [email protected]
* Adrian Jackson - [email protected]
* David Taylor - [email protected]
* Lars Kristensen - [email protected]
*/
package net.sf.jasperreports.engine.export;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.util.List;
import net.sf.jasperreports.engine.DefaultJasperReportsContext;
import net.sf.jasperreports.engine.JRAbstractExporter;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRGenericElementType;
import net.sf.jasperreports.engine.JRPrintPage;
import net.sf.jasperreports.engine.JRPrintText;
import net.sf.jasperreports.engine.JRPropertiesUtil;
import net.sf.jasperreports.engine.JRRuntimeException;
import net.sf.jasperreports.engine.JasperReportsContext;
import net.sf.jasperreports.engine.PrintPageFormat;
import net.sf.jasperreports.engine.export.draw.FrameDrawer;
import net.sf.jasperreports.engine.export.draw.PrintDrawVisitor;
import net.sf.jasperreports.engine.util.JRGraphEnvInitializer;
import net.sf.jasperreports.export.Graphics2DExporterConfiguration;
import net.sf.jasperreports.export.Graphics2DExporterOutput;
import net.sf.jasperreports.export.Graphics2DReportConfiguration;
import net.sf.jasperreports.export.ReportExportConfiguration;
import net.sf.jasperreports.renderers.RenderersCache;
/**
* Exports a JasperReports document to a Graphics2D
object.
*
* JasperReports relies on AWT for text measurements and all sorts of layout calculations
* during report filling, so documents created using AWT will certainly look perfect when
* rendered with AWT on a java.awt.Graphics2D
context. For this reason, the
* {@link net.sf.jasperreports.engine.export.JRGraphics2DExporter} is the perfect
* exporter. The output it produces is considered to be the reference in terms of layout
* capabilities and element styling.
*
* Generally speaking, the document quality produced by all the other exporters is only an
* approximation of the perfect output that the Graphics2D exporter can produce. As its
* name indicates, this exporter is special because it does not produce files or send character
* or binary data to an output stream. Instead, its only target for rendering the content of a
* page is a java.awt.Graphics2D
object. This exporter is also special because it can
* export only one page at a time.
*
* This exporter is used by the built-in Swing viewer to render the content of each page, and
* it is also used when printing the documents. The documents are printed page by page,
* and the exporter is invoked to draw each document page on the graphic context
* associated with the selected printer job.
*
* Because we are relying on the same code (same exporter) when viewing the documents
* using the built-in viewer and when printing them, JasperReports is a perfect WYSIWYG
* tool. The document quality on paper is the same as on the screen.
*
* In terms of exporter input, note that this exporter does not work in batch mode. If a
* java.util.List
of JasperPrint documents is supplied to it through a
* {@link net.sf.jasperreports.export.SimpleExporterInput} instance, the exporter
* considers only the first one for exporting and ignores all the others.
*
* Furthermore, this exporter can export only a single page at a time. The index of the page
* to be exported can be set using either the
* {@link net.sf.jasperreports.export.ReportExportConfiguration#getStartPageIndex() getStartPageIndex()}
* exporter configuration setting or the
* {@link net.sf.jasperreports.export.ReportExportConfiguration#getPageIndex() getPageIndex()}.
* Note that if present, {@link net.sf.jasperreports.export.ReportExportConfiguration#getPageIndex() getPageIndex()} overrides the value of
* {@link net.sf.jasperreports.export.ReportExportConfiguration#getStartPageIndex() getStartPageIndex()}.
* Therefore, this exporter actually exports only the first page from
* the specified page range, no matter how the page range is specified.
*
* As already mentioned, this exporter needs a target java.awt.Graphics2D
object onto
* which to render the specified page. This Graphics2D object can be set using the special
* exporter output setting {@link net.sf.jasperreports.export.Graphics2DExporterOutput#getGraphics2D() getGraphics2D()}.
* If this setting is not present, the exporter will throw an
* exception signaling to the caller program that no output target was specified for the
* export process.
*
* By default, the exporter renders the content of the page at normal proportions. However,
* it can also render it at different proportions if needed. For instance, when used inside the
* Swing viewer, the Graphics2D exporter must render the page using the user-defined
* zoom ratio. To set the zoom ratio for the exporter, supply a java.lang.Float
value
* ranging from 0 to 1 as the value for the
* {@link net.sf.jasperreports.export.Graphics2DReportConfiguration#getZoomRatio() getZoomRatio()} export
* configuration setting.
*
* The Graphics2D exporter is also used when printing directly from Java. The Java Print
* Service exporter relies on the Graphics2D exporter
* and delegates to it all the rendering that needs to be performed on the printer's graphic
* context. Some of the existing JVM implementations have problems related to the huge
* size of the printer spool jobs that are created even for small documents. To avoid this, a
* bug fix was introduced in the Graphics2D exporter to minimize the impact of this
* problem and reduce the size of print spool jobs, while preserving document quality when
* printing. However, the bug fix itself is not perfect, and users might experience problems
* when printing bidirectional writing texts such as Arabic and Hebrew.
*
* This is why the special
* {@link net.sf.jasperreports.export.Graphics2DReportConfiguration#isMinimizePrinterJobSize() isMinimizePrinterJobSize()}
* export configuration setting was introduced, along with a configuration property called
* net.sf.jasperreports.export.graphics2d.min.job.size
, to allow users to turn
* on and off this rendering optimization, depending on their actual needs. The
* configuration property value is used only in the absence of the export configuration setting.
*
* @see net.sf.jasperreports.export.Graphics2DExporterOutput
* @see net.sf.jasperreports.export.Graphics2DReportConfiguration
* @see net.sf.jasperreports.export.ReportExportConfiguration
* @see net.sf.jasperreports.export.SimpleExporterInput
* @author Teodor Danciu ([email protected])
*/
public class JRGraphics2DExporter extends JRAbstractExporter
{
private static final float DEFAULT_ZOOM = 1f;
private static final String GRAPHICS2D_EXPORTER_PROPERTIES_PREFIX = JRPropertiesUtil.PROPERTY_PREFIX + "export.graphics2d.";
/**
* The exporter key, as used in
* {@link GenericElementHandlerEnviroment#getElementHandler(JRGenericElementType, String)}.
*/
public static final String GRAPHICS2D_EXPORTER_KEY = JRPropertiesUtil.PROPERTY_PREFIX + "graphics2d";
/**
*
*/
protected PrintDrawVisitor drawVisitor;
private boolean whitePageBackground = true;
protected class ExporterContext extends BaseExporterContext implements JRGraphics2DExporterContext
{
}
/**
* @see #JRGraphics2DExporter(JasperReportsContext)
*/
public JRGraphics2DExporter() throws JRException
{
this(DefaultJasperReportsContext.getInstance());
}
/**
*
*/
public JRGraphics2DExporter(JasperReportsContext jasperReportsContext) throws JRException
{
super(jasperReportsContext);
JRGraphEnvInitializer.initializeGraphEnv();
exporterContext = new ExporterContext();
}
@Override
protected Class getConfigurationInterface()
{
return Graphics2DExporterConfiguration.class;
}
@Override
protected Class getItemConfigurationInterface()
{
return Graphics2DReportConfiguration.class;
}
@Override
@SuppressWarnings("deprecation")
protected void ensureOutput()
{
if (exporterOutput == null)
{
exporterOutput = new net.sf.jasperreports.export.parameters.ParametersGraphics2DExporterOutput(parameters);
}
}
@Override
public void exportReport() throws JRException
{
/* */
ensureJasperReportsContext();
ensureInput();
initExport();
ensureOutput();
Graphics2D grx = getExporterOutput().getGraphics2D();
try
{
exportReportToGraphics2D(grx);
}
finally
{
resetExportContext();
}
}
@Override
protected void initExport()
{
super.initExport();
}
@Override
protected void initReport()
{
super.initReport();
setOffset(false);
Graphics2DReportConfiguration configuration = getCurrentItemConfiguration();
Boolean isMinimizePrinterJobSize = configuration.isMinimizePrinterJobSize();
Boolean isIgnoreMissingFont = configuration.isIgnoreMissingFont();
boolean defaultIndentFirstLine =
propertiesUtil.getBooleanProperty(
jasperPrint,
JRPrintText.PROPERTY_AWT_INDENT_FIRST_LINE,
true
);
boolean defaultJustifyLastLine =
propertiesUtil.getBooleanProperty(
jasperPrint,
JRPrintText.PROPERTY_AWT_JUSTIFY_LAST_LINE,
false
);
drawVisitor =
new PrintDrawVisitor(
exporterContext,
getRenderersCache(),
isMinimizePrinterJobSize == null ? Boolean.TRUE : isMinimizePrinterJobSize,
isIgnoreMissingFont == null ? Boolean.FALSE : isIgnoreMissingFont,
defaultIndentFirstLine,
defaultJustifyLastLine
);
whitePageBackground = configuration.isWhitePageBackground();
}
/**
*
*/
protected RenderersCache getRenderersCache()
{
return new RenderersCache(getJasperReportsContext());
}
/**
*
*/
public void exportReportToGraphics2D(Graphics2D grx) throws JRException
{
grx.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//grx.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
grx.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
grx.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
setCurrentExporterInputItem(exporterInput.getItems().get(0));
ReportExportConfiguration configuration = getCurrentItemConfiguration();
AffineTransform atrans = new AffineTransform();
atrans.translate(
configuration.getOffsetX() == null ? 0 : configuration.getOffsetX(),
configuration.getOffsetY() == null ? 0 : configuration.getOffsetY()
);
float zoom = getZoom();
atrans.scale(zoom, zoom);
grx.transform(atrans);
List pages = jasperPrint.getPages();
if (pages != null)
{
PageRange pageRange = getPageRange();
int startPageIndex = (pageRange == null || pageRange.getStartPageIndex() == null) ? 0 : pageRange.getStartPageIndex();
Shape oldClipShape = grx.getClip();
PrintPageFormat pageFormat = jasperPrint.getPageFormat(startPageIndex);
grx.clip(new Rectangle(0, 0, pageFormat.getPageWidth(), pageFormat.getPageHeight()));
try
{
exportPage(grx, startPageIndex);
}
finally
{
grx.setClip(oldClipShape);
}
}
}
/**
*
*/
protected void exportPage(Graphics2D grx, int pageIndex) throws JRException
{
List pages = jasperPrint.getPages();
JRPrintPage page = pages.get(pageIndex);
PrintPageFormat pageFormat = jasperPrint.getPageFormat(pageIndex);
if (whitePageBackground)
{
grx.setColor(Color.white);
grx.fillRect(
0,
0,
pageFormat.getPageWidth(),
pageFormat.getPageHeight()
);
}
grx.setColor(Color.black);
grx.setStroke(new BasicStroke(1));
/* */
drawVisitor.getFrameDrawer().draw(grx, page.getElements(), getOffsetX(), getOffsetY());
JRExportProgressMonitor progressMonitor = getCurrentItemConfiguration().getProgressMonitor();
if (progressMonitor != null)
{
progressMonitor.afterPageExport();
}
}
@Override
public String getExporterKey()
{
return GRAPHICS2D_EXPORTER_KEY;
}
@Override
public String getExporterPropertiesPrefix()
{
return GRAPHICS2D_EXPORTER_PROPERTIES_PREFIX;
}
/**
*
*/
public PrintDrawVisitor getDrawVisitor()
{
return drawVisitor;
}
/**
* @deprecated Replaced by {@link #getDrawVisitor()}.
*/
public FrameDrawer getFrameDrawer()
{
return drawVisitor.getFrameDrawer();
}
private float getZoom()//FIXMEEXPORT
{
float zoom = DEFAULT_ZOOM;
Float zoomRatio = getCurrentItemConfiguration().getZoomRatio();
if (zoomRatio != null)
{
zoom = zoomRatio;
if (zoom <= 0)
{
throw
new JRRuntimeException(
EXCEPTION_MESSAGE_KEY_INVALID_ZOOM_RATIO,
new Object[]{zoom}
);
}
}
return zoom;
}
}