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