java/cewolf-1.0/src/main/java/de/laures/cewolf/util/Renderer.java
author František Kučera <franta-hg@frantovo.cz>
Sat, 28 Feb 2009 21:31:02 +0100
changeset 1 639991d0808a
permissions -rw-r--r--
Rozbalená knihovna verze 1.0
     1 /* ================================================================
     2  * Cewolf : Chart enabling Web Objects Framework
     3  * ================================================================
     4  *
     5  * Project Info:  http://cewolf.sourceforge.net
     6  * Project Lead:  Guido Laures (guido@laures.de);
     7  *
     8  * (C) Copyright 2002, by Guido Laures
     9  *
    10  * This library is free software; you can redistribute it and/or modify it under the terms
    11  * of the GNU Lesser General Public License as published by the Free Software Foundation;
    12  * either version 2.1 of the License, or (at your option) any later version.
    13  *
    14  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
    15  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    16  * See the GNU Lesser General Public License for more details.
    17  *
    18  * You should have received a copy of the GNU Lesser General Public License along with this
    19  * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
    20  * Boston, MA 02111-1307, USA.
    21  */
    22 
    23 package de.laures.cewolf.util;
    24 
    25 import java.awt.Color;
    26 import java.awt.Dimension;
    27 import java.awt.Graphics2D;
    28 import java.awt.Rectangle;
    29 import java.awt.geom.Rectangle2D;
    30 import java.awt.image.BufferedImage;
    31 import java.io.ByteArrayOutputStream;
    32 import java.io.IOException;
    33 import java.io.OutputStreamWriter;
    34 import java.util.Iterator;
    35 import java.util.List;
    36 
    37 import org.apache.batik.dom.GenericDOMImplementation;
    38 import org.apache.batik.svggen.SVGGeneratorContext;
    39 import org.apache.batik.svggen.SVGGraphics2D;
    40 import org.apache.commons.logging.Log;
    41 import org.apache.commons.logging.LogFactory;
    42 import org.jfree.chart.ChartRenderingInfo;
    43 import org.jfree.chart.ChartUtilities;
    44 import org.jfree.chart.JFreeChart;
    45 import org.jfree.chart.block.RectangleConstraint;
    46 import org.jfree.chart.entity.StandardEntityCollection;
    47 import org.jfree.chart.title.LegendTitle;
    48 import org.jfree.ui.RectangleEdge;
    49 import org.w3c.dom.DOMImplementation;
    50 import org.w3c.dom.Document;
    51 
    52 import com.sun.image.codec.jpeg.JPEGCodec;
    53 import com.sun.image.codec.jpeg.JPEGEncodeParam;
    54 import com.sun.image.codec.jpeg.JPEGImageEncoder;
    55 
    56 import de.laures.cewolf.CewolfException;
    57 import de.laures.cewolf.ChartImage;
    58 import de.laures.cewolf.ChartRenderingException;
    59 import de.laures.cewolf.ConfigurationException;
    60 import de.laures.cewolf.WebConstants;
    61 
    62 /**
    63  * Renderer for ChartImageDefinitions.
    64  *
    65  * @author glaures
    66  * @author tbardzil
    67  * @see    de.laures.cewolf.ChartImage
    68  */
    69 public class Renderer implements WebConstants {
    70 	
    71 	private final static Log log = LogFactory.getLog(Renderer.class);
    72 
    73 	/** Creates a new instance of Renderer */
    74 	private Renderer() {
    75 	};
    76 
    77 	/**
    78 	 * Renders a chart image
    79 	 *
    80 	 * @param  cd                  the chart to render
    81 	 * @return                     the rendered image
    82 	 * @throws CewolfException
    83 	 */
    84 	public static RenderedImage render(ChartImage cd, Object chart) throws CewolfException {
    85 		log.debug("rendering " + cd);
    86 		switch (cd.getType()) {
    87 			case ChartImage.IMG_TYPE_CHART :
    88 				return renderChart(cd, chart);
    89 			case ChartImage.IMG_TYPE_LEGEND :
    90 				return renderLegend(cd, chart);
    91 			default :
    92 				throw new ConfigurationException(cd.getType() + " is not a supported image type");
    93 		}
    94 	}
    95 
    96 	/**
    97 	 * Renders a chart
    98 	 * @param cd the chart image to be rendered
    99 	 * @return the rendered image
   100 	 * @throws CewolfException
   101 	 */
   102 	private static RenderedImage renderChart(ChartImage cd, Object chart) throws CewolfException {
   103 		try {
   104 			final ByteArrayOutputStream baos = new ByteArrayOutputStream();
   105 			final ChartRenderingInfo info = new ChartRenderingInfo(new StandardEntityCollection());
   106 			final String mimeType = cd.getMimeType();
   107 			if (MIME_PNG.equals(mimeType)) {
   108 				handlePNG(baos, (JFreeChart)chart, cd.getWidth(), cd.getHeight(), info);
   109 			} else if (MIME_JPEG.equals(mimeType)) {
   110 			    handleJPEG(baos, (JFreeChart)chart, cd.getWidth(), cd.getHeight(), info);
   111 			} else if (MIME_SVG.equals(mimeType)) {
   112 				handleSVG(baos, (JFreeChart)chart, cd.getWidth(), cd.getHeight());
   113 			} else {
   114 				throw new RenderingException("Mime type " + mimeType + " is unsupported.");
   115 			}
   116 			baos.close();
   117 			return new RenderedImage(baos.toByteArray(), mimeType, info);
   118 		} catch (IOException ioe) {
   119 			log.error(ioe);
   120 			throw new ChartRenderingException(ioe.getMessage(),ioe);
   121 		}
   122 	}
   123 
   124 	/**
   125 	 * Handles rendering a chart as a PNG. Currently this method is synchronized
   126 	 * because of concurrency issues with JFreeChart.
   127 	 *
   128 	 * @param  baos
   129 	 * @param  chart
   130 	 * @param  width
   131 	 * @param  height
   132 	 * @param  info
   133 	 * @throws IOException
   134 	 */
   135 	private static synchronized void handlePNG(
   136 		ByteArrayOutputStream baos,
   137 		JFreeChart chart,
   138 		int width,
   139 		int height,
   140 		ChartRenderingInfo info)
   141 		throws IOException {
   142 		ChartUtilities.writeChartAsPNG(baos, chart, width, height, info);
   143 	}
   144 	
   145 	/**
   146 	 * Handles rendering a chart as a JPEG. Currently this method is synchronized
   147 	 * because of concurrency issues with JFreeChart.
   148 	 *
   149 	 * @param  baos
   150 	 * @param  chart
   151 	 * @param  width
   152 	 * @param  height
   153 	 * @param  info
   154 	 * @throws IOException
   155 	 */
   156 	private static synchronized void handleJPEG(
   157 		ByteArrayOutputStream baos,
   158 		JFreeChart chart,
   159 		int width,
   160 		int height,
   161 		ChartRenderingInfo info)
   162 		throws IOException {
   163 		ChartUtilities.writeChartAsJPEG(baos, chart, width, height, info);
   164 	}			
   165 
   166 	/**
   167 	 * Handles rendering a chart as a SVG. Currently this method is synchronized
   168 	 * because of concurrency issues with JFreeChart.
   169 	 *
   170 	 * @param  baos
   171 	 * @param  chart
   172 	 * @param  width
   173 	 * @param  height
   174 	 * @throws IOException
   175 	 */
   176 	private static synchronized void handleSVG(ByteArrayOutputStream baos, JFreeChart chart, int width, int height)
   177 		throws IOException {
   178 		OutputStreamWriter writer = new OutputStreamWriter(baos, "UTF-8");
   179 		DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
   180 		Document document = domImpl.createDocument("cewolf-svg", "svg", null);
   181 		SVGGeneratorContext ctx = SVGGeneratorContext.createDefault(document);
   182 		ctx.setComment("Generated by Cewolf using JFreeChart and Apache Batik SVG Generator");
   183 		SVGGraphics2D svgGenerator = new SVGGraphics2D(ctx, false);
   184 		svgGenerator.setSVGCanvasSize(new Dimension(width, height));
   185 		chart.draw(svgGenerator, new Rectangle2D.Double(0, 0, width, height), null);
   186 		svgGenerator.stream(writer, false);
   187 		writer.close();
   188 	}
   189 
   190   //gets first legend in the list
   191   public static LegendTitle getLegend(JFreeChart chart)
   192   {
   193     //i need to find the legend now.
   194     LegendTitle legend = null;
   195     List subTitles = chart.getSubtitles();
   196     Iterator iter = subTitles.iterator();
   197     while (iter.hasNext())
   198     {
   199       Object o = iter.next();
   200       if (o instanceof LegendTitle)
   201       {
   202         legend = (LegendTitle) o;
   203         break;
   204       }
   205     }
   206     return legend;
   207   }
   208   
   209   //removes first legend in the list
   210   public static void removeLegend(JFreeChart chart)
   211   {
   212     List subTitles = chart.getSubtitles();
   213     Iterator iter = subTitles.iterator();
   214     while (iter.hasNext())
   215     {
   216       Object o = iter.next();
   217       if (o instanceof LegendTitle)
   218       {
   219         iter.remove();
   220         break;
   221       }
   222     }
   223   }
   224   
   225 	/**
   226 	 * Renders a legend
   227 	 * @param cd the chart iamge to be rendred
   228 	 * @return the rendered image
   229 	 * @throws CewolfException
   230 	 */
   231 	private static RenderedImage renderLegend(ChartImage cd, Object c) throws CewolfException {
   232 		try {
   233 		    JFreeChart chart = (JFreeChart) c;
   234 			final int width = cd.getWidth();
   235 			final int height = cd.getHeight();
   236 			LegendTitle legend = getLegend(chart);
   237 			boolean haslegend = true;
   238 			
   239 			// with JFreeChart v0.9.20, the only way to get a valid legend,
   240 			// is either to retrieve it from the chart or to assign a new
   241 			// one to the chart. In the case where the chart has no legend,
   242 			// a new one must be assigned, but just for rendering. After, we
   243 			// have to reset the legend to null in the chart.
   244 			if (null == legend) {
   245 				haslegend = false;
   246 				legend = new LegendTitle(chart.getPlot());   
   247 			}
   248 			legend.setPosition(RectangleEdge.BOTTOM);
   249 			BufferedImage bimage = ImageHelper.createImage(width, height);
   250 			Graphics2D g = bimage.createGraphics();
   251 			g.setColor(Color.white);
   252 			g.fillRect(0, 0, width, height);
   253 			legend.arrange(g,new RectangleConstraint(width,height));
   254  			legend.draw(g, new Rectangle(width, height));
   255 			ByteArrayOutputStream out = new ByteArrayOutputStream();
   256 			JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
   257 			JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bimage);
   258 			param.setQuality(1.0f, true);
   259 			encoder.encode(bimage, param);
   260 			out.close();
   261 
   262 			// if the chart had no legend, reset it to null in order to give back the
   263 			// chart in the state we received it.
   264 			if (!haslegend) {
   265 				removeLegend(chart);
   266 			}
   267 			
   268 			return new RenderedImage(
   269 				out.toByteArray(),
   270 				"image/jpeg",
   271 				new ChartRenderingInfo(new StandardEntityCollection()));
   272 		} catch (IOException ioex) {
   273 			log.error(ioex);
   274 			throw new ChartRenderingException(ioex.getMessage(), ioex);
   275 		}
   276 	}
   277 
   278 }