diff -r 1612dbcec451 -r 639991d0808a java/cewolf-1.0/src/main/java/de/laures/cewolf/util/Renderer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java/cewolf-1.0/src/main/java/de/laures/cewolf/util/Renderer.java Sat Feb 28 21:31:02 2009 +0100 @@ -0,0 +1,278 @@ +/* ================================================================ + * Cewolf : Chart enabling Web Objects Framework + * ================================================================ + * + * Project Info: http://cewolf.sourceforge.net + * Project Lead: Guido Laures (guido@laures.de); + * + * (C) Copyright 2002, by Guido Laures + * + * 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. + */ + +package de.laures.cewolf.util; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.util.Iterator; +import java.util.List; + +import org.apache.batik.dom.GenericDOMImplementation; +import org.apache.batik.svggen.SVGGeneratorContext; +import org.apache.batik.svggen.SVGGraphics2D; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jfree.chart.ChartRenderingInfo; +import org.jfree.chart.ChartUtilities; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.block.RectangleConstraint; +import org.jfree.chart.entity.StandardEntityCollection; +import org.jfree.chart.title.LegendTitle; +import org.jfree.ui.RectangleEdge; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; + +import com.sun.image.codec.jpeg.JPEGCodec; +import com.sun.image.codec.jpeg.JPEGEncodeParam; +import com.sun.image.codec.jpeg.JPEGImageEncoder; + +import de.laures.cewolf.CewolfException; +import de.laures.cewolf.ChartImage; +import de.laures.cewolf.ChartRenderingException; +import de.laures.cewolf.ConfigurationException; +import de.laures.cewolf.WebConstants; + +/** + * Renderer for ChartImageDefinitions. + * + * @author glaures + * @author tbardzil + * @see de.laures.cewolf.ChartImage + */ +public class Renderer implements WebConstants { + + private final static Log log = LogFactory.getLog(Renderer.class); + + /** Creates a new instance of Renderer */ + private Renderer() { + }; + + /** + * Renders a chart image + * + * @param cd the chart to render + * @return the rendered image + * @throws CewolfException + */ + public static RenderedImage render(ChartImage cd, Object chart) throws CewolfException { + log.debug("rendering " + cd); + switch (cd.getType()) { + case ChartImage.IMG_TYPE_CHART : + return renderChart(cd, chart); + case ChartImage.IMG_TYPE_LEGEND : + return renderLegend(cd, chart); + default : + throw new ConfigurationException(cd.getType() + " is not a supported image type"); + } + } + + /** + * Renders a chart + * @param cd the chart image to be rendered + * @return the rendered image + * @throws CewolfException + */ + private static RenderedImage renderChart(ChartImage cd, Object chart) throws CewolfException { + try { + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + final ChartRenderingInfo info = new ChartRenderingInfo(new StandardEntityCollection()); + final String mimeType = cd.getMimeType(); + if (MIME_PNG.equals(mimeType)) { + handlePNG(baos, (JFreeChart)chart, cd.getWidth(), cd.getHeight(), info); + } else if (MIME_JPEG.equals(mimeType)) { + handleJPEG(baos, (JFreeChart)chart, cd.getWidth(), cd.getHeight(), info); + } else if (MIME_SVG.equals(mimeType)) { + handleSVG(baos, (JFreeChart)chart, cd.getWidth(), cd.getHeight()); + } else { + throw new RenderingException("Mime type " + mimeType + " is unsupported."); + } + baos.close(); + return new RenderedImage(baos.toByteArray(), mimeType, info); + } catch (IOException ioe) { + log.error(ioe); + throw new ChartRenderingException(ioe.getMessage(),ioe); + } + } + + /** + * Handles rendering a chart as a PNG. Currently this method is synchronized + * because of concurrency issues with JFreeChart. + * + * @param baos + * @param chart + * @param width + * @param height + * @param info + * @throws IOException + */ + private static synchronized void handlePNG( + ByteArrayOutputStream baos, + JFreeChart chart, + int width, + int height, + ChartRenderingInfo info) + throws IOException { + ChartUtilities.writeChartAsPNG(baos, chart, width, height, info); + } + + /** + * Handles rendering a chart as a JPEG. Currently this method is synchronized + * because of concurrency issues with JFreeChart. + * + * @param baos + * @param chart + * @param width + * @param height + * @param info + * @throws IOException + */ + private static synchronized void handleJPEG( + ByteArrayOutputStream baos, + JFreeChart chart, + int width, + int height, + ChartRenderingInfo info) + throws IOException { + ChartUtilities.writeChartAsJPEG(baos, chart, width, height, info); + } + + /** + * Handles rendering a chart as a SVG. Currently this method is synchronized + * because of concurrency issues with JFreeChart. + * + * @param baos + * @param chart + * @param width + * @param height + * @throws IOException + */ + private static synchronized void handleSVG(ByteArrayOutputStream baos, JFreeChart chart, int width, int height) + throws IOException { + OutputStreamWriter writer = new OutputStreamWriter(baos, "UTF-8"); + DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation(); + Document document = domImpl.createDocument("cewolf-svg", "svg", null); + SVGGeneratorContext ctx = SVGGeneratorContext.createDefault(document); + ctx.setComment("Generated by Cewolf using JFreeChart and Apache Batik SVG Generator"); + SVGGraphics2D svgGenerator = new SVGGraphics2D(ctx, false); + svgGenerator.setSVGCanvasSize(new Dimension(width, height)); + chart.draw(svgGenerator, new Rectangle2D.Double(0, 0, width, height), null); + svgGenerator.stream(writer, false); + writer.close(); + } + + //gets first legend in the list + public static LegendTitle getLegend(JFreeChart chart) + { + //i need to find the legend now. + LegendTitle legend = null; + List subTitles = chart.getSubtitles(); + Iterator iter = subTitles.iterator(); + while (iter.hasNext()) + { + Object o = iter.next(); + if (o instanceof LegendTitle) + { + legend = (LegendTitle) o; + break; + } + } + return legend; + } + + //removes first legend in the list + public static void removeLegend(JFreeChart chart) + { + List subTitles = chart.getSubtitles(); + Iterator iter = subTitles.iterator(); + while (iter.hasNext()) + { + Object o = iter.next(); + if (o instanceof LegendTitle) + { + iter.remove(); + break; + } + } + } + + /** + * Renders a legend + * @param cd the chart iamge to be rendred + * @return the rendered image + * @throws CewolfException + */ + private static RenderedImage renderLegend(ChartImage cd, Object c) throws CewolfException { + try { + JFreeChart chart = (JFreeChart) c; + final int width = cd.getWidth(); + final int height = cd.getHeight(); + LegendTitle legend = getLegend(chart); + boolean haslegend = true; + + // with JFreeChart v0.9.20, the only way to get a valid legend, + // is either to retrieve it from the chart or to assign a new + // one to the chart. In the case where the chart has no legend, + // a new one must be assigned, but just for rendering. After, we + // have to reset the legend to null in the chart. + if (null == legend) { + haslegend = false; + legend = new LegendTitle(chart.getPlot()); + } + legend.setPosition(RectangleEdge.BOTTOM); + BufferedImage bimage = ImageHelper.createImage(width, height); + Graphics2D g = bimage.createGraphics(); + g.setColor(Color.white); + g.fillRect(0, 0, width, height); + legend.arrange(g,new RectangleConstraint(width,height)); + legend.draw(g, new Rectangle(width, height)); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); + JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bimage); + param.setQuality(1.0f, true); + encoder.encode(bimage, param); + out.close(); + + // if the chart had no legend, reset it to null in order to give back the + // chart in the state we received it. + if (!haslegend) { + removeLegend(chart); + } + + return new RenderedImage( + out.toByteArray(), + "image/jpeg", + new ChartRenderingInfo(new StandardEntityCollection())); + } catch (IOException ioex) { + log.error(ioex); + throw new ChartRenderingException(ioex.getMessage(), ioex); + } + } + +}