    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}