/*
 * This code is part of Project Waterloo from King's College London
 * 
 *
 * Copyright King's College London 2011-
 *
 * @author Malcolm Lidierth, King's College London  [Contact]
 *
 * Project Waterloo 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 3 of the License, or
 * (at your option) any later version.
 *
 * Project Waterloo 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 program.  If not, see .
 *
 */
package kcl.waterloo.export;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.zip.GZIPOutputStream;
import javax.swing.JComponent;
import kcl.waterloo.defaults.GJDefaults;
import kcl.waterloo.deploy.svg.WSVGGraphics2D;
import org.apache.batik.dom.GenericDOMImplementation;
import org.apache.batik.svggen.DOMGroupManager;
import org.apache.batik.svggen.SVGGeneratorContext;
import org.apache.batik.svggen.SVGGraphics2D;
import org.apache.batik.svggen.SVGGraphics2DIOException;
import org.apache.batik.transcoder.TranscoderException;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.XMLAbstractTranscoder;
import org.apache.fop.svg.PDFTranscoder;
import org.apache.xmlgraphics.java2d.ps.EPSDocumentGraphics2D;
import org.apache.xmlgraphics.java2d.ps.PSDocumentGraphics2D;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Element;

/**
 * ExportFactory provides static methods to support vector graphics output.
 *
 * @author Malcolm Lidierth, King's College London  [Contact]
 */
public class ExportFactory {

    private static int containerCounter = 0;
    private static int graphCounter = 0;
    private static int axisCounter = 0;
    private static int plotCounter = 0;

    private static final class Singleton {

        private static PDFTranscoder transcoder;
        private static final Singleton instance = new Singleton();

        private Singleton() {
            if (System.getProperty("waterloo_pdf_supported") == null || System.getProperty("waterloo_pdf_supported").equals("true")) {
                transcoder = new PDFTranscoder();
                transcoder.setLogger(null);
                transcoder.setErrorHandler(null);
                transcoder.addTranscodingHint(XMLAbstractTranscoder.KEY_XML_PARSER_VALIDATING, Boolean.FALSE);
                transcoder.addTranscodingHint(PDFTranscoder.KEY_STROKE_TEXT, Boolean.FALSE);
            }
        }

    }

    private ExportFactory() {
    }

    /**
     * Returns the image in SVG format as a String
     *
     * @param c an AWT component
     * @return the SVG code
     * @throws IOException
     */
    public static String saveAsSVG(Component c) throws IOException {
        StringWriter stream = new StringWriter();
        return doSVG(c, stream);
    }

    /**
     * Saves the image to an SVG file
     *
     * @param c an AWT component
     * @param str the file name as a String
     * @throws IOException
     */
    public static void saveAsSVG(Component c, String str) throws IOException {
        //Create output stream
        FileOutputStream outputStream = createOutputStream(str);
        doSVG(c, outputStream);
    }

    /**
     * Saves the image to an SVG file
     *
     * @param c an AWT component
     * @param f the file to save as a File instance
     * @throws IOException
     */
    public static void saveAsSVG(Component c, File f) throws IOException {
        //Create output stream
        FileOutputStream outputStream = new FileOutputStream(f);
        try {
            doSVG(c, outputStream);
        } finally {
            outputStream.close();
        }
    }

    public static void saveAsCompressedSVG(Component c, File f) throws IOException {
        //Create output stream
        GZIPOutputStream outputStream = new GZIPOutputStream(new FileOutputStream(f));
        try {
            doSVG(c, outputStream);
        } finally {
            outputStream.close();
        }
    }

    /**
     * @param c an AWT component
     * @return PDF code as a ByteArrayInputStream
     * @throws IOException
     */
    public static ByteArrayInputStream saveAsPDF(Component c) throws IOException {
        StringWriter stream = new StringWriter();
        return convertSVG2PDF(doSVG(c, stream));
    }

    /**
     * @param c an AWT component
     * @param s the file name as a String
     * @throws IOException
     */
    public static void saveAsPDF(Component c, String s) throws IOException {
        saveAsPDF(c, new File(s));
    }

    /**
     * @param c an AWT component
     * @param f the File to save to
     * @throws IOException
     */
    public static void saveAsPDF(Component c, File f) throws IOException {
        StringWriter stream = new StringWriter();
        String s = doSVG(c, stream);
        convertSVG2PDF(s, f);
    }

    /**
     * @param c an AWT component
     * @return the EPS code as a ByteArrayOutputStream
     * @throws IOException
     */
    public static ByteArrayOutputStream saveAsEPS(Component c) throws IOException {
        EPSDocumentGraphics2D g2d = new EPSDocumentGraphics2D(false);
        g2d.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        g2d.setupDocument(stream, c.getWidth(), c.getHeight());
        paint(c, g2d);
        g2d.finish();
        return stream;
    }

    /**
     * @param c an AWT component
     * @param f the File to save to
     * @throws IOException
     */
    public static void saveAsEPS(Component c, File f) throws IOException {
        EPSDocumentGraphics2D g2d = new EPSDocumentGraphics2D(false);
        g2d.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
        FileOutputStream stream = createOutputStream(f);
        g2d.setupDocument(stream, c.getWidth(), c.getHeight()); //400pt x 200pt
        paint(c, g2d);
        g2d.finish();
        stream.close();
    }

    /**
     * @param c an AWT component
     * @return the PS code as a ByteArrayOutputStream
     * @throws IOException
     */
    public static ByteArrayOutputStream saveAsPS(Component c) throws IOException {
        PSDocumentGraphics2D g2d = new PSDocumentGraphics2D(false);
        g2d.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        g2d.setupDocument(stream, c.getWidth(), c.getHeight()); //400pt x 200pt
        paint(c, g2d);
        g2d.finish();
        return stream;
    }

    /**
     * @param c an AWT component
     * @param f the File to save to
     * @throws IOException
     */
    public static void saveAsPS(Component c, File f) throws IOException {
        PSDocumentGraphics2D g2d = new PSDocumentGraphics2D(false);
        g2d.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
        FileOutputStream stream = createOutputStream(f);
        g2d.setupDocument(stream, c.getWidth(), c.getHeight()); //400pt x 200pt
        paint(c, g2d);
        g2d.finish();
        stream.close();
    }

    /**
     * @param c an AWT component
     * @return the SVG code as a String
     * @throws IOException
     */
    private static String doSVG(Component c) throws IOException {
        return doSVG(c, new StringWriter(), false);
    }

    /**
     * @param c
     * @param svgOut
     * @throws IOException
     */
    private static void doSVG(Component c, OutputStream svgOut) throws IOException {
        doSVG(c, svgOut, false);
    }

    /**
     * @param c
     * @param svgOut
     * @throws IOException
     */
    private static void doSVG(Component c, OutputStream svgOut, boolean textAsStrokes) throws IOException {
        // Get a DOMImplementation.
        DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
        // Create an instance of org.w3c.dom.Document.
        String svgNS = "http://www.w3.org/2000/svg";
        org.w3c.dom.Document document = domImpl.createDocument(svgNS, "svg", null);
        // Create an instance of the SVG Generator.
        SVGGeneratorContext ctx = SVGGeneratorContext.createDefault(document);
        ctx.setComment("Generated by the Project Waterloo Graphics Library using the Apache Batik SVG Generator");
        SVGGraphics2D svgGenerator = new SVGGraphics2D(ctx, textAsStrokes);
        svgGenerator.setSVGCanvasSize(c.getSize());

        //See https://issues.apache.org/jira/browse/BATIK-555
        Element root = document.getDocumentElement();
        svgGenerator.getRoot(root);

        WSVGGraphics2D g = new WSVGGraphics2D(svgGenerator);
        // Render into the SVG Graphics2D implementation.
        paint(c, g);
        Writer out = null;
        try {
            try {
                out = new OutputStreamWriter(svgOut, "UTF-8");
            } catch (UnsupportedEncodingException ex) {
            }
            try {
                svgGenerator.stream(out, textAsStrokes);
            } catch (SVGGraphics2DIOException ex) {
            }
        } finally {
            svgOut.close();
        }
    }

    private static String doSVG(Component c, StringWriter out) throws IOException {
        return doSVG(c, out, false);
    }

    /**
     * @param c an AWT component
     * @param out
     * @return
     * @throws IOException
     */
    private static String doSVG(Component c, StringWriter out, boolean textAsStrokes) {
        DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
        String svgNS = "http://www.w3.org/2000/svg";
        org.w3c.dom.Document document = domImpl.createDocument(svgNS, "svg", null);
        SVGGeneratorContext ctx = SVGGeneratorContext.createDefault(document);
        ctx.setEmbeddedFontsOn(true);
        ctx.setComment("Generated by the Project Waterloo Graphics Library using the Apache Batik SVG Generator");
        SVGGraphics2D svgGenerator = new SVGGraphics2D(ctx, false);
        svgGenerator.setSVGCanvasSize(c.getSize());

        //See https://issues.apache.org/jira/browse/BATIK-555
        Element root = document.getDocumentElement();
        svgGenerator.getRoot(root);

        paint(c, svgGenerator);
        try {
            try {
                svgGenerator.stream(out, textAsStrokes);
            } catch (SVGGraphics2DIOException ex) {
            }
        } finally {
        }
        return out.toString();
    }

    public static void deploySVG(Component c2, File f, Dimension dim, boolean inline,
            String cssLoc, boolean httpdFlag, ArrayList keyWords, String title,
            String description) throws IOException {

        String svg = ExportFactory.doSVG(c2);
        String jsLoc = ((String) GJDefaults.getMap().get("SVG.jsLocation"));
        if (!((Boolean) GJDefaults.getMap().get("SVG.canvg")).booleanValue()) {
            jsLoc = "";
        }
        WSVGGraphics2D.deploy(f,
                svg,
                dim.getSize(),
                inline,
                jsLoc,
                cssLoc,
                httpdFlag,
                keyWords,
                title,
                description);
    }

    public static String doHTML5(Component c) throws IOException {
        return doSVG(c, new StringWriter());
    }

    /**
     * Converts an FO file to a PDF file using FOP
     *
     * @param svg the SVG file
     * @param pdf the target PDF file
     * @throws IOException In case of an I/O problem
     * @throws TranscoderException In case of a transcoding problem
     */
    private static void convertSVG2PDF(String svg, File pdf) throws IOException {

        if (Singleton.transcoder != null) {
            synchronized (Singleton.instance) {
                ByteArrayInputStream in = new ByteArrayInputStream(svg.getBytes("UTF-8"));
                try {
                    TranscoderInput input = new TranscoderInput(in);

                    //Setup output
                    OutputStream out = new java.io.FileOutputStream(pdf);
                    out = new java.io.BufferedOutputStream(out);
                    try {
                        TranscoderOutput output = new TranscoderOutput(out);
                        try {
                            //Do the transformation
                            Singleton.transcoder.transcode(input, output);
                        } catch (TranscoderException ex) {
                        }
                    } finally {
                        out.close();
                    }
                } finally {
                    in.close();
                }
            }
        }
    }

    /**
     * @param svg
     * @return
     * @throws IOException
     */
    public static ByteArrayInputStream convertSVG2PDF(String svg) throws IOException {

        if (Singleton.transcoder != null) {
            synchronized (Singleton.instance) {
                ByteArrayOutputStream out;
                TranscoderOutput output;
                TranscoderInput input = new TranscoderInput(new StringReader(svg));
                out = new java.io.ByteArrayOutputStream();
                output = new TranscoderOutput(out);
                try {
                    Singleton.transcoder.transcode(input, output);
                } catch (TranscoderException ex) {
                }
                out.flush();
                ByteArrayInputStream pdf = new ByteArrayInputStream(out.toByteArray());
                out.close();
                return pdf;
            }
        } else {
            return null;
        }
    }

    /**
     * @param thisFile
     * @return
     */
    private static FileOutputStream createOutputStream(File thisFile) {
        FileOutputStream OutputStream = null;
        try {
            OutputStream = new FileOutputStream(thisFile);
        } catch (FileNotFoundException ex) {
        }
        return OutputStream;
    }

    /**
     * @param str
     * @return
     */
    private static FileOutputStream createOutputStream(String str) {
        File thisFile = new File(str);
        return createOutputStream(thisFile);
    }

    public static void initGroupMarker() {
        containerCounter = 0;
        graphCounter = 0;
        axisCounter = 0;
        plotCounter = 0;
    }

    public static void createGroupMarker(Object o, String s, Graphics g) {
        if (g instanceof SVGGraphics2D) {
            SVGGraphics2D g2 = (SVGGraphics2D) g;
            DOMGroupManager domGroupManager = new DOMGroupManager(g2.getGraphicContext(), g2.getDOMTreeManager());
            g2.getDOMTreeManager().addGroupManager(domGroupManager);
            // Outer group. ID is hashCode for o
            Element el0 = g2.getDOMFactory().createElementNS(null, "g");
            el0.setAttributeNS(null, "class", "waterloo_graphics_element");
            el0.setAttributeNS(null, "id", String.format("kcl_%x", o.hashCode()));

            // Inner group.
            Element el1 = g2.getDOMFactory().createElementNS(null, "g");
            el0.appendChild(el1);
            String classString = o.getClass().toString().replaceAll("class ", "");
            el1.setAttributeNS(null, "class", classString);
            if (classString.contains("GraphContainer")) {
                el1.setAttributeNS(null, "id", "Container" + containerCounter);
                containerCounter++;
            } else if (classString.contains("Graph")) {
                el1.setAttributeNS(null, "id", "Graph" + graphCounter);
                graphCounter++;
            } else if (classString.contains("AxisPanel")) {
                el1.setAttributeNS(null, "id", "Axis" + axisCounter);
                axisCounter++;
            } else {
                el1.setAttributeNS(null, "id", "Plot" + plotCounter);
                plotCounter++;
            }

            Element el2 = g2.getDOMFactory().createElementNS(null, "title");
            el2.setTextContent(s);
            el1.appendChild(el2);

            Element el3 = g2.getDOMFactory().createElementNS(null, "desc");
            el3.setTextContent("Beginning of " + classString + " section");
            el1.appendChild(el3);
            domGroupManager.addElement(el0);

        }
    }

    private static void paint(Component c, Graphics g) {
        if (c instanceof JComponent) {
            boolean state = c.isOpaque();
            ((JComponent) c).setOpaque(true);
            c.paint(g);
            ((JComponent) c).setOpaque(state);
        } else {
            c.paint(g);
        }
    }

    public static boolean isPresent() {
        return true;
    }
}

 

Ads help maintain this website.