Bug 12389 fixed: Axes sizes were not taken into account in offscreen export
[scilab.git] / scilab / modules / graphic_export / src / java / org / scilab / modules / graphic_export / Export.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2012 - Scilab Enterprises - Calixte Denizet
4  *
5  * This file must be used under the terms of the CeCILL.
6  * This source file is licensed as described in the file COPYING, which
7  * you should have received as part of this distribution.  The terms
8  * are also available at
9  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12
13 package org.scilab.modules.graphic_export;
14
15 import java.awt.Dimension;
16 import java.awt.Graphics2D;
17 import java.awt.geom.AffineTransform;
18 import java.awt.image.BufferedImage;
19 import java.io.BufferedOutputStream;
20 import java.io.ByteArrayOutputStream;
21 import java.io.File;
22 import java.io.FileOutputStream;
23 import java.io.IOException;
24 import java.io.OutputStream;
25 import java.io.OutputStreamWriter;
26 import java.io.Writer;
27 import java.text.AttributedCharacterIterator;
28 import java.util.HashMap;
29 import java.util.Map;
30 import java.util.WeakHashMap;
31
32 import org.apache.batik.dom.GenericDOMImplementation;
33 import org.apache.batik.svggen.SVGGeneratorContext;
34 import org.apache.batik.svggen.SVGGraphics2D;
35 import org.apache.fop.Version;
36 import org.apache.fop.svg.PDFDocumentGraphics2D;
37 import org.apache.xmlgraphics.java2d.GraphicContext;
38 import org.apache.xmlgraphics.java2d.ps.AbstractPSDocumentGraphics2D;
39 import org.apache.xmlgraphics.java2d.ps.EPSDocumentGraphics2D;
40 import org.apache.xmlgraphics.java2d.ps.PSDocumentGraphics2D;
41 import org.apache.xmlgraphics.ps.DSCConstants;
42 import org.scilab.forge.scirenderer.Canvas;
43 import org.scilab.forge.scirenderer.implementation.g2d.G2DCanvas;
44 import org.scilab.forge.scirenderer.implementation.g2d.G2DCanvasFactory;
45 import org.scilab.forge.scirenderer.implementation.jogl.JoGLCanvas;
46 import org.scilab.forge.scirenderer.implementation.jogl.JoGLCanvasFactory;
47 import org.scilab.modules.commons.ScilabCommonsUtils;
48 import org.scilab.modules.graphic_export.convertToPPM.PPMEncoder;
49 import org.scilab.modules.graphic_objects.figure.Figure;
50 import org.scilab.modules.graphic_objects.graphicController.GraphicController;
51 import org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties;
52 import org.scilab.modules.renderer.JoGLView.DrawerVisitor;
53 import org.w3c.dom.DOMImplementation;
54 import org.w3c.dom.Document;
55
56 /**
57  * Main class to export
58  * Dependancies are put in inner classes to avoid the deps loading.
59  *
60  * @author Calixte DENIZET
61  */
62 public class Export {
63
64     public static final int SUCCESS = 0;
65     public static final int IOEXCEPTION_ERROR = 1;
66     public static final int INVALID_FILE = 2;
67     public static final int MEMORY_ERROR = 3;
68     public static final int UNKNOWN_ERROR = 4;
69
70     private static final float DEFAULT_JPEG_COMPRESSION = 0.95f;
71
72     private static final String CLASSPATH_PDF_PS_EPS_EXPORT_NAME = "pdf_ps_eps_graphic_export";
73     private static final String CLASSPATH_SVG_EXPORT_NAME = "svg_graphic_export";
74
75     private static final Map<DrawerVisitor, Exporter> visitorsToExp = new WeakHashMap<DrawerVisitor, Exporter>();
76
77     private static final Map<String, Integer> extToType = new HashMap<String, Integer>();
78     static {
79         extToType.put("bmp", 1);
80         extToType.put("gif", 2);
81         extToType.put("jpeg", 3);
82         extToType.put("jpg", 3);
83         extToType.put("png", 4);
84         extToType.put("ppm", 5);
85         extToType.put("eps", 6);
86         extToType.put("pdf", 7);
87         extToType.put("svg", 8);
88         extToType.put("ps", 9);
89         extToType.put("pos", 9);
90     }
91
92     private static boolean svgLoaded;
93     private static boolean pdfLoaded;
94
95     public enum TYPE { PNG, JPEG, GIF, BMP, PPM, SVG, PS, EPS, PDF }
96     private static final TYPE[] types = new TYPE[] {TYPE.PNG, TYPE.BMP, TYPE.GIF, TYPE.JPEG, TYPE.PNG, TYPE.PPM, TYPE.EPS, TYPE.PDF, TYPE.SVG, TYPE.PS};
97
98     /**
99      * @param type the image type
100      * @return true if bitmap image format
101      */
102     public static boolean isBitmapFormat(TYPE type) {
103         return type == TYPE.PNG || type == TYPE.JPEG || type == TYPE.GIF || type == TYPE.BMP || type == TYPE.PPM;
104     }
105
106     public static int getType(String ext) {
107         Integer type = extToType.get(ext.toLowerCase());
108         if (type == null) {
109             return -1;
110         }
111
112         return type;
113     }
114
115     /**
116      * Export in drawing in a Graphics2D
117      * @param uid the figure uid
118      * @param type the export type
119      * @param fileName the file name
120      * @param params the export paramaters
121      * @return the export status
122      */
123     public static int export(String uid, int type, String fileName, ExportParams params, boolean headless) {
124         // Check that the fileName contains an extension
125         int dotPosition = fileName.lastIndexOf('.'); // position of the dot
126         boolean extensionFound = false;
127         if (dotPosition > 0 && dotPosition <= fileName.length() - 2) {
128             extensionFound = true;
129         }
130
131         String extendedFilename = fileName;
132         if (!extensionFound) { // Add default extension if no one found
133             String[] extensions = {"png", "bmp", "gif", "jpeg", "png", "ppm", "eps", "pdf", "svg", "ps"};
134             extendedFilename = fileName + "." + extensions[type];
135         }
136
137         DrawerVisitor visitor = DrawerVisitor.getVisitor(uid);
138         if (visitor != null) {
139             Canvas canvas = visitor.getCanvas();
140             if (canvas instanceof JoGLCanvas && isBitmapFormat(types[type])) {
141                 try {
142                     return exportBitmap(uid, type, extendedFilename, true, params);
143                 } catch (OutOfMemoryError e) {
144                     return MEMORY_ERROR;
145                 } catch (Throwable e) {
146                     return UNKNOWN_ERROR;
147                 }
148             }
149         }
150
151         return exportVectorial(uid, type, extendedFilename, params, headless);
152     }
153
154
155     /**
156      * Export in drawing in a Graphics2D
157      * @param uid the figure uid
158      * @param type the export type
159      * @param fileName the file name
160      * @param params the export paramaters
161      * @return the export status
162      */
163     public static int exportVectorial(String uid, int type, String fileName, ExportParams params, boolean headless) {
164         if (fileName == null) {
165             return INVALID_FILE;
166         }
167
168         File f = new File(fileName);
169         int ret = Utils.checkWritePermission(f);
170         if (ret != SUCCESS) {
171             return ret;
172         }
173
174         try {
175             return exportVectorial(uid, types[type], f, params, headless);
176         } catch (IOException e) {
177             return IOEXCEPTION_ERROR;
178         }
179     }
180
181     /**
182      * Export in drawing in a Graphics2D
183      * @param uid the figure uid
184      * @param type the export type
185      * @param file the file where to export
186      * @param params the export paramaters
187      */
188     public static int exportVectorial(String uid, TYPE type, File file, ExportParams params, boolean headless) throws IOException {
189         Figure figure = (Figure) GraphicController.getController().getObjectFromId(uid);
190
191         if (!headless) {
192             Exporter exporter = getExporter(type);
193             Integer[] dims = figure.getAxesSize();
194             int width = dims[0];
195             int height = dims[1];
196
197             Graphics2D g2d = exporter.getGraphics2D(width, height, file, params);
198             params.setParamsOnGraphics(g2d);
199
200             Canvas canvas = G2DCanvasFactory.createCanvas(g2d, width, height);
201             DrawerVisitor oldVisitor = DrawerVisitor.getVisitor(uid);
202             DrawerVisitor visitor = new DrawerVisitor(null, canvas, figure) {
203                 @Override
204                 public void updateObject(String id, int property) {
205                     // Don't update during the export
206                 }
207             };
208
209             try {
210                 canvas.setMainDrawer(visitor);
211                 canvas.redraw();
212                 exporter.write();
213             } catch (OutOfMemoryError e) {
214                 return MEMORY_ERROR;
215             } catch (Throwable e) {
216                 return UNKNOWN_ERROR;
217             } finally {
218                 GraphicController.getController().unregister(visitor);
219                 DrawerVisitor.changeVisitor(figure, oldVisitor);
220                 exporter.dispose();
221                 exporter = null;
222                 visitorsToExp.remove(visitor);
223             }
224         } else {
225             DrawerVisitor visitor = DrawerVisitor.getVisitor(uid);
226             G2DCanvas canvas = (G2DCanvas) visitor.getCanvas();
227             canvas.enableDraw();
228             Exporter exporter = null;
229             try {
230                 canvas.redraw();
231                 exporter = visitorsToExp.get(visitor);
232                 if (exporter != null) {
233                     exporter.file = file;
234                     exporter.write();
235                 }
236             } catch (OutOfMemoryError e) {
237                 return MEMORY_ERROR;
238             } catch (Throwable e) {
239                 return UNKNOWN_ERROR;
240             } finally {
241                 if (exporter != null) {
242                     exporter.dispose();
243                     exporter = null;
244                     visitorsToExp.remove(visitor);
245                 }
246                 DrawerVisitor.changeVisitor(figure, null);
247                 GraphicController.getController().unregister(visitor);
248             }
249         }
250
251         return SUCCESS;
252     }
253
254     /**
255      * Export in getting a buffered image from JoGL
256      * @param uid the figure uid
257      * @param type the export type
258      * @param fileName the file name
259      * @param fromScreen if true, then use the screen view
260      * @param params the export paramaters
261      * @return the export status
262      */
263     public static int exportBitmap(String uid, int type, String fileName, boolean fromScreen, ExportParams params) {
264         if (fileName == null) {
265             return INVALID_FILE;
266         }
267
268         File f = new File(fileName);
269         int ret = Utils.checkWritePermission(f);
270         if (ret != SUCCESS) {
271             return ret;
272         }
273
274         try {
275             exportBitmap(uid, types[type], f, fromScreen, params);
276         } catch (IOException e) {
277             return IOEXCEPTION_ERROR;
278         }
279
280         return SUCCESS;
281     }
282
283     /**
284      * Export in getting a buffered image from JoGL
285      * @param uid the figure uid
286      * @param type the export type
287      * @param file the file where to export
288      * @param fromScreen if true, then use the screen view
289      * @param params the export paramaters
290      */
291     public static void exportBitmap(String uid, TYPE type, File file, boolean fromScreen, ExportParams params) throws IOException {
292         if (isBitmapFormat(type)) {
293             JoGLCanvas joglCanvas = null;
294             if (fromScreen) {
295                 DrawerVisitor visitor = DrawerVisitor.getVisitor(uid);
296                 Canvas canvas = visitor.getCanvas();
297                 if (canvas instanceof JoGLCanvas) {
298                     joglCanvas = (JoGLCanvas) canvas;
299                 }
300             } else {
301                 Figure figure = (Figure) GraphicController.getController().getObjectFromId(uid);
302                 Integer[] dims = figure.getAxesSize();
303                 DrawerVisitor oldVisitor = DrawerVisitor.getVisitor(uid);
304                 joglCanvas = (JoGLCanvas) JoGLCanvasFactory.createCanvas(dims[0], dims[1]);
305                 DrawerVisitor visitor = new DrawerVisitor(null, joglCanvas, figure) {
306                     @Override
307                     public void updateObject(String id, int property) {
308                         // Don't update during the export
309                     }
310
311                     @Override
312                     public void deleteObject(String id) {
313                         // Don't delete during the export
314                     }
315                 };
316                 joglCanvas.setMainDrawer(visitor);
317                 joglCanvas.redraw();
318                 GraphicController.getController().unregister(visitor);
319                 DrawerVisitor.changeVisitor(figure, oldVisitor);
320             }
321
322             if (joglCanvas != null) {
323                 BufferedImage image = joglCanvas.getImage();
324                 //joglCanvas.destroy();
325                 PNGExporter exporter = (PNGExporter) getExporter(type);
326                 exporter.setImage(file, image, params);
327                 exporter.write();
328                 exporter.dispose();
329             }
330         }
331     }
332
333     /**
334      * Export in drawing in a Graphics2D
335      * @param uid the figure uid
336      * @param type the export type
337      * @param file the file where to export
338      * @param params the export paramaters
339      */
340     public static void setVisitor(String uid, int type, final ExportParams params) {
341         final Exporter exporter = getExporter(types[type]);
342         Figure figure = (Figure) GraphicController.getController().getObjectFromId(uid);
343         Integer[] dims = figure.getAxesSize();
344         int width = dims[0];
345         int height = dims[1];
346
347         Graphics2D g2d = exporter.getGraphics2D(width, height, null, params);
348         params.setParamsOnGraphics(g2d);
349
350         G2DCanvas canvas = G2DCanvasFactory.createCanvas(g2d, width, height);
351         canvas.disableDraw();
352         DrawerVisitor visitor = new DrawerVisitor(null, canvas, figure) {
353             @Override
354             public void deleteObject(String id) {
355                 // Don't delete during the export
356             }
357
358             @Override
359             public void updateObject(String id, int property) {
360                 if (property == GraphicObjectProperties.__GO_AXES_SIZE__) {
361                     Integer[] size = getFigure().getAxesSize();
362                     Graphics2D g2d = exporter.getGraphics2D(size[0], size[1], null, params);
363                     params.setParamsOnGraphics(g2d);
364
365                     G2DCanvas canvas = G2DCanvasFactory.createCanvas(g2d, size[0], size[1]);
366                     canvas.disableDraw();
367                     setCanvas(canvas);
368
369                     setDrawingTools(canvas.getDrawingTools());
370                     canvas.setMainDrawer(this);
371                 }
372             }
373         };
374         visitor.setDrawingTools(canvas.getDrawingTools());
375         canvas.setMainDrawer(visitor);
376         visitorsToExp.put(visitor, exporter);
377     }
378
379     /**
380      * Get an exporter from a type
381      * @param type the exporter type.
382      * @return the corresponding exporter/
383      */
384     private static Exporter getExporter(TYPE type) {
385         switch (type) {
386             case PNG :
387                 return new PNGExporter();
388             case GIF :
389                 return new GIFExporter();
390             case JPEG :
391                 return new JPEGExporter();
392             case BMP :
393                 return new BMPExporter();
394             case PPM :
395                 return new PPMExporter();
396             case SVG :
397                 if (!svgLoaded) {
398                     ScilabCommonsUtils.loadOnUse(CLASSPATH_SVG_EXPORT_NAME);
399                     svgLoaded = true;
400                 }
401                 return new SVGExporter();
402             case PDF :
403                 loadPDF();
404                 return new PDFExporter();
405             case PS :
406                 loadPDF();
407                 return new PSExporter();
408             case EPS :
409                 loadPDF();
410                 return new EPSExporter();
411             default :
412                 break;
413         }
414
415         return null;
416     }
417
418     /**
419      * Load the PDF/PS/EPS dependencies
420      */
421     private static final void loadPDF() {
422         if (!pdfLoaded) {
423             ScilabCommonsUtils.loadOnUse(CLASSPATH_PDF_PS_EPS_EXPORT_NAME);
424             pdfLoaded = true;
425         }
426     }
427
428     /**
429      * Interface to export
430      */
431     private static abstract class Exporter {
432
433         protected File file;
434
435         /**
436          * @param width graphics width
437          * @param height graphisc height
438          * @param file the file
439          * @param params the export parameters
440          */
441         abstract Graphics2D getGraphics2D(int width, int height, File file, ExportParams params);
442
443         /**
444          * Write the file
445          */
446         abstract void write() throws IOException;
447
448         abstract void dispose();
449     }
450
451     /**
452      * PNG Exporter
453      */
454     private static class PNGExporter extends Exporter {
455
456         protected BufferedImage image;
457         protected Graphics2D g2d;
458         protected ExportParams params;
459
460         public PNGExporter() { }
461
462         public void setImage(File file, BufferedImage image, ExportParams params) {
463             this.file = file;
464             this.image = image;
465             this.params = params;
466         }
467
468         @Override
469         public Graphics2D getGraphics2D(int width, int height, File file, ExportParams params) {
470             this.file = file;
471             this.params = params;
472             image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
473             g2d = image.createGraphics();
474
475             return g2d;
476         }
477
478         @Override
479         public void write() throws IOException {
480             ExportBitmap.writeFile(image, "png", file);
481         }
482
483         @Override
484         public void dispose() {
485             if (g2d != null) {
486                 g2d.dispose();
487             }
488         }
489     }
490
491     /**
492      * GIF Exporter
493      */
494     private static class GIFExporter extends PNGExporter {
495
496         public GIFExporter() { }
497
498         @Override
499         public void write() throws IOException {
500             ExportBitmap.writeFile(image, "gif", file);
501         }
502     }
503
504     /**
505      * BMP Exporter
506      */
507     private static class BMPExporter extends PNGExporter {
508
509         public BMPExporter() { }
510
511         @Override
512         public Graphics2D getGraphics2D(int width, int height, File file, ExportParams params) {
513             this.file = file;
514             this.params = params;
515             image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
516             g2d = image.createGraphics();
517
518             return g2d;
519         }
520
521         @Override
522         public void write() throws IOException {
523             ExportBitmap.writeFile(image, "bmp", file);
524         }
525     }
526
527     /**
528      * JPEG Exporter
529      */
530     private static class JPEGExporter extends BMPExporter {
531
532         public JPEGExporter() { }
533
534         @Override
535         public void write() throws IOException {
536             if (params.compressionQuality == -1) {
537                 ExportBitmap.writeJPEG(image, DEFAULT_JPEG_COMPRESSION, file);
538             } else {
539                 ExportBitmap.writeJPEG(image, params.compressionQuality, file);
540             }
541         }
542     }
543
544     /**
545      * PPM Exporter
546      */
547     private static class PPMExporter extends BMPExporter {
548
549         public PPMExporter() { }
550
551         @Override
552         public void write() throws IOException {
553             OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
554             PPMEncoder encoder = new PPMEncoder(image, out);
555             int[] pixels = image.getRGB(0, 0, image.getWidth(), image.getHeight(), null, 0, image.getWidth());
556             encoder.encodeStart(image.getWidth(), image.getHeight());
557             encoder.encodePixels(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());
558             out.flush();
559             out.close();
560         }
561     }
562
563     /**
564      * SVG Exporter
565      */
566     private static class SVGExporter extends Exporter {
567
568         private SVGGraphics2D g2d;
569         private ExportParams params;
570
571         public SVGExporter() { }
572
573         @Override
574         public Graphics2D getGraphics2D(int width, int height, File file, ExportParams params) {
575             this.file = file;
576             this.params = params;
577             DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
578             Document document = domImpl.createDocument("http://www.w3.org/2000/svg", "svg", null);
579             final SVGGeneratorContext ctx = SVGGeneratorContext.createDefault(document);
580             ctx.setComment("Generated by Scilab with Batik SVG Generator");
581             // TODO: better handle of LaTeX fonts (should remove the 'true' below and include the font in the SVG)
582             // same thing for PDF & co...
583             ctx.setEmbeddedFontsOn(true);
584             g2d = new SVGGraphics2D(ctx, false) {
585
586                 public void drawString(String s, float x, float y) {
587                     textAsShapes = getFont().getFontName().startsWith("jlm");
588                     super.drawString(s, x, y);
589                 }
590
591                 public void drawString(AttributedCharacterIterator ati, float x, float y) {
592                     textAsShapes = getFont().getFontName().startsWith("jlm");
593                     super.drawString(ati, x, y);
594                 }
595             };
596             if (params.orientation == ExportParams.LANDSCAPE) {
597                 g2d.setSVGCanvasSize(new Dimension(height, width));
598                 AffineTransform transf = AffineTransform.getRotateInstance(Math.PI / 2);
599                 transf.preConcatenate(AffineTransform.getTranslateInstance(height, 0));
600                 g2d.setTransform(transf);
601             } else {
602                 g2d.setSVGCanvasSize(new Dimension(width, height));
603             }
604             return g2d;
605         }
606
607         @Override
608         public void write() throws IOException {
609             boolean useCSS = true;
610             OutputStream svgs = new BufferedOutputStream(new FileOutputStream(file));
611             Writer out = new OutputStreamWriter(svgs, "UTF-8");
612             g2d.stream(out, useCSS);
613             svgs.flush();
614             svgs.close();
615         }
616
617         @Override
618         public void dispose() {
619             if (g2d != null) {
620                 g2d.dispose();
621             }
622         }
623     }
624
625     /**
626      * PDF Exporter
627      */
628     private static class PDFExporter extends Exporter {
629
630         private OutputStream out;
631         private PDFDocumentGraphics2D g2d;
632         private ExportParams params;
633         private ByteArrayOutputStream buffer;
634
635         public PDFExporter() { }
636
637         @Override
638         public Graphics2D getGraphics2D(int width, int height, File file, ExportParams params) {
639             this.file = file;
640             this.params = params;
641             try {
642                 if (file == null) {
643                     buffer = new ByteArrayOutputStream();
644                     out = new BufferedOutputStream(buffer);
645                 } else {
646                     out = new BufferedOutputStream(new FileOutputStream(file));
647                 }
648                 g2d = new PDFDocumentGraphics2D(true);
649                 g2d.setupDefaultFontInfo();
650                 g2d.getPDFDocument().getInfo().setProducer("Generated by Scilab with Apache FOP Version " + Version.getVersion());
651                 g2d.setGraphicContext(new GraphicContext());
652                 if (params.orientation == ExportParams.LANDSCAPE) {
653                     g2d.setupDocument(out, height, width);
654                     g2d.setSVGDimension(height, width);
655                     double s = PDFDocumentGraphics2D.NORMAL_PDF_RESOLUTION / g2d.getDeviceDPI();
656                     AffineTransform transf = AffineTransform.getRotateInstance(Math.PI / 2);
657                     transf.preConcatenate(AffineTransform.getTranslateInstance(height / s, 0));
658                     g2d.setTransform(transf);
659                 } else {
660                     g2d.setupDocument(out, width, height);
661                     g2d.setSVGDimension(width, height);
662                 }
663             } catch (IOException e) { }
664
665             return g2d;
666         }
667
668         @Override
669         public void write() throws IOException {
670             if (g2d != null) {
671                 g2d.finish();
672             }
673             if (buffer != null && file != null) {
674                 FileOutputStream fos = new FileOutputStream(file);
675                 buffer.writeTo(fos);
676                 buffer.close();
677                 fos.flush();
678                 fos.close();
679             }
680             if (out != null) {
681                 out.close();
682             }
683         }
684
685         @Override
686         public void dispose() {
687             g2d.dispose();
688         }
689     }
690
691     /**
692      * PS Exporter
693      */
694     private static class PSExporter extends Exporter {
695
696         protected OutputStream out;
697         protected AbstractPSDocumentGraphics2D g2d;
698         protected ExportParams params;
699         protected ByteArrayOutputStream buffer;
700
701         public PSExporter() { }
702
703         @Override
704         public Graphics2D getGraphics2D(int width, int height, File file, final ExportParams params) {
705             this.file = file;
706             this.params = params;
707             try {
708                 if (file == null) {
709                     buffer = new ByteArrayOutputStream();
710                     out = new BufferedOutputStream(buffer);
711                 } else {
712                     out = new BufferedOutputStream(new FileOutputStream(file));
713                 }
714                 g2d = new PSDocumentGraphics2D(true, out, width, height) {
715                     @Override
716                     protected void writePageHeader() throws IOException {
717                         super.writePageHeader();
718                         if (params.orientation == ExportParams.LANDSCAPE) {
719                             gen.writeDSCComment(DSCConstants.PAGE_ORIENTATION, "Landscape");
720                         } else {
721                             gen.writeDSCComment(DSCConstants.PAGE_ORIENTATION, "Portrait");
722                         }
723                     }
724                 };
725                 g2d.setGraphicContext(new GraphicContext());
726             } catch (IOException e) { }
727
728             return g2d;
729         }
730
731         @Override
732         public void write() throws IOException {
733             if (g2d != null) {
734                 g2d.finish();
735             }
736             if (buffer != null && file != null) {
737                 FileOutputStream fos = new FileOutputStream(file);
738                 buffer.writeTo(fos);
739                 buffer.close();
740                 fos.flush();
741                 fos.close();
742             }
743             if (out != null) {
744                 out.close();
745             }
746         }
747
748         @Override
749         public void dispose() {
750             if (g2d != null) {
751                 g2d.dispose();
752             }
753         }
754     }
755
756     /**
757      * EPS Exporter
758      */
759     private static class EPSExporter extends PSExporter {
760
761         public EPSExporter() { }
762
763         @Override
764         public Graphics2D getGraphics2D(int width, int height, File file, final ExportParams params) {
765             this.file = file;
766             this.params = params;
767             try {
768                 if (file == null) {
769                     buffer = new ByteArrayOutputStream();
770                     out = new BufferedOutputStream(buffer);
771                 } else {
772                     out = new BufferedOutputStream(new FileOutputStream(file));
773                 }
774                 g2d = new EPSDocumentGraphics2D(true) {
775                     @Override
776                     protected void writePageHeader() throws IOException {
777                         super.writePageHeader();
778                         if (params.orientation == ExportParams.LANDSCAPE) {
779                             gen.writeDSCComment(DSCConstants.PAGE_ORIENTATION, "Landscape");
780                         } else {
781                             gen.writeDSCComment(DSCConstants.PAGE_ORIENTATION, "Portrait");
782                         }
783                     }
784                 };
785                 g2d.setupDocument(out, width, height);
786                 g2d.setGraphicContext(new GraphicContext());
787             } catch (IOException e) { }
788
789             return g2d;
790         }
791     }
792 }