1 /* Copyright (C) 2001-2012 Artifex Software, Inc. 2 All Rights Reserved. 3 4 This software is provided AS-IS with no warranty, either express or 5 implied. 6 7 This software is distributed under license and may not be copied, 8 modified or distributed except as expressly authorized under the terms 9 of the license contained in the file LICENSE in this distribution. 10 11 Refer to licensing information at http://www.artifex.com or contact 12 Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, San Rafael, 13 CA 94903, U.S.A., +1(415)492-9861, for further information. 14 */ 15 16 17 /* Internal definitions for "objects" for pdfwrite driver. */ 18 19 #ifndef gdevpdfo_INCLUDED 20 # define gdevpdfo_INCLUDED 21 22 /* 23 * This file defines the structures and support procedures for what Adobe 24 * calls "Cos objects". (We don't know what "Cos" stands for, but in our 25 * case, it's a good acronym for "Collection and stream".) We only 26 * support arrays, dictionaries, and streams: we merge all other types into a 27 * single string type, which holds the printed representation that will be 28 * written on the output file, and we only support that type as an element 29 * of the collection types. 30 * 31 * Note that Cos objects are *not* reference-counted. Objects without 32 * an ID are assumed to be referenced from only one place; objects with 33 * IDs are managed manually. We also assume that strings (the keys of 34 * dictionaries, and non-object values in arrays and dictionaries) are 35 * "owned" by their referencing object. 36 */ 37 38 #include "gsparam.h" 39 #include "smd5.h" 40 41 /* Define some needed abstract types. */ 42 #ifndef gx_device_pdf_DEFINED 43 # define gx_device_pdf_DEFINED 44 typedef struct gx_device_pdf_s gx_device_pdf; 45 #endif 46 47 /* ---------------- Structures ---------------- */ 48 49 /* Define the abstract types if they aren't defined already (in gdevpdfx.h). */ 50 #ifndef cos_types_DEFINED 51 # define cos_types_DEFINED 52 typedef struct cos_object_s cos_object_t; 53 typedef struct cos_stream_s cos_stream_t; 54 typedef struct cos_dict_s cos_dict_t; 55 typedef struct cos_array_s cos_array_t; 56 typedef struct cos_value_s cos_value_t; 57 typedef struct cos_object_procs_s cos_object_procs_t; 58 typedef const cos_object_procs_t *cos_type_t; 59 #endif 60 61 /* Abstract types (defined concretely in gdevpdfo.c) */ 62 typedef struct cos_element_s cos_element_t; 63 typedef struct cos_stream_piece_s cos_stream_piece_t; 64 65 /* 66 * Define the object procedures for Cos objects. 67 */ 68 /*typedef struct cos_object_s cos_object_t;*/ 69 /*typedef*/ struct cos_object_procs_s { 70 71 #define cos_proc_release(proc)\ 72 void proc(cos_object_t *pco, client_name_t cname) 73 cos_proc_release((*release)); 74 75 #define cos_proc_write(proc)\ 76 int proc(const cos_object_t *pco, gx_device_pdf *pdev, gs_id object_id) 77 cos_proc_write((*write)); 78 79 #define cos_proc_equal(proc)\ 80 int proc(const cos_object_t *pco0, const cos_object_t *pco1, gx_device_pdf *pdev) 81 cos_proc_equal((*equal)); 82 83 #define cos_proc_hash(proc)\ 84 int proc(const cos_object_t *pco0, gs_md5_state_t *md5, gs_md5_byte_t *hash, gx_device_pdf *pdev) 85 cos_proc_hash((*hash)); 86 87 } /*cos_object_procs_t*/; 88 /*typedef const cos_object_procs_t *cos_type_t;*/ 89 #define cos_type(pco) ((pco)->cos_procs) 90 91 /* 92 * Define the generic structure for Cos objects. Note that all Cos 93 * objects have the same structure and type, aside from their elements. 94 * This allows us to "mutate" a forward-referenced object into its 95 * proper type in place. 96 * 97 * Note that we distinguish elements from contents. Arrays and 98 * dictionaries have only elements; streams have both elements 99 * (additional elements of the stream dictionary) and contents pieces. 100 * 101 * The is_open member currently has no function other than error checking. 102 * It is set to true when the object is created, to false by the CLOSE 103 * and EP pdfmarks, and is checked by CLOSE, PUT, and SP. 104 * 105 * The is_graphics member exists only to ensure that the stream argument 106 * of SP was created by BP/EP. 107 * 108 * The written member records whether the object has been written (copied) 109 * into the contents or resource file. 110 */ 111 #define cos_object_struct(otype_s, etype)\ 112 struct otype_s {\ 113 const cos_object_procs_t *cos_procs; /* must be first */\ 114 long id;\ 115 etype *elements;\ 116 cos_stream_piece_t *pieces;\ 117 gx_device_pdf *pdev;\ 118 pdf_resource_t *pres; /* only for BP/EP XObjects */\ 119 byte is_open; /* see above */\ 120 byte is_graphics; /* see above */\ 121 byte written; /* see above */\ 122 long length; /* only for stream objects */\ 123 stream *input_strm; /* only for stream objects */\ 124 gs_md5_state_t md5; /* used to create MD5 hash to test equality */\ 125 int md5_valid; /* 1 if hash created, 0 otherwise */\ 126 byte hash[16]; /* MD5 hash value */\ 127 int stream_md5_valid; /* (for streams) 1 if hash created, 0 otherwise */\ 128 byte stream_hash[16]; /* MD5 hash value (if stream) */\ 129 /* input_strm is introduced recently for pdfmark. */\ 130 /* Using this field, psdf_binary_writer_s may be simplified. */\ 131 } 132 cos_object_struct(cos_object_s, cos_element_t); 133 #define private_st_cos_object() /* in gdevpdfo.c */\ 134 gs_private_st_ptrs5(st_cos_object, cos_object_t, "cos_object_t",\ 135 cos_object_enum_ptrs, cos_object_reloc_ptrs, elements, pieces,\ 136 pdev, pres, input_strm) 137 extern const cos_object_procs_t cos_generic_procs; 138 #define cos_type_generic (&cos_generic_procs) 139 140 extern const cos_object_procs_t cos_reference_procs; 141 #define cos_type_reference (&cos_reference_procs) 142 143 /* 144 * Define the macro for casting any cos object to type cos_object_t. 145 * Using cos_procs ensures that the argument is, in fact, a cos object. 146 */ 147 #define COS_OBJECT(pc) ((cos_object_t *)&((pc)->cos_procs)) 148 #define CONST_COS_OBJECT(pc) ((const cos_object_t *)&((pc)->cos_procs)) 149 150 /* 151 * Define the structure for the value of an array or dictionary element. 152 * This is where we create the union of composite and scalar types. 153 */ 154 /*typedef struct cos_value_s cos_value_t;*/ 155 typedef enum { 156 COS_VALUE_SCALAR = 0, /* heap-allocated string */ 157 COS_VALUE_CONST, /* shared (constant) string */ 158 COS_VALUE_OBJECT, /* object referenced by # # R */ 159 COS_VALUE_RESOURCE /* object referenced by /R# */ 160 } cos_value_type_t; 161 struct cos_value_s { 162 cos_value_type_t value_type; 163 union vc_ { 164 gs_string chars; /* SCALAR, CONST */ 165 cos_object_t *object; /* OBJECT, RESOURCE */ 166 } contents; 167 }; 168 #define private_st_cos_value() /* in gdevpdfo.c */\ 169 gs_private_st_composite(st_cos_value, cos_value_t,\ 170 "cos_value_t", cos_value_enum_ptrs, cos_value_reloc_ptrs) 171 172 /* 173 * Define Cos arrays, dictionaries, and streams. 174 * 175 * The elements of arrays are stored sorted in decreasing index order. 176 * The elements of dictionaries/streams are not sorted. 177 * The contents pieces of streams are stored in reverse order. 178 */ 179 /* array */ 180 typedef struct cos_array_element_s cos_array_element_t; 181 cos_object_struct(cos_array_s, cos_array_element_t); 182 extern const cos_object_procs_t cos_array_procs; 183 #define cos_type_array (&cos_array_procs) 184 /* dict */ 185 typedef struct cos_dict_element_s cos_dict_element_t; 186 cos_object_struct(cos_dict_s, cos_dict_element_t); 187 extern const cos_object_procs_t cos_dict_procs; 188 #define cos_type_dict (&cos_dict_procs) 189 /* stream */ 190 cos_object_struct(cos_stream_s, cos_dict_element_t); 191 extern const cos_object_procs_t cos_stream_procs; 192 #define cos_type_stream (&cos_stream_procs) 193 194 /* ---------------- Procedures ---------------- */ 195 196 /* 197 * NOTE: Procedures that include "_c_" in their name do not copy their C 198 * string argument(s). To copy the argument, use the procedure that takes 199 * a byte pointer and a length. 200 */ 201 202 /* Create a Cos object. */ 203 cos_object_t *cos_object_alloc(gx_device_pdf *, client_name_t); 204 cos_array_t *cos_array_alloc(gx_device_pdf *, client_name_t); 205 cos_array_t *cos_array_from_floats(gx_device_pdf *, const float *, uint, 206 client_name_t); 207 cos_dict_t *cos_dict_alloc(gx_device_pdf *, client_name_t); 208 cos_stream_t *cos_stream_alloc(gx_device_pdf *, client_name_t); 209 210 /* A 'dummy object, used only to create a reference in a dict when writing */ 211 cos_object_t *cos_reference_alloc(gx_device_pdf *, client_name_t); 212 213 /* Get the allocator for a Cos object. */ 214 gs_memory_t *cos_object_memory(const cos_object_t *); 215 #define COS_OBJECT_MEMORY(pc) cos_object_memory(CONST_COS_OBJECT(pc)) 216 217 /* Set the type of a generic Cos object. */ 218 int cos_become(cos_object_t *, cos_type_t); 219 220 /* Define wrappers for calling the object procedures. */ 221 cos_proc_release(cos_release); 222 #define COS_RELEASE(pc, cname) cos_release(COS_OBJECT(pc), cname) 223 cos_proc_write(cos_write); 224 #define COS_WRITE(pc, pdev) cos_write(CONST_COS_OBJECT(pc), pdev, (pc)->id) 225 226 /* Make a value to store into a composite object. */ 227 const cos_value_t *cos_string_value(cos_value_t *, const byte *, uint); 228 const cos_value_t *cos_c_string_value(cos_value_t *, const char *); 229 const cos_value_t *cos_object_value(cos_value_t *, cos_object_t *); 230 #define COS_OBJECT_VALUE(pcv, pc) cos_object_value(pcv, COS_OBJECT(pc)) 231 /* A resource value is an object value referenced as /R#, not # # R. */ 232 const cos_value_t *cos_resource_value(cos_value_t *, cos_object_t *); 233 #define COS_RESOURCE_VALUE(pcv, pc) cos_resource_value(pcv, COS_OBJECT(pc)) 234 235 /* Test whether a value is an object */ 236 #define COS_VALUE_IS_OBJECT(pv) ((pv)->value_type >= COS_VALUE_OBJECT) 237 238 /* 239 * Put an element in / add an element to a Cos object. The _no_copy 240 * procedures assume that the value, if not an object, is a newly allocated, 241 * unshared string, allocated by the same allocator as the collection 242 * itself, that should not be copied. 243 */ 244 /* array */ 245 int cos_array_put(cos_array_t *, long, const cos_value_t *); 246 int cos_array_put_no_copy(cos_array_t *, long, const cos_value_t *); 247 int cos_array_add(cos_array_t *, const cos_value_t *); 248 int cos_array_add_no_copy(cos_array_t *, const cos_value_t *); 249 int cos_array_add_c_string(cos_array_t *, const char *); 250 int cos_array_add_int(cos_array_t *, int); 251 int cos_array_add_real(cos_array_t *, floatp); 252 int cos_array_add_object(cos_array_t *, cos_object_t *); 253 /* add adds at the end, unadd removes the last element */ 254 int cos_array_unadd(cos_array_t *, cos_value_t *); 255 /* dict */ 256 int cos_dict_put(cos_dict_t *, const byte *, uint, const cos_value_t *); 257 int cos_dict_put_no_copy(cos_dict_t *, const byte *, uint, 258 const cos_value_t *); 259 int cos_dict_put_c_key(cos_dict_t *, const char *, const cos_value_t *); 260 int cos_dict_put_c_key_string(cos_dict_t *, const char *, const byte *, uint); 261 int cos_dict_put_c_key_int(cos_dict_t *, const char *, int); 262 int cos_dict_put_c_key_bool(cos_dict_t *pcd, const char *key, bool value); 263 int cos_dict_put_c_key_real(cos_dict_t *, const char *, floatp); 264 int cos_dict_put_c_key_floats(cos_dict_t *, const char *, const float *, uint); 265 int cos_dict_put_c_key_object(cos_dict_t *, const char *, cos_object_t *); 266 int cos_dict_put_string(cos_dict_t *, const byte *, uint, const byte *, uint); 267 int cos_dict_put_string_copy(cos_dict_t *pcd, const char *key, const char *value); 268 int cos_dict_put_c_strings(cos_dict_t *, const char *, const char *); 269 /* move all the elements from one dict to another */ 270 int cos_dict_move_all(cos_dict_t *, cos_dict_t *); 271 /* stream */ 272 int cos_stream_add(cos_stream_t *, uint); 273 int cos_stream_add_bytes(cos_stream_t *, const byte *, uint); 274 int cos_stream_add_stream_contents(cos_stream_t *, stream *); 275 int cos_stream_release_pieces(cos_stream_t *pcs); 276 cos_dict_t *cos_stream_dict(cos_stream_t *); 277 278 /* 279 * Get the first / next element for enumerating an array. Usage: 280 * const cos_array_element_t *elt = cos_array_element_first(pca); 281 * while (elt) { 282 * long idx; 283 * const cos_value_t *pvalue; 284 * elt = cos_array_element_next(elt, &idx, &pvalue); 285 * ... 286 * } 287 * The order in which the elements are returned is not defined. 288 * If the client adds elements to the array during the enumeration, 289 * they may or may not be included in the enumeration. 290 */ 291 const cos_array_element_t * 292 cos_array_element_first(const cos_array_t *); 293 const cos_array_element_t * 294 cos_array_element_next(const cos_array_element_t *, long *, 295 const cos_value_t **); 296 297 /* Look up a key in a dictionary. */ 298 const cos_value_t *cos_dict_find(const cos_dict_t *, const byte *, uint); 299 const cos_value_t *cos_dict_find_c_key(const cos_dict_t *, const char *); 300 /* Process all entries in a dictionary. */ 301 int cos_dict_forall(const cos_dict_t *pcd, void *client_data, 302 int (*proc)(void *client_data, const byte *key_data, uint key_size, const cos_value_t *v)); 303 304 /* Set up a parameter list that writes into a Cos dictionary. */ 305 typedef struct cos_param_list_writer_s { 306 gs_param_list_common; 307 cos_dict_t *pcd; 308 int print_ok; 309 } cos_param_list_writer_t; 310 int cos_param_list_writer_init(cos_param_list_writer_t *, cos_dict_t *, 311 int print_ok); 312 313 /* Create a stream that writes into a Cos stream. */ 314 /* Closing the stream will free it. */ 315 stream *cos_write_stream_alloc(cos_stream_t *pcs, gx_device_pdf *pdev, 316 client_name_t cname); 317 318 /* Get cos stream from pipeline. */ 319 cos_stream_t * cos_stream_from_pipeline(stream *s); 320 /* Get cos write stream from pipeline. */ 321 stream * cos_write_stream_from_pipeline(stream *s); 322 323 /* Write a Cos value on the output. */ 324 int cos_value_write(const cos_value_t *, gx_device_pdf *); 325 326 /* Write the elements of a dictionary/stream on the output. */ 327 int cos_dict_elements_write(const cos_dict_t *, gx_device_pdf *); 328 int cos_stream_elements_write(const cos_stream_t *, gx_device_pdf *); /* = dict_elements_write */ 329 int cos_stream_contents_write(const cos_stream_t *, gx_device_pdf *); 330 331 /* Find the total length of a stream. */ 332 long cos_stream_length(const cos_stream_t *pcs); 333 334 /* Write/delete definitions of named objects. */ 335 /* This is a special-purpose facility for pdf_close. */ 336 int cos_dict_objects_write(const cos_dict_t *, gx_device_pdf *); 337 int cos_dict_objects_delete(cos_dict_t *); 338 339 /* Write a cos object as a PDF object. */ 340 int cos_write_object(cos_object_t *pco, gx_device_pdf *pdev, pdf_resource_type_t type); 341 #define COS_WRITE_OBJECT(pc, pdev, type) cos_write_object(COS_OBJECT(pc), pdev, type) 342 343 /* Free a Cos value owned by a Cos object. */ 344 void cos_value_free(const cos_value_t *, const cos_object_t *, client_name_t); 345 346 /* Free a cos object. */ 347 void cos_free(cos_object_t *pco, client_name_t cname); 348 #define COS_FREE(pc, cname) cos_free(COS_OBJECT(pc), cname) 349 350 #endif /* gdevpdfo_INCLUDED */ 351