Mercurial > dive4elements > river
comparison flys-artifacts/src/main/java/de/intevation/flys/exports/ChartExportHelper.java @ 152:956445dd601d
Added a helper class to export charts.
flys-artifacts/trunk@1585 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Ingo Weinzierl <ingo.weinzierl@intevation.de> |
---|---|
date | Mon, 28 Mar 2011 10:48:27 +0000 |
parents | |
children | 084995dd1c9c |
comparison
equal
deleted
inserted
replaced
151:4eddbb219866 | 152:956445dd601d |
---|---|
1 /* | |
2 * Copyright (c) 2011 by Intevation GmbH | |
3 * | |
4 * This program is free software under the LGPL (>=v2.1) | |
5 * Read the file LGPL.txt coming with the software for details | |
6 * or visit http://www.gnu.org/licenses/ if it does not exist. | |
7 */ | |
8 package de.intevation.flys.exports; | |
9 | |
10 import com.lowagie.text.Document; | |
11 import com.lowagie.text.DocumentException; | |
12 import com.lowagie.text.PageSize; | |
13 import com.lowagie.text.Rectangle; | |
14 | |
15 import com.lowagie.text.pdf.PdfContentByte; | |
16 import com.lowagie.text.pdf.PdfTemplate; | |
17 import com.lowagie.text.pdf.PdfWriter; | |
18 | |
19 import java.awt.Graphics2D; | |
20 import java.awt.Transparency; | |
21 | |
22 import java.awt.geom.Rectangle2D.Double; | |
23 | |
24 import java.awt.geom.Rectangle2D; | |
25 | |
26 import java.awt.image.BufferedImage; | |
27 | |
28 import java.io.IOException; | |
29 import java.io.OutputStream; | |
30 import java.io.OutputStreamWriter; | |
31 import java.io.UnsupportedEncodingException; | |
32 | |
33 import javax.imageio.ImageIO; | |
34 | |
35 import org.apache.batik.svggen.SVGGraphics2D; | |
36 import org.apache.batik.svggen.SVGGraphics2DIOException; | |
37 | |
38 import org.apache.log4j.Logger; | |
39 | |
40 import org.jfree.chart.JFreeChart; | |
41 | |
42 import de.intevation.artifacts.CallContext; | |
43 | |
44 import de.intevation.artifacts.common.utils.XMLUtils; | |
45 | |
46 | |
47 /** | |
48 * This class is a helper class which supports some methods to export charts | |
49 * into specific formats. | |
50 * | |
51 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> | |
52 */ | |
53 public class ChartExportHelper { | |
54 | |
55 /** | |
56 * Constant field to define A4 as default page size. | |
57 */ | |
58 private static final String DEFAULT_PAGE_SIZE = "A4"; | |
59 | |
60 /** | |
61 * Constant field to define UTF-8 as default encoding. | |
62 */ | |
63 private static final String DEFAULT_ENCODING = "UTF-8"; | |
64 | |
65 /** | |
66 * Logger used for logging with log4j. | |
67 */ | |
68 private static Logger log = Logger.getLogger(ChartExportHelper.class); | |
69 | |
70 | |
71 /** | |
72 * A method to export a <code>JFreeChart</code> as image to an | |
73 * <code>OutputStream</code> with a given format, width and height. | |
74 * | |
75 * @param out OutputStream | |
76 * @param chart JFreeChart object to be exported. | |
77 * @param format Format (e.g. png, gif, jpg) | |
78 * @param width Width, the image used to be | |
79 * @param height Height, the image used to be | |
80 * | |
81 * @throws IOException if writing image to OutputStream failed. | |
82 */ | |
83 public static void exportImage( | |
84 OutputStream out, | |
85 JFreeChart chart, | |
86 String format, | |
87 int width, | |
88 int height | |
89 ) | |
90 throws IOException | |
91 { | |
92 log.info("export chart as png"); | |
93 | |
94 ImageIO.write( | |
95 chart.createBufferedImage( | |
96 width, height, Transparency.BITMASK, null | |
97 ), | |
98 format, | |
99 out | |
100 ); | |
101 } | |
102 | |
103 | |
104 /** | |
105 * A method to export a <code>JFreeChart</code> as SVG to an | |
106 * <code>OutputStream</code>. | |
107 * | |
108 * @param out OutputStream | |
109 * @param chart JFreeChart to be exported | |
110 * @param encoding Encoding, defaults to {@link #DEFAULT_ENCODING} if null | |
111 * @param width Width the svg used to be | |
112 * @param height Height the svg used to be | |
113 */ | |
114 public static void exportSVG( | |
115 OutputStream out, | |
116 JFreeChart chart, | |
117 String encoding, | |
118 int width, | |
119 int height | |
120 ) { | |
121 log.info("export chart as svg"); | |
122 | |
123 if (encoding == null) | |
124 encoding = DEFAULT_ENCODING; | |
125 | |
126 org.w3c.dom.Document document = XMLUtils.newDocument(); | |
127 SVGGraphics2D graphics = new SVGGraphics2D(document); | |
128 | |
129 chart.draw(graphics, new Rectangle2D.Double(0.0D, 0.0D,width,height)); | |
130 | |
131 try { | |
132 graphics.stream(new OutputStreamWriter(out, encoding)); | |
133 } | |
134 catch (SVGGraphics2DIOException svge) { | |
135 log.error("Error while writing svg export to output stream.", svge); | |
136 } | |
137 catch (UnsupportedEncodingException uee) { | |
138 log.error("Unsupported encoding: " + encoding, uee); | |
139 } | |
140 } | |
141 | |
142 | |
143 /** | |
144 * A method to export a <code>JFreeChart</code> as PDF to an | |
145 * <code>OutputStream</code>. | |
146 * | |
147 * @param out OutputStream | |
148 * @param chart JFreeChart | |
149 * @param pageFormat String to specify a page format, {@link | |
150 * #DEFAULT_PAGE_SIZE} is used if no pageFormat is given | |
151 * @param landscape If this is true, the pdf is delivered in landscape | |
152 * format | |
153 * @param marginLeft Space to left border | |
154 * @param marginRight Space to right border | |
155 * @param marginTop Space to upper border | |
156 * @param marginBottom Space to lower border | |
157 */ | |
158 public static void exportPDF( | |
159 OutputStream out, | |
160 JFreeChart chart, | |
161 String pageFormat, | |
162 float marginLeft, | |
163 float marginRight, | |
164 float marginTop, | |
165 float marginBottom, | |
166 CallContext context | |
167 ) { | |
168 log.info("export chart as pdf."); | |
169 | |
170 if (pageFormat == null) | |
171 pageFormat = DEFAULT_PAGE_SIZE; | |
172 | |
173 // max size of the chart | |
174 Rectangle page = PageSize.getRectangle(pageFormat); | |
175 float pageWidth = page.getWidth(); | |
176 float pageHeight = page.getHeight(); | |
177 | |
178 // the chart width | |
179 int chartWidth = (Integer) context.getContextValue("chart.width"); | |
180 int chartHeight = (Integer) context.getContextValue("chart.height"); | |
181 | |
182 boolean landscape = chartWidth > chartHeight ? true : false; | |
183 | |
184 float width = 0; | |
185 float height = 0; | |
186 if (landscape) { | |
187 width = pageHeight; | |
188 height = pageWidth; | |
189 } | |
190 else { | |
191 width = pageWidth; | |
192 height = pageHeight; | |
193 } | |
194 | |
195 float spaceX = width - marginLeft - marginRight; | |
196 if (chartWidth > spaceX) { | |
197 log.warn("Width of the chart is too big for pdf -> resize it now."); | |
198 double ratio = ((double)spaceX) / chartWidth; | |
199 chartWidth *= ratio; | |
200 chartHeight *= ratio; | |
201 log.debug("Resized chart to " + chartWidth + "x" + chartHeight); | |
202 } | |
203 | |
204 float spaceY = height - marginTop - marginBottom; | |
205 if (chartHeight > spaceY) { | |
206 log.warn("Height of the chart is too big for pdf -> resize it now."); | |
207 double ratio = ((double)spaceY) / chartHeight; | |
208 chartWidth *= ratio; | |
209 chartHeight *= ratio; | |
210 log.debug("Resized chart to " + chartWidth + "x" + chartHeight); | |
211 } | |
212 | |
213 Document document = null; | |
214 if (landscape) { | |
215 document = new Document(page.rotate()); | |
216 log.debug("Create landscape pdf."); | |
217 } | |
218 else | |
219 document = new Document(page); | |
220 | |
221 try { | |
222 PdfWriter writer = PdfWriter.getInstance(document, out); | |
223 | |
224 document.addSubject(chart.getTitle().getText()); | |
225 document.addCreationDate(); | |
226 document.open(); | |
227 | |
228 PdfContentByte content = writer.getDirectContent(); | |
229 | |
230 PdfTemplate template = content.createTemplate(width, height); | |
231 Graphics2D graphics = template.createGraphics(width, height); | |
232 | |
233 double[] origin = getCenteredAnchor( | |
234 marginLeft, marginRight, marginBottom, marginTop, | |
235 width, height, | |
236 chartWidth, chartHeight); | |
237 | |
238 Rectangle2D area = new Rectangle2D.Double( | |
239 origin[0], origin[1], chartWidth, chartHeight); | |
240 | |
241 chart.draw(graphics, area); | |
242 graphics.dispose(); | |
243 content.addTemplate(template, 0f, 0f); | |
244 } | |
245 catch (DocumentException de) { | |
246 log.error("Error while exporting chart to pdf.", de); | |
247 } | |
248 finally { | |
249 document.close(); | |
250 } | |
251 } | |
252 | |
253 | |
254 /** | |
255 * This method returns the anchor of the chart so that the chart is centered | |
256 * according to the given parameters. | |
257 * | |
258 * @param mLeft Left margin | |
259 * @param mRight Right margin | |
260 * @param mBottom Bottom margin | |
261 * @param mTop Top margin | |
262 * @param width The complete width of the drawing area. | |
263 * @param height The complete height of the drawing area. | |
264 * @param chartWidth The width of the chart. | |
265 * @param chartHeight The height of the chart. | |
266 * | |
267 * @return an array that contains the anchor for a chart with the given | |
268 * parameters. The first value is the x point, the second value is the y | |
269 * point. | |
270 */ | |
271 public static double[] getCenteredAnchor( | |
272 double mLeft, double mRight, double mBottom, double mTop, | |
273 double width, double height, | |
274 double chartWidth, double chartHeight | |
275 ) { | |
276 if (log.isDebugEnabled()) { | |
277 log.debug("Calculate centered origin..."); | |
278 log.debug("-> PDF width : " + width); | |
279 log.debug("-> PDF height : " + height); | |
280 log.debug("-> Chart width : " + chartWidth); | |
281 log.debug("-> Chart height : " + chartHeight); | |
282 log.debug("-> margin left : " + mLeft); | |
283 log.debug("-> margin right : " + mRight); | |
284 log.debug("-> margin bottom: " + mBottom); | |
285 log.debug("-> margin top : " + mTop); | |
286 } | |
287 | |
288 double[] origin = new double[2]; | |
289 | |
290 double centerX = width / 2; | |
291 double centerY = height / 2; | |
292 | |
293 origin[0] = centerX - chartWidth / 2; | |
294 origin[1] = centerY - chartHeight / 2; | |
295 | |
296 origin[0] = origin[0] >= mLeft ? origin[0] : mLeft; | |
297 origin[1] = origin[1] >= mTop ? origin[1] : mTop; | |
298 | |
299 if (log.isDebugEnabled()) { | |
300 log.debug("==> centered left origin: " + origin[0]); | |
301 log.debug("==> centered top origin: " + origin[1]); | |
302 } | |
303 | |
304 return origin; | |
305 } | |
306 } | |
307 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : |