KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > fop > render > ps > ASCII85OutputStream


1 /*
2  * $Id: ASCII85OutputStream.java,v 1.1.2.3 2003/04/23 20:50:04 jeremias Exp $
3  * ============================================================================
4  * The Apache Software License, Version 1.1
5  * ============================================================================
6  *
7  * Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without modifica-
10  * tion, are permitted provided that the following conditions are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  *
19  * 3. The end-user documentation included with the redistribution, if any, must
20  * include the following acknowledgment: "This product includes software
21  * developed by the Apache Software Foundation (http://www.apache.org/)."
22  * Alternately, this acknowledgment may appear in the software itself, if
23  * and wherever such third-party acknowledgments normally appear.
24  *
25  * 4. The names "FOP" and "Apache Software Foundation" must not be used to
26  * endorse or promote products derived from this software without prior
27  * written permission. For written permission, please contact
28  * apache@apache.org.
29  *
30  * 5. Products derived from this software may not be called "Apache", nor may
31  * "Apache" appear in their name, without prior written permission of the
32  * Apache Software Foundation.
33  *
34  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
35  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
36  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
37  * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
38  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
39  * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
40  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
41  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
42  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
43  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44  * ============================================================================
45  *
46  * This software consists of voluntary contributions made by many individuals
47  * on behalf of the Apache Software Foundation and was originally created by
48  * James Tauber <jtauber@jtauber.com>. For more information on the Apache
49  * Software Foundation, please see <http://www.apache.org/>.
50  */

51 package org.apache.fop.render.ps;
52
53 import java.io.OutputStream JavaDoc;
54 import java.io.FilterOutputStream JavaDoc;
55 import java.io.IOException JavaDoc;
56
57 /**
58  * This class applies a ASCII85 encoding to the stream.
59  *
60  * @author Jeremias Maerki
61  * @version $Id: ASCII85OutputStream.java,v 1.1.2.3 2003/04/23 20:50:04 jeremias Exp $
62  */

