001/* ===========================================================
002 * Orson Charts : a 3D chart library for the Java(tm) platform
003 * ===========================================================
004 * 
005 * (C)opyright 2013-2016, by Object Refinery Limited.  All rights reserved.
006 * 
007 * http://www.object-refinery.com/orsoncharts/index.html
008 * 
009 * This program is free software: you can redistribute it and/or modify
010 * it under the terms of the GNU General Public License as published by
011 * the Free Software Foundation, either version 3 of the License, or
012 * (at your option) any later version.
013 *
014 * This program is distributed in the hope that it will be useful,
015 * but WITHOUT ANY WARRANTY; without even the implied warranty of
016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
017 * GNU General Public License for more details.
018 *
019 * You should have received a copy of the GNU General Public License
020 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
021 * 
022 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 
023 * Other names may be trademarks of their respective owners.]
024 * 
025 * If you do not wish to be bound by the terms of the GPL, an alternative
026 * commercial license can be purchased.  For details, please see visit the
027 * Orson Charts home page:
028 * 
029 * http://www.object-refinery.com/orsoncharts/index.html
030 * 
031 */
032
033package com.orsoncharts.graphics3d;
034
035import java.awt.Graphics2D;
036import java.awt.Rectangle;
037import java.awt.geom.Rectangle2D;
038import java.awt.image.BufferedImage;
039import java.io.BufferedOutputStream;
040import java.io.File;
041import java.io.FileNotFoundException;
042import java.io.FileOutputStream;
043import java.io.IOException;
044import java.io.OutputStream;
045import java.lang.reflect.Constructor;
046import java.lang.reflect.InvocationTargetException;
047import java.lang.reflect.Method;
048import javax.imageio.ImageIO;
049import com.orsoncharts.util.ArgChecks;
050import com.orsoncharts.util.ExportFormats;
051
052/**
053 * Export utility methods.
054 * 
055 * @since 1.4
056 */
057public class ExportUtils {
058    
059    /**
060     * Writes the current content to the specified file in SVG format.  This 
061     * will only work when the JFreeSVG library is found on the classpath.
062     * Reflection is used to ensure there is no compile-time dependency on
063     * JFreeSVG.  Any exceptions that occur while writing the file are
064     * caught and wrapped in a {@code RuntimeException} that is then thrown.
065     * 
066     * @param drawable  the drawable ({@code null} not permitted).
067     * @param w  the chart width.
068     * @param h  the chart height.
069     * @param file  the output file ({@code null} not permitted).
070     * 
071     * @return The rendering info.
072     */
073    public static RenderingInfo writeAsSVG(Drawable3D drawable, int w, int h, 
074            File file) {
075        if (!ExportFormats.isJFreeSVGAvailable()) {
076            throw new IllegalStateException(
077                    "JFreeSVG is not present on the classpath.");
078        }
079        ArgChecks.nullNotPermitted(drawable, "drawable");
080        ArgChecks.nullNotPermitted(file, "file");
081        try {
082            Class<?> svg2Class = Class.forName(
083                    "org.jfree.graphics2d.svg.SVGGraphics2D");
084            Constructor<?> c1 = svg2Class.getConstructor(int.class, int.class);
085            Graphics2D svg2 = (Graphics2D) c1.newInstance(w, h);
086            Rectangle2D drawArea = new Rectangle2D.Double(0, 0, w, h);
087            RenderingInfo info = drawable.draw(svg2, drawArea);
088            Class<?> svgUtilsClass = Class.forName(
089                    "org.jfree.graphics2d.svg.SVGUtils");
090            Method m1 = svg2Class.getMethod("getSVGElement", (Class[]) null);
091            String element = (String) m1.invoke(svg2, (Object[]) null);
092            Method m2 = svgUtilsClass.getMethod("writeToSVG", File.class, 
093                    String.class);
094            m2.invoke(svgUtilsClass, file, element);
095            return info;
096        } catch (ClassNotFoundException ex) {
097            throw new RuntimeException(ex);
098        } catch (InstantiationException ex) {
099            throw new RuntimeException(ex);
100        } catch (IllegalAccessException ex) {
101            throw new RuntimeException(ex);
102        } catch (NoSuchMethodException ex) {
103            throw new RuntimeException(ex);
104        } catch (SecurityException ex) {
105            throw new RuntimeException(ex);
106        } catch (IllegalArgumentException ex) {
107            throw new RuntimeException(ex);
108        } catch (InvocationTargetException ex) {
109            throw new RuntimeException(ex);
110        }
111    }
112
113    /**
114     * Writes a {@link Drawable3D} to the specified file in PDF format.  This 
115     * will only work when the OrsonPDF library is found on the classpath.
116     * Reflection is used to ensure there is no compile-time dependency on
117     * OrsonPDF.  Any exceptions that occur while writing the file are
118     * caught and wrapped in a {@code RuntimeException} that is then thrown.
119     * 
120     * @param drawable  the drawable ({code null} not permitted).
121     * @param w  the chart width.
122     * @param h  the chart height.
123     * @param file  the output file ({code null} not permitted).
124     * 
125     * @return The rendering info.
126     */
127    public static final RenderingInfo writeAsPDF(Drawable3D drawable, 
128            int w, int h, File file) {
129        if (!ExportFormats.isOrsonPDFAvailable()) {
130            throw new IllegalStateException(
131                    "OrsonPDF is not present on the classpath.");
132        }
133        ArgChecks.nullNotPermitted(drawable, "drawable");
134        ArgChecks.nullNotPermitted(file, "file");
135        try {
136            Class<?> pdfDocClass = Class.forName("com.orsonpdf.PDFDocument");
137            Object pdfDoc = pdfDocClass.newInstance();
138            Method m = pdfDocClass.getMethod("createPage", Rectangle2D.class);
139            Rectangle2D rect = new Rectangle(w, h);
140            Object page = m.invoke(pdfDoc, rect);
141            Method m2 = page.getClass().getMethod("getGraphics2D");
142            Graphics2D g2 = (Graphics2D) m2.invoke(page);
143            Rectangle2D drawArea = new Rectangle2D.Double(0, 0, w, h);
144            RenderingInfo info = drawable.draw(g2, drawArea);
145            Method m3 = pdfDocClass.getMethod("writeToFile", File.class);
146            m3.invoke(pdfDoc, file);
147            return info;
148        } catch (ClassNotFoundException ex) {
149            throw new RuntimeException(ex);
150        } catch (InstantiationException ex) {
151            throw new RuntimeException(ex);
152        } catch (IllegalAccessException ex) {
153            throw new RuntimeException(ex);
154        } catch (NoSuchMethodException ex) {
155            throw new RuntimeException(ex);
156        } catch (SecurityException ex) {
157            throw new RuntimeException(ex);
158        } catch (IllegalArgumentException ex) {
159            throw new RuntimeException(ex);
160        } catch (InvocationTargetException ex) {
161            throw new RuntimeException(ex);
162        }
163    }
164    
165    /**
166     * Writes the current content to the specified file in PNG format.
167     * 
168     * @param drawable  the drawable ({@code null} not permitted).
169     * @param w  the chart width.
170     * @param h  the chart height.
171     * @param file  the output file ({@code null} not permitted).
172     * 
173     * @return The rendering info.
174     * 
175     * @throws FileNotFoundException if the file is not found.
176     * @throws IOException if there is an I/O problem.
177     */
178    public static RenderingInfo writeAsPNG(Drawable3D drawable, int w, int h, 
179            File file) throws FileNotFoundException, IOException {
180        BufferedImage image = new BufferedImage(w, h, 
181                BufferedImage.TYPE_INT_ARGB);
182        Graphics2D g2 = image.createGraphics();
183        RenderingInfo result = drawable.draw(g2, new Rectangle(w, h));
184        OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
185        try {
186            ImageIO.write(image, "png", out);
187        }
188        finally {
189            out.close();
190        }
191        return result;
192    }
193
194    /**
195     * Writes the current content to the specified file in JPEG format.
196     * 
197     * @param drawable  the drawable ({@code null} not permitted).
198     * @param w  the chart width.
199     * @param h  the chart height.
200     * @param file  the output file ({@code null} not permitted).
201     * 
202     * @return The rendering info.
203     * 
204     * @throws FileNotFoundException if the file is not found.
205     * @throws IOException if there is an I/O problem.
206     */
207    public static RenderingInfo writeAsJPEG(Drawable3D drawable, int w, int h, 
208            File file) throws FileNotFoundException, IOException {
209        BufferedImage image = new BufferedImage(w, h, 
210                BufferedImage.TYPE_INT_RGB);
211        Graphics2D g2 = image.createGraphics();
212        RenderingInfo result = drawable.draw(g2, new Rectangle(w, h));
213        OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
214        try {
215            ImageIO.write(image, "jpg", out);
216        }
217        finally {
218            out.close();
219        }
220        return result;
221    }
222
223}