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 8.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  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(AbstractAFPObject.class);
  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. /** Length of bytes of a Structured Field Header */
  50. protected static final int SF_HEADER_LENGTH = SF_HEADER.length;
  51. /**
  52. * Copies the template structured field data array to the given byte array
  53. *
  54. * @param data the structured field data byte array
  55. * @param type the type code
  56. * @param category the category code
  57. */
  58. protected void copySF(byte[] data, byte type, byte category) {
  59. copySF(data, SF_CLASS, type, category);
  60. }
  61. /**
  62. * Copies the template structured field data array to the given byte array
  63. *
  64. * @param data the structured field data byte array
  65. * @param clazz the class code
  66. * @param type the type code
  67. * @param category the category code
  68. */
  69. protected static void copySF(byte[] data, byte clazz, byte type, byte category) {
  70. System.arraycopy(SF_HEADER, 0, data, 0, SF_HEADER_LENGTH);
  71. data[3] = clazz;
  72. data[4] = type;
  73. data[5] = category;
  74. }
  75. /**
  76. * Writes a collection of Streamable to the AFP Datastream.
  77. *
  78. * @param objects a list of AFPObjects
  79. * @param <S> Streamable view of an AFPObject
  80. * @param os The stream to write to
  81. * @throws java.io.IOException an I/O exception of some sort has occurred.
  82. */
  83. protected <S extends Streamable> void writeObjects(Collection<S> objects, OutputStream os)
  84. throws IOException {
  85. if (objects != null) {
  86. Iterator<S> it = objects.iterator();
  87. while (it.hasNext()) {
  88. Streamable s = it.next();
  89. s.writeToStream(os);
  90. it.remove(); // once written, immediately remove the object
  91. }
  92. }
  93. }
  94. /**
  95. * Writes data chunks to a given outputstream
  96. *
  97. * @param data the data byte array
  98. * @param dataHeader the header data
  99. * @param lengthOffset offset of length field in data chunk
  100. * @param maxChunkLength the maximum chunk length
  101. * @param os the outputstream to write to
  102. * @throws IOException thrown if an I/O exception of some sort has occurred.
  103. */
  104. protected static void writeChunksToStream(byte[] data, byte[] dataHeader,
  105. int lengthOffset, int maxChunkLength, OutputStream os) throws IOException {
  106. int dataLength = data.length;
  107. int numFullChunks = dataLength / maxChunkLength;
  108. int lastChunkLength = dataLength % maxChunkLength;
  109. int headerLen = dataHeader.length - lengthOffset;
  110. // length field is just before data so do not include in data length
  111. if (headerLen == 2) {
  112. headerLen = 0;
  113. }
  114. byte[] len;
  115. int off = 0;
  116. if (numFullChunks > 0) {
  117. // write out full data chunks
  118. len = BinaryUtils.convert(headerLen + maxChunkLength, 2);
  119. dataHeader[lengthOffset] = len[0]; // Length byte 1
  120. dataHeader[lengthOffset + 1] = len[1]; // Length byte 2
  121. for (int i = 0; i < numFullChunks; i++, off += maxChunkLength) {
  122. os.write(dataHeader);
  123. os.write(data, off, maxChunkLength);
  124. }
  125. }
  126. if (lastChunkLength > 0) {
  127. // write last data chunk
  128. len = BinaryUtils.convert(headerLen + lastChunkLength, 2);
  129. dataHeader[lengthOffset] = len[0]; // Length byte 1
  130. dataHeader[lengthOffset + 1] = len[1]; // Length byte 2
  131. os.write(dataHeader);
  132. os.write(data, off, lastChunkLength);
  133. }
  134. }
  135. /**
  136. * Truncates the string as necessary
  137. *
  138. * @param str a character string
  139. * @param maxLength the maximum length allowed for the string
  140. * @return a possibly truncated string
  141. */
  142. protected static String truncate(String str, int maxLength) {
  143. if (str.length() > maxLength) {
  144. str = str.substring(0, maxLength);
  145. LOG.warn("truncated character string '"
  146. + str + "', longer than " + maxLength + " chars");
  147. }
  148. return str;
  149. }
  150. /** structured field type codes */
  151. public interface Type {
  152. /** Attribute */
  153. byte ATTRIBUTE = (byte)0xA0;
  154. /** Copy Count */
  155. byte COPY_COUNT = (byte)0xA2;
  156. /** Descriptor */
  157. byte DESCRIPTOR = (byte)0xA6;
  158. /** Control */
  159. byte CONTROL = (byte)0xA7;
  160. /** Begin */
  161. byte BEGIN = (byte)0xA8;
  162. /** End */
  163. byte END = (byte)0xA9;
  164. /** Map */
  165. byte MAP = (byte)0xAB;
  166. /** Position */
  167. byte POSITION = (byte)0xAC;
  168. /** Process */
  169. byte PROCESS = (byte)0xAD;
  170. /** Include */
  171. byte INCLUDE = (byte)0xAF;
  172. /** Table */
  173. byte TABLE = (byte)0xB0;
  174. /** Migration */
  175. byte MIGRATION = (byte)0xB1;
  176. /** Variable */
  177. byte VARIABLE = (byte)0xB2;
  178. /** Link */
  179. byte LINK = (byte)0xB4;
  180. /** Data */
  181. byte DATA = (byte)0xEE;
  182. }
  183. /** structured field category codes */
  184. public interface Category {
  185. /** Page Segment */
  186. byte PAGE_SEGMENT = (byte)0x5F;
  187. /** Object Area */
  188. byte OBJECT_AREA = (byte)0x6B;
  189. /** Color Attribute Table */
  190. byte COLOR_ATTRIBUTE_TABLE = (byte)0x77;
  191. /** IM Image */
  192. byte IM_IMAGE = (byte)0x7B;
  193. /** Medium */
  194. byte MEDIUM = (byte)0x88;
  195. /** Coded Font */
  196. byte CODED_FONT = (byte)0x8A;
  197. /** Process Element */
  198. byte PROCESS_ELEMENT = (byte)0x90;
  199. /** Object Container */
  200. byte OBJECT_CONTAINER = (byte)0x92;
  201. /** Presentation Text */
  202. byte PRESENTATION_TEXT = (byte)0x9B;
  203. /** Index */
  204. byte INDEX = (byte)0xA7;
  205. /** Document */
  206. byte DOCUMENT = (byte)0xA8;
  207. /** Page Group */
  208. byte PAGE_GROUP = (byte)0xAD;
  209. /** Page */
  210. byte PAGE = (byte)0xAF;
  211. /** Graphics */
  212. byte GRAPHICS = (byte)0xBB;
  213. /** Data Resource */
  214. byte DATA_RESOURCE = (byte)0xC3;
  215. /** Document Environment Group (DEG) */
  216. byte DOCUMENT_ENVIRONMENT_GROUP = (byte)0xC4;
  217. /** Resource Group */
  218. byte RESOURCE_GROUP = (byte)0xC6;
  219. /** Object Environment Group (OEG) */
  220. byte OBJECT_ENVIRONMENT_GROUP = (byte)0xC7;
  221. /** Active Environment Group (AEG) */
  222. byte ACTIVE_ENVIRONMENT_GROUP = (byte)0xC9;
  223. /** Medium Map */
  224. byte MEDIUM_MAP = (byte)0xCC;
  225. /** Form Map */
  226. byte FORM_MAP = (byte)0xCD;
  227. /** Name Resource */
  228. byte NAME_RESOURCE = (byte)0xCE;
  229. /** Page Overlay */
  230. byte PAGE_OVERLAY = (byte)0xD8;
  231. /** Resource Environment Group (REG) */
  232. byte RESOURCE_ENVIROMENT_GROUP = (byte)0xD9;
  233. /** Overlay */
  234. byte OVERLAY = (byte)0xDF;
  235. /** Data Suppression */
  236. byte DATA_SUPRESSION = (byte)0xEA;
  237. /** Bar Code */
  238. byte BARCODE = (byte)0xEB;
  239. /** No Operation */
  240. byte NO_OPERATION = (byte)0xEE;
  241. /** Image */
  242. byte IMAGE = (byte)0xFB;
  243. }
  244. }