    001/* ===========================================================
    002 * Orson Charts : a 3D chart library for the Java(tm) platform
    003 * ===========================================================
    004 *
    005 * (C)opyright 2013-2022, by David Gilbert.  All rights reserved.
    006 *
    007 * https://github.com/jfree/orson-charts
    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 org.jfree.chart3d.export;
    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 org.jfree.chart3d.graphics3d.Drawable3D;
    050import org.jfree.chart3d.graphics3d.RenderingInfo;
    051import org.jfree.chart3d.internal.Args;
    052
    053/**
    054 * Export utility methods.
    055 *
    056 * @since 1.4
    057 */
    058public class ExportUtils {
    059
    060    /**
    061     * Writes the current content to the specified file in SVG format.  This
    062     * will only work when the JFreeSVG library is found on the classpath.
    063     * Reflection is used to ensure there is no compile-time dependency on
    064     * JFreeSVG.  Any exceptions that occur while writing the file are
    065     * caught and wrapped in a {@code RuntimeException} that is then thrown.
    066     *
    067     * @param drawable  the drawable ({@code null} not permitted).
    068     * @param w  the chart width.
    069     * @param h  the chart height.
    070     * @param file  the output file ({@code null} not permitted).
    071     *
    072     * @return The rendering info.
    073     */
    074    public static RenderingInfo writeAsSVG(Drawable3D drawable, int w, int h,
    075            File file) {
    076        if (!ExportFormats.isJFreeSVGAvailable()) {
    077            throw new IllegalStateException(
    078                    "JFreeSVG is not present on the classpath.");
    079        }
    080        Args.nullNotPermitted(drawable, "drawable");
    081        Args.nullNotPermitted(file, "file");
    082        try {
    083            Class<?> svg2Class = Class.forName(
    084                    "org.jfree.svg.SVGGraphics2D");
    085            Constructor<?> c1 = svg2Class.getConstructor(double.class, double.class);
    086            Graphics2D svg2 = (Graphics2D) c1.newInstance(w, h);
    087            Rectangle2D drawArea = new Rectangle2D.Double(0, 0, w, h);
    088            RenderingInfo info = drawable.draw(svg2, drawArea);
    089            Class<?> svgUtilsClass = Class.forName(
    090                    "org.jfree.svg.SVGUtils");
    091            Method m1 = svg2Class.getMethod("getSVGElement", (Class[]) null);
    092            String element = (String) m1.invoke(svg2, (Object[]) null);
    093            Method m2 = svgUtilsClass.getMethod("writeToSVG", File.class,
    094                    String.class);
    095            m2.invoke(svgUtilsClass, file, element);
    096            return info;
    097        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException
    098                | NoSuchMethodException | SecurityException | IllegalArgumentException
    099                | InvocationTargetException ex) {
    100            throw new RuntimeException(ex);
    101        }
    102    }
    103
    104    /**
    105     * Writes a {@link Drawable3D} to the specified file in PDF format.  This
    106     * will only work when the OrsonPDF library is found on the classpath.
    107     * Reflection is used to ensure there is no compile-time dependency on
    108     * OrsonPDF.  Any exceptions that occur while writing the file are
    109     * caught and wrapped in a {@code RuntimeException} that is then thrown.
    110     *
    111     * @param drawable  the drawable ({code null} not permitted).
    112     * @param w  the chart width.
    113     * @param h  the chart height.
    114     * @param file  the output file ({code null} not permitted).
    115     *
    116     * @return The rendering info.
    117     */
    118    public static RenderingInfo writeAsPDF(Drawable3D drawable, int w, int h,
    119                                           File file) {
    120        if (!ExportFormats.isJFreePDFAvailable()) {
    121            throw new IllegalStateException(
    122                    "JFreePDF is not present on the classpath.");
    123        }
    124        Args.nullNotPermitted(drawable, "drawable");
    125        Args.nullNotPermitted(file, "file");
    126        try {
    127            Class<?> pdfDocClass = Class.forName("org.jfree.pdf.PDFDocument");
    128            Object pdfDoc = pdfDocClass.getDeclaredConstructor().newInstance();
    129            Method m = pdfDocClass.getMethod("createPage", Rectangle2D.class);
    130            Rectangle2D rect = new Rectangle(w, h);
    131            Object page = m.invoke(pdfDoc, rect);
    132            Method m2 = page.getClass().getMethod("getGraphics2D");
    133            Graphics2D g2 = (Graphics2D) m2.invoke(page);
    134            Rectangle2D drawArea = new Rectangle2D.Double(0, 0, w, h);
    135            RenderingInfo info = drawable.draw(g2, drawArea);
    136            Method m3 = pdfDocClass.getMethod("writeToFile", File.class);
    137            m3.invoke(pdfDoc, file);
    138            return info;
    139        } catch (ClassNotFoundException | InstantiationException ex) {
    140            throw new RuntimeException(ex);
    141        } catch (IllegalAccessException ex) {
    142            throw new RuntimeException(ex);
    143        } catch (NoSuchMethodException ex) {
    144            throw new RuntimeException(ex);
    145        } catch (SecurityException ex) {
    146            throw new RuntimeException(ex);
    147        } catch (IllegalArgumentException ex) {
    148            throw new RuntimeException(ex);
    149        } catch (InvocationTargetException ex) {
    150            throw new RuntimeException(ex);
    151        }
    152    }
    153
    154    /**
    155     * Writes the current content to the specified file in PNG format.
    156     *
    157     * @param drawable  the drawable ({@code null} not permitted).
    158     * @param w  the chart width.
    159     * @param h  the chart height.
    160     * @param file  the output file ({@code null} not permitted).
    161     *
    162     * @return The rendering info.
    163     *
    164     * @throws FileNotFoundException if the file is not found.
    165     * @throws IOException if there is an I/O problem.
    166     */
    167    public static RenderingInfo writeAsPNG(Drawable3D drawable, int w, int h,
    168            File file) throws FileNotFoundException, IOException {
    169        BufferedImage image = new BufferedImage(w, h,
    170                BufferedImage.TYPE_INT_ARGB);
    171        Graphics2D g2 = image.createGraphics();
    172        RenderingInfo result = drawable.draw(g2, new Rectangle(w, h));
    173        OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
    174        try {
    175            ImageIO.write(image, "png", out);
    176        }
    177        finally {
    178            out.close();
    179        }
    180        return result;
    181    }
    182
    183    /**
    184     * Writes the current content to the specified file in JPEG format.
    185     *
    186     * @param drawable  the drawable ({@code null} not permitted).
    187     * @param w  the chart width.
    188     * @param h  the chart height.
    189     * @param file  the output file ({@code null} not permitted).
    190     *
    191     * @return The rendering info.
    192     *
    193     * @throws FileNotFoundException if the file is not found.
    194     * @throws IOException if there is an I/O problem.
    195     */
    196    public static RenderingInfo writeAsJPEG(Drawable3D drawable, int w, int h,
    197            File file) throws FileNotFoundException, IOException {
    198        BufferedImage image = new BufferedImage(w, h,
    199                BufferedImage.TYPE_INT_RGB);
    200        Graphics2D g2 = image.createGraphics();
    201        RenderingInfo result = drawable.draw(g2, new Rectangle(w, h));
    202        OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
    203        try {
    204            ImageIO.write(image, "jpg", out);
    205        }
    206        finally {
    207            out.close();
    208        }
    209        return result;
    210    }
    211
    212}