View Javadoc

1   // Copyright 2003-2007, FreeHEP.
2   package org.freehep.graphicsio.java;
3   
4   import java.awt.AlphaComposite;
5   import java.awt.BasicStroke;
6   import java.awt.Color;
7   import java.awt.Component;
8   import java.awt.Composite;
9   import java.awt.Dimension;
10  import java.awt.Font;
11  import java.awt.FontMetrics;
12  import java.awt.GradientPaint;
13  import java.awt.Graphics;
14  import java.awt.GraphicsConfiguration;
15  import java.awt.Image;
16  import java.awt.Insets;
17  import java.awt.Paint;
18  import java.awt.Polygon;
19  import java.awt.Rectangle;
20  import java.awt.RenderingHints;
21  import java.awt.Shape;
22  import java.awt.Stroke;
23  import java.awt.TexturePaint;
24  import java.awt.Toolkit;
25  import java.awt.font.FontRenderContext;
26  import java.awt.font.GlyphVector;
27  import java.awt.font.ImageGraphicAttribute;
28  import java.awt.font.ShapeGraphicAttribute;
29  import java.awt.geom.AffineTransform;
30  import java.awt.geom.PathIterator;
31  import java.awt.geom.Point2D;
32  import java.awt.geom.Rectangle2D;
33  import java.awt.image.BufferedImage;
34  import java.awt.image.BufferedImageOp;
35  import java.awt.image.ImageObserver;
36  import java.awt.image.RenderedImage;
37  import java.awt.image.AffineTransformOp;
38  import java.awt.image.ConvolveOp;
39  import java.awt.image.Kernel;
40  import java.awt.image.renderable.RenderableImage;
41  import java.io.ByteArrayOutputStream;
42  import java.io.File;
43  import java.io.FileNotFoundException;
44  import java.io.FileOutputStream;
45  import java.io.OutputStream;
46  import java.io.OutputStreamWriter;
47  import java.io.PrintWriter;
48  import java.io.IOException;
49  import java.io.BufferedOutputStream;
50  import java.io.StringWriter;
51  import java.text.AttributedCharacterIterator;
52  import java.util.HashMap;
53  import java.util.Iterator;
54  import java.util.Map;
55  import java.util.Properties;
56  import java.util.SortedSet;
57  import java.util.TooManyListenersException;
58  import java.util.TreeSet;
59  import java.util.HashSet;
60  
61  import org.freehep.graphics2d.TagString;
62  import org.freehep.graphics2d.VectorGraphics;
63  import org.freehep.graphicsio.png.PNGEncoder;
64  import org.freehep.util.UserProperties;
65  import org.freehep.util.Value;
66  import org.freehep.util.io.IndentPrintWriter;
67  import org.freehep.util.io.LineNumberWriter;
68  
69  /**
70   * Exports the java calls made to Graphics2D as source code, with the associated
71   * class, field and method definitions, resulting in a class which, when run
72   * will produce the same display. Generating such source code may be helpful in
73   * setting up test cases without a lot of machinery around it and in debugging
74   * problems for different formats.
75   * 
76   * Due to size limitations in the bytecode, see Lindholm and Yellin, "The Java
77   * Virtual Machine Specification", p. 136-137, 1997, the following was taken
78   * into account:
79   * <ul>
80   * <li>Maximum size of bytecode is 65535 per method; we chain paint() methods
81   * and limit them by number of lines (our best approximation for bytecode).
82   * <li>Maximum number of constants is 65535 per class; we generate separate
83   * inner classes for each paint method (see above) so that the number of
84   * constants is limited.
85   * </ul>
86   * 
87   * @author Mark Donszelmann
88   * @version $Id: JAVAGraphics2D.java 12618 2007-06-07 17:27:14Z duns $
89   */
90  public class JAVAGraphics2D extends VectorGraphics implements
91          LineNumberWriter.LineNumberListener {
92  
93      private static final int MAX_LINES_PER_METHOD = 200;
94  
95      private Map /* <VectorGraphics, Value> */vg = new HashMap();
96  
97      private SortedSet /*<String>*/ imports = new TreeSet();
98      
99      private Value vgIndex = new Value().set(0);
100 
101     private Value paintSequenceNo = new Value().set(0);
102 
103     private Value blockLevel = new Value().set(0);
104 
105     private UserProperties properties;
106 
107     private int width = 800;
108 
109     private int height = 600;
110 
111     private String className = "TemporaryName";
112 
113     private OutputStream os;
114     
115     private ByteArrayOutputStream bos;
116     
117     private LineNumberWriter lineWriter;
118 
119     private IndentPrintWriter out;
120 
121     private Color backgroundColor;
122 
123     private Color color = Color.WHITE;
124 
125     private Paint paint = Color.BLACK;
126 
127     private String creator = "FreeHEP JAVAGraphics2D";
128 
129     private int colorMode = 0; // CHECK
130 
131     private Stroke stroke = new BasicStroke(); // CHECK
132 
133     private AffineTransform transform = new AffineTransform();
134 
135     private RenderingHints hints = new RenderingHints(null);
136 
137     private boolean isDeviceIndependent;
138 
139     private Composite composite;
140 
141     private Shape clip;
142 
143     private Font font = new Font("Serif", Font.PLAIN, 12);
144 
145     private static final String rootKey = JAVAGraphics2D.class.getName();
146 
147     public static final String PACKAGE_NAME = rootKey + ".PackageName";
148 
149     /**
150      * if set to true image in the resulting .java file
151      * are referenced by complete path of creation,
152      * default false
153      */
154     public static final String COMPLETE_IMAGE_PATHS = rootKey + ".CompleteImagePath";
155 
156     /**
157      * if set to true images are stored as byte[] inside the .java file,
158      * default false.
159      * Setting this option to true can lead to a not compilable .java file
160      * because of the its size.
161      */
162     public static final String EMBED_IMAGES = rootKey + ".EmbedImages";
163 
164     private static final UserProperties defaultProperties = new UserProperties();
165 
166     /**
167      * file name prefix for external images include the full path
168      */
169     private final static String imagePrefix = "-image-";
170 
171     /**
172      * Path to store the class and its images in with a "/" at the end
173      */
174     private String classPath;
175 
176     static {
177         defaultProperties.setProperty(PACKAGE_NAME, "");
178         defaultProperties.setProperty(COMPLETE_IMAGE_PATHS, false);
179         defaultProperties.setProperty(EMBED_IMAGES, false);
180     }
181 
182     public static Properties getDefaultProperties() {
183         return defaultProperties;
184     }
185 
186     public static void setDefaultProperties(Properties newProperties) {
187         defaultProperties.setProperties(newProperties);
188     }
189 
190     public final static String version = "$Revision: 12618 $";
191 
192     public JAVAGraphics2D(File file, Dimension size)
193             throws FileNotFoundException {
194         this(new FileOutputStream(file), size);
195         init(file);
196     }
197 
198     public JAVAGraphics2D(File file, Component component)
199             throws FileNotFoundException {
200         this(new FileOutputStream(file), component);
201         init(file);
202     }
203 
204     public JAVAGraphics2D(OutputStream os, Dimension size) {
205         super();
206         init(os);
207         width = size.width;
208         height = size.height;
209     }
210 
211     public JAVAGraphics2D(OutputStream os, Component component) {
212         super();
213         init(os);
214         width = component.getWidth();
215         height = component.getHeight();
216         font = component.getFont();
217         color = component.getForeground();
218         paint = component.getForeground();
219         backgroundColor = component.getBackground();
220     }
221 
222     private void init(File file) {
223         init();
224 
225         // determine className
226         String name = file.getName();
227         className = name.substring(0, name.lastIndexOf(".java"));
228 
229         // determine path for external images
230         classPath = file.getParentFile().getAbsolutePath().replace('\\', '/') + "/";
231     }
232 
233     private void init(OutputStream os) {
234         init();
235         this.os = os;
236         vg.put(this, new Integer(vgIndex.getInt()));
237         bos = new ByteArrayOutputStream();
238         lineWriter = new LineNumberWriter(new OutputStreamWriter(bos));
239         lineWriter.setLineNumber(1);
240         out = new IndentPrintWriter(lineWriter);
241         out.setIndentString("    ");
242         try {
243             lineWriter.addLineNumberListener(this, MAX_LINES_PER_METHOD);
244         } catch (TooManyListenersException tmle) {
245             System.err.println(tmle);
246         }
247     }
248 
249     private void init() {
250         initProperties(getDefaultProperties());
251         isDeviceIndependent = false;
252         composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER);
253     }
254 
255     protected JAVAGraphics2D(JAVAGraphics2D graphics) {
256         vg = graphics.vg;
257         vgIndex = graphics.vgIndex;
258         imports = graphics.imports;
259         paintSequenceNo = graphics.paintSequenceNo;
260         blockLevel = graphics.blockLevel;
261 
262         properties = graphics.properties;
263         width = graphics.width;
264         height = graphics.height;
265         className = graphics.className;
266         os = graphics.os;
267         bos = graphics.bos;
268         out = graphics.out;
269         backgroundColor = graphics.backgroundColor;
270         color = graphics.color;
271         paint = graphics.paint;
272         creator = graphics.creator;
273         colorMode = graphics.colorMode;
274         stroke = graphics.stroke;
275         transform = graphics.transform;
276         hints = graphics.hints;
277 
278         isDeviceIndependent = graphics.isDeviceIndependent;
279         composite = graphics.composite;
280         clip = graphics.clip;
281         font = graphics.font;
282 
283         vgIndex.set(vgIndex.getInt() + 1);
284         vg.put(this, new Integer(vgIndex.getInt()));
285     }
286 
287     public void setProperties(Properties newProperties) {
288         if (newProperties == null)
289             return;
290         properties.setProperties(newProperties);
291     }
292 
293     protected void initProperties(Properties defaults) {
294         properties = new UserProperties();
295         properties.setProperties(defaults);
296     }
297 
298     public Properties getProperties() {
299         return properties;
300     }
301 
302     public String getProperty(String key) {
303         return properties.getProperty(key);
304     }
305 
306     public Color getPropertyColor(String key) {
307         return properties.getPropertyColor(key);
308     }
309 
310     public Rectangle getPropertyRectangle(String key) {
311         return properties.getPropertyRectangle(key);
312     }
313 
314     public Insets getPropertyInsets(String key) {
315         return properties.getPropertyInsets(key);
316     }
317 
318     public Dimension getPropertyDimension(String key) {
319         return properties.getPropertyDimension(key);
320     }
321 
322     public int getPropertyInt(String key) {
323         return properties.getPropertyInt(key);
324     }
325 
326     public double getPropertyDouble(String key) {
327         return properties.getPropertyDouble(key);
328     }
329 
330     public boolean isProperty(String key) {
331         return properties.isProperty(key);
332     }
333 
334     public void clearRect(int x, int y, int width, int height) {
335         out.println(vg() + ".clearRect(" + x + ", " + y + ", " + width + ", "
336                 + height + ");");
337     }
338 
339     public void clipRect(int x, int y, int width, int height) {
340         out.println(vg() + ".clipRect(" + x + ", " + y + ", " + width + ", "
341                 + height + ");");
342         clip = new Rectangle(x, y, width, height);
343     }
344 
345     public void copyArea(int x, int y, int width, int height, int dx, int dy) {
346         out.println(vg() + ".copyArea(" + x + ", " + y + ", " + width + ", "
347                 + height + ", " + dx + ", " + dy + ");");
348     }
349 
350     public Graphics create() {
351         JAVAGraphics2D g = new JAVAGraphics2D(this);
352         out.println(g.vg() + " = (VectorGraphics)" + vg() + ".create();");
353         return g;
354     }
355 
356     public Graphics create(int x, int y, int width, int height) {
357         JAVAGraphics2D g = new JAVAGraphics2D(this);
358         out.println(g.vg() + " = (VectorGraphics)" + vg() + ".create(" + x
359                 + ", " + y + ", " + width + ", " + height + ");");
360         return g;
361     }
362 
363     public Graphics create(double x, double y, double width, double height) {
364         JAVAGraphics2D g = new JAVAGraphics2D(this);
365         out.println(g.vg() + " = (VectorGraphics)" + vg() + ".create(" + x
366                 + ", " + y + ", " + width + ", " + height + ");");
367         return g;
368     }
369 
370     public void dispose() {
371         out.println(vg() + ".dispose();");
372     }
373 
374     public void draw3DRect(int x, int y, int width, int height, boolean raised) {
375         out.println(vg() + ".draw3DRect(" + x + ", " + y + ", " + width + ", "
376                 + height + ", " + raised + ");");
377     }
378 
379     public void fill3DRect(int x, int y, int width, int height, boolean raised) {
380         out.println(vg() + ".fill3DRect(" + x + ", " + y + ", " + width + ", "
381                 + height + ", " + raised + ");");
382     }
383 
384     public void drawArc(int x, int y, int width, int height, int startAngle,
385             int arcAngle) {
386         out.println(vg() + ".drawArc(" + x + ", " + y + ", " + width + ", "
387                 + height + ", " + startAngle + ", " + arcAngle + ");");
388     }
389 
390     public void fillArc(int x, int y, int width, int height, int startAngle,
391             int arcAngle) {
392         out.println(vg() + ".drawArc(" + x + ", " + y + ", " + width + ", "
393                 + height + ", " + startAngle + ", " + arcAngle + ");");
394     }
395 
396     public void drawBytes(byte[] data, int offset, int length, int x, int y) {
397         out.print(vg() + ".drawBytes(");
398         write(data, offset + length);
399         out.println(", " + offset + ", " + length + ", " + x + ", " + y + ");");
400     }
401 
402     public void drawChars(char[] data, int offset, int length, int x, int y) {
403         block();
404         out.print(vg() + ".drawChars(");
405         write(data, offset + length);
406         unblock();
407         out.println(", " + offset + ", " + length + ", " + x + ", " + y + ");");
408     }
409 
410     public boolean drawImage(Image image, int x, int y, ImageObserver observer) {
411         block();
412         out.print(vg() + ".drawImage(");
413         write(image);
414         unblock();
415         out.println(", " + x + ", " + y + ", " + "null" + ");");
416         return true;
417     }
418 
419     public boolean drawImage(Image image, int x, int y, int width, int height,
420             ImageObserver observer) {
421         block();
422         out.print(vg() + ".drawImage(");
423         write(image);
424         unblock();
425         out.println(", " + x + ", " + y + ", " + width + ", " + height + ", "
426                 + "null" + ");");
427         return true;
428     }
429 
430     public boolean drawImage(Image image, int x, int y, Color bgColor,
431             ImageObserver observer) {
432         block();
433         out.print(vg() + ".drawImage(");
434         write(image);
435         out.print(", " + x + ", " + y + ", ");
436         write(bgColor);
437         unblock();
438         out.println(", " + "null" + ");");
439         return true;
440     }
441 
442     public boolean drawImage(Image image, int x, int y, int width, int height,
443             Color bgColor, ImageObserver observer) {
444         block();
445         out.print(vg() + ".drawImage(");
446         write(image);
447         out.print(", " + x + ", " + y + ", " + width + ", " + height + ", ");
448         write(bgColor);
449         unblock();
450         out.println(", " + "null" + ");");
451         return true;
452     }
453 
454     public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2,
455             int sx1, int sy1, int sx2, int sy2, ImageObserver observer) {
456         block();
457         out.print(vg() + ".drawImage(");
458         write(image);
459         out.print(", " + dx1 + ", " + dy1 + ", " + dx2 + ", " + dy2);
460         out.print(", " + sx1 + ", " + sy1 + ", " + sx2 + ", " + sy2);
461         unblock();
462         out.println(", " + "null" + ");");
463         return true;
464     }
465 
466     public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2,
467             int sx1, int sy1, int sx2, int sy2, Color bgColor,
468             ImageObserver observer) {
469         block();
470         out.print(vg() + ".drawImage(");
471         write(image);
472         out.print(", " + dx1 + ", " + dy1 + ", " + dx2 + ", " + dy2);
473         out.print(", " + sx1 + ", " + sy1 + ", " + sx2 + ", " + sy2 + ", ");
474         write(bgColor);
475         unblock();
476         out.println(", " + "null" + ");");
477         return true;
478     }
479 
480     public void drawLine(int x1, int y1, int x2, int y2) {
481         out.println(vg() + ".drawLine(" + x1 + ", " + y1 + ", " + x2 + ", "
482                 + y2 + ");");
483     }
484 
485     public void drawOval(int x, int y, int width, int height) {
486         out.println(vg() + ".drawOval(" + x + ", " + y + ", " + width + ", "
487                 + height + ");");
488     }
489 
490     public void fillOval(int x, int y, int width, int height) {
491         out.println(vg() + ".fillOval(" + x + ", " + y + ", " + width + ", "
492                 + height + ");");
493     }
494 
495     public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints) {
496         block();
497         out.print(vg() + ".drawPolygon(");
498         write(xPoints);
499         out.print(", ");
500         write(yPoints);
501         unblock();
502         out.println(", " + nPoints + ");");
503     }
504 
505     public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints) {
506         block();
507         out.print(vg() + ".fillPolygon(");
508         write(xPoints);
509         out.print(", ");
510         write(yPoints);
511         unblock();
512         out.println(", " + nPoints + ");");
513     }
514 
515     public void drawPolygon(Polygon p) {
516         block();
517         out.print(vg() + ".drawPolygon(");
518         write(p);
519         unblock();
520         out.println(");");
521     }
522 
523     public void fillPolygon(Polygon p) {
524         block();
525         out.print(vg() + ".fillPolygon(");
526         write(p);
527         unblock();
528         out.println(");");
529     }
530 
531     public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints) {
532         block();
533         out.print(vg() + ".drawPolyline(");
534         write(xPoints);
535         out.print(", ");
536         write(yPoints);
537         unblock();
538         out.println(", " + nPoints + ");");
539     }
540 
541     public void drawRect(int x, int y, int width, int height) {
542         out.println(vg() + ".drawRect(" + x + ", " + y + ", " + width + ", "
543                 + height + ");");
544     }
545 
546     public void fillRect(int x, int y, int width, int height) {
547         out.println(vg() + ".fillRect(" + x + ", " + y + ", " + width + ", "
548                 + height + ");");
549     }
550 
551     public void drawRoundRect(int x, int y, int width, int height,
552             int arcWidth, int arcHeight) {
553         out.println(vg() + ".drawRoundRect(" + x + ", " + y + ", " + width
554                 + ", " + height + ", " + arcWidth + ", " + arcHeight + ");");
555     }
556 
557     public void fillRoundRect(int x, int y, int width, int height,
558             int arcWidth, int arcHeight) {
559         out.println(vg() + ".fillRoundRect(" + x + ", " + y + ", " + width
560                 + ", " + height + ", " + arcWidth + ", " + arcHeight + ");");
561     }
562 
563     public void drawString(AttributedCharacterIterator iterator, int x, int y) {
564         drawString(iterator, (float)x, (float)y);
565     }
566 
567     public void drawString(String str, int x, int y) {
568         block();
569         out.print(vg() + ".drawString(");
570         write(str);
571         unblock();
572         out.println(", " + x + ", " + y + ");");
573     }
574 
575     public void finalize() {
576         out.println(vg() + ".finalize();");
577         super.finalize();
578     }
579 
580     public Shape getClip() {
581         return clip;
582     }
583 
584     public Rectangle getClipBounds() {
585         return (clip == null) ? null : clip.getBounds();
586     }
587 
588     public Rectangle getClipBounds(Rectangle r) {
589         Rectangle c = getClipBounds();
590         if (c != null) {
591             r.x = c.x;
592             r.y = c.y;
593             r.width = c.width;
594             r.height = c.height;
595         }
596         return r;
597     }
598 
599     /**
600      * @deprecated probably forwards to getClipBounds()
601      */
602     // public Rectangle getClipRect() {
603     // return null;
604     // }
605     public Color getColor() {
606         return color;
607     }
608 
609     public Font getFont() {
610         return font;
611     }
612 
613     public FontMetrics getFontMetrics() {
614         return getFontMetrics(getFont());
615     }
616     
617     /**
618      * @param font
619      * @deprecated
620      */
621     public FontMetrics getFontMetrics(Font font) {
622         return Toolkit.getDefaultToolkit().getFontMetrics(font);
623     }
624 
625     public boolean hitClip(int x, int y, int width, int height) {
626         return clip.intersects(x, y, width, height);
627     }
628 
629     public void setClip(int x, int y, int width, int height) {
630         out.println(vg() + ".setClip(" + x + ", " + y + ", " + width + ", "
631                 + height + ");");
632         clip = new Rectangle(x, y, width, height);
633     }
634 
635     public void setClip(Shape clip) {
636         block();
637         out.print(vg() + ".setClip(");
638         write(clip);
639         unblock();
640         out.println(");");
641         this.clip = clip;
642     }
643 
644     public void setColor(Color c) {
645         block();
646         out.print(vg() + ".setColor(");
647         write(c);
648         unblock();
649         out.println(");");
650         color = c;
651     }
652 
653     public void setFont(Font font) {
654         block();
655         out.print(vg() + ".setFont(");
656         write(font);
657         unblock();
658         out.println(");");
659         this.font = font;
660     }
661 
662     public void setPaintMode() {
663         out.println(vg() + ".setPaintMode();");
664     }
665 
666     public void setXORMode(Color c1) {
667         block();
668         out.print(vg() + ".setXORMode(");
669         write(c1);
670         unblock();
671         out.println(");");
672     }
673 
674     public String toString() {
675         return "JavaGraphics2D";
676     }
677 
678     public void translate(int x, int y) {
679         out.println(vg() + ".translate(" + x + ", " + y + ");");
680     }
681 
682     public void addRenderingHints(Map hints) {
683         // store hints
684         hints.putAll(hints);
685 
686         // write hints out
687         out.print(vg() + ".addRenderingHints(");
688         writeHintMap(hints);
689         out.println(");");
690     }
691 
692     public void clip(Shape s) {
693         block();
694         out.print(vg() + ".clip(");
695         write(s);
696         unblock();
697         out.println(");");
698         clip = s;
699     }
700 
701     public void draw(Shape s) {
702         block();
703         out.print(vg() + ".draw(");
704         write(s);
705         unblock();
706         out.println(");");
707     }
708 
709     public void drawGlyphVector(GlyphVector g, float x, float y) {
710         fill(g.getOutline(x, y));
711     }
712 
713     public void drawImage(BufferedImage img, BufferedImageOp op, int x, int y) {
714         if (op instanceof AffineTransformOp) {
715             out.print(vg() + ".drawImage(");
716             out.indent();
717             write(img);
718             out.println(",");
719             write((AffineTransformOp)op);
720             out.println(",");
721             out.println(x + ", " + y + ");");
722             out.outdent();
723         } else if (op instanceof ConvolveOp) {
724             out.print(vg() + ".drawImage(");
725             out.indent();
726             write(img);
727             out.println(",");
728             write((ConvolveOp)op);
729             out.println(",");
730             out.println(x + ", " + y + ");");
731             out.outdent();
732         } else {
733             out.println(
734                 "System.err.println(\""
735                 + getClass()
736                 + ": drawImage(BufferedImage, BufferedImageOp, int, int) not implemented.\");");
737         }
738     }
739 
740     private void write(ConvolveOp op) {
741         if (op == null) {
742             out.print("null");
743             return;
744         }
745 
746         imports.add("java.awt.image.ConvolveOp");
747         out.print("new ConvolveOp(");
748         write(op.getKernel());
749         out.print(", ");
750         out.print(op.getEdgeCondition());
751         out.print(", ");
752 
753         if (op.getRenderingHints() != null) {
754             out.print("new RenderingHints(");
755             writeHintMap(op.getRenderingHints());
756             out.print(")");
757         } else {
758             out.print("null");
759         }
760 
761         out.print(")");
762     }
763 
764     private void writeHintMap(Map hints) {
765         if (hints == null) {
766             out.print("null");
767             return;
768         }
769 
770         imports.add("org.freehep.graphicsio.java.JAVAArrayMap");
771         out.print("new JAVAArrayMap(new Object[] {");
772 
773         Iterator keys = hints.keySet().iterator();
774         while(keys.hasNext()) {
775             Object key = keys.next();
776             String keyString = (String) JAVAArrayMap.HINTS.get(key);
777             if (keyString == null) {
778                 continue;
779             }
780 
781             Object value = hints.get(key);
782             String valueString = (String) JAVAArrayMap.HINTS.get(value);
783             if (valueString == null) {
784                 continue;
785             }
786 
787             out.print(keyString);
788             out.print(", ");
789             out.print(valueString);
790             if (keys.hasNext()) {
791                 out.print(", ");
792             }
793         }
794         out.print("})");
795     }
796 
797     private void write(Kernel kernel) {
798         imports.add("java.awt.image.Kernel");
799         out.print("new Kernel(");
800         out.print(kernel.getWidth());
801         out.print(", ");
802         out.print(kernel.getHeight());
803         out.print(", ");
804         write(kernel.getKernelData(null));
805         out.print(")");
806     }
807 
808     private void write(AffineTransformOp op) {
809         imports.add("java.awt.image.AffineTransformOp");
810         out.print("new AffineTransformOp(");
811         write(op.getTransform());
812         out.print(", ");
813         out.print(op.getInterpolationType());
814         out.print(")");
815     }
816 
817     public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) {
818         out.println(vg() + ".drawImage(");
819         out.indent();
820         write(img);
821         out.println(",");
822         write(xform);
823         out.println(",");
824         out.println("null);");
825         out.outdent();
826         return true;
827     }
828 
829     public void drawRenderableImage(RenderableImage img, AffineTransform xform) {
830         out
831                 .println("System.err.println(\""
832                         + getClass()
833                         + ": drawRenderableImage(RenderableImage, AffineTransform) not implemented.\");");
834     }
835 
836     public void drawRenderedImage(RenderedImage img, AffineTransform xform) {
837         out
838                 .println("System.err.println(\""
839                         + getClass()
840                         + ": drawRenderedImage(RenderedImage, AffineTransform) not implemented.\");");
841     }
842 
843     /**
844      * converts all textAttributes in the AttributedCharacterIterator
845      * to a java-line that adds this attribute to an AttributedString.
846      * To avoid double Attributes this method stores the lines in a
847      * HashSet and returns them to
848      * {@link #drawString(java.text.AttributedCharacterIterator, float, float)}.
849      * To do so the IndentPrintWriter out for this object is temporary
850      * redirected to an IndentPrintWriter of this method.
851      *
852      * @param iterator the AttributedCharacterIterator
853      * @param imports list of imported classes
854      * @param text will be filled with chars from the iterator
855      * @return HashSet with entries like "addAttribute(TextAttribute.FONT, new Font("Arial", 11f), 10, 20)"
856      */
857     private HashSet getAttributes(
858         AttributedCharacterIterator iterator,
859         HashSet imports,
860         StringBuffer text) {
861 
862         // return this later
863         HashSet result = new HashSet(0);
864 
865         // iterate the Characters
866         for (
867             char c = iterator.first();
868             c != AttributedCharacterIterator.DONE;
869             c = iterator.next()) {
870 
871             // append the char
872             text.append(c);
873 
874             Map /*<Attribute, Object>*/ attributes = iterator.getAttributes();
875             Iterator /*<Attribute>*/ keys = attributes.keySet().iterator();
876             while (keys.hasNext()) {
877                 StringBuffer attribute = new StringBuffer();
878 
879                 // define key and value
880                 AttributedCharacterIterator.Attribute key =
881                     (AttributedCharacterIterator.Attribute) keys.next();
882                 Object value = attributes.get(key);
883 
884                 String className = key.getClass().getName();
885 
886                 attribute.append(".addAttribute(");
887                 attribute.append(className.substring(className.lastIndexOf(".") + 1));
888                 attribute.append(".");
889 
890                 imports.add(className);
891 
892                 // taken from Attribute.toString() toString is
893                 // getClass().getName() + "(" + name + ")";
894                 String keyName = key.toString().substring(
895                     key.toString().lastIndexOf("(") + 1,
896                     key.toString().lastIndexOf(")"));
897                 attribute.append(keyName.toUpperCase());
898                 attribute.append(", ");
899 
900                 // redirect the output
901                 IndentPrintWriter old = out;
902                 StringWriter s = new StringWriter(0);
903                 out = new IndentPrintWriter(s);
904 
905                 // write out the value
906                 if (value instanceof String || value == null) {
907                     write((String)value);
908                 } else if (value instanceof Float) {
909                     write((Float)value);
910                 } else if (value instanceof Double) {
911                     write((Double)value);
912                 } else if (value instanceof Integer) {
913                     write((Integer)value);
914                 } else if (value instanceof Byte) {
915                     write((Byte)value);
916                 } else if (value instanceof Boolean) {
917                     write((Boolean)value);
918                 } else if (value instanceof Paint) {
919                     // FIXME: TexturePaint writes multiple images
920                     // even so they can't be changed between calls of this method
921                     write((Paint)value);
922                 } else if (value instanceof Dimension) {
923                     write((Dimension)value);
924                 } else if (value instanceof AffineTransform) {
925                     write((AffineTransform)value);
926                 } else if (value instanceof Font) {
927                     write((Font)value);
928                 } else if (value instanceof ImageGraphicAttribute) {
929                     write((ImageGraphicAttribute)value);
930                 } else if (value instanceof ShapeGraphicAttribute) {
931                     write((ShapeGraphicAttribute)value);
932                 } else {
933                     write(value.toString());
934                 }
935 
936                 // write content of out
937                 out.close();
938                 attribute.append(s.getBuffer());
939 
940                 // redirect out to old IndentPrintWriter
941                 out = old;
942 
943                 // append the range of the TextAttribute
944                 attribute.append(", ");
945                 attribute.append(iterator.getRunStart(key));
946                 attribute.append(", ");
947                 attribute.append(iterator.getRunLimit(key));
948                 attribute.append(");");
949 
950                 // store the result
951                 result.add(attribute.toString());
952             }
953         }
954 
955         // return all lines of code
956         return result;
957     }
958 
959     /**
960      * needed to create unique instances of AttributedString
961      */
962     private static int attributedStringCounter = 0;
963 
964     /**
965      * Creates an Java-output using an AttributedString.
966      * Each textAttribute is added to this one.
967      *
968      * @param iterator String with TextAttributes
969      * @param x x-position for drawing
970      * @param y y-position for drawing
971      */
972     public void drawString(
973         AttributedCharacterIterator iterator,
974         float x,
975         float y) {
976 
977         imports.add("java.text.AttributedString");
978 
979         // define a name for an AttributedString
980         String asName = "as" + (attributedStringCounter++);
981 
982         // filled by {@link #getAttributes()}
983         StringBuffer attributeName = new StringBuffer();
984         HashSet attributeImports = new HashSet(0);
985 
986         // get Attributes and fill attributeName and attributeImports
987         Iterator attributes = getAttributes(
988             iterator,
989             attributeImports,
990             attributeName).iterator();
991 
992         // add the collected imports
993         imports.addAll(attributeImports);
994 
995         // write something like:
996         // AttributedString as243 = new AttributedString("attributed_text");
997         out.print("AttributedString ");
998         out.print(asName);
999         out.print("= new AttributedString(\"");
1000         out.print(attributeName.toString());
1001         out.println("\");");
1002 
1003         // add all TextAttributes by writing the attribute lines of code
1004         while (attributes.hasNext()) {
1005             out.print(asName);
1006             out.println(attributes.next());
1007         }
1008         
1009         // write something like:
1010         // vg[0].drawString(as243, 23, 24);
1011         out.print(vg());
1012         out.print(".drawString(");
1013         out.print(asName);
1014         out.print(".getIterator(), ");
1015         out.print(x);
1016         out.print("f, ");
1017         out.print(y);
1018         out.println("f);");
1019     }
1020 
1021     private void write(Boolean b) {
1022         if (b.booleanValue()) {
1023             out.print("Boolean.TRUE");
1024         } else {
1025             out.print("Boolean.FALSE");
1026         }
1027     }
1028 
1029     private void write(Byte b) {
1030         out.print("new Byte(");
1031         out.print(b.byteValue());
1032         out.print("b)");
1033     }
1034 
1035     private void write(Float f) {
1036         out.print("new Float(");
1037         out.print(f.floatValue());
1038         out.print("f)");
1039     }
1040 
1041     private void write(Double d) {
1042         out.print("new Double(");
1043         out.print(d.doubleValue());
1044         out.print(")");
1045     }
1046 
1047     private void write(Integer i) {
1048         out.print("new Integer(");
1049         out.print(i.intValue());
1050         out.print(")");
1051     }
1052 
1053     private void write(Dimension d) {
1054         imports.add("java.awt.Dimension");
1055         out.print("new Dimension(");
1056         out.print(d.getWidth());
1057         out.print(", ");
1058         out.print(d.getHeight());
1059         out.print(")");
1060     }
1061 
1062     private void write(ImageGraphicAttribute iga) {
1063         // ImageGraphicAttribute has no getImage() so
1064         // it can't be fully supported
1065 
1066         imports.add("java.awt.font.ImageGraphicAttribute");
1067         out.print("new ImageGraphicAttribute(");
1068         write(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB));
1069         out.print("/* ImageGraphicAttribute.getImage() not supported */");
1070         out.print(", ");
1071         out.print(iga.getAlignment());
1072         out.print(", ");
1073         out.print(- iga.getBounds().getX());
1074         out.print(", ");
1075         out.print(- iga.getBounds().getY());
1076         out.print(")");
1077     }
1078 
1079     private void write(ShapeGraphicAttribute sga) {
1080         // ShapeGraphicAttribute has no getShape()
1081         // and getStroke() so it can't be fully supported
1082 
1083         imports.add("java.awt.font.ShapeGraphicAttribute");
1084         out.print("new ShapeGraphicAttribute(");
1085         write(sga.getBounds().getBounds2D());
1086         out.print("/* ShapeGraphicAttribute.getShape() not supported */");
1087         out.print(", ");
1088         out.print(sga.getAlignment());
1089         out.print(", ");
1090         write(new BasicStroke());
1091         out.print("/* ShapeGraphicAttribute.getStroke() not supported */");
1092         out.print(")");
1093     }
1094 
1095     public void drawString(String str, float x, float y) {
1096         block();
1097         out.print(vg() + ".drawString(");
1098         write(str);
1099         unblock();
1100         out.println(", " + x + ", " + y + ");");
1101     }
1102 
1103     public void fill(Shape s) {
1104         block();
1105         out.print(vg() + ".fill(");
1106         write(s);
1107         unblock();
1108         out.println(");");
1109     }
1110 
1111     public Color getBackground() {
1112         return backgroundColor;
1113     }
1114 
1115     public Composite getComposite() {
1116         return composite;
1117     }
1118 
1119     public GraphicsConfiguration getDeviceConfiguration() {
1120         // FIXME
1121         return null;
1122     }
1123 
1124     public FontRenderContext getFontRenderContext() {
1125         return new FontRenderContext(new AffineTransform(), false, false);
1126     }
1127 
1128     public Paint getPaint() {
1129         return paint;
1130     }
1131 
1132     public Object getRenderingHint(RenderingHints.Key key) {
1133         return hints.get(key);
1134     }
1135 
1136     public RenderingHints getRenderingHints() {
1137         return hints;
1138     }
1139 
1140     public Stroke getStroke() {
1141         return stroke;
1142     }
1143 
1144     public AffineTransform getTransform() {
1145         return transform;
1146     }
1147 
1148     public boolean hit(Rectangle rect, Shape s, boolean onStroke) {
1149         out.println("System.err.println(\"" + getClass()
1150                 + ": hit(Rectangle, Shape, boolean) not implemented.\");");
1151         return false;
1152     }
1153 
1154     public void rotate(double theta) {
1155         out.println(vg() + ".rotate(" + theta + ");");
1156     }
1157 
1158     public void rotate(double theta, double x, double y) {
1159         out.println(vg() + ".rotate(" + theta + ", " + x + ", " + y + ");");
1160     }
1161 
1162     public void scale(double sx, double sy) {
1163         out.println(vg() + ".scale(" + sx + ", " + sy + ");");
1164     }
1165 
1166     public void setBackground(Color c) {
1167         block();
1168         out.print(vg() + ".setBackground(");
1169         write(c);
1170         unblock();
1171         out.println(");");
1172         backgroundColor = c;
1173     }
1174 
1175     public void setComposite(Composite c) {
1176         if (c instanceof AlphaComposite) {
1177             block();
1178             out.print(vg() + ".setComposite(");
1179             write((AlphaComposite) c);
1180             unblock();
1181             out.println(");");
1182         } else {
1183             out.println("System.err.println(\"" + getClass()
1184                     + ": setComposite(Composite) not implemented.\");");
1185         }
1186         composite = c;
1187     }
1188 
1189     public void setPaint(Paint p) {
1190         block();
1191         out.print(vg() + ".setPaint(");
1192         write(p);
1193         unblock();
1194         out.println(");");
1195         paint = p;
1196     }
1197 
1198     public void setRenderingHint(RenderingHints.Key hintKey, Object hintValue) {
1199         // store hints
1200         if (hintValue != null) {
1201             hints.put(hintKey, hintValue);
1202         } else {
1203             hints.remove(hintKey);
1204         }
1205 
1206         // RenderingHints --> String
1207         String key = (String) JAVAArrayMap.HINTS.get(hintKey);
1208         if (key == null) {
1209              out.println("System.err.println(\"" + getClass()
1210                     + ": setRenderingHint(RenderingHints.Key, Object) key not supported '"
1211                     + hintKey + "'.\");");
1212             return;
1213         }
1214 
1215         String value = (String) JAVAArrayMap.HINTS.get(hintValue);
1216         if (value == null) {
1217              out.println("System.err.println(\"" + getClass()
1218                     + ": setRenderingHint(RenderingHints.Key, Object) key not supported '"
1219                     + hintKey + "'.\");");
1220             return;
1221         }
1222 
1223         // write out
1224         imports.add("java.awt.RenderingHints");
1225         out.print(vg() + ".setRenderingHint(");
1226         out.print(key);
1227         out.print(", ");
1228         out.print(value);
1229         out.println(");");
1230     }
1231 
1232     public void setRenderingHints(Map hints) {
1233         this.hints = new RenderingHints(hints);
1234 
1235         // write them out
1236         out.print(vg() + ".setRenderingHints(");
1237         writeHintMap(hints);
1238         out.println(");");
1239     }
1240 
1241     public void setStroke(Stroke s) {
1242         if (s instanceof BasicStroke) {
1243             block();
1244             out.print(vg() + ".setStroke(");
1245             write((BasicStroke) s);
1246             unblock();
1247             out.println(");");
1248         } else {
1249             out.println("System.err.println(\"" + getClass()
1250                     + ": setStroke(Stroke) not implemented.\");");
1251         }
1252         stroke = s;
1253     }
1254 
1255     public void setTransform(AffineTransform xform) {
1256         block();
1257         out.print(vg() + ".setTransform(");
1258         write(xform);
1259         unblock();
1260         out.println(");");
1261     }
1262 
1263     public void shear(double shx, double shy) {
1264         out.println(vg() + ".shear(" + shx + ", " + shy + ");");
1265     }
1266 
1267     public void transform(AffineTransform xform) {
1268         block();
1269         out.print(vg() + ".transform(");
1270         write(xform);
1271         unblock();
1272         out.println(");");
1273     }
1274 
1275     public void translate(double tx, double ty) {
1276         out.println(vg() + ".translate(" + tx + ", " + ty + ");");
1277     }
1278 
1279     public void clearRect(double x, double y, double width, double height) {
1280         out.println(vg() + ".clearRect(" + x + ", " + y + ", " + width + ", "
1281                 + height + ");");
1282     }
1283 
1284     public void clipRect(double x, double y, double width, double height) {
1285         out.println(vg() + ".clipRect(" + x + ", " + y + ", " + width + ", "
1286                 + height + ");");
1287         clip = new Rectangle2D.Double(x, y, width, height);
1288     }
1289 
1290     public void drawArc(double x, double y, double width, double height,
1291             double startAngle, double arcAngle) {
1292         out.println(vg() + ".drawArc(" + x + ", " + y + ", " + width + ", "
1293                 + height + ", " + startAngle + ", " + arcAngle + ");");
1294     }
1295 
1296     public void drawLine(double x1, double y1, double x2, double y2) {
1297         out.println(vg() + ".drawLine(" + x1 + ", " + y1 + ", " + x2 + ", "
1298                 + y2 + ");");
1299     }
1300 
1301     public void drawOval(double x, double y, double width, double height) {
1302         out.println(vg() + ".drawOval(" + x + ", " + y + ", " + width + ", "
1303                 + height + ");");
1304     }
1305 
1306     public void drawPolygon(double[] xPoints, double[] yPoints, int nPoints) {
1307         block();
1308         out.print(vg() + ".drawPolygon(");
1309         write(xPoints);
1310         out.print(", ");
1311         write(yPoints);
1312         unblock();
1313         out.println(", " + nPoints + ");");
1314     }
1315 
1316     public void drawPolyline(double[] xPoints, double[] yPoints, int nPoints) {
1317         block();
1318         out.print(vg() + ".drawPolyline(");
1319         write(xPoints);
1320         out.print(", ");
1321         write(yPoints);
1322         unblock();
1323         out.println(", " + nPoints + ");");
1324     }
1325 
1326     public void drawRect(double x, double y, double width, double height) {
1327         out.println(vg() + ".drawRect(" + x + ", " + y + ", " + width + ", "
1328                 + height + ");");
1329     }
1330 
1331     public void drawRoundRect(double x, double y, double width, double height,
1332             double arcWidth, double arcHeight) {
1333         out.println(vg() + ".drawRoundRect(" + x + ", " + y + ", " + width
1334                 + ", " + height + ", " + arcWidth + ", " + arcHeight + ");");
1335     }
1336 
1337     public void drawSymbol(int x, int y, int size, int symbol) {
1338         out.println(vg() + ".drawSymbol(" + x + ", " + y + ", " + size + ", "
1339                 + symbol + ");");
1340     }
1341 
1342     public void fillAndDrawSymbol(int x, int y, int size, int symbol,
1343             Color fillColor) {
1344         // FIXME
1345     }
1346 
1347     public void drawSymbol(double x, double y, double size, int symbol) {
1348         out.println(vg() + ".drawSymbol(" + x + ", " + y + ", " + size + ", "
1349                 + symbol + ");");
1350     }
1351 
1352     public void fillSymbol(int x, int y, int size, int symbol) {
1353         out.println(vg() + ".fillSymbol(" + x + ", " + y + ", " + size + ", "
1354                 + symbol + ");");
1355     }
1356 
1357     public void fillSymbol(double x, double y, double size, int symbol) {
1358         out.println(vg() + ".fillSymbol(" + x + ", " + y + ", " + size + ", "
1359                 + symbol + ");");
1360     }
1361 
1362     public void fillAndDrawSymbol(double x, double y, double size, int symbol,
1363             Color fillColor) {
1364         // FIXME
1365     }
1366 
1367     public void drawString(String str, double x, double y) {
1368         block();
1369         out.print(vg() + ".drawString(");
1370         write(str);
1371         unblock();
1372         out.println(", " + x + ", " + y + ");");
1373     }
1374 
1375     public void drawString(TagString str, double x, double y) {
1376         block();
1377         out.print(vg() + ".drawString(");
1378         write(str);
1379         unblock();
1380         out.println(", " + x + ", " + y + ");");
1381     }
1382 
1383     public void drawString(String str, double x, double y, int horizontal,
1384             int vertical) {
1385         block();
1386         out.print(vg() + ".drawString(");
1387         write(str);
1388         unblock();
1389         out.println(", " + x + ", " + y + ", " + horizontal + ", " + vertical
1390                 + ");");
1391     }
1392 
1393     public void drawString(TagString str, double x, double y, int horizontal,
1394             int vertical) {
1395         block();
1396         out.print(vg() + ".drawString(");
1397         write(str);
1398         unblock();
1399         out.println(", " + x + ", " + y + ", " + horizontal + ", " + vertical
1400                 + ");");
1401     }
1402 
1403     public void drawString(String str, double x, double y, int horizontal,
1404             int vertical, boolean framed, Color frameColor, double frameWidth,
1405             boolean banner, Color bannerColor) {
1406         block();
1407         out.print(vg() + ".drawString(");
1408         write(str);
1409         out.print(", " + x + ", " + y + ", " + horizontal + ", " + vertical
1410                 + ", " + framed + ", ");
1411         write(frameColor);
1412         out.print(", " + frameWidth + ", " + banner + ", ");
1413         write(bannerColor);
1414         unblock();
1415         out.println(");");
1416     }
1417 
1418     public void drawString(TagString str, double x, double y, int horizontal,
1419             int vertical, boolean framed, Color frameColor, double frameWidth,
1420             boolean banner, Color bannerColor) {
1421         block();
1422         out.print(vg() + ".drawString(");
1423         write(str);
1424         out.print(", " + x + ", " + y + ", " + horizontal + ", " + vertical
1425                 + ", " + framed + ", ");
1426         write(frameColor);
1427         out.print(", " + frameWidth + ", " + banner + ", ");
1428         write(bannerColor);
1429         unblock();
1430         out.println(");");
1431     }
1432 
1433     public void fillAndDraw(Shape s, Color fillColor) {
1434         block();
1435         out.print(vg() + ".fillAndDraw(");
1436         write(s);
1437         out.print(", ");
1438         write(fillColor);
1439         unblock();
1440         out.println(");");
1441     }
1442 
1443     public void fillArc(double x, double y, double width, double height,
1444             double startAngle, double arcAngle) {
1445         out.println(vg() + ".fillArc(" + x + ", " + y + ", " + width + ", "
1446                 + height + ", " + startAngle + ", " + arcAngle + ");");
1447     }
1448 
1449     public void fillOval(double x, double y, double width, double height) {
1450         out.println(vg() + ".fillOval(" + x + ", " + y + ", " + width + ", "
1451                 + height + ");");
1452     }
1453 
1454     public void fillPolygon(double[] xPoints, double[] yPoints, int nPoints) {
1455         block();
1456         out.print(vg() + ".fillPolygon(");
1457         write(xPoints);
1458         out.print(", ");
1459         write(yPoints);
1460         unblock();
1461         out.println(", " + nPoints + ");");
1462     }
1463 
1464     public void fillRect(double x, double y, double width, double height) {
1465         out.println(vg() + ".fillRect(" + x + ", " + y + ", " + width + ", "
1466                 + height + ");");
1467     }
1468 
1469     public void fillRoundRect(double x, double y, double width, double height,
1470             double arcWidth, double arcHeight) {
1471         out.println(vg() + ".fillRoundRect(" + x + ", " + y + ", " + width
1472                 + ", " + height + ", " + arcWidth + ", " + arcHeight + ");");
1473     }
1474 
1475     public int getColorMode() {
1476         return colorMode;
1477     }
1478 
1479     public String getCreator() {
1480         return creator;
1481     }
1482 
1483     public boolean isDeviceIndependent() {
1484         return false;
1485     }
1486 
1487     public void printComment(String comment) {
1488         block();
1489         out.print(vg() + ".printComment(");
1490         write(comment);
1491         unblock();
1492         out.println(");");
1493     }
1494 
1495     public void setClip(double x, double y, double width, double height) {
1496         out.println(vg() + ".setClip(" + x + ", " + y + ", " + width + ", "
1497                 + height + ");");
1498         clip = new Rectangle2D.Double(x, y, width, height);
1499     }
1500 
1501     public void setColorMode(int colorMode) {
1502         out.println(vg() + ".setColorMode(" + colorMode + ");");
1503         this.colorMode = colorMode;
1504     }
1505 
1506     public void setCreator(String creator) {
1507         if (creator != null) {
1508             this.creator = creator;
1509         }
1510     }
1511 
1512     public void setDeviceIndependent(boolean isDeviceIndependent) {
1513         this.isDeviceIndependent = true;
1514     }
1515 
1516     public void setLineWidth(int width) {
1517         out.println(vg() + ".setLineWidth(" + width + ");");
1518     }
1519 
1520     public void setLineWidth(double width) {
1521         out.println(vg() + ".setLineWidth(" + width + ");");
1522     }
1523 
1524     public void startExport() {
1525         block();
1526         imports.add("java.awt.Graphics");
1527         imports.add("java.io.IOException");
1528         imports.add("org.freehep.graphics2d.VectorGraphics");
1529         imports.add("org.freehep.graphicsio.test.TestingPanel");
1530                 
1531         out.println("public class " + className + " extends TestingPanel {");
1532         out.println();
1533         out.indent();
1534 
1535         out.println("public " + className
1536                 + "(String[] args) throws Exception {");
1537         out.indent();
1538         out.println("super(args);");
1539         out.print("setName(");
1540         write(className);
1541         out.println(");");
1542         out.outdent();
1543         out.println("} // contructor");
1544 
1545         out.println();
1546         out.println("public void paint(Graphics g) {");
1547         out.indent();
1548         out.println("vg[0] = VectorGraphics.create(g);");
1549         out.print("vg[0].setCreator(");
1550         write(creator);
1551         out.println(");");
1552 
1553         out.println("try {");
1554         out.indent();
1555         out.println("Paint0s" + paintSequenceNo.getInt() + ".paint(vg);");
1556         out.outdent();
1557         out.println("} catch (IOException e) {");
1558         out.indent();
1559         out.println("e.printStackTrace();");
1560         out.outdent();
1561         out.println("}");
1562 
1563 
1564         out.outdent();
1565         out.println("} // paint");
1566         out.println();
1567 
1568         startClass();
1569         unblock();
1570     }
1571 
1572     public void endExport() {
1573         block();
1574         endClass();
1575 
1576         out.println("private VectorGraphics vg[] = new VectorGraphics["
1577                 + vg.size() + "];");
1578         out.println();
1579 
1580         out
1581                 .println("public static void main(String[] args) throws Exception {");
1582         out.indent();
1583         out.println("new " + className + "(args).runTest(" + width + ", "
1584                 + height + ");");
1585         out.outdent();
1586         out.println("}");
1587         out.outdent();
1588         out.println("} // class");
1589         out.close();
1590         unblock();
1591 
1592         // now write the header
1593         PrintWriter writer = new PrintWriter(os);
1594         
1595         writer.println("// AUTOMATICALLY GENERATED by " + creator);
1596         writer.println();
1597         if ((getProperty(PACKAGE_NAME) != null)
1598                 && !getProperty(PACKAGE_NAME).equals("")) {
1599             writer.println("package " + getProperty(PACKAGE_NAME) + ";");
1600             writer.println();
1601         }
1602         for (Iterator i=imports.iterator(); i.hasNext(); ) {
1603             writer.println("import "+i.next()+";");
1604         }
1605         writer.println();    
1606         
1607         // and the buffer
1608         writer.print(bos.toString());
1609         
1610         writer.close();
1611     }
1612 
1613     public void lineNumberReached(LineNumberWriter.LineNumberEvent event) {
1614         if (!block()) {
1615             lineWriter.setLineNumber(1);
1616 
1617             out.println(
1618                 "Paint0s" + (paintSequenceNo.getInt() + 1) + ".paint(vg);");
1619 
1620             endClass();
1621 
1622             paintSequenceNo.set(paintSequenceNo.getInt() + 1);
1623             startClass();
1624         }
1625         unblock();
1626     }
1627 
1628     private boolean block() {
1629         boolean blocked = blockLevel.getInt() > 0;
1630         blockLevel.set(blockLevel.getInt() + 1);
1631         return blocked;
1632     }
1633 
1634     private void unblock() {
1635         if (blockLevel.getInt() > 0)
1636             blockLevel.set(blockLevel.getInt() - 1);
1637     }
1638 
1639     private void startClass() {
1640         block();
1641         out.println("private static class Paint0s" + paintSequenceNo.getInt()
1642                 + " {");
1643         out.indent();
1644         out.println("public static void paint(VectorGraphics[] vg) throws IOException {");
1645         out.indent();
1646         unblock();
1647     }
1648 
1649     private void endClass() {
1650         block();
1651         out.outdent();
1652         out.println("} // paint");
1653         out.outdent();
1654         out.println("} // class Paint0s" + paintSequenceNo.getInt());
1655         out.println();
1656         unblock();
1657     }
1658 
1659     //
1660     // Private Methods to write objects
1661     //
1662     private void write(Color c) {
1663         if (c == null) {
1664             out.print("null");
1665             return;
1666         }
1667 
1668         imports.add("java.awt.Color");
1669         out.print("new Color(" + c.getRed() + ", " + c.getGreen() + ", "
1670                 + c.getBlue() + ", " + c.getAlpha() + ")");
1671     }
1672 
1673     private void write(Font font) {
1674         if (font == null) {
1675             out.print("null");
1676             return;
1677         }
1678 
1679         imports.add("java.awt.Font");
1680         out.print("new Font(");
1681         write(font.getName());
1682         out.print(", " + font.getStyle() + ", " + font.getSize() + ")");
1683     }
1684 
1685     private void write(AffineTransform t) {
1686         if (t == null) {
1687             out.print("null");
1688             return;
1689         }
1690 
1691         double[] m = new double[6];
1692         t.getMatrix(m);
1693         imports.add("java.awt.geom.AffineTransform");
1694         out.print("new AffineTransform(" + m[0] + ", " + m[1] + ", " + m[2]
1695                 + ", " + m[3] + ", " + m[4] + ", " + m[5] + ")");
1696     }
1697 
1698     private void write(Shape s) {
1699         if (s == null) {
1700             out.print("null");
1701             return;
1702         }
1703 
1704         PathIterator i = s.getPathIterator(null);
1705         imports.add("org.freehep.graphicsio.java.JAVAGeneralPath");
1706         out.println("new JAVAGeneralPath(" + i.getWindingRule()
1707                 + ", new JAVAGeneralPath.PathElement[] {");
1708         out.indent();
1709         float[] c = new float[6];
1710         while (!i.isDone()) {
1711             int type = i.currentSegment(c);
1712             switch (type) {
1713             case PathIterator.SEG_MOVETO:
1714                 out.print("new JAVAGeneralPath.MoveTo(" + c[0] + "f, " + c[1]
1715                         + "f)");
1716                 break;
1717             case PathIterator.SEG_LINETO:
1718                 out.print("new JAVAGeneralPath.LineTo(" + c[0] + "f, " + c[1]
1719                         + "f)");
1720                 break;
1721             case PathIterator.SEG_CUBICTO:
1722                 out.print("new JAVAGeneralPath.CurveTo(" + c[0] + "f, " + c[1]
1723                         + "f, " + c[2] + "f, " + c[3] + "f, " + c[4] + "f, "
1724                         + c[5] + "f)");
1725                 break;
1726             case PathIterator.SEG_QUADTO:
1727                 out.print("new JAVAGeneralPath.QuadTo(" + c[0] + "f, " + c[1]
1728                         + "f, " + c[2] + "f, " + c[3] + "f)");
1729                 break;
1730             case PathIterator.SEG_CLOSE:
1731                 out.print("new JAVAGeneralPath.ClosePath()");
1732                 break;
1733             default:
1734                 break;
1735             }
1736             i.next();
1737             out.println(i.isDone() ? "" : ",");
1738         }
1739         out.outdent();
1740         out.print("})");
1741     }
1742 
1743     private void write(double[] a) {
1744         if (a == null) {
1745             out.print("null");
1746             return;
1747         }
1748         write(a, a.length);
1749     }
1750 
1751     private void write(double[] a, int length) {
1752         if (a == null) {
1753             out.print("null");
1754             return;
1755         }
1756 
1757         out.println("new double[] {");
1758         out.indent();
1759         for (int i = 0; i < length; i++) {
1760             if (i != 0)
1761                 out.print(", ");
1762             out.print(a[i]);
1763         }
1764         out.outdent();
1765         out.println();
1766         out.print("}");
1767     }
1768 
1769     private void write(float[] a) {
1770         if (a == null) {
1771             out.print("null");
1772             return;
1773         }
1774         write(a, a.length);
1775     }
1776 
1777     private void write(float[] a, int length) {
1778         if (a == null) {
1779             out.print("null");
1780             return;
1781         }
1782 
1783         out.print("new float[] {");
1784         out.indent();
1785         for (int i = 0; i < length; i++) {
1786             if (i % 10 == 0) {
1787                 out.println();
1788             }
1789             if (i != 0) {
1790                 out.print(", ");
1791             }
1792             out.print(a[i] + "f");
1793         }
1794         out.outdent();
1795         out.println();
1796         out.print("}");
1797     }
1798 
1799     private void write(int[] a) {
1800         if (a == null) {
1801             out.print("null");
1802             return;
1803         }
1804         write(a, a.length);
1805     }
1806 
1807     private void write(int[] a, int length) {
1808         if (a == null) {
1809             out.print("null");
1810             return;
1811         }
1812 
1813         out.print("new int[] {");
1814         out.indent();
1815         for (int i = 0; i < length; i++) {
1816             if (i % 10 == 0) {
1817                 out.println();
1818             }
1819             if (i != 0) {
1820                 out.print(", ");
1821             }
1822             out.print(a[i]);
1823         }
1824         out.outdent();
1825         out.println();
1826         out.print("}");
1827     }
1828 
1829     private void write(byte[] a) {
1830         if (a == null) {
1831             out.print("null");
1832             return;
1833         }
1834         write(a, a.length);
1835     }
1836 
1837     private void write(byte[] a, int length) {
1838         if (a == null) {
1839             out.print("null");
1840             return;
1841         }
1842 
1843         out.print("new byte[] {");
1844         out.indent();
1845         for (int i = 0; i < length; i++) {
1846             if (i % 10 == 0) {
1847                 out.println();
1848             }
1849             if (i != 0) {
1850                 out.print(", ");
1851             }
1852             out.print(a[i]);
1853         }
1854         out.outdent();
1855         out.println();
1856         out.print("}");
1857     }
1858 
1859 /*
1860     private void write(char[] a) {
1861         if (a == null) {
1862             out.print("null");
1863             return;
1864         }
1865         write(a, a.length);
1866     }
1867 */
1868     private void write(char[] a, int length) {
1869         if (a == null) {
1870             out.print("null");
1871             return;
1872         }
1873 
1874         out.println("new char[] {");
1875         out.indent();
1876         for (int i = 0; i < length; i++) {
1877             if (i != 0)
1878                 out.print(", ");
1879             out.print("'");
1880             switch (a[i]) {
1881             case '\b':
1882                 out.print("\\b");
1883                 break;
1884             case '\t':
1885                 out.print("\\t");
1886                 break;
1887             case '\n':
1888                 out.print("\\n");
1889                 break;
1890             case '\f':
1891                 out.print("\\f");
1892                 break;
1893             case '\r':
1894                 out.print("\\r");
1895                 break;
1896             case '\"':
1897                 out.print("\\\"");
1898                 break;
1899             case '\'':
1900                 out.print("\\'");
1901                 break;
1902             case '\\':
1903                 out.print("\\\\");
1904                 break;
1905             default:
1906                 out.print(toUnicode(a[i]));
1907                 break;
1908             }
1909             out.print("'");
1910             if (i % 10 == 0) {
1911                 out.println();
1912             }
1913         }
1914         out.outdent();
1915         out.println();
1916         out.print("}");
1917     }
1918 
1919     private void write(Polygon p) {
1920         if (p == null) {
1921             out.print("null");
1922             return;
1923         }
1924 
1925         imports.add("java.awt.Polygon");
1926         out.println("new Polygon(");
1927         out.indent();
1928         write(p.xpoints, p.npoints);
1929         out.print(", ");
1930         write(p.ypoints, p.npoints);
1931         out.println(", " + p.npoints);
1932         out.outdent();
1933         out.print(")");
1934     }
1935 
1936     private static int imageCounter = 0;
1937 
1938     private void write(Image image) {
1939         if (image == null) {
1940             out.print("null");
1941             return;
1942         }
1943 
1944         // prepare the image encoder
1945         PNGEncoder encoder = new PNGEncoder(image, true, PNGEncoder.FILTER_NONE, 9);
1946 
1947         // embed the image
1948         if (isProperty(EMBED_IMAGES)) {
1949             imports.add("javax.imageio.ImageIO");
1950             imports.add("java.io.ByteArrayInputStream");
1951             out.println("ImageIO.read(new ByteArrayInputStream(");
1952             out.indent();
1953             write(encoder.pngEncode());
1954             out.outdent();
1955             out.print("))");
1956         }
1957 
1958         // write as external file
1959         else {
1960             // we do not reuse any written images because
1961             // they could be changed between write operations
1962 
1963             // determin path to image
1964             String imageName = className + imagePrefix  + (imageCounter ++) + ".png";
1965             if (isProperty(COMPLETE_IMAGE_PATHS)) {
1966                 imageName = classPath + imageName;
1967             }
1968 
1969             // write the image
1970             try {
1971                 FileOutputStream fos = new FileOutputStream(imageName);
1972                 BufferedOutputStream bos = new BufferedOutputStream(fos);
1973                 bos.write(encoder.pngEncode());
1974                 bos.close();
1975             } catch (IOException e) {
1976                 e.printStackTrace();
1977             }
1978 
1979             imports.add("javax.imageio.ImageIO");
1980             imports.add("java.io.File");
1981             out.print("ImageIO.read(new File(\"" + imageName + "\"))");
1982         }
1983     }
1984 
1985     private void write(Paint p) {
1986         if (p == null) {
1987             out.print("(Paint)null");
1988         } else if (p instanceof Color) {
1989             write((Color)p);
1990         } else if (p instanceof TexturePaint) {
1991             write((TexturePaint)p);
1992         } else if (p instanceof GradientPaint) {
1993             write((GradientPaint)p);
1994         } else {
1995             write(Color.red);
1996             out.print("/* not supported '");
1997             out.print(p.toString());
1998             out.print("' */");
1999         }
2000     }
2001 
2002     private void write(GradientPaint gp) {
2003         if (gp == null) {
2004             out.print("null");
2005             return;
2006         }
2007 
2008         imports.add("java.awt.GradientPaint");
2009         out.println("new GradientPaint(");
2010         out.indent();
2011         write(gp.getPoint1());
2012         out.print(", ");
2013         write(gp.getColor1());
2014         out.println(", ");
2015         write(gp.getPoint2());
2016         out.print(", ");
2017         write(gp.getColor2());
2018         out.println(", " + gp.isCyclic());
2019         out.outdent();
2020         out.print(")");
2021     }
2022 
2023     private void write(TexturePaint tp) {
2024         if (tp == null) {
2025             out.print("null");
2026             return;
2027         }
2028 
2029         imports.add("java.awt.TexturePaint");
2030         out.println("new TexturePaint(");
2031         out.indent();
2032         write(tp.getImage());
2033         out.print(", ");
2034         write(tp.getAnchorRect());
2035         out.outdent();
2036         out.print(")");
2037     }
2038 
2039     private void write(BasicStroke bs) {
2040         if (bs == null) {
2041             out.print("null");
2042             return;
2043         }
2044 
2045         imports.add("java.awt.BasicStroke");
2046         out.println("new BasicStroke(");
2047         out.indent();
2048         out.println(bs.getLineWidth() + "f, " + bs.getEndCap() + ", ");
2049         out.println(bs.getLineJoin() + ", " + bs.getMiterLimit() + "f, ");
2050         write(bs.getDashArray());
2051         out.println(", " + bs.getDashPhase() + "f");
2052         out.outdent();
2053         out.print(")");
2054     }
2055 
2056     private void write(AlphaComposite ac) {
2057         if (ac == null) {
2058             out.print("null");
2059             return;
2060         }
2061 
2062         imports.add("java.awt.AlphaComposite");
2063         out.print("AlphaComposite.getInstance(" + ac.getRule() + ", "
2064                 + ac.getAlpha() + "f)");
2065     }
2066 
2067     private void write(Point2D p) {
2068         if (p == null) {
2069             out.print("null");
2070             return;
2071         }
2072 
2073         imports.add("java.awt.geom.Point2D");
2074         out.print("new Point2D.Double(" + p.getX() + ", " + p.getY() + ")");
2075     }
2076 
2077     private void write(Rectangle2D r) {
2078         if (r == null) {
2079             out.print("null");
2080             return;
2081         }
2082 
2083         imports.add("java.awt.geom.Rectangle2D");
2084         out.print("new Rectangle2D.Double(" + r.getX() + ", " + r.getY() + ", "
2085                 + r.getWidth() + ", " + r.getHeight() + ")");
2086     }
2087 
2088     private void write(String s) {
2089         if (s == null) {
2090             out.print("(String)null");
2091             return;
2092         }
2093 
2094         StringBuffer sb = new StringBuffer();
2095         for (int i = 0; i < s.length(); i++) {
2096             char c = s.charAt(i);
2097             switch (c) {
2098             case '\\':
2099                 sb.append("\\\\");
2100                 break;
2101             case '"':
2102                 sb.append("\\\"");
2103                 break;
2104             default:
2105                 sb.append(toUnicode(c));
2106                 break;
2107             }
2108         }
2109         out.print("\"" + sb.toString() + "\"");
2110     }
2111 
2112     private void write(TagString s) {
2113         if (s == null) {
2114             out.print("null");
2115             return;
2116         }
2117 
2118         imports.add("org.freehep.graphics2d.TagString");
2119         out.print("new TagString(");
2120         write(s.toString());
2121         out.print(")");
2122     }
2123 
2124     private String vg() {
2125         Integer index = (Integer) vg.get(this);
2126         return "vg["
2127                 + ((index != null) ? String.valueOf(index.intValue()) : "null")
2128                 + "]";
2129     }
2130 
2131     private String toUnicode(char c) {
2132         if ((c <= 0x1f) || (0x7f <= c)) {
2133             String unicode = "0000" + Integer.toHexString(c);
2134             return "\\u" + unicode.substring(unicode.length() - 4);
2135         } else {
2136             return String.valueOf(c);
2137         }
2138     }
2139 }