# HG changeset patch # User Ingo Weinzierl # Date 1301309307 0 # Node ID 956445dd601db70cb955598d8623b2ec7803da63 # Parent 4eddbb219866d72469e29d57b5279513b46c66b0 Added a helper class to export charts. flys-artifacts/trunk@1585 c6561f87-3c4e-4783-a992-168aeb5c3f6f diff -r 4eddbb219866 -r 956445dd601d flys-artifacts/ChangeLog --- a/flys-artifacts/ChangeLog Mon Mar 28 09:17:25 2011 +0000 +++ b/flys-artifacts/ChangeLog Mon Mar 28 10:48:27 2011 +0000 @@ -1,3 +1,10 @@ +2011-03-28 Ingo Weinzierl + + * src/main/java/de/intevation/flys/exports/ChartExportHelper.java: + New. A helper class to exports charts. + + * pom.xml: Added dependencies to iText, Batik and JFreeChart. + 2011-03-28 Sascha L. Teichmann * src/main/java/de/intevation/flys/artifacts/model/GaugesFactory.java: diff -r 4eddbb219866 -r 956445dd601d flys-artifacts/pom.xml --- a/flys-artifacts/pom.xml Mon Mar 28 09:17:25 2011 +0000 +++ b/flys-artifacts/pom.xml Mon Mar 28 10:48:27 2011 +0000 @@ -55,5 +55,25 @@ flys-backend 1.0-SNAPSHOT + + jfree + jfreechart + 1.0.13 + + + org.apache.xmlgraphics + batik-dom + 1.7 + + + org.apache.xmlgraphics + batik-svggen + 1.7 + + + com.lowagie + itext + 2.1.7 + diff -r 4eddbb219866 -r 956445dd601d flys-artifacts/src/main/java/de/intevation/flys/exports/ChartExportHelper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/ChartExportHelper.java Mon Mar 28 10:48:27 2011 +0000 @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2011 by Intevation GmbH + * + * This program is free software under the LGPL (>=v2.1) + * Read the file LGPL.txt coming with the software for details + * or visit http://www.gnu.org/licenses/ if it does not exist. + */ +package de.intevation.flys.exports; + +import com.lowagie.text.Document; +import com.lowagie.text.DocumentException; +import com.lowagie.text.PageSize; +import com.lowagie.text.Rectangle; + +import com.lowagie.text.pdf.PdfContentByte; +import com.lowagie.text.pdf.PdfTemplate; +import com.lowagie.text.pdf.PdfWriter; + +import java.awt.Graphics2D; +import java.awt.Transparency; + +import java.awt.geom.Rectangle2D.Double; + +import java.awt.geom.Rectangle2D; + +import java.awt.image.BufferedImage; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.UnsupportedEncodingException; + +import javax.imageio.ImageIO; + +import org.apache.batik.svggen.SVGGraphics2D; +import org.apache.batik.svggen.SVGGraphics2DIOException; + +import org.apache.log4j.Logger; + +import org.jfree.chart.JFreeChart; + +import de.intevation.artifacts.CallContext; + +import de.intevation.artifacts.common.utils.XMLUtils; + + +/** + * This class is a helper class which supports some methods to export charts + * into specific formats. + * + * @author Ingo Weinzierl + */ +public class ChartExportHelper { + + /** + * Constant field to define A4 as default page size. + */ + private static final String DEFAULT_PAGE_SIZE = "A4"; + + /** + * Constant field to define UTF-8 as default encoding. + */ + private static final String DEFAULT_ENCODING = "UTF-8"; + + /** + * Logger used for logging with log4j. + */ + private static Logger log = Logger.getLogger(ChartExportHelper.class); + + + /** + * A method to export a JFreeChart as image to an + * OutputStream with a given format, width and height. + * + * @param out OutputStream + * @param chart JFreeChart object to be exported. + * @param format Format (e.g. png, gif, jpg) + * @param width Width, the image used to be + * @param height Height, the image used to be + * + * @throws IOException if writing image to OutputStream failed. + */ + public static void exportImage( + OutputStream out, + JFreeChart chart, + String format, + int width, + int height + ) + throws IOException + { + log.info("export chart as png"); + + ImageIO.write( + chart.createBufferedImage( + width, height, Transparency.BITMASK, null + ), + format, + out + ); + } + + + /** + * A method to export a JFreeChart as SVG to an + * OutputStream. + * + * @param out OutputStream + * @param chart JFreeChart to be exported + * @param encoding Encoding, defaults to {@link #DEFAULT_ENCODING} if null + * @param width Width the svg used to be + * @param height Height the svg used to be + */ + public static void exportSVG( + OutputStream out, + JFreeChart chart, + String encoding, + int width, + int height + ) { + log.info("export chart as svg"); + + if (encoding == null) + encoding = DEFAULT_ENCODING; + + org.w3c.dom.Document document = XMLUtils.newDocument(); + SVGGraphics2D graphics = new SVGGraphics2D(document); + + chart.draw(graphics, new Rectangle2D.Double(0.0D, 0.0D,width,height)); + + try { + graphics.stream(new OutputStreamWriter(out, encoding)); + } + catch (SVGGraphics2DIOException svge) { + log.error("Error while writing svg export to output stream.", svge); + } + catch (UnsupportedEncodingException uee) { + log.error("Unsupported encoding: " + encoding, uee); + } + } + + + /** + * A method to export a JFreeChart as PDF to an + * OutputStream. + * + * @param out OutputStream + * @param chart JFreeChart + * @param pageFormat String to specify a page format, {@link + * #DEFAULT_PAGE_SIZE} is used if no pageFormat is given + * @param landscape If this is true, the pdf is delivered in landscape + * format + * @param marginLeft Space to left border + * @param marginRight Space to right border + * @param marginTop Space to upper border + * @param marginBottom Space to lower border + */ + public static void exportPDF( + OutputStream out, + JFreeChart chart, + String pageFormat, + float marginLeft, + float marginRight, + float marginTop, + float marginBottom, + CallContext context + ) { + log.info("export chart as pdf."); + + if (pageFormat == null) + pageFormat = DEFAULT_PAGE_SIZE; + + // max size of the chart + Rectangle page = PageSize.getRectangle(pageFormat); + float pageWidth = page.getWidth(); + float pageHeight = page.getHeight(); + + // the chart width + int chartWidth = (Integer) context.getContextValue("chart.width"); + int chartHeight = (Integer) context.getContextValue("chart.height"); + + boolean landscape = chartWidth > chartHeight ? true : false; + + float width = 0; + float height = 0; + if (landscape) { + width = pageHeight; + height = pageWidth; + } + else { + width = pageWidth; + height = pageHeight; + } + + float spaceX = width - marginLeft - marginRight; + if (chartWidth > spaceX) { + log.warn("Width of the chart is too big for pdf -> resize it now."); + double ratio = ((double)spaceX) / chartWidth; + chartWidth *= ratio; + chartHeight *= ratio; + log.debug("Resized chart to " + chartWidth + "x" + chartHeight); + } + + float spaceY = height - marginTop - marginBottom; + if (chartHeight > spaceY) { + log.warn("Height of the chart is too big for pdf -> resize it now."); + double ratio = ((double)spaceY) / chartHeight; + chartWidth *= ratio; + chartHeight *= ratio; + log.debug("Resized chart to " + chartWidth + "x" + chartHeight); + } + + Document document = null; + if (landscape) { + document = new Document(page.rotate()); + log.debug("Create landscape pdf."); + } + else + document = new Document(page); + + try { + PdfWriter writer = PdfWriter.getInstance(document, out); + + document.addSubject(chart.getTitle().getText()); + document.addCreationDate(); + document.open(); + + PdfContentByte content = writer.getDirectContent(); + + PdfTemplate template = content.createTemplate(width, height); + Graphics2D graphics = template.createGraphics(width, height); + + double[] origin = getCenteredAnchor( + marginLeft, marginRight, marginBottom, marginTop, + width, height, + chartWidth, chartHeight); + + Rectangle2D area = new Rectangle2D.Double( + origin[0], origin[1], chartWidth, chartHeight); + + chart.draw(graphics, area); + graphics.dispose(); + content.addTemplate(template, 0f, 0f); + } + catch (DocumentException de) { + log.error("Error while exporting chart to pdf.", de); + } + finally { + document.close(); + } + } + + + /** + * This method returns the anchor of the chart so that the chart is centered + * according to the given parameters. + * + * @param mLeft Left margin + * @param mRight Right margin + * @param mBottom Bottom margin + * @param mTop Top margin + * @param width The complete width of the drawing area. + * @param height The complete height of the drawing area. + * @param chartWidth The width of the chart. + * @param chartHeight The height of the chart. + * + * @return an array that contains the anchor for a chart with the given + * parameters. The first value is the x point, the second value is the y + * point. + */ + public static double[] getCenteredAnchor( + double mLeft, double mRight, double mBottom, double mTop, + double width, double height, + double chartWidth, double chartHeight + ) { + if (log.isDebugEnabled()) { + log.debug("Calculate centered origin..."); + log.debug("-> PDF width : " + width); + log.debug("-> PDF height : " + height); + log.debug("-> Chart width : " + chartWidth); + log.debug("-> Chart height : " + chartHeight); + log.debug("-> margin left : " + mLeft); + log.debug("-> margin right : " + mRight); + log.debug("-> margin bottom: " + mBottom); + log.debug("-> margin top : " + mTop); + } + + double[] origin = new double[2]; + + double centerX = width / 2; + double centerY = height / 2; + + origin[0] = centerX - chartWidth / 2; + origin[1] = centerY - chartHeight / 2; + + origin[0] = origin[0] >= mLeft ? origin[0] : mLeft; + origin[1] = origin[1] >= mTop ? origin[1] : mTop; + + if (log.isDebugEnabled()) { + log.debug("==> centered left origin: " + origin[0]); + log.debug("==> centered top origin: " + origin[1]); + } + + return origin; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :