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