2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2012 - Scilab Enterprises - Calixte Denizet
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.1-en.txt
13 package org.scilab.modules.graphic_export;
15 import java.awt.Dimension;
17 import java.awt.Graphics2D;
18 import java.awt.Shape;
19 import java.awt.geom.AffineTransform;
20 import java.awt.geom.Ellipse2D;
21 import java.awt.geom.Path2D;
22 import java.awt.geom.PathIterator;
23 import java.awt.image.BufferedImage;
24 import java.io.BufferedOutputStream;
25 import java.io.ByteArrayOutputStream;
27 import java.io.FileNotFoundException;
28 import java.io.FileOutputStream;
29 import java.io.IOException;
30 import java.io.OutputStream;
31 import java.io.OutputStreamWriter;
32 import java.io.Writer;
33 import java.lang.reflect.Constructor;
34 import java.lang.reflect.InvocationTargetException;
35 import java.lang.reflect.Type;
36 import java.nio.charset.Charset;
37 import java.nio.charset.CharsetEncoder;
38 import java.text.AttributedCharacterIterator;
39 import java.util.HashMap;
41 import java.util.WeakHashMap;
43 import org.apache.batik.dom.GenericDOMImplementation;
44 import org.apache.batik.svggen.SVGGeneratorContext;
45 import org.apache.batik.svggen.SVGGraphics2D;
46 import org.apache.fop.Version;
47 import org.apache.fop.svg.PDFDocumentGraphics2D;
48 import org.apache.xmlgraphics.java2d.GraphicContext;
49 import org.apache.xmlgraphics.java2d.ps.AbstractPSDocumentGraphics2D;
50 import org.apache.xmlgraphics.java2d.ps.EPSDocumentGraphics2D;
51 import org.apache.xmlgraphics.java2d.ps.PSDocumentGraphics2D;
52 import org.apache.xmlgraphics.ps.DSCConstants;
53 import org.apache.xmlgraphics.ps.PSGenerator;
54 import org.scilab.forge.scirenderer.Canvas;
55 import org.scilab.forge.scirenderer.implementation.g2d.G2DCanvas;
56 import org.scilab.forge.scirenderer.implementation.g2d.G2DCanvasFactory;
57 import org.scilab.forge.scirenderer.implementation.jogl.JoGLCanvas;
58 import org.scilab.forge.scirenderer.implementation.jogl.JoGLCanvasFactory;
59 import org.scilab.modules.commons.ScilabCommonsUtils;
60 import org.scilab.modules.graphic_export.convertToPPM.PPMEncoder;
61 import org.scilab.modules.graphic_objects.figure.Figure;
62 import org.scilab.modules.graphic_objects.graphicController.GraphicController;
63 import org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties;
64 import org.scilab.modules.renderer.JoGLView.DrawerVisitor;
65 import org.w3c.dom.DOMImplementation;
66 import org.w3c.dom.Document;
69 * Main class to export
70 * Dependancies are put in inner classes to avoid the deps loading.
72 * @author Calixte DENIZET
76 public static final int SUCCESS = 0;
77 public static final int IOEXCEPTION_ERROR = 1;
78 public static final int INVALID_FILE = 2;
79 public static final int MEMORY_ERROR = 3;
80 public static final int UNKNOWN_ERROR = 4;
81 public static final int FILENOTFOUND_ERROR = 5;
82 public static final int NOWRITER_ERROR = 5;
84 private static final float DEFAULT_JPEG_COMPRESSION = 0.95f;
86 private static final String CLASSPATH_PDF_PS_EPS_EXPORT_NAME = "pdf_ps_eps_graphic_export";
87 private static final String CLASSPATH_SVG_EXPORT_NAME = "svg_graphic_export";
88 private static final String CLASSPATH_EMF_EXPORT_NAME = "emf_graphic_export";
90 private static final Map<DrawerVisitor, Exporter> visitorsToExp = new WeakHashMap<DrawerVisitor, Exporter>();
92 private static final Map<String, Integer> extToType = new HashMap<String, Integer>();
94 extToType.put("bmp", 1);
95 extToType.put("gif", 2);
96 extToType.put("jpeg", 3);
97 extToType.put("jpg", 3);
98 extToType.put("png", 4);
99 extToType.put("ppm", 5);
100 extToType.put("eps", 6);
101 extToType.put("pdf", 7);
102 extToType.put("svg", 8);
103 extToType.put("ps", 9);
104 extToType.put("pos", 9);
105 extToType.put("emf", 10);
108 private static boolean emfLoaded;
109 private static boolean svgLoaded;
110 private static boolean pdfLoaded;
112 public enum TYPE { PNG, JPEG, GIF, BMP, PPM, SVG, PS, EPS, PDF, EMF }
113 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, TYPE.EMF};
116 * @param type the image type
117 * @return true if bitmap image format
119 public static boolean isBitmapFormat(TYPE type) {
120 return type == TYPE.PNG || type == TYPE.JPEG || type == TYPE.GIF || type == TYPE.BMP || type == TYPE.PPM;
123 public static int getType(String ext) {
124 Integer type = extToType.get(ext.toLowerCase());
133 * Export in drawing in a Graphics2D
134 * @param uid the figure uid
135 * @param type the export type
136 * @param fileName the file name
137 * @param params the export paramaters
138 * @return the export status
140 public static int export(int uid, int type, String fileName, ExportParams params, boolean headless) {
141 // Check that the fileName contains an extension
142 int dotPosition = fileName.lastIndexOf('.'); // position of the dot
143 boolean extensionFound = false;
144 if (dotPosition > 0 && dotPosition <= fileName.length() - 2) {
145 extensionFound = true;
148 String extendedFilename = fileName;
149 if (!extensionFound) { // Add default extension if no one found
150 String[] extensions = {"png", "bmp", "gif", "jpeg", "png", "ppm", "eps", "pdf", "svg", "ps", "emf"};
151 extendedFilename = fileName + "." + extensions[type];
154 DrawerVisitor visitor = DrawerVisitor.getVisitor(uid);
155 if (visitor != null) {
156 Canvas canvas = visitor.getCanvas();
157 if (canvas instanceof JoGLCanvas && isBitmapFormat(types[type]) && visitor.getFigure().getVisible()) {
159 return exportBitmap(uid, type, extendedFilename, true, params);
160 } catch (OutOfMemoryError e) {
162 } catch (Throwable e) {
163 return UNKNOWN_ERROR;
168 return exportVectorial(uid, type, extendedFilename, params, headless);
172 * Export in drawing in a Graphics2D
173 * @param uid the figure uid
174 * @param type the export type
175 * @param fileName the file name
176 * @param params the export paramaters
177 * @return the export status
179 public static int exportVectorial(int uid, int type, String fileName, ExportParams params, boolean headless) {
180 if (fileName == null) {
184 File f = new File(fileName);
185 int ret = Utils.checkWritePermission(f);
186 if (ret != SUCCESS) {
191 return exportVectorial(uid, types[type], f, params, headless);
192 } catch (IOException e) {
193 if (e instanceof FileNotFoundException) {
194 return FILENOTFOUND_ERROR;
196 return IOEXCEPTION_ERROR;
201 * Export in drawing in a Graphics2D
202 * @param uid the figure uid
203 * @param type the export type
204 * @param file the file where to export
205 * @param params the export paramaters
207 public static int exportVectorial(int uid, TYPE type, File file, ExportParams params, boolean headless) throws IOException {
208 Figure figure = (Figure) GraphicController.getController().getObjectFromId(uid);
211 Exporter exporter = getExporter(type);
212 Integer[] dims = figure.getAxesSize();
214 int height = dims[1];
216 Graphics2D g2d = exporter.getGraphics2D(width, height, file, params);
218 return FILENOTFOUND_ERROR;
221 params.setParamsOnGraphics(g2d);
223 Canvas canvas = G2DCanvasFactory.createCanvas(g2d, width, height);
224 DrawerVisitor oldVisitor = DrawerVisitor.getVisitor(uid);
225 DrawerVisitor visitor = new DrawerVisitor(null, canvas, figure) {
227 public void updateObject(Integer id, int property) {
228 // Don't update during the export
232 public void visit(Figure figure) {
233 // Fix for bug 13676: allow vectorial export even if the figure is invisible
234 synchronized (figure) {
236 if (!figure.getVisible()) {
237 askAcceptVisitor(figure.getChildren());
244 canvas.setMainDrawer(visitor);
247 } catch (OutOfMemoryError e) {
249 } catch (IOException e) {
251 } catch (Throwable e) {
252 return UNKNOWN_ERROR;
254 GraphicController.getController().unregister(visitor);
255 DrawerVisitor.changeVisitor(figure, oldVisitor);
258 visitorsToExp.remove(visitor);
262 DrawerVisitor visitor = DrawerVisitor.getVisitor(uid);
263 if (visitor.getCanvas() instanceof G2DCanvas) {
264 G2DCanvas canvas = (G2DCanvas) visitor.getCanvas();
266 Exporter exporter = null;
269 exporter = visitorsToExp.get(visitor);
270 if (exporter != null) {
271 exporter.file = file;
274 } catch (OutOfMemoryError e) {
276 } catch (IOException e) {
278 } catch (Throwable e) {
279 return UNKNOWN_ERROR;
281 if (exporter != null) {
284 visitorsToExp.remove(visitor);
286 DrawerVisitor.changeVisitor(figure, null);
287 GraphicController.getController().unregister(visitor);
297 * Export in getting a buffered image from JoGL
298 * @param uid the figure uid
299 * @param type the export type
300 * @param fileName the file name
301 * @param fromScreen if true, then use the screen view
302 * @param params the export paramaters
303 * @return the export status
305 public static int exportBitmap(int uid, int type, String fileName, boolean fromScreen, ExportParams params) {
306 if (fileName == null) {
310 File f = new File(fileName);
311 int ret = Utils.checkWritePermission(f);
312 if (ret != SUCCESS) {
317 exportBitmap(uid, types[type], f, fromScreen, params);
318 } catch (IOException e) {
319 if (e instanceof FileNotFoundException) {
320 return FILENOTFOUND_ERROR;
322 return IOEXCEPTION_ERROR;
329 * Export in getting a buffered image from JoGL
330 * @param uid the figure uid
331 * @param type the export type
332 * @param file the file where to export
333 * @param fromScreen if true, then use the screen view
334 * @param params the export paramaters
336 public static void exportBitmap(int uid, TYPE type, File file, boolean fromScreen, ExportParams params) throws IOException {
337 if (isBitmapFormat(type)) {
338 JoGLCanvas joglCanvas = null;
340 DrawerVisitor visitor = DrawerVisitor.getVisitor(uid);
341 Canvas canvas = visitor.getCanvas();
342 if (canvas instanceof JoGLCanvas) {
343 joglCanvas = (JoGLCanvas) canvas;
346 Figure figure = (Figure) GraphicController.getController().getObjectFromId(uid);
347 Integer[] dims = figure.getAxesSize();
348 DrawerVisitor oldVisitor = DrawerVisitor.getVisitor(uid);
349 joglCanvas = (JoGLCanvas) JoGLCanvasFactory.createCanvas(dims[0], dims[1]);
350 DrawerVisitor visitor = new DrawerVisitor(null, joglCanvas, figure) {
352 public void updateObject(Integer id, int property) {
353 // Don't update during the export
357 public void deleteObject(Integer id) {
358 // Don't delete during the export
361 joglCanvas.setMainDrawer(visitor);
363 GraphicController.getController().unregister(visitor);
364 DrawerVisitor.changeVisitor(figure, oldVisitor);
367 if (joglCanvas != null) {
368 BufferedImage image = joglCanvas.getImage();
369 PNGExporter exporter = (PNGExporter) getExporter(type);
370 exporter.setImage(file, image, params);
371 int exportStatus = exporter.write();
373 if (isBitmapFormat(type) && exportStatus == Export.NOWRITER_ERROR) {
374 // If export fails because no writer was found for bitmap format
375 // ==> Retry without Alpha channel in image
376 // Needed after JoGL 2.2.4 version
377 image = joglCanvas.getImage(false);
378 exporter = (PNGExporter) getExporter(type);
379 exporter.setImage(file, image, params);
389 * Export in drawing in a Graphics2D
390 * @param uid the figure uid
391 * @param type the export type
392 * @param file the file where to export
393 * @param params the export paramaters
395 public static void setVisitor(int uid, int type, final ExportParams params) {
396 final Exporter exporter = getExporter(types[type]);
397 Figure figure = (Figure) GraphicController.getController().getObjectFromId(uid);
398 final Integer[] dims = figure.getAxesSize();
400 int height = dims[1];
402 final Graphics2D g2d = exporter.getGraphics2D(width, height, null, params);
403 params.setParamsOnGraphics(g2d);
405 final G2DCanvas canvas = G2DCanvasFactory.createCanvas(g2d, width, height);
406 canvas.disableDraw();
407 DrawerVisitor visitor = new DrawerVisitor(null, canvas, figure) {
409 public void deleteObject(Integer id) {
410 // Don't delete during the export
414 public void updateObject(Integer id, int property) {
415 if (needUpdate(id, property)) {
416 axesDrawer.update(id, property);
417 if (property == GraphicObjectProperties.__GO_AXES_SIZE__) {
418 Integer[] size = getFigure().getAxesSize();
419 if (size[0] != dims[0] || size[1] != dims[1]) {
420 Graphics2D newg2d = exporter.getGraphics2D(size[0], size[1], null, params);
421 params.setParamsOnGraphics(newg2d);
422 canvas.setGraphics(newg2d, size[0], size[1]);
428 } else if (property == GraphicObjectProperties.__GO_ANTIALIASING__) {
429 canvas.setAntiAliasingLevel(getFigure().getAntialiasing());
434 visitor.setDrawingTools(canvas.getDrawingTools());
435 canvas.setMainDrawer(visitor);
436 visitorsToExp.put(visitor, exporter);
440 * Get an exporter from a type
441 * @param type the exporter type.
442 * @return the corresponding exporter/
444 private static Exporter getExporter(TYPE type) {
447 return new PNGExporter();
449 return new GIFExporter();
451 return new JPEGExporter();
453 return new BMPExporter();
455 return new PPMExporter();
458 ScilabCommonsUtils.loadOnUse(CLASSPATH_SVG_EXPORT_NAME);
461 return new SVGExporter();
464 return new PDFExporter();
467 return new PSExporter();
470 return new EPSExporter();
473 ScilabCommonsUtils.loadOnUse(CLASSPATH_EMF_EXPORT_NAME);
476 return new EMFExporter();
485 * Load the PDF/PS/EPS dependencies
487 private static final void loadPDF() {
489 ScilabCommonsUtils.loadOnUse(CLASSPATH_PDF_PS_EPS_EXPORT_NAME);
495 * Interface to export
497 private static abstract class Exporter {
502 * @param width graphics width
503 * @param height graphisc height
504 * @param file the file
505 * @param params the export parameters
507 abstract Graphics2D getGraphics2D(int width, int height, File file, ExportParams params);
512 abstract int write() throws IOException;
514 abstract void dispose();
520 private static class PNGExporter extends Exporter {
522 protected BufferedImage image;
523 protected Graphics2D g2d;
524 protected ExportParams params;
526 public PNGExporter() { }
528 public void setImage(File file, BufferedImage image, ExportParams params) {
531 this.params = params;
535 public Graphics2D getGraphics2D(int width, int height, File file, ExportParams params) {
537 this.params = params;
538 image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
539 g2d = image.createGraphics();
545 public int write() throws IOException {
546 return ExportBitmap.writeFile(image, "png", file);
550 public void dispose() {
560 private static class GIFExporter extends PNGExporter {
562 public GIFExporter() { }
565 public int write() throws IOException {
566 return ExportBitmap.writeFile(image, "gif", file);
573 private static class BMPExporter extends PNGExporter {
575 public BMPExporter() { }
578 public Graphics2D getGraphics2D(int width, int height, File file, ExportParams params) {
580 this.params = params;
581 image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
582 g2d = image.createGraphics();
588 public int write() throws IOException {
589 return ExportBitmap.writeFile(image, "bmp", file);
596 private static class JPEGExporter extends BMPExporter {
598 public JPEGExporter() { }
601 public int write() throws IOException {
602 if (params.compressionQuality == -1) {
603 return ExportBitmap.writeJPEG(image, DEFAULT_JPEG_COMPRESSION, file);
605 return ExportBitmap.writeJPEG(image, params.compressionQuality, file);
613 private static class PPMExporter extends BMPExporter {
615 public PPMExporter() { }
618 public int write() throws IOException {
619 OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
620 PPMEncoder encoder = new PPMEncoder(image, out);
621 int[] pixels = image.getRGB(0, 0, image.getWidth(), image.getHeight(), null, 0, image.getWidth());
622 encoder.encodeStart(image.getWidth(), image.getHeight());
623 encoder.encodePixels(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());
626 return Export.SUCCESS;
633 private static class SVGExporter extends Exporter {
635 private SVGGraphics2D g2d;
636 private ExportParams params;
638 public SVGExporter() { }
641 public Graphics2D getGraphics2D(int width, int height, File file, ExportParams params) {
643 this.params = params;
644 DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
645 Document document = domImpl.createDocument("http://www.w3.org/2000/svg", "svg", null);
646 final SVGGeneratorContext ctx = SVGGeneratorContext.createDefault(document);
647 ctx.setComment("Generated by Scilab with Batik SVG Generator");
648 // TODO: better handle of LaTeX fonts (should remove the 'true' below and include the font in the SVG)
649 // same thing for PDF & co...
650 ctx.setEmbeddedFontsOn(true);
651 g2d = new SVGGraphics2D(ctx, false) {
654 public void drawString(String s, float x, float y) {
655 textAsShapes = getFont().getFontName().startsWith("jlm");
656 super.drawString(s, x, y);
660 public void drawString(AttributedCharacterIterator ati, float x, float y) {
661 textAsShapes = getFont().getFontName().startsWith("jlm");
662 super.drawString(ati, x, y);
665 if (params.orientation == ExportParams.LANDSCAPE) {
666 g2d.setSVGCanvasSize(new Dimension(height, width));
667 AffineTransform transf = AffineTransform.getRotateInstance(Math.PI / 2);
668 transf.preConcatenate(AffineTransform.getTranslateInstance(height, 0));
669 g2d.setTransform(transf);
671 g2d.setSVGCanvasSize(new Dimension(width, height));
677 public int write() throws IOException {
678 boolean useCSS = true;
679 OutputStream svgs = new BufferedOutputStream(new FileOutputStream(file));
680 Writer out = new OutputStreamWriter(svgs, "UTF-8");
681 g2d.stream(out, useCSS);
684 return Export.SUCCESS;
688 public void dispose() {
698 private static class PDFExporter extends Exporter {
700 private OutputStream out;
701 private PDFDocumentGraphics2D g2d;
702 private ExportParams params;
703 private ByteArrayOutputStream buffer;
705 public PDFExporter() { }
708 public Graphics2D getGraphics2D(int width, int height, File file, ExportParams params) {
710 this.params = params;
713 buffer = new ByteArrayOutputStream();
714 out = new BufferedOutputStream(buffer);
716 out = new BufferedOutputStream(new FileOutputStream(file));
718 g2d = new PDFDocumentGraphics2D(true);
719 g2d.setupDefaultFontInfo();
720 g2d.getPDFDocument().getInfo().setProducer("Generated by Scilab with Apache FOP Version " + Version.getVersion());
721 g2d.setGraphicContext(new GraphicContext());
722 if (params.orientation == ExportParams.LANDSCAPE) {
723 g2d.setupDocument(out, height, width);
724 g2d.setSVGDimension(height, width);
725 double s = PDFDocumentGraphics2D.NORMAL_PDF_RESOLUTION / g2d.getDeviceDPI();
726 AffineTransform transf = AffineTransform.getRotateInstance(Math.PI / 2);
727 transf.preConcatenate(AffineTransform.getTranslateInstance(height / s, 0));
728 g2d.setTransform(transf);
730 g2d.setupDocument(out, width, height);
731 g2d.setSVGDimension(width, height);
733 } catch (IOException e) { }
739 public int write() throws IOException {
743 if (buffer != null && file != null) {
744 FileOutputStream fos = new FileOutputStream(file);
753 return Export.SUCCESS;
757 public void dispose() {
765 private static class PSExporter extends Exporter {
767 protected OutputStream out;
768 protected AbstractPSDocumentGraphics2D g2d;
769 protected ExportParams params;
770 protected ByteArrayOutputStream buffer;
772 public PSExporter() { }
775 public Graphics2D getGraphics2D(int width, int height, File file, final ExportParams params) {
777 this.params = params;
780 buffer = new ByteArrayOutputStream();
781 out = new BufferedOutputStream(buffer);
783 out = new BufferedOutputStream(new FileOutputStream(file));
785 g2d = new PSDocumentGraphics2D(true, out, width, height) {
787 protected void writePageHeader() throws IOException {
788 super.writePageHeader();
789 if (params.orientation == ExportParams.LANDSCAPE) {
790 gen.writeDSCComment(DSCConstants.PAGE_ORIENTATION, "Landscape");
792 gen.writeDSCComment(DSCConstants.PAGE_ORIENTATION, "Portrait");
794 gen.writeln("/ReEncode { /MyEncoding exch def exch findfont dup length dict begin {def} forall /Encoding MyEncoding def currentdict end definefont } def");
795 gen.writeln("/Helvetica /HelveticaLatin1 ISOLatin1Encoding ReEncode");
796 gen.writeln("/Times /TimesLatin1 ISOLatin1Encoding ReEncode");
797 gen.writeln("/DP {/Points exch def N Points 0 get Points 1 get M 2 2 Points length 1 sub {/i exch def Points i get Points i 1 add get L}for} def");
801 public void drawString(String s, float x, float y) {
802 if (s != null && !s.isEmpty()) {
803 CharsetEncoder encoder = Charset.forName("ISO-8859-1").newEncoder();
804 if (encoder.canEncode(s)) {
805 Font font = getFont();
806 boolean sserif = font.getName().equals("SansSerif");
807 boolean serif = font.getName().equals("Serif");
808 if (sserif || serif) {
811 establishColor(getColor());
812 gen.writeln((sserif ? "/HelveticaLatin1" : "/TimesLatin1") + " " + gen.formatDouble(getFont().getSize()) + " F");
814 gen.saveGraphicsState();
815 Shape imclip = getClip();
818 AffineTransform trans = getTransform();
819 boolean newTransform = gen.getCurrentState().checkTransform(trans) && !trans.isIdentity();
822 gen.concatMatrix(trans);
825 gen.writeln(gen.formatDouble(x)
826 + " " + gen.formatDouble(y)
829 StringBuffer buf = new StringBuffer("(");
830 for (int i = 0; i < s.length(); i++) {
831 PSGenerator.escapeChar(s.charAt(i), buf);
835 gen.writeln(buf.toString());
837 gen.restoreGraphicsState();
838 } catch (IOException e) {
839 System.err.println(e);
846 super.drawString(s, x, y);
851 public boolean shouldBeClipped(Shape clip, Shape s) {
852 if (clip == null || s == null) {
856 return clip.getBounds2D().intersects(s.getBounds2D());
860 public int processShape(Shape s, boolean b) throws IOException {
861 if (s instanceof Ellipse2D.Double) {
862 Ellipse2D.Double ell = (Ellipse2D.Double) s;
863 if (ell.height == ell.width) {
864 gen.writeln(gen.formatDouble(ell.x + ell.width / 2)
865 + " " + gen.formatDouble(ell.y + ell.height / 2)
866 + " " + gen.formatDouble(ell.width / 2)
867 + " " + gen.formatDouble(0d)
868 + " " + gen.formatDouble(360d)
871 return PathIterator.WIND_NON_ZERO;
873 } else if (s instanceof Path2D) {
874 StringBuilder buffer = new StringBuilder();
875 double[] coords = new double[6];
876 PathIterator it = ((Path2D) s).getPathIterator(new AffineTransform());
878 int type = it.currentSegment(coords);
879 if (type == PathIterator.SEG_MOVETO) {
880 buffer.append("[").append(gen.formatDouble(coords[0])).append(" ").append(gen.formatDouble(coords[1]));
883 return super.processShape(s, b);
886 return super.processShape(s, b);
889 for (; !it.isDone(); it.next()) {
890 int type = it.currentSegment(coords);
891 if (type == PathIterator.SEG_LINETO) {
892 buffer.append(" ").append(gen.formatDouble(coords[0])).append(" ").append(gen.formatDouble(coords[1]));
894 return super.processShape(s, b);
897 buffer.append("] DP");
898 gen.writeln(buffer.toString());
899 return PathIterator.WIND_NON_ZERO;
902 return super.processShape(s, b);
905 g2d.setGraphicContext(new GraphicContext());
906 } catch (IOException e) { }
912 public int write() throws IOException {
916 if (buffer != null && file != null) {
917 FileOutputStream fos = new FileOutputStream(file);
926 return Export.SUCCESS;
930 public void dispose() {
940 private static class EPSExporter extends PSExporter {
942 public EPSExporter() { }
945 public Graphics2D getGraphics2D(int width, int height, File file, final ExportParams params) {
947 this.params = params;
950 buffer = new ByteArrayOutputStream();
951 out = new BufferedOutputStream(buffer);
953 out = new BufferedOutputStream(new FileOutputStream(file));
955 g2d = new EPSDocumentGraphics2D(true) {
957 protected void writePageHeader() throws IOException {
958 super.writePageHeader();
959 if (params.orientation == ExportParams.LANDSCAPE) {
960 gen.writeDSCComment(DSCConstants.PAGE_ORIENTATION, "Landscape");
962 gen.writeDSCComment(DSCConstants.PAGE_ORIENTATION, "Portrait");
964 gen.writeln("/ReEncode { /MyEncoding exch def exch findfont dup length dict begin {def} forall /Encoding MyEncoding def currentdict end definefont } def");
965 gen.writeln("/Helvetica /HelveticaLatin1 ISOLatin1Encoding ReEncode");
966 gen.writeln("/Times /TimesLatin1 ISOLatin1Encoding ReEncode");
968 // DP macro is used to draw an array as a polyline
969 gen.writeln("/DP {/Points exch def Points 0 get Points 1 get M 2 2 Points length 1 sub {/i exch def Points i get Points i 1 add get L}for} def");
973 public boolean shouldBeClipped(Shape clip, Shape s) {
974 if (clip == null || s == null) {
978 return clip.getBounds2D().intersects(s.getBounds2D());
982 public void drawString(String s, float x, float y) {
983 if (s != null && !s.isEmpty()) {
984 CharsetEncoder encoder = Charset.forName("ISO-8859-1").newEncoder();
985 if (encoder.canEncode(s)) {
986 Font font = getFont();
987 boolean sserif = font.getName().equals("SansSerif");
988 boolean serif = font.getName().equals("Serif");
989 if (sserif || serif) {
992 establishColor(getColor());
993 gen.writeln((sserif ? "/HelveticaLatin1" : "/TimesLatin1") + " " + gen.formatDouble(getFont().getSize()) + " F");
995 gen.saveGraphicsState();
996 Shape imclip = getClip();
999 AffineTransform trans = getTransform();
1000 boolean newTransform = gen.getCurrentState().checkTransform(trans) && !trans.isIdentity();
1003 gen.concatMatrix(trans);
1006 gen.writeln(gen.formatDouble(x)
1007 + " " + gen.formatDouble(y)
1010 StringBuffer buf = new StringBuffer("(");
1011 for (int i = 0; i < s.length(); i++) {
1012 PSGenerator.escapeChar(s.charAt(i), buf);
1016 gen.writeln(buf.toString());
1018 gen.restoreGraphicsState();
1019 } catch (IOException e) {
1020 System.err.println(e);
1027 super.drawString(s, x, y);
1032 public int processShape(Shape s, boolean b) throws IOException {
1033 if (s instanceof Ellipse2D.Double) {
1034 Ellipse2D.Double ell = (Ellipse2D.Double) s;
1035 if (ell.height == ell.width) {
1036 gen.writeln(gen.formatDouble(ell.x + ell.width / 2)
1037 + " " + gen.formatDouble(ell.y + ell.height / 2)
1038 + " " + gen.formatDouble(ell.width / 2)
1039 + " " + gen.formatDouble(0d)
1040 + " " + gen.formatDouble(360d)
1043 return PathIterator.WIND_NON_ZERO;
1045 } else if (s instanceof Path2D) {
1046 StringBuilder buffer = new StringBuilder();
1047 double[] coords = new double[6];
1048 PathIterator it = ((Path2D) s).getPathIterator(new AffineTransform());
1050 int type = it.currentSegment(coords);
1051 if (type == PathIterator.SEG_MOVETO) {
1052 buffer.append("[").append(gen.formatDouble(coords[0])).append(" ").append(gen.formatDouble(coords[1]));
1055 return super.processShape(s, b);
1058 return super.processShape(s, b);
1061 for (; !it.isDone(); it.next()) {
1062 int type = it.currentSegment(coords);
1063 if (type == PathIterator.SEG_LINETO) {
1064 buffer.append(" ").append(gen.formatDouble(coords[0])).append(" ").append(gen.formatDouble(coords[1]));
1066 return super.processShape(s, b);
1069 buffer.append("] DP");
1070 gen.writeln(buffer.toString());
1071 return PathIterator.WIND_NON_ZERO;
1074 return super.processShape(s, b);
1078 g2d.setupDocument(out, width, height);
1079 g2d.setGraphicContext(new GraphicContext());
1080 } catch (IOException e) { }
1089 private static class EMFExporter extends Exporter {
1091 private OutputStream out;
1092 private Class<Graphics2D> g2dClass;
1093 private Constructor<Graphics2D> g2dCtor;
1094 private Graphics2D g2d;
1095 private ByteArrayOutputStream buffer;
1097 public EMFExporter() {
1099 g2dClass = (Class<Graphics2D>) Class.forName("org.freehep.graphicsio.emf.EMFGraphics2D");
1100 } catch (ClassNotFoundException e) {
1101 throw new RuntimeException("This Scilab build does not provide EMF support");
1104 final Constructor[] ctors = g2dClass.getDeclaredConstructors();
1105 Constructor ctor = null;
1106 for (int i = 0; i < ctors.length; i++) {
1108 final Type[] args = ctor.getGenericParameterTypes();
1109 if (args.length != 2) {
1112 if (args[0] != OutputStream.class) {
1115 if (args[1] != Dimension.class) {
1125 public Graphics2D getGraphics2D(int width, int height, File file, final ExportParams params) {
1129 buffer = new ByteArrayOutputStream();
1130 out = new BufferedOutputStream(buffer);
1132 out = new BufferedOutputStream(new FileOutputStream(file));
1134 if (params.orientation == ExportParams.LANDSCAPE) {
1135 g2d = g2dCtor.newInstance(out, new Dimension(height, width));
1136 g2dClass.getMethod("startExport").invoke(g2d);
1137 AffineTransform transf = AffineTransform.getRotateInstance(Math.PI / 2);
1138 transf.preConcatenate(AffineTransform.getTranslateInstance(height, 0));
1139 g2d.setTransform(transf);
1141 g2d = g2dCtor.newInstance(out, new Dimension(width, height));
1142 g2dClass.getMethod("startExport").invoke(g2d);
1144 } catch (IOException e) {
1145 } catch (IllegalAccessException e) {
1146 } catch (IllegalArgumentException e) {
1147 } catch (InvocationTargetException e) {
1148 } catch (NoSuchMethodException e) {
1149 } catch (SecurityException e) {
1150 } catch (InstantiationException e) {
1157 public int write() throws IOException {
1160 g2dClass.getMethod("endExport").invoke(g2d);
1161 g2dClass.getMethod("closeStream").invoke(g2d);
1162 } catch (IllegalAccessException e) {
1163 } catch (IllegalArgumentException e) {
1164 } catch (InvocationTargetException e) {
1165 } catch (NoSuchMethodException e) {
1166 } catch (SecurityException e) {
1169 if (buffer != null && file != null) {
1170 FileOutputStream fos = new FileOutputStream(file);
1171 buffer.writeTo(fos);
1179 return Export.SUCCESS;
1183 public void dispose() {