1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/java/cewolf-1.0/src/main/java/de/laures/cewolf/util/Renderer.java Sat Feb 28 21:31:02 2009 +0100
1.3 @@ -0,0 +1,278 @@
1.4 +/* ================================================================
1.5 + * Cewolf : Chart enabling Web Objects Framework
1.6 + * ================================================================
1.7 + *
1.8 + * Project Info: http://cewolf.sourceforge.net
1.9 + * Project Lead: Guido Laures (guido@laures.de);
1.10 + *
1.11 + * (C) Copyright 2002, by Guido Laures
1.12 + *
1.13 + * This library is free software; you can redistribute it and/or modify it under the terms
1.14 + * of the GNU Lesser General Public License as published by the Free Software Foundation;
1.15 + * either version 2.1 of the License, or (at your option) any later version.
1.16 + *
1.17 + * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
1.18 + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1.19 + * See the GNU Lesser General Public License for more details.
1.20 + *
1.21 + * You should have received a copy of the GNU Lesser General Public License along with this
1.22 + * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
1.23 + * Boston, MA 02111-1307, USA.
1.24 + */
1.25 +
1.26 +package de.laures.cewolf.util;
1.27 +
1.28 +import java.awt.Color;
1.29 +import java.awt.Dimension;
1.30 +import java.awt.Graphics2D;
1.31 +import java.awt.Rectangle;
1.32 +import java.awt.geom.Rectangle2D;
1.33 +import java.awt.image.BufferedImage;
1.34 +import java.io.ByteArrayOutputStream;
1.35 +import java.io.IOException;
1.36 +import java.io.OutputStreamWriter;
1.37 +import java.util.Iterator;
1.38 +import java.util.List;
1.39 +
1.40 +import org.apache.batik.dom.GenericDOMImplementation;
1.41 +import org.apache.batik.svggen.SVGGeneratorContext;
1.42 +import org.apache.batik.svggen.SVGGraphics2D;
1.43 +import org.apache.commons.logging.Log;
1.44 +import org.apache.commons.logging.LogFactory;
1.45 +import org.jfree.chart.ChartRenderingInfo;
1.46 +import org.jfree.chart.ChartUtilities;
1.47 +import org.jfree.chart.JFreeChart;
1.48 +import org.jfree.chart.block.RectangleConstraint;
1.49 +import org.jfree.chart.entity.StandardEntityCollection;
1.50 +import org.jfree.chart.title.LegendTitle;
1.51 +import org.jfree.ui.RectangleEdge;
1.52 +import org.w3c.dom.DOMImplementation;
1.53 +import org.w3c.dom.Document;
1.54 +
1.55 +import com.sun.image.codec.jpeg.JPEGCodec;
1.56 +import com.sun.image.codec.jpeg.JPEGEncodeParam;
1.57 +import com.sun.image.codec.jpeg.JPEGImageEncoder;
1.58 +
1.59 +import de.laures.cewolf.CewolfException;
1.60 +import de.laures.cewolf.ChartImage;
1.61 +import de.laures.cewolf.ChartRenderingException;
1.62 +import de.laures.cewolf.ConfigurationException;
1.63 +import de.laures.cewolf.WebConstants;
1.64 +
1.65 +/**
1.66 + * Renderer for ChartImageDefinitions.
1.67 + *
1.68 + * @author glaures
1.69 + * @author tbardzil
1.70 + * @see de.laures.cewolf.ChartImage
1.71 + */
1.72 +public class Renderer implements WebConstants {
1.73 +
1.74 + private final static Log log = LogFactory.getLog(Renderer.class);
1.75 +
1.76 + /** Creates a new instance of Renderer */
1.77 + private Renderer() {
1.78 + };
1.79 +
1.80 + /**
1.81 + * Renders a chart image
1.82 + *
1.83 + * @param cd the chart to render
1.84 + * @return the rendered image
1.85 + * @throws CewolfException
1.86 + */
1.87 + public static RenderedImage render(ChartImage cd, Object chart) throws CewolfException {
1.88 + log.debug("rendering " + cd);
1.89 + switch (cd.getType()) {
1.90 + case ChartImage.IMG_TYPE_CHART :
1.91 + return renderChart(cd, chart);
1.92 + case ChartImage.IMG_TYPE_LEGEND :
1.93 + return renderLegend(cd, chart);
1.94 + default :
1.95 + throw new ConfigurationException(cd.getType() + " is not a supported image type");
1.96 + }
1.97 + }
1.98 +
1.99 + /**
1.100 + * Renders a chart
1.101 + * @param cd the chart image to be rendered
1.102 + * @return the rendered image
1.103 + * @throws CewolfException
1.104 + */
1.105 + private static RenderedImage renderChart(ChartImage cd, Object chart) throws CewolfException {
1.106 + try {
1.107 + final ByteArrayOutputStream baos = new ByteArrayOutputStream();
1.108 + final ChartRenderingInfo info = new ChartRenderingInfo(new StandardEntityCollection());
1.109 + final String mimeType = cd.getMimeType();
1.110 + if (MIME_PNG.equals(mimeType)) {
1.111 + handlePNG(baos, (JFreeChart)chart, cd.getWidth(), cd.getHeight(), info);
1.112 + } else if (MIME_JPEG.equals(mimeType)) {
1.113 + handleJPEG(baos, (JFreeChart)chart, cd.getWidth(), cd.getHeight(), info);
1.114 + } else if (MIME_SVG.equals(mimeType)) {
1.115 + handleSVG(baos, (JFreeChart)chart, cd.getWidth(), cd.getHeight());
1.116 + } else {
1.117 + throw new RenderingException("Mime type " + mimeType + " is unsupported.");
1.118 + }
1.119 + baos.close();
1.120 + return new RenderedImage(baos.toByteArray(), mimeType, info);
1.121 + } catch (IOException ioe) {
1.122 + log.error(ioe);
1.123 + throw new ChartRenderingException(ioe.getMessage(),ioe);
1.124 + }
1.125 + }
1.126 +
1.127 + /**
1.128 + * Handles rendering a chart as a PNG. Currently this method is synchronized
1.129 + * because of concurrency issues with JFreeChart.
1.130 + *
1.131 + * @param baos
1.132 + * @param chart
1.133 + * @param width
1.134 + * @param height
1.135 + * @param info
1.136 + * @throws IOException
1.137 + */
1.138 + private static synchronized void handlePNG(
1.139 + ByteArrayOutputStream baos,
1.140 + JFreeChart chart,
1.141 + int width,
1.142 + int height,
1.143 + ChartRenderingInfo info)
1.144 + throws IOException {
1.145 + ChartUtilities.writeChartAsPNG(baos, chart, width, height, info);
1.146 + }
1.147 +
1.148 + /**
1.149 + * Handles rendering a chart as a JPEG. Currently this method is synchronized
1.150 + * because of concurrency issues with JFreeChart.
1.151 + *
1.152 + * @param baos
1.153 + * @param chart
1.154 + * @param width
1.155 + * @param height
1.156 + * @param info
1.157 + * @throws IOException
1.158 + */
1.159 + private static synchronized void handleJPEG(
1.160 + ByteArrayOutputStream baos,
1.161 + JFreeChart chart,
1.162 + int width,
1.163 + int height,
1.164 + ChartRenderingInfo info)
1.165 + throws IOException {
1.166 + ChartUtilities.writeChartAsJPEG(baos, chart, width, height, info);
1.167 + }
1.168 +
1.169 + /**
1.170 + * Handles rendering a chart as a SVG. Currently this method is synchronized
1.171 + * because of concurrency issues with JFreeChart.
1.172 + *
1.173 + * @param baos
1.174 + * @param chart
1.175 + * @param width
1.176 + * @param height
1.177 + * @throws IOException
1.178 + */
1.179 + private static synchronized void handleSVG(ByteArrayOutputStream baos, JFreeChart chart, int width, int height)
1.180 + throws IOException {
1.181 + OutputStreamWriter writer = new OutputStreamWriter(baos, "UTF-8");
1.182 + DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
1.183 + Document document = domImpl.createDocument("cewolf-svg", "svg", null);
1.184 + SVGGeneratorContext ctx = SVGGeneratorContext.createDefault(document);
1.185 + ctx.setComment("Generated by Cewolf using JFreeChart and Apache Batik SVG Generator");
1.186 + SVGGraphics2D svgGenerator = new SVGGraphics2D(ctx, false);
1.187 + svgGenerator.setSVGCanvasSize(new Dimension(width, height));
1.188 + chart.draw(svgGenerator, new Rectangle2D.Double(0, 0, width, height), null);
1.189 + svgGenerator.stream(writer, false);
1.190 + writer.close();
1.191 + }
1.192 +
1.193 + //gets first legend in the list
1.194 + public static LegendTitle getLegend(JFreeChart chart)
1.195 + {
1.196 + //i need to find the legend now.
1.197 + LegendTitle legend = null;
1.198 + List subTitles = chart.getSubtitles();
1.199 + Iterator iter = subTitles.iterator();
1.200 + while (iter.hasNext())
1.201 + {
1.202 + Object o = iter.next();
1.203 + if (o instanceof LegendTitle)
1.204 + {
1.205 + legend = (LegendTitle) o;
1.206 + break;
1.207 + }
1.208 + }
1.209 + return legend;
1.210 + }
1.211 +
1.212 + //removes first legend in the list
1.213 + public static void removeLegend(JFreeChart chart)
1.214 + {
1.215 + List subTitles = chart.getSubtitles();
1.216 + Iterator iter = subTitles.iterator();
1.217 + while (iter.hasNext())
1.218 + {
1.219 + Object o = iter.next();
1.220 + if (o instanceof LegendTitle)
1.221 + {
1.222 + iter.remove();
1.223 + break;
1.224 + }
1.225 + }
1.226 + }
1.227 +
1.228 + /**
1.229 + * Renders a legend
1.230 + * @param cd the chart iamge to be rendred
1.231 + * @return the rendered image
1.232 + * @throws CewolfException
1.233 + */
1.234 + private static RenderedImage renderLegend(ChartImage cd, Object c) throws CewolfException {
1.235 + try {
1.236 + JFreeChart chart = (JFreeChart) c;
1.237 + final int width = cd.getWidth();
1.238 + final int height = cd.getHeight();
1.239 + LegendTitle legend = getLegend(chart);
1.240 + boolean haslegend = true;
1.241 +
1.242 + // with JFreeChart v0.9.20, the only way to get a valid legend,
1.243 + // is either to retrieve it from the chart or to assign a new
1.244 + // one to the chart. In the case where the chart has no legend,
1.245 + // a new one must be assigned, but just for rendering. After, we
1.246 + // have to reset the legend to null in the chart.
1.247 + if (null == legend) {
1.248 + haslegend = false;
1.249 + legend = new LegendTitle(chart.getPlot());
1.250 + }
1.251 + legend.setPosition(RectangleEdge.BOTTOM);
1.252 + BufferedImage bimage = ImageHelper.createImage(width, height);
1.253 + Graphics2D g = bimage.createGraphics();
1.254 + g.setColor(Color.white);
1.255 + g.fillRect(0, 0, width, height);
1.256 + legend.arrange(g,new RectangleConstraint(width,height));
1.257 + legend.draw(g, new Rectangle(width, height));
1.258 + ByteArrayOutputStream out = new ByteArrayOutputStream();
1.259 + JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
1.260 + JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bimage);
1.261 + param.setQuality(1.0f, true);
1.262 + encoder.encode(bimage, param);
1.263 + out.close();
1.264 +
1.265 + // if the chart had no legend, reset it to null in order to give back the
1.266 + // chart in the state we received it.
1.267 + if (!haslegend) {
1.268 + removeLegend(chart);
1.269 + }
1.270 +
1.271 + return new RenderedImage(
1.272 + out.toByteArray(),
1.273 + "image/jpeg",
1.274 + new ChartRenderingInfo(new StandardEntityCollection()));
1.275 + } catch (IOException ioex) {
1.276 + log.error(ioex);
1.277 + throw new ChartRenderingException(ioex.getMessage(), ioex);
1.278 + }
1.279 + }
1.280 +
1.281 +}