Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

ASCII85OutputStream.java 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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. * @version $Id$
  25. */
  26. public class ASCII85OutputStream extends FilterOutputStream
  27. implements ASCII85Constants, Finalizable {
  28. private static final boolean DEBUG = false;
  29. private int pos = 0;
  30. private long buffer = 0;
  31. private int posinline = 0;
  32. private int bw = 0;
  33. /** @see java.io.FilterOutputStream **/
  34. public ASCII85OutputStream(OutputStream out) {
  35. super(out);
  36. }
  37. /** @see java.io.FilterOutputStream **/
  38. public void write(int b) throws IOException {
  39. if (pos == 0) {
  40. buffer += (b << 24) & 0xff000000L;
  41. } else if (pos == 1) {
  42. buffer += (b << 16) & 0xff0000L;
  43. } else if (pos == 2) {
  44. buffer += (b << 8) & 0xff00L;
  45. } else {
  46. buffer += b & 0xffL;
  47. }
  48. pos++;
  49. if (pos > 3) {
  50. checkedWrite(convertWord(buffer));
  51. buffer = 0;
  52. pos = 0;
  53. }
  54. }
  55. /* UNUSED ATM
  56. private void checkedWrite(int b) throws IOException {
  57. if (posinline == 80) {
  58. out.write(EOL); bw++;
  59. posinline = 0;
  60. }
  61. checkedWrite(b);
  62. posinline++;
  63. bw++;
  64. }*/
  65. private void checkedWrite(byte[] buf) throws IOException {
  66. checkedWrite(buf, buf.length, false);
  67. }
  68. private void checkedWrite(byte[] buf, boolean nosplit) throws IOException {
  69. checkedWrite(buf, buf.length, nosplit);
  70. }
  71. private void checkedWrite(byte[] buf , int len) throws IOException {
  72. checkedWrite(buf, len, false);
  73. }
  74. private void checkedWrite(byte[] buf , int len, boolean nosplit) throws IOException {
  75. if (posinline + len > 80) {
  76. int firstpart = (nosplit ? 0 : len - (posinline + len - 80));
  77. if (firstpart > 0) {
  78. out.write(buf, 0, firstpart);
  79. }
  80. out.write(EOL); bw++;
  81. int rest = len - firstpart;
  82. if (rest > 0) {
  83. out.write(buf, firstpart, rest);
  84. }
  85. posinline = rest;
  86. } else {
  87. out.write(buf, 0, len);
  88. posinline += len;
  89. }
  90. bw += len;
  91. }
  92. /**
  93. * This converts a 32 bit value (4 bytes) into 5 bytes using base 85.
  94. * each byte in the result starts with zero at the '!' character so
  95. * the resulting base85 number fits into printable ascii chars
  96. *
  97. * @param word the 32 bit unsigned (hence the long datatype) word
  98. * @return 5 bytes (or a single byte of the 'z' character for word
  99. * values of 0)
  100. */
  101. private byte[] convertWord(long word) {
  102. word = word & 0xffffffff;
  103. if (word == 0) {
  104. return ZERO_ARRAY;
  105. } else {
  106. if (word < 0) {
  107. word = -word;
  108. }
  109. byte c1 =
  110. (byte)((word
  111. / POW85[0]) & 0xFF);
  112. byte c2 =
  113. (byte)(((word - (c1 * POW85[0]))
  114. / POW85[1]) & 0xFF);
  115. byte c3 =
  116. (byte)(((word - (c1 * POW85[0])
  117. - (c2 * POW85[1]))
  118. / POW85[2]) & 0xFF);
  119. byte c4 =
  120. (byte)(((word - (c1 * POW85[0])
  121. - (c2 * POW85[1])
  122. - (c3 * POW85[2]))
  123. / POW85[3]) & 0xFF);
  124. byte c5 =
  125. (byte)(((word - (c1 * POW85[0])
  126. - (c2 * POW85[1])
  127. - (c3 * POW85[2])
  128. - (c4 * POW85[3])))
  129. & 0xFF);
  130. byte[] ret = {
  131. (byte)(c1 + START), (byte)(c2 + START),
  132. (byte)(c3 + START), (byte)(c4 + START),
  133. (byte)(c5 + START)
  134. };
  135. if (DEBUG) {
  136. for (int i = 0; i < ret.length; i++) {
  137. if (ret[i] < 33 || ret[i] > 117) {
  138. System.out.println("Illegal char value "
  139. + new Integer(ret[i]));
  140. }
  141. }
  142. }
  143. return ret;
  144. }
  145. }
  146. /** @see Finalizable **/
  147. public void finalizeStream() throws IOException {
  148. // now take care of the trailing few bytes.
  149. // with n leftover bytes, we append 0 bytes to make a full group of 4
  150. // then convert like normal (except not applying the special zero rule)
  151. // and write out the first n+1 bytes from the result
  152. if (pos > 0) {
  153. int rest = pos;
  154. /*
  155. byte[] lastdata = new byte[4];
  156. int i = 0;
  157. for (int j = 0; j < 4; j++) {
  158. if (j < rest) {
  159. lastdata[j] = data[i++];
  160. } else {
  161. lastdata[j] = 0;
  162. }
  163. }
  164. long val = ((lastdata[0] << 24) & 0xff000000L)
  165. + ((lastdata[1] << 16) & 0xff0000L)
  166. + ((lastdata[2] << 8) & 0xff00L)
  167. + (lastdata[3] & 0xffL);
  168. */
  169. byte[] conv;
  170. // special rule for handling zeros at the end
  171. if (buffer != 0) {
  172. conv = convertWord(buffer);
  173. } else {
  174. conv = new byte[5];
  175. for (int j = 0; j < 5; j++) {
  176. conv[j] = (byte)'!';
  177. }
  178. }
  179. // assert rest+1 <= 5
  180. checkedWrite(conv, rest + 1);
  181. }
  182. // finally write the two character end of data marker
  183. checkedWrite(EOD, true);
  184. flush();
  185. if (out instanceof Finalizable) {
  186. ((Finalizable)out).finalizeStream();
  187. }
  188. }
  189. /** @see java.io.FilterOutputStream **/
  190. public void close() throws IOException {
  191. finalizeStream();
  192. super.close();
  193. }
  194. }