JAL-1521 updated xerces to 2.11 along with xml-apis
[jalview.git] / src / org / jibble / epsgraphics / EpsDocument.java
1 /*
2  Copyright Paul James Mutton, 2001-2004, http://www.jibble.org/
3
4  This file is part of EpsGraphics2D.
5
6  This software is dual-licensed, allowing you to choose between the GNU
7  General Public License (GPL) and the www.jibble.org Commercial License.
8  Since the GPL may be too restrictive for use in a proprietary application,
9  a commercial license is also provided. Full license information can be
10  found at http://www.jibble.org/licenses/
11
12  $Author$
13  $Id$
14
15  */
16
17 package org.jibble.epsgraphics;
18
19 import java.io.*;
20 import java.util.*;
21
22 /**
23  * This represents an EPS document. Several EpsGraphics2D objects may point to
24  * the same EpsDocument.
25  * <p>
26  * Copyright Paul Mutton, <a
27  * href="http://www.jibble.org/">http://www.jibble.org/</a>
28  * 
29  */
30 public class EpsDocument
31 {
32
33   /**
34    * Constructs an empty EpsDevice.
35    */
36   public EpsDocument(String title)
37   {
38     _title = title;
39     minX = Float.POSITIVE_INFINITY;
40     minY = Float.POSITIVE_INFINITY;
41     maxX = Float.NEGATIVE_INFINITY;
42     maxY = Float.NEGATIVE_INFINITY;
43     _stringWriter = new StringWriter();
44     _bufferedWriter = new BufferedWriter(_stringWriter);
45   }
46
47   /**
48    * Constructs an empty EpsDevice that writes directly to a file. Bounds must
49    * be set before use.
50    */
51   public EpsDocument(String title, OutputStream outputStream, int minX,
52           int minY, int maxX, int maxY) throws IOException
53   {
54     _title = title;
55     this.minX = minX;
56     this.minY = minY;
57     this.maxX = maxX;
58     this.maxY = maxY;
59     _bufferedWriter = new BufferedWriter(new OutputStreamWriter(
60             outputStream));
61     write(_bufferedWriter);
62   }
63
64   /**
65    * Returns the title of the EPS document.
66    */
67   public synchronized String getTitle()
68   {
69     return _title;
70   }
71
72   /**
73    * Updates the bounds of the current EPS document.
74    */
75   public synchronized void updateBounds(double x, double y)
76   {
77     if (x > maxX)
78     {
79       maxX = (float) x;
80     }
81     if (x < minX)
82     {
83       minX = (float) x;
84     }
85     if (y > maxY)
86     {
87       maxY = (float) y;
88     }
89     if (y < minY)
90     {
91       minY = (float) y;
92     }
93   }
94
95   /**
96    * Appends a line to the EpsDocument. A new line character is added to the end
97    * of the line when it is added.
98    */
99   public synchronized void append(EpsGraphics2D g, String line)
100   {
101     if (_lastG == null)
102     {
103       _lastG = g;
104     }
105     else if (g != _lastG)
106     {
107       EpsGraphics2D lastG = _lastG;
108       _lastG = g;
109       // We are being drawn on with a different EpsGraphics2D context.
110       // We may need to update the clip, etc from this new context.
111       if (g.getClip() != lastG.getClip())
112       {
113         g.setClip(g.getClip());
114       }
115       if (!g.getColor().equals(lastG.getColor()))
116       {
117         g.setColor(g.getColor());
118       }
119       if (!g.getBackground().equals(lastG.getBackground()))
120       {
121         g.setBackground(g.getBackground());
122       }
123       // We don't need this, as this only affects the stroke and font,
124       // which are dealt with separately later on.
125       // if (!g.getTransform().equals(lastG.getTransform())) {
126       // g.setTransform(g.getTransform());
127       // }
128       if (!g.getPaint().equals(lastG.getPaint()))
129       {
130         g.setPaint(g.getPaint());
131       }
132       if (!g.getComposite().equals(lastG.getComposite()))
133       {
134         g.setComposite(g.getComposite());
135       }
136       if (!g.getComposite().equals(lastG.getComposite()))
137       {
138         g.setComposite(g.getComposite());
139       }
140       if (!g.getFont().equals(lastG.getFont()))
141       {
142         g.setFont(g.getFont());
143       }
144       if (!g.getStroke().equals(lastG.getStroke()))
145       {
146         g.setStroke(g.getStroke());
147       }
148     }
149     _lastG = g;
150
151     try
152     {
153       _bufferedWriter.write(line + "\n");
154     } catch (IOException e)
155     {
156       throw new EpsException("Could not write to the output file: " + e);
157     }
158   }
159
160   /**
161    * Outputs the contents of the EPS document to the specified Writer, complete
162    * with headers and bounding box.
163    */
164   public synchronized void write(Writer writer) throws IOException
165   {
166     float offsetX = -minX;
167     float offsetY = -minY;
168
169     writer.write("%!PS-Adobe-3.0 EPSF-3.0\n");
170     writer.write("%%Creator: Jalview "
171             + jalview.bin.Cache.getProperty("VERSION") + " \n");
172     writer.write("%%Title: " + _title + "\n");
173     writer.write("%%CreationDate: " + new Date() + "\n");
174     writer.write("%%BoundingBox: 0 0 " + ((int) Math.ceil(maxX + offsetX))
175             + " " + ((int) Math.ceil(maxY + offsetY)) + "\n");
176     writer.write("%%DocumentData: Clean7Bit\n");
177     writer.write("%%DocumentProcessColors: Black\n");
178     writer.write("%%ColorUsage: Color\n");
179     writer.write("%%Origin: 0 0\n");
180     writer.write("%%Pages: 1\n");
181     writer.write("%%Page: 1 1\n");
182     writer.write("%%EndComments\n\n");
183
184     writer.write("gsave\n");
185
186     if (_stringWriter != null)
187     {
188       writer.write(offsetX + " " + (offsetY) + " translate\n");
189
190       _bufferedWriter.flush();
191       StringBuffer buffer = _stringWriter.getBuffer();
192       for (int i = 0; i < buffer.length(); i++)
193       {
194         writer.write(buffer.charAt(i));
195       }
196
197       writeFooter(writer);
198     }
199     else
200     {
201       writer.write(offsetX + " " + ((maxY - minY) - offsetY)
202               + " translate\n");
203     }
204
205     writer.flush();
206   }
207
208   private void writeFooter(Writer writer) throws IOException
209   {
210     writer.write("grestore\n");
211     if (isClipSet())
212     {
213       writer.write("grestore\n");
214     }
215     writer.write("showpage\n");
216     writer.write("\n");
217     writer.write("%%EOF");
218     writer.flush();
219   }
220
221   public synchronized void flush() throws IOException
222   {
223     _bufferedWriter.flush();
224   }
225
226   public synchronized void close() throws IOException
227   {
228     if (_stringWriter == null)
229     {
230       writeFooter(_bufferedWriter);
231       _bufferedWriter.flush();
232       _bufferedWriter.close();
233     }
234   }
235
236   public boolean isClipSet()
237   {
238     return _isClipSet;
239   }
240
241   public void setClipSet(boolean isClipSet)
242   {
243     _isClipSet = isClipSet;
244   }
245
246   private float minX;
247
248   private float minY;
249
250   private float maxX;
251
252   private float maxY;
253
254   private boolean _isClipSet = false;
255
256   private String _title;
257
258   private StringWriter _stringWriter;
259
260   private BufferedWriter _bufferedWriter = null;
261
262   // We need to remember which was the last EpsGraphics2D object to use
263   // us, as we need to replace the clipping region if another EpsGraphics2D
264   // object tries to use us.
265   private EpsGraphics2D _lastG = null;
266
267 }