You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ASCII85OutputStream.java 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /*
  2. * Copyright 1999-2004 The Apache Software Foundation.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /* $Id$ */
  17. package org.apache.fop.util;
  18. import java.io.OutputStream;
  19. import java.io.FilterOutputStream;
  20. import java.io.IOException;
  21. /**
  22. * This class applies a ASCII85 encoding to the stream.
  23. *
  24. * @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a>
  25. * @version $Id$
  26. */
  27. public class ASCII85OutputStream extends FilterOutputStream
  28. implements ASCII85Constants, Finalizable {
  29. private static final boolean DEBUG = false;
  30. private int pos = 0;
  31. private long buffer = 0;
  32. private int posinline = 0;
  33. private int bw = 0;
  34. /** @see java.io.FilterOutputStream **/
  35. public ASCII85OutputStream(OutputStream out) {
  36. super(out);
  37. }
  38. /** @see java.io.FilterOutputStream **/
  39. public void write(int b) throws IOException {
  40. if (pos == 0) {
  41. buffer += (b << 24) & 0xff000000L;
  42. } else if (pos == 1) {
  43. buffer += (b << 16) & 0xff0000L;
  44. } else if (pos == 2) {
  45. buffer += (b << 8) & 0xff00L;
  46. } else {
  47. buffer += b & 0xffL;
  48. }
  49. pos++;
  50. if (pos > 3) {
  51. checkedWrite(convertWord(buffer));
  52. buffer = 0;
  53. pos = 0;
  54. }
  55. }
  56. /* UNUSED ATM
  57. private void checkedWrite(int b) throws IOException {
  58. if (posinline == 80) {
  59. out.write(EOL); bw++;
  60. posinline = 0;
  61. }
  62. checkedWrite(b);
  63. posinline++;
  64. bw++;
  65. }*/
  66. private void checkedWrite(byte[] buf) throws IOException {
  67. checkedWrite(buf, buf.length, false);
  68. }
  69. private void checkedWrite(byte[] buf, boolean nosplit) throws IOException {
  70. checkedWrite(buf, buf.length, nosplit);
  71. }
  72. private void checkedWrite(byte[] buf , int len) throws IOException {
  73. checkedWrite(buf, len, false);
  74. }
  75. private void checkedWrite(byte[] buf , int len, boolean nosplit) throws IOException {
  76. if (posinline + len > 80) {
  77. int firstpart = (nosplit ? 0 : len - (posinline + len - 80));
  78. if (firstpart > 0) {
  79. out.write(buf, 0, firstpart);
  80. }
  81. out.write(EOL); bw++;
  82. int rest = len - firstpart;
  83. if (rest > 0) {
  84. out.write(buf, firstpart, rest);
  85. }
  86. posinline = rest;
  87. } else {
  88. out.write(buf, 0, len);
  89. posinline += len;
  90. }
  91. bw += len;
  92. }
  93. /**
  94. * This converts a 32 bit value (4 bytes) into 5 bytes using base 85.
  95. * each byte in the result starts with zero at the '!' character so
  96. * the resulting base85 number fits into printable ascii chars
  97. *
  98. * @param word the 32 bit unsigned (hence the long datatype) word
  99. * @return 5 bytes (or a single byte of the 'z' character for word
  100. * values of 0)
  101. */
  102. private byte[] convertWord(long word) {
  103. word = word & 0xffffffff;
  104. if (word == 0) {
  105. return ZERO_ARRAY;
  106. } else {
  107. if (word < 0) {
  108. word = -word;
  109. }
  110. byte c1 =
  111. (byte)((word
  112. / POW85[0]) & 0xFF);
  113. byte c2 =
  114. (byte)(((word - (c1 * POW85[0]))
  115. / POW85[1]) & 0xFF);
  116. byte c3 =
  117. (byte)(((word - (c1 * POW85[0])
  118. - (c2 * POW85[1]))
  119. / POW85[2]) & 0xFF);
  120. byte c4 =
  121. (byte)(((word - (c1 * POW85[0])
  122. - (c2 * POW85[1])
  123. - (c3 * POW85[2]))
  124. / POW85[3]) & 0xFF);
  125. byte c5 =
  126. (byte)(((word - (c1 * POW85[0])
  127. - (c2 * POW85[1])
  128. - (c3 * POW85[2])
  129. - (c4 * POW85[3])))
  130. & 0xFF);
  131. byte[] ret = {
  132. (byte)(c1 + START), (byte)(c2 + START),
  133. (byte)(c3 + START), (byte)(c4 + START),
  134. (byte)(c5 + START)
  135. };
  136. if (DEBUG) {
  137. for (int i = 0; i < ret.length; i++) {
  138. if (ret[i] < 33 || ret[i] > 117) {
  139. System.out.println("Illegal char value "
  140. + new Integer(ret[i]));
  141. }
  142. }
  143. }
  144. return ret;
  145. }
  146. }
  147. /** @see Finalizable **/
  148. public void finalizeStream() throws IOException {
  149. // now take care of the trailing few bytes.
  150. // with n leftover bytes, we append 0 bytes to make a full group of 4
  151. // then convert like normal (except not applying the special zero rule)
  152. // and write out the first n+1 bytes from the result
  153. if (pos > 0) {
  154. int rest = pos;
  155. /*
  156. byte[] lastdata = new byte[4];
  157. int i = 0;
  158. for (int j = 0; j < 4; j++) {
  159. if (j < rest) {
  160. lastdata[j] = data[i++];
  161. } else {
  162. lastdata[j] = 0;
  163. }
  164. }
  165. long val = ((lastdata[0] << 24) & 0xff000000L)
  166. + ((lastdata[1] << 16) & 0xff0000L)
  167. + ((lastdata[2] << 8) & 0xff00L)
  168. + (lastdata[3] & 0xffL);
  169. */
  170. byte[] conv;
  171. // special rule for handling zeros at the end
  172. if (buffer != 0) {
  173. conv = convertWord(buffer);
  174. } else {
  175. conv = new byte[5];
  176. for (int j = 0; j < 5; j++) {
  177. conv[j] = (byte)'!';
  178. }
  179. }
  180. // assert rest+1 <= 5
  181. checkedWrite(conv, rest + 1);
  182. }
  183. // finally write the two character end of data marker
  184. checkedWrite(EOD, true);
  185. flush();
  186. if (out instanceof Finalizable) {
  187. ((Finalizable)out).finalizeStream();
  188. }
  189. }
  190. /** @see java.io.FilterOutputStream **/
  191. public void close() throws IOException {
  192. finalizeStream();
  193. super.close();
  194. }
  195. }