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