63 public class ASCII85OutputStream extends FilterOutputStream JavaDoc
64             implements Finalizable {
65
66     private static final int ZERO = 0x7A; //"z"
67
private static final byte[] ZERO_ARRAY = {(byte)ZERO};
68     private static final int START = 0x21; //"!"
69
private static final int EOL = 0x0A; //"\n"
70
private static final byte[] EOD = {0x7E, 0x3E}; //"~>"
71

72     private static final long base85_4 = 85;
73     private static final long base85_3 = base85_4 * base85_4;
74     private static final long base85_2 = base85_3 * base85_4;
75     private static final long base85_1 = base85_2 * base85_4;
76
77     private static final boolean DEBUG = false;
78
79     private int pos = 0;
80     private long buffer = 0;
81     private int posinline = 0;
82     private int bw = 0;
83
84
85     public ASCII85OutputStream(OutputStream JavaDoc out) {
86         super(out);
87     }
88
89
90     public void write(int b) throws IOException JavaDoc {
91         if (pos == 0) {
92             buffer += (b << 24) & 0xff000000L;
93         } else if (pos == 1) {
94             buffer += (b << 16) & 0xff0000L;
95         } else if (pos == 2) {
96             buffer += (b << 8) & 0xff00L;
97         } else {
98             buffer += b & 0xffL;
99         }
100         pos++;
101
102         if (pos > 3) {
103             checkedWrite(convertWord(buffer));
104             buffer = 0;
105             pos = 0;
106         }
107     }
108
109
110     private void checkedWrite(int b) throws IOException JavaDoc {
111         if (posinline == 80) {
112             out.write(EOL); bw++;
113             posinline = 0;
114         }
115         checkedWrite(b);
116         posinline++;
117         bw++;
118     }
119
120
121     private void checkedWrite(byte[] buf) throws IOException JavaDoc {
122         checkedWrite(buf, buf.length, false);
123     }
124
125
126     private void checkedWrite(byte[] buf, boolean nosplit) throws IOException JavaDoc {
127         checkedWrite(buf, buf.length, nosplit);
128     }
129
130
131     private void checkedWrite(byte[] buf , int len) throws IOException JavaDoc {
132         checkedWrite(buf, len, false);
133     }
134
135
136     private void checkedWrite(byte[] buf , int len, boolean nosplit) throws IOException JavaDoc {
137         if (posinline + len > 80) {
138             int firstpart = (nosplit ? 0 : len - (posinline + len - 80));
139             if (firstpart > 0) out.write(buf, 0, firstpart);
140             out.write(EOL); bw++;
141             int rest = len - firstpart;
142             if (rest > 0) out.write(buf, firstpart, rest);
143             posinline = rest;
144         } else {
145             out.write(buf, 0, len);
146             posinline += len;
147         }
148         bw += len;
149     }
150
151
152     /**
153      * This converts a 32 bit value (4 bytes) into 5 bytes using base 85.
154      * each byte in the result starts with zero at the '!' character so
155      * the resulting base85 number fits into printable ascii chars
156      *
157      * @param word the 32 bit unsigned (hence the long datatype) word
158      * @return 5 bytes (or a single byte of the 'z' character for word
159      * values of 0)
160      */

161     private byte[] convertWord(long word) {
162         word = word & 0xffffffff;
163
164         if (word == 0) {
165             return ZERO_ARRAY;
166         } else {
167             if (word < 0) {
168                 word = -word;
169             }
170             byte c1 = (byte)((word / base85_1) & 0xFF);
171             byte c2 = (byte)(((word - (c1 * base85_1)) / base85_2) & 0xFF);
172             byte c3 =
173                 (byte)(((word - (c1 * base85_1) - (c2 * base85_2)) / base85_3)
174                        & 0xFF);
175             byte c4 =
176                 (byte)(((word - (c1 * base85_1) - (c2 * base85_2) - (c3 * base85_3)) / base85_4)
177                        & 0xFF);
178             byte c5 =
179                 (byte)(((word - (c1 * base85_1) - (c2 * base85_2) - (c3 * base85_3) - (c4 * base85_4)))
180                        & 0xFF);
181
182             byte[] ret = {
183                 (byte)(c1 + START), (byte)(c2 + START),
184                 (byte)(c3 + START), (byte)(c4 + START),
185                 (byte)(c5 + START)
186             };
187
188             if (DEBUG) {
189                 for (int i = 0; i < ret.length; i++) {
190                     if (ret[i] < 33 || ret[i] > 117) {
191                         System.out.println("Illegal char value "
192                                         + new Integer JavaDoc(ret[i]));
193                     }
194                 }
195             }
196             return ret;
197         }
198     }
199
200
201     public void finalizeStream() throws IOException JavaDoc {
202         // now take care of the trailing few bytes.
203
// with n leftover bytes, we append 0 bytes to make a full group of 4
204
// then convert like normal (except not applying the special zero rule)
205
// and write out the first n+1 bytes from the result
206
if (pos > 0) {
207             int rest = pos;
208             /*
209             byte[] lastdata = new byte[4];
210             int i = 0;
211             for (int j = 0; j < 4; j++) {
212                 if (j < rest) {
213                     lastdata[j] = data[i++];
214                 } else {
215                     lastdata[j] = 0;
216                 }
217             }
218
219             long val = ((lastdata[0] << 24) & 0xff000000L)
220                        + ((lastdata[1] << 16) & 0xff0000L)
221                        + ((lastdata[2] << 8) & 0xff00L)
222                        + (lastdata[3] & 0xffL);
223             */

224
225             byte[] conv;
226             // special rule for handling zeros at the end
227
if (buffer != 0) {
228                 conv = convertWord(buffer);
229             } else {
230                 conv = new byte[5];
231                 for (int j = 0; j < 5; j++) {
232                     conv[j] = (byte)'!';
233                 }
234             }
235             // assert rest+1 <= 5
236
checkedWrite(conv, rest + 1);
237         }
238         // finally write the two character end of data marker
239
checkedWrite(EOD, true);
240
241         flush();
242         if (out instanceof Finalizable) {
243             ((Finalizable)out).finalizeStream();
244         }
245     }
246
247
248     public void close() throws IOException JavaDoc {
249         finalizeStream();
250         super.close();
251     }
252
253 }
254
255
256
Popular Tags