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.

AbstractAFPObject.java 9.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. /* $Id$ */
  18. package org.apache.fop.afp.modca;
  19. import java.io.IOException;
  20. import java.io.InputStream;
  21. import java.io.OutputStream;
  22. import java.util.Collection;
  23. import java.util.Iterator;
  24. import org.apache.commons.logging.Log;
  25. import org.apache.commons.logging.LogFactory;
  26. import org.apache.fop.afp.Streamable;
  27. import org.apache.fop.afp.util.BinaryUtils;
  28. /**
  29. * This is the base class for all data stream objects. Page objects are
  30. * responsible for building and generating the binary datastream in an
  31. * AFP format.
  32. */
  33. public abstract class AbstractAFPObject implements Streamable {
  34. /** Static logging instance */
  35. protected static final Log log = LogFactory.getLog("org.apache.xmlgraphics.afp.modca");
  36. /** the structured field class id */
  37. protected static final byte SF_CLASS = (byte)0xD3;
  38. private static final byte[] SF_HEADER = new byte[] {
  39. 0x5A, // Structured field identifier
  40. 0x00, // Length byte 1
  41. 0x10, // Length byte 2
  42. SF_CLASS, // Structured field id byte 1
  43. (byte) 0x00, // Structured field id byte 2
  44. (byte) 0x00, // Structured field id byte 3
  45. 0x00, // Flags
  46. 0x00, // Reserved
  47. 0x00, // Reserved
  48. };
  49. /**
  50. * Copies the template structured field data array to the given byte array
  51. *
  52. * @param data the structured field data byte array
  53. * @param type the type code
  54. * @param category the category code
  55. */
  56. protected void copySF(byte[] data, byte type, byte category) {
  57. copySF(data, SF_CLASS, type, category);
  58. }
  59. /**
  60. * Copies the template structured field data array to the given byte array
  61. *
  62. * @param data the structured field data byte array
  63. * @param clazz the class code
  64. * @param type the type code
  65. * @param category the category code
  66. */
  67. protected static void copySF(byte[] data, byte clazz, byte type, byte category) {
  68. System.arraycopy(SF_HEADER, 0, data, 0, SF_HEADER.length);
  69. data[3] = clazz;
  70. data[4] = type;
  71. data[5] = category;
  72. }
  73. /**
  74. * Writes a collection of Streamable to the AFP Datastream.
  75. *
  76. * @param objects a list of AFPObjects
  77. * @param os The stream to write to
  78. * @throws java.io.IOException an I/O exception of some sort has occurred.
  79. */
  80. protected void writeObjects(Collection/*<Streamable>*/ objects, OutputStream os)
  81. throws IOException {
  82. if (objects != null && objects.size() > 0) {
  83. Iterator it = objects.iterator();
  84. while (it.hasNext()) {
  85. Object object = it.next();
  86. if (object instanceof Streamable) {
  87. ((Streamable)object).writeToStream(os);
  88. it.remove(); // once written, immediately remove the object
  89. }
  90. }
  91. }
  92. }
  93. /**
  94. * Reads data chunks from an InputStream
  95. * and then formats them with a structured header to a given OutputStream
  96. *
  97. * @param dataHeader the header data
  98. * @param lengthOffset offset of length field in data chunk
  99. * @param maxChunkLength the maximum chunk length
  100. * @param inputStream the InputStream to read from
  101. * @param outputStream the OutputStream to write to
  102. * @throws IOException thrown if an I/O exception of some sort has occurred.
  103. */
  104. protected static void copyChunks(byte[] dataHeader, int lengthOffset,
  105. int maxChunkLength, InputStream inputStream, OutputStream outputStream)
  106. throws IOException {
  107. int headerLen = dataHeader.length - lengthOffset;
  108. // length field is just before data so do not include in data length
  109. if (headerLen == 2) {
  110. headerLen = 0;
  111. }
  112. byte[] data = new byte[maxChunkLength];
  113. int numBytesRead = 0;
  114. while ((numBytesRead = inputStream.read(data, 0, maxChunkLength)) > 0) {
  115. byte[] len = BinaryUtils.convert(headerLen + numBytesRead, 2);
  116. dataHeader[lengthOffset] = len[0]; // Length byte 1
  117. dataHeader[lengthOffset + 1] = len[1]; // Length byte 2
  118. outputStream.write(dataHeader);
  119. outputStream.write(data, 0, numBytesRead);
  120. }
  121. }
  122. /**
  123. * Writes data chunks to a given outputstream
  124. *
  125. * @param data the data byte array
  126. * @param dataHeader the header data
  127. * @param lengthOffset offset of length field in data chunk
  128. * @param maxChunkLength the maximum chunk length
  129. * @param os the outputstream to write to
  130. * @throws IOException thrown if an I/O exception of some sort has occurred.
  131. */
  132. protected static void writeChunksToStream(byte[] data, byte[] dataHeader,
  133. int lengthOffset, int maxChunkLength, OutputStream os) throws IOException {
  134. int dataLength = data.length;
  135. int numFullChunks = dataLength / maxChunkLength;
  136. int lastChunkLength = dataLength % maxChunkLength;
  137. int headerLen = dataHeader.length - lengthOffset;
  138. // length field is just before data so do not include in data length
  139. if (headerLen == 2) {
  140. headerLen = 0;
  141. }
  142. byte[] len;
  143. int off = 0;
  144. if (numFullChunks > 0) {
  145. // write out full data chunks
  146. len = BinaryUtils.convert(headerLen + maxChunkLength, 2);
  147. dataHeader[lengthOffset] = len[0]; // Length byte 1
  148. dataHeader[lengthOffset + 1] = len[1]; // Length byte 2
  149. for (int i = 0; i < numFullChunks; i++, off += maxChunkLength) {
  150. os.write(dataHeader);
  151. os.write(data, off, maxChunkLength);
  152. }
  153. }
  154. if (lastChunkLength > 0) {
  155. // write last data chunk
  156. len = BinaryUtils.convert(headerLen + lastChunkLength, 2);
  157. dataHeader[lengthOffset] = len[0]; // Length byte 1
  158. dataHeader[lengthOffset + 1] = len[1]; // Length byte 2
  159. os.write(dataHeader);
  160. os.write(data, off, lastChunkLength);
  161. }
  162. }
  163. /** structured field type codes */
  164. public interface Type {
  165. /** Attribute */
  166. byte ATTRIBUTE = (byte)0x0A;
  167. /** Copy Count */
  168. byte COPY_COUNT = (byte)0xA2;
  169. /** Descriptor */
  170. byte DESCRIPTOR = (byte)0xA6;
  171. /** Control */
  172. byte CONTROL = (byte)0xA7;
  173. /** Begin */
  174. byte BEGIN = (byte)0xA8;
  175. /** End */
  176. byte END = (byte)0xA9;
  177. /** Map */
  178. byte MAP = (byte)0xAB;
  179. /** Position */
  180. byte POSITION = (byte)0xAC;
  181. /** Process */
  182. byte PROCESS = (byte)0xAD;
  183. /** Include */
  184. byte INCLUDE = (byte)0xAF;
  185. /** Table */
  186. byte TABLE = (byte)0xB0;
  187. /** Migration */
  188. byte MIGRATION = (byte)0xB1;
  189. /** Variable */
  190. byte VARIABLE = (byte)0xB2;
  191. /** Link */
  192. byte LINK = (byte)0xB4;
  193. /** Data */
  194. byte DATA = (byte)0xEE;
  195. }
  196. /** structured field category codes */
  197. public interface Category {
  198. /** Page Segment */
  199. byte PAGE_SEGMENT = (byte)0x5F;
  200. /** Object Area */
  201. byte OBJECT_AREA = (byte)0x6B;
  202. /** Color Attribute Table */
  203. byte COLOR_ATTRIBUTE_TABLE = (byte)0x77;
  204. /** IM Image */
  205. byte IM_IMAGE = (byte)0x7B;
  206. /** Medium */
  207. byte MEDIUM = (byte)0x88;
  208. /** Coded Font */
  209. byte CODED_FONT = (byte)0x8A;
  210. /** Process Element */
  211. byte PROCESS_ELEMENT = (byte)0x90;
  212. /** Object Container */
  213. byte OBJECT_CONTAINER = (byte)0x92;
  214. /** Presentation Text */
  215. byte PRESENTATION_TEXT = (byte)0x9B;
  216. /** Index */
  217. byte INDEX = (byte)0xA7;
  218. /** Document */
  219. byte DOCUMENT = (byte)0xA8;
  220. /** Page Group */
  221. byte PAGE_GROUP = (byte)0xAD;
  222. /** Page */
  223. byte PAGE = (byte)0xAF;
  224. /** Graphics */
  225. byte GRAPHICS = (byte)0xBB;
  226. /** Data Resource */
  227. byte DATA_RESOURCE = (byte)0xC3;
  228. /** Document Environment Group (DEG) */
  229. byte DOCUMENT_ENVIRONMENT_GROUP = (byte)0xC4;
  230. /** Resource Group */
  231. byte RESOURCE_GROUP = (byte)0xC6;
  232. /** Object Environment Group (OEG) */
  233. byte OBJECT_ENVIRONMENT_GROUP = (byte)0xC7;
  234. /** Active Environment Group (AEG) */
  235. byte ACTIVE_ENVIRONMENT_GROUP = (byte)0xC9;
  236. /** Medium Map */
  237. byte MEDIUM_MAP = (byte)0xCC;
  238. /** Form Map */
  239. byte FORM_MAP = (byte)0xCD;
  240. /** Name Resource */
  241. byte NAME_RESOURCE = (byte)0xCE;
  242. /** Page Overlay */
  243. byte PAGE_OVERLAY = (byte)0xD8;
  244. /** Resource Environment Group (REG) */
  245. byte RESOURCE_ENVIROMENT_GROUP = (byte)0xD9;
  246. /** Overlay */
  247. byte OVERLAY = (byte)0xDF;
  248. /** Data Suppression */
  249. byte DATA_SUPRESSION = (byte)0xEA;
  250. /** Bar Code */
  251. byte BARCODE = (byte)0xEB;
  252. /** No Operation */
  253. byte NO_OPERATION = (byte)0xEE;
  254. /** Image */
  255. byte IMAGE = (byte)0xFB;
  256. }
  257. }