/src/ghostpdl/devices/vector/gdevpdfx.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2025 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., 39 Mesa Street, Suite 108A, San Francisco, |
13 | | CA 94129, USA, for further information. |
14 | | */ |
15 | | |
16 | | |
17 | | /* Internal definitions for PDF-writing driver. */ |
18 | | |
19 | | #ifndef gdevpdfx_INCLUDED |
20 | | # define gdevpdfx_INCLUDED |
21 | | |
22 | | #include "gsparam.h" |
23 | | #include "gsuid.h" |
24 | | #include "gxdevice.h" |
25 | | #include "gxfont.h" |
26 | | #include "gxline.h" |
27 | | #include "stream.h" |
28 | | #include "spprint.h" |
29 | | #include "gdevpsdf.h" |
30 | | #include "gxdevmem.h" |
31 | | #include "sarc4.h" |
32 | | #include "gsfunc.h" |
33 | | |
34 | | #define FINE_GLYPH_USAGE 1 /* Old code = 0, new code = 1 */ |
35 | | |
36 | | /* ---------------- Acrobat limitations ---------------- */ |
37 | | |
38 | | /* |
39 | | * The PDF reference manual, 2nd ed., claims that the limit for coordinates |
40 | | * is +/- 32767. However, testing indicates that Acrobat Reader 4 for |
41 | | * Windows and Linux fail with coordinates outside +/- 16383. Hence, we |
42 | | * limit coordinates to 16k, with a little slop. |
43 | | */ |
44 | | /* 28/05/2020 This was only being applied to text and a subset of paths. Since |
45 | | * Acrobat 4 is now more than 20 years old, lets just drop support for it. The |
46 | | * PDF specification never had this limit, just Adobe's software. |
47 | | */ |
48 | | /* 31/05/2021 However, it transpires that the PDF/A-1 specification adopted the |
49 | | * implementation limits of Acrobat 5 as part of the specification. So we need |
50 | | * to handle that, but we don't need to limit ourselves to the more restrictive |
51 | | * Acrobat 4 limit of 16384 ( MAX_USER_COORD 16300), we can use 32767. THis is only |
52 | | * used when creating PDF/A-1 files. |
53 | | */ |
54 | 53.2M | #define MAX_USER_COORD 32700 |
55 | | |
56 | | /* ---------------- Statically allocated sizes ---------------- */ |
57 | | /* These should really be dynamic.... */ |
58 | | |
59 | | /* Define the maximum depth of an outline tree. */ |
60 | | /* Note that there is no limit on the breadth of the tree. */ |
61 | 68.0k | #define INITIAL_MAX_OUTLINE_DEPTH 32 |
62 | | |
63 | | /* Define the maximum size of a destination array string. */ |
64 | 1.18k | #define MAX_DEST_STRING 80 |
65 | | |
66 | | /* Define the maximum number of objects stored in an ObjStm */ |
67 | 71.0k | #define MAX_OBJSTM_OBJECTS 200 |
68 | | |
69 | | /* ================ Types and structures ================ */ |
70 | | |
71 | | typedef struct pdf_base_font_s pdf_base_font_t; |
72 | | |
73 | | /* Define the possible contexts for the output stream. */ |
74 | | typedef enum { |
75 | | PDF_IN_NONE, |
76 | | PDF_IN_STREAM, |
77 | | PDF_IN_TEXT, |
78 | | PDF_IN_STRING |
79 | | } pdf_context_t; |
80 | | |
81 | | /* ---------------- Cos objects ---------------- */ |
82 | | |
83 | | /* |
84 | | * These are abstract types for cos objects. The concrete types are in |
85 | | * gdevpdfo.h. |
86 | | */ |
87 | | typedef struct cos_object_s cos_object_t; |
88 | | typedef struct cos_stream_s cos_stream_t; |
89 | | typedef struct cos_dict_s cos_dict_t; |
90 | | typedef struct cos_array_s cos_array_t; |
91 | | typedef struct cos_value_s cos_value_t; |
92 | | typedef struct cos_object_procs_s cos_object_procs_t; |
93 | | typedef const cos_object_procs_t *cos_type_t; |
94 | | #define cos_types_DEFINED |
95 | | |
96 | | typedef struct pdf_text_state_s pdf_text_state_t; |
97 | | |
98 | | typedef struct pdf_char_glyph_pairs_s pdf_char_glyph_pairs_t; |
99 | | |
100 | | /* ---------------- Resources ---------------- */ |
101 | | |
102 | | typedef enum { |
103 | | /* |
104 | | * Standard PDF resources. Font must be last, because resources |
105 | | * up to but not including Font are written page-by-page. |
106 | | */ |
107 | | resourceColorSpace, |
108 | | resourceExtGState, |
109 | | resourcePattern, |
110 | | resourceShading, |
111 | | resourceXObject, |
112 | | resourceProperties, |
113 | | resourceOther, /* Anything else that needs to be stored for a time. |
114 | | * Can be any of the types defined below NUM_RESOURCE_TYPES |
115 | | * but this is the type used to identify the object. |
116 | | */ |
117 | | resourceFont, |
118 | | /* |
119 | | * Internally used (pseudo-)resources. |
120 | | */ |
121 | | resourceCharProc, |
122 | | resourceCIDFont, |
123 | | resourceCMap, |
124 | | resourceFontDescriptor, |
125 | | resourceGroup, |
126 | | resourceSoftMaskDict, |
127 | | resourceFunction, |
128 | | resourcePage, |
129 | | NUM_RESOURCE_TYPES, |
130 | | /* These resource types were 'resourceOther', but we want to track them |
131 | | * for ps2write. They are not stored in the pdf device structure, unlike |
132 | | * the reource types above. |
133 | | */ |
134 | | resourceEncoding, |
135 | | resourceCIDSystemInfo, |
136 | | resourceHalftone, |
137 | | resourceLength, |
138 | | resourceStream, |
139 | | resourceOutline, |
140 | | resourceArticle, |
141 | | resourceDests, |
142 | | resourceLabels, |
143 | | resourceThread, |
144 | | resourceCatalog, |
145 | | resourceEncrypt, |
146 | | resourcePagesTree, |
147 | | resourceMetadata, |
148 | | resourceICC, |
149 | | resourceAnnotation, |
150 | | resourceEmbeddedFiles, |
151 | | resourceFontFile, |
152 | | resourceNone /* Special, used when this isn't a resource at all |
153 | | * eg when we execute a resource we've just written, such as |
154 | | * a Pattern. |
155 | | */ |
156 | | } pdf_resource_type_t; |
157 | | |
158 | | #define PDF_RESOURCE_TYPE_NAMES\ |
159 | 0 | "/ColorSpace", "/ExtGState", "/Pattern", "/Shading", "/XObject", "/Properties", 0, "/Font",\ |
160 | 0 | 0, "/Font", "/CMap", "/FontDescriptor", "/Group", "/Mask", 0, 0, 0, 0, 0,\ |
161 | 0 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
162 | | #define PDF_RESOURCE_TYPE_STRUCTS\ |
163 | | &st_pdf_color_space, /* gdevpdfg.h / gdevpdfc.c */\ |
164 | | &st_pdf_resource, /* see below */\ |
165 | | &st_pdf_pattern,\ |
166 | | &st_pdf_resource,\ |
167 | | &st_pdf_x_object, /* see below */\ |
168 | | &st_pdf_resource,\ |
169 | | &st_pdf_resource,\ |
170 | | &st_pdf_font_resource, /* gdevpdff.h / gdevpdff.c */\ |
171 | | &st_pdf_char_proc, /* gdevpdff.h / gdevpdff.c */\ |
172 | | &st_pdf_font_resource, /* gdevpdff.h / gdevpdff.c */\ |
173 | | &st_pdf_resource,\ |
174 | | &st_pdf_font_descriptor, /* gdevpdff.h / gdevpdff.c */\ |
175 | | &st_pdf_resource,\ |
176 | | &st_pdf_resource,\ |
177 | | &st_pdf_resource,\ |
178 | | &st_pdf_resource |
179 | | |
180 | | /* |
181 | | * rname is currently R<id> for all resources other than synthesized fonts; |
182 | | * for synthesized fonts, rname is A, B, .... The string is null-terminated. |
183 | | */ |
184 | | |
185 | | /* WARNING WILL ROBINSON! |
186 | | * these 2 pointers may *look* like a double linked list but in fact these are pointers |
187 | | * to two *different* single-linked lists. 'next' points to the next resource |
188 | | * of this type, which is stored in the resource chains pointed to by the array |
189 | | * 'resources' in the device structure. 'prev' is a pointer |
190 | | * to the list of stored resources of all types, pointed to by the |
191 | | * 'last_resource' member of the device structure. |
192 | | */ |
193 | | #define pdf_resource_common(typ)\ |
194 | | typ *next; /* next resource of this type */\ |
195 | | pdf_resource_t *prev; /* previously allocated resource */\ |
196 | | gs_id rid; /* optional ID key */\ |
197 | | bool named;\ |
198 | | bool global; /* ps2write only */\ |
199 | | char rname[1/*R*/ + (sizeof(int64_t) * 8 / 3 + 1) + 1/*\0*/];\ |
200 | | uint64_t where_used; /* 1 bit per level of content stream */\ |
201 | | cos_object_t *object |
202 | | typedef struct pdf_resource_s pdf_resource_t; |
203 | | struct pdf_resource_s { |
204 | | pdf_resource_common(pdf_resource_t); |
205 | | }; |
206 | | |
207 | | /* The descriptor is public for subclassing. */ |
208 | | extern_st(st_pdf_resource); |
209 | | #define public_st_pdf_resource() /* in gdevpdfu.c */\ |
210 | | gs_public_st_ptrs3(st_pdf_resource, pdf_resource_t, "pdf_resource_t",\ |
211 | | pdf_resource_enum_ptrs, pdf_resource_reloc_ptrs, next, prev, object) |
212 | | |
213 | | /* |
214 | | * We define XObject resources here because they are used for Image, |
215 | | * Form, and PS XObjects, which are implemented in different files. |
216 | | */ |
217 | | typedef struct pdf_x_object_s pdf_x_object_t; |
218 | | struct pdf_x_object_s { |
219 | | pdf_resource_common(pdf_x_object_t); |
220 | | int width, height; /* specified width and height for images */ |
221 | | int data_height; /* actual data height for images */ |
222 | | }; |
223 | | #define private_st_pdf_x_object() /* in gdevpdfu.c */\ |
224 | | gs_private_st_suffix_add0(st_pdf_x_object, pdf_x_object_t,\ |
225 | | "pdf_x_object_t", pdf_x_object_enum_ptrs, pdf_x_object_reloc_ptrs,\ |
226 | | st_pdf_resource) |
227 | | |
228 | | /* Define the mask for which procsets have been used on a page. */ |
229 | | typedef enum { |
230 | | NoMarks = 0, |
231 | | ImageB = 1, |
232 | | ImageC = 2, |
233 | | ImageI = 4, |
234 | | Text = 8 |
235 | | } pdf_procset_t; |
236 | | |
237 | | /* ------ Fonts ------ */ |
238 | | |
239 | | /* Define abstract types. */ |
240 | | typedef struct pdf_char_proc_s pdf_char_proc_t; /* gdevpdff.h */ |
241 | | typedef struct pdf_char_proc_ownership_s pdf_char_proc_ownership_t; /* gdevpdff.h */ |
242 | | typedef struct pdf_font_s pdf_font_t; /* gdevpdff.h */ |
243 | | typedef struct pdf_text_data_s pdf_text_data_t; /* gdevpdft.h */ |
244 | | |
245 | | /* ---------------- Other auxiliary structures ---------------- */ |
246 | | |
247 | | /* Outline nodes and levels */ |
248 | | typedef struct pdf_outline_node_s { |
249 | | int64_t id, parent_id, prev_id, first_id, last_id; |
250 | | int count; |
251 | | cos_dict_t *action; |
252 | | } pdf_outline_node_t; |
253 | | typedef struct pdf_outline_level_s { |
254 | | pdf_outline_node_t first; |
255 | | pdf_outline_node_t last; |
256 | | int left; |
257 | | } pdf_outline_level_t; |
258 | | /* |
259 | | * The GC descriptor is implicit, since outline levels occur only in an |
260 | | * embedded array in the gx_device_pdf structure. |
261 | | */ |
262 | | |
263 | | /* Articles */ |
264 | | typedef struct pdf_bead_s { |
265 | | int64_t id, article_id, prev_id, next_id, page_id; |
266 | | gs_rect rect; |
267 | | } pdf_bead_t; |
268 | | typedef struct pdf_article_s pdf_article_t; |
269 | | struct pdf_article_s { |
270 | | pdf_article_t *next; |
271 | | cos_dict_t *contents; |
272 | | pdf_bead_t first; |
273 | | pdf_bead_t last; |
274 | | }; |
275 | | |
276 | | #define private_st_pdf_article()\ |
277 | | gs_private_st_ptrs2(st_pdf_article, pdf_article_t,\ |
278 | | "pdf_article_t", pdf_article_enum_ptrs, pdf_article_reloc_ptrs,\ |
279 | | next, contents) |
280 | | |
281 | | /* ---------------- The device structure ---------------- */ |
282 | | |
283 | | /* Resource lists */ |
284 | | /* We seem to split the resources up into 'NUM_RESOURCE_CHAINS' linked |
285 | | * lists purely as a performance boost. Presumably it save searching very |
286 | | * long lists. |
287 | | */ |
288 | 301M | #define NUM_RESOURCE_CHAINS 16 |
289 | | typedef struct pdf_resource_list_s { |
290 | | pdf_resource_t *chains[NUM_RESOURCE_CHAINS]; |
291 | | } pdf_resource_list_t; |
292 | | |
293 | | /* Define the hash function for gs_ids. */ |
294 | 2.48M | #define gs_id_hash(rid) ((rid) + ((rid) / NUM_RESOURCE_CHAINS)) |
295 | | /* Define the accessor for the proper hash chain. */ |
296 | | #define PDF_RESOURCE_CHAIN(pdev, type, rid)\ |
297 | 2.33M | (&(pdev)->resources[type].chains[gs_id_hash(rid) % NUM_RESOURCE_CHAINS]) |
298 | | |
299 | | /* Define the bookkeeping for an open stream. */ |
300 | | typedef struct pdf_stream_position_s { |
301 | | int64_t length_id; |
302 | | gs_offset_t start_pos; |
303 | | } pdf_stream_position_t; |
304 | | |
305 | | /* |
306 | | * Define the structure for keeping track of text rotation. |
307 | | * There is one for the current page (for AutoRotate /PageByPage) |
308 | | * and one for the whole document (for AutoRotate /All). |
309 | | */ |
310 | | typedef struct pdf_text_rotation_s { |
311 | | int64_t counts[5]; /* 0, 90, 180, 270, other */ |
312 | | int Rotate; /* computed rotation, -1 means none */ |
313 | | } pdf_text_rotation_t; |
314 | 21.3k | #define pdf_text_rotation_angle_values 0, 90, 180, 270, -1 |
315 | | |
316 | | /* |
317 | | * Define document and page information derived from DSC comments. |
318 | | */ |
319 | | typedef struct pdf_page_dsc_info_s { |
320 | | int orientation; /* -1 .. 3 */ |
321 | | int viewing_orientation; /* -1 .. 3 */ |
322 | | gs_rect bounding_box; |
323 | | } pdf_page_dsc_info_t; |
324 | | |
325 | | /* |
326 | | * Define the stored information for a page. Because pdfmarks may add |
327 | | * information to any page anywhere in the document, we have to wait |
328 | | * until the end to write the page dictionaries. |
329 | | */ |
330 | | typedef struct pdf_page_s { |
331 | | cos_dict_t *Page; |
332 | | gs_point MediaBox; |
333 | | pdf_procset_t procsets; |
334 | | int64_t contents_id; |
335 | | int64_t resource_ids[resourceFont + 1]; /* resources thru Font, see above */ |
336 | | int64_t group_id; |
337 | | cos_array_t *Annots; |
338 | | pdf_text_rotation_t text_rotation; |
339 | | pdf_page_dsc_info_t dsc_info; |
340 | | bool NumCopies_set; /* ps2write only. */ |
341 | | int NumCopies; /* ps2write only. */ |
342 | | float UserUnit; /* pdfwrite only */ |
343 | | } pdf_page_t; |
344 | | #define private_st_pdf_page() /* in gdevpdf.c */\ |
345 | | gs_private_st_ptrs2(st_pdf_page, pdf_page_t, "pdf_page_t",\ |
346 | | pdf_page_enum_ptrs, pdf_page_reloc_ptrs, Page, Annots) |
347 | | |
348 | | /* |
349 | | * Define the structure for the temporary files used while writing. |
350 | | * There are 4 of these, described below. |
351 | | */ |
352 | | typedef struct pdf_temp_file_s { |
353 | | char file_name[gp_file_name_sizeof]; |
354 | | gp_file *file; |
355 | | stream *strm; |
356 | | byte *strm_buf; |
357 | | stream *save_strm; /* save pdev->strm while writing here */ |
358 | | } pdf_temp_file_t; |
359 | | |
360 | | typedef struct gx_device_pdf_s gx_device_pdf; |
361 | | |
362 | | /* Structures and definitions for linearisation */ |
363 | | typedef struct linearisation_record_s { |
364 | | int PageUsage; |
365 | | int NumPagesUsing; |
366 | | int *PageList; |
367 | | uint NewObjectNumber; |
368 | | gs_offset_t OriginalOffset; |
369 | | gs_offset_t LinearisedOffset; |
370 | | gs_offset_t Length; |
371 | | } pdf_linearisation_record_t; |
372 | | |
373 | | #define private_st_pdf_linearisation_record()\ |
374 | | gs_private_st_ptrs1(st_pdf_linearisation_record, pdf_linearisation_record_t,\ |
375 | | "pdf_linearisation_record_t", pdf_linearisation_record_enum_ptrs, pdf_linearisation_record_reloc_ptrs,\ |
376 | | PageList) |
377 | | |
378 | | typedef struct page_hint_stream_header_s { |
379 | | unsigned int LeastObjectsPerPage; /* Including the page object */ |
380 | | /* Item 2 is already stored elsewhere */ |
381 | | unsigned int MostObjectsPerPage; |
382 | | unsigned short ObjectNumBits; |
383 | | unsigned int LeastPageLength; /* From beginning of page object to end of last object used by page */ |
384 | | unsigned int MostPageLength; |
385 | | unsigned short PageLengthNumBits; |
386 | | unsigned int LeastPageOffset; |
387 | | unsigned int MostPageOffset; |
388 | | unsigned short PageOffsetNumBits; |
389 | | unsigned int LeastContentLength; |
390 | | unsigned int MostContentLength; |
391 | | unsigned short ContentLengthNumBits; |
392 | | unsigned int MostSharedObjects; |
393 | | unsigned int LargestSharedObject; |
394 | | unsigned short SharedObjectNumBits; |
395 | | } page_hint_stream_header_t; |
396 | | |
397 | | typedef struct page_hint_stream_s { |
398 | | unsigned int NumUniqueObjects; /* biased by the least number of objects on any page */ |
399 | | unsigned int PageLength; /* biased by the least page length*/ |
400 | | unsigned int NumSharedObjects; |
401 | | unsigned int *SharedObjectRef; /* one for each shaed object on the page */ |
402 | | /* Item 5 we invent */ |
403 | | gs_offset_t ContentOffset; /* biased by the least offset to the conent stream for any page */ |
404 | | gs_offset_t ContentLength;/* biased by the least content stream length */ |
405 | | } page_hint_stream_t; |
406 | | |
407 | | typedef struct shared_hint_stream_header_s { |
408 | | unsigned int FirstSharedObject; |
409 | | gs_offset_t FirstObjectOffset; |
410 | | unsigned int FirstPageEntries; |
411 | | unsigned int NumSharedObjects; |
412 | | /* Item 5 is always 1 as far as we are concerned */ |
413 | | unsigned int LeastObjectLength; |
414 | | unsigned int MostObjectLength; |
415 | | unsigned short LengthNumBits; |
416 | | } shared_hint_stream_header_t; |
417 | | |
418 | | typedef struct share_hint_stream_s { |
419 | | unsigned int ObjectNumber; |
420 | | gs_offset_t ObjectOffset; |
421 | | unsigned int ObjectLength; /* biased by the LeastObjectLength */ |
422 | | /* item 2 is always 0 */ |
423 | | /* Which means that item 3 is never present */ |
424 | | /* Finally item 4 is always 0 (1 less than the number of objects in the group, which is always 1) */ |
425 | | } shared_hint_stream_t; |
426 | | |
427 | | typedef struct pdf_linearisation_s { |
428 | | gp_file *sfile; |
429 | | pdf_temp_file_t Lin_File; |
430 | | char HintBuffer[256]; |
431 | | unsigned char HintBits; |
432 | | unsigned char HintByte; |
433 | | int64_t Catalog_id; |
434 | | int64_t Info_id; |
435 | | int64_t Pages_id; |
436 | | int64_t NumPage1Resources; |
437 | | int64_t NumPart1StructureResources; |
438 | | int64_t NumSharedResources; |
439 | | int64_t NumUniquePageResources; |
440 | | int64_t NumPart9Resources; |
441 | | int64_t NumNonPageResources; |
442 | | int64_t LastResource; |
443 | | int64_t MainFileEnd; |
444 | | gs_offset_t *Offsets; |
445 | | gs_offset_t xref; |
446 | | gs_offset_t FirstxrefOffset; |
447 | | gs_offset_t FirsttrailerOffset; |
448 | | gs_offset_t LDictOffset; |
449 | | gs_offset_t FileLength; |
450 | | gs_offset_t T; |
451 | | gs_offset_t E; |
452 | | page_hint_stream_header_t PageHintHeader; |
453 | | int NumPageHints; |
454 | | page_hint_stream_t *PageHints; |
455 | | shared_hint_stream_header_t SharedHintHeader; |
456 | | int NumSharedHints; |
457 | | shared_hint_stream_t *SharedHints; |
458 | | } pdf_linearisation_t; |
459 | | |
460 | | /* These are the values for 'PageUsage' above, values > 0 indicate the page number that uses the resource */ |
461 | 0 | #define resource_usage_not_referenced 0 |
462 | 0 | #define resource_usage_page_shared -1 |
463 | | /* Thses need to be lower than the shared value */ |
464 | 9.18k | #define resource_usage_part1_structure -2 |
465 | 27.5k | #define resource_usage_part9_structure -3 |
466 | | #define resource_usage_written -4 |
467 | | |
468 | | /* |
469 | | * Define the structure for PDF font cache element. |
470 | | */ |
471 | | typedef struct pdf_font_cache_elem_s pdf_font_cache_elem_t; |
472 | | struct pdf_font_cache_elem_s { |
473 | | pdf_font_cache_elem_t *next; |
474 | | gs_id font_id; |
475 | | int num_chars; /* safety purpose only */ |
476 | | int num_widths; /* safety purpose only */ |
477 | | struct pdf_font_resource_s *pdfont; |
478 | | byte *glyph_usage; |
479 | | double *real_widths; /* [count] (not used for Type 0) */ |
480 | | }; |
481 | | |
482 | | #define private_st_pdf_font_cache_elem()\ |
483 | | gs_private_st_ptrs4(st_pdf_font_cache_elem, pdf_font_cache_elem_t,\ |
484 | | "pdf_font_cache_elem_t", pdf_font_cache_elem_enum,\ |
485 | | pdf_font_cache_elem_reloc, next, pdfont,\ |
486 | | glyph_usage, real_widths) |
487 | | |
488 | | /* |
489 | | * pdf_viewer_state tracks the graphic state of a viewer, |
490 | | * which would interpret the generated PDF file |
491 | | * immediately when it is generated. |
492 | | */ |
493 | | typedef struct pdf_viewer_state_s { |
494 | | int transfer_not_identity; /* bitmask */ |
495 | | gs_id transfer_ids[4]; |
496 | | float strokeconstantalpha; |
497 | | float fillconstantalpha; |
498 | | bool alphaisshape; |
499 | | gs_blend_mode_t blend_mode; /* state.blend_mode */ |
500 | | gs_id halftone_id; |
501 | | gs_id black_generation_id; |
502 | | gs_id undercolor_removal_id; |
503 | | int overprint_mode; |
504 | | float smoothness; /* state.smoothness */ |
505 | | float flatness; |
506 | | bool text_knockout; /* state.text_knockout */ |
507 | | bool fill_overprint; |
508 | | bool stroke_overprint; |
509 | | int stroke_adjust; /* state.stroke_adjust */ |
510 | | bool fill_used_process_color; |
511 | | bool stroke_used_process_color; |
512 | | gx_hl_saved_color saved_fill_color; |
513 | | gx_hl_saved_color saved_stroke_color; |
514 | | gx_line_params line_params; |
515 | | float *dash_pattern; |
516 | | uint dash_pattern_size; |
517 | | gs_id soft_mask_id; |
518 | | } pdf_viewer_state; |
519 | | |
520 | | /* |
521 | | * Define a structure for saving context when entering |
522 | | * a contents stream accumulation mode (charproc, Type 1 pattern). |
523 | | */ |
524 | | typedef struct pdf_substream_save_s { |
525 | | pdf_context_t context; |
526 | | pdf_text_state_t *text_state; |
527 | | gx_path *clip_path; |
528 | | gs_id clip_path_id; |
529 | | int vgstack_bottom; |
530 | | stream *strm; |
531 | | cos_dict_t *substream_Resources; |
532 | | pdf_procset_t procsets; |
533 | | bool skip_colors; |
534 | | pdf_resource_t *font3; |
535 | | pdf_resource_t *accumulating_substream_resource; |
536 | | bool charproc_just_accumulated; |
537 | | bool accumulating_a_global_object; |
538 | | pdf_resource_t *pres_soft_mask_dict; |
539 | | gs_const_string objname; |
540 | | int last_charpath_op; |
541 | | } pdf_substream_save; |
542 | | |
543 | | #define private_st_pdf_substream_save()\ |
544 | | gs_private_st_strings1_ptrs7(st_pdf_substream_save, pdf_substream_save,\ |
545 | | "pdf_substream_save", pdf_substream_save_enum,\ |
546 | | pdf_substream_save_reloc, objname, text_state, clip_path, strm, \ |
547 | | substream_Resources, font3, accumulating_substream_resource, pres_soft_mask_dict) |
548 | | #define private_st_pdf_substream_save_element()\ |
549 | | gs_private_st_element(st_pdf_substream_save_element, pdf_substream_save,\ |
550 | | "pdf_substream_save[]", pdf_substream_save_elt_enum_ptrs,\ |
551 | | pdf_substream_save_elt_reloc_ptrs, st_pdf_substream_save) |
552 | | |
553 | | typedef enum { |
554 | | pdf_compress_none, |
555 | | pdf_compress_LZW, /* not currently used, thanks to Unisys */ |
556 | | pdf_compress_Flate, |
557 | | pdf_compress_Brotli |
558 | | } pdf_compression_type; |
559 | | |
560 | | typedef enum { |
561 | | OCR_UnInit, |
562 | | OCR_Rendering, |
563 | | OCR_Rendered, |
564 | | OCR_UnicodeAvailable, |
565 | | OCR_Failed |
566 | | } pdf_OCR_stage; |
567 | | |
568 | | typedef enum { |
569 | | UseOCRNever, |
570 | | UseOCRAsNeeded, |
571 | | UseOCRAlways |
572 | | } pdf_OCR_usage; |
573 | | |
574 | | typedef struct ocr_glyph_s{ |
575 | | byte *data; |
576 | | int x; |
577 | | int y; |
578 | | int width; |
579 | | int height; |
580 | | int raster; |
581 | | void *next; |
582 | | gs_char char_code; |
583 | | gs_glyph glyph; |
584 | | bool is_space; |
585 | | } ocr_glyph_t; |
586 | | |
587 | | /* Define the device structure. */ |
588 | | struct gx_device_pdf_s { |
589 | | gx_device_psdf_common; |
590 | | gs_font_dir *pdf_font_dir; /* Our own font cache, so that PCL can free its own ones, we set our font copeis to use this */ |
591 | | /* see 'pdf_free_pdf_font_cache' in gdevpdf.c for more details. */ |
592 | | bool is_ps2write; /* ps2write (true) versus pdfwrite (false); never changed */ |
593 | | /* PDF-specific distiller parameters */ |
594 | | double CompatibilityLevel; |
595 | | int EndPage; |
596 | | int StartPage; |
597 | | bool Optimize; |
598 | | bool ParseDSCCommentsForDocInfo; |
599 | | bool ParseDSCComments; |
600 | | bool EmitDSCWarnings; |
601 | | bool CreateJobTicket; |
602 | | bool PreserveEPSInfo; |
603 | | bool AutoPositionEPSFiles; |
604 | | bool PreserveCopyPage; |
605 | | bool UsePrologue; |
606 | | int OffOptimizations; |
607 | | /* End of distiller parameters */ |
608 | | /* PDF/X parameters */ |
609 | | gs_param_float_array PDFXTrimBoxToMediaBoxOffset; |
610 | | gs_param_float_array PDFXBleedBoxToTrimBoxOffset; |
611 | | bool PDFXSetBleedBoxToMediaBox; |
612 | | /* OCR Parameters */ |
613 | | char ocr_language[1024]; |
614 | | int ocr_engine; |
615 | | /* Other parameters */ |
616 | | bool ReAssignCharacters; |
617 | | bool ReEncodeCharacters; |
618 | | int64_t FirstObjectNumber; |
619 | | bool CompressFonts; |
620 | | bool CompressStreams; |
621 | | bool PrintStatistics; |
622 | | gs_param_string DocumentUUID; |
623 | | gs_param_string InstanceUUID; |
624 | | int DocumentTimeSeq; |
625 | | bool ForOPDFRead; /* PS2WRITE only. */ |
626 | | bool Eps2Write; /* EPS2WRITE only */ |
627 | | bool CompressEntireFile; /* PS2WRITE only. */ |
628 | | bool ResourcesBeforeUsage; /* PS2WRITE only. */ |
629 | | bool HavePDFWidths; /* PS2WRITE only. */ |
630 | | bool HaveStrokeColor; /* PS2WRITE only. */ |
631 | | bool ProduceDSC; /* PS2WRITE only. */ |
632 | | bool HaveTransparency; |
633 | | bool PatternImagemask; /* The target viewer|printer handles imagemask |
634 | | with pattern color. */ |
635 | | int PDFX; /* Generate PDF/X */ |
636 | | int PDFA; /* Generate PDF/A 0 = don't produce, otherwise level of PDF/A */ |
637 | | bool AbortPDFAX; /* Abort generation of PDFA or X, produce regular PDF */ |
638 | | int64_t MaxClipPathSize; /* The maximal number of elements of a clipping path |
639 | | that the target viewer|printer can handle. */ |
640 | | int64_t MaxShadingBitmapSize; /* The maximal number of bytes in |
641 | | a bitmap representation of a shading. |
642 | | (Bigger shadings to be downsampled). */ |
643 | | int64_t MaxInlineImageSize; |
644 | | /* Encryption parameters */ |
645 | | gs_param_string OwnerPassword; |
646 | | gs_param_string UserPassword; |
647 | | uint KeyLength; |
648 | | int32_t Permissions; |
649 | | uint EncryptionR; |
650 | | gs_param_string NoEncrypt; |
651 | | bool EncryptMetadata; |
652 | | /* End of parameters */ |
653 | | bool ComputeDocumentDigest; /* Developer needs only; Always true in production. */ |
654 | | /* Encryption data */ |
655 | | byte EncryptionO[32]; |
656 | | byte EncryptionU[32]; |
657 | | byte EncryptionKey[16]; |
658 | | uint EncryptionV; |
659 | | /* Values derived from DSC comments */ |
660 | | bool is_EPS; |
661 | | int AccumulatingBBox; |
662 | | gs_rect BBox; |
663 | | pdf_page_dsc_info_t doc_dsc_info; /* document default */ |
664 | | pdf_page_dsc_info_t page_dsc_info; /* current page */ |
665 | | /* Additional graphics state */ |
666 | | bool fill_overprint, stroke_overprint; |
667 | | int rendering_intent; |
668 | | bool user_icc; |
669 | | bool remap_fill_color, remap_stroke_color; |
670 | | gs_id halftone_id; |
671 | | gs_id transfer_ids[4]; |
672 | | int transfer_not_identity; /* bitmask */ |
673 | | gs_id black_generation_id, undercolor_removal_id; |
674 | | /* Following are set when device is opened. */ |
675 | | pdf_compression_type compression; |
676 | | pdf_compression_type compression_at_page_start; |
677 | | /* pdf_memory is 'stable' memory, it is not subject to save and restore |
678 | | * and is the allocator which should be used for pretty much ewverything |
679 | | */ |
680 | 6.61M | #define pdf_memory v_memory |
681 | | /* |
682 | | * The xref temporary file is logically an array of longs. |
683 | | * xref[id - FirstObjectNumber] is the position in the output file |
684 | | * of the object with the given id. |
685 | | * |
686 | | * Note that xref, unlike the other temporary files, does not have |
687 | | * an associated stream or stream buffer. |
688 | | */ |
689 | | pdf_temp_file_t xref; |
690 | | /* |
691 | | * asides holds resources and other "aside" objects. It is |
692 | | * copied verbatim to the output file at the end of the document. |
693 | | */ |
694 | | pdf_temp_file_t asides; |
695 | | /* |
696 | | * streams holds data for stream-type Cos objects. The data is |
697 | | * copied to the output file at the end of the document. |
698 | | * |
699 | | * Note that streams.save_strm is not used, since we don't interrupt |
700 | | * normal output when saving stream data. |
701 | | */ |
702 | | pdf_temp_file_t streams; |
703 | | /* |
704 | | * ObjStm holds a tream of objects being stored in an ObjStm, up to MAX_OBJSTM_OBJECTS, |
705 | | * We keep a record of the offset of each object within the stream in ObjStmOffsets, so |
706 | | * that later on we can write the offset within the stream for each object into the |
707 | | * beginning of the ObjStm. NumObjStmOffsets is used to keep track of how many we have, |
708 | | * and ObjStm_id is the id of the stream which we'll eventually store in the 'asides' |
709 | | * file, containing the ObjStm. |
710 | | */ |
711 | | pdf_temp_file_t ObjStm; |
712 | | int64_t ObjStm_id; |
713 | | gs_offset_t *ObjStmOffsets; |
714 | | int NumObjStmObjects; |
715 | | bool doubleXref; |
716 | | |
717 | | /* ................ */ |
718 | | int64_t next_id; |
719 | | /* The following 3 objects, and only these, are allocated */ |
720 | | /* when the file is opened. */ |
721 | | cos_dict_t *Catalog; |
722 | | cos_dict_t *Info; |
723 | | cos_dict_t *Pages; |
724 | 0 | #define pdf_num_initial_ids 3 |
725 | | int64_t outlines_id; |
726 | | int next_page; |
727 | | int max_referred_page; |
728 | | int64_t contents_id; |
729 | | pdf_context_t context; |
730 | | int64_t contents_length_id; |
731 | | gs_offset_t contents_pos; |
732 | | pdf_procset_t procsets; /* used on this page */ |
733 | | pdf_text_data_t *text; |
734 | | pdf_text_rotation_t text_rotation; |
735 | 68.0k | #define initial_num_pages 50 |
736 | | pdf_page_t *pages; |
737 | | int num_pages; |
738 | | uint64_t used_mask; /* for where_used: page level = 1 */ |
739 | | pdf_resource_list_t resources[NUM_RESOURCE_TYPES]; |
740 | | /* cs_Patterns[0] is colored; 1,3,4 are uncolored + Gray,RGB,CMYK */ |
741 | | pdf_resource_t *cs_Patterns[5]; |
742 | | pdf_resource_t *Identity_ToUnicode_CMaps[2]; /* WMode = 0,1 */ |
743 | | pdf_resource_t *last_resource; |
744 | | pdf_resource_t *OneByteIdentityH; |
745 | | gs_id IdentityCIDSystemInfo_id; |
746 | | pdf_outline_level_t *outline_levels; |
747 | | int outline_depth; |
748 | | int max_outline_depth; |
749 | | int closed_outline_depth; |
750 | | int outlines_open; |
751 | | pdf_article_t *articles; |
752 | | cos_dict_t *Dests; |
753 | | cos_dict_t *EmbeddedFiles; |
754 | | cos_array_t *AF; |
755 | | byte fileID[16]; |
756 | | /* Use a single time moment for all UUIDs to minimize an indeterminizm. */ |
757 | | /* This needs to be a long because we call the platform code gp_get_realtime |
758 | | * to fill it in, and that takes a long *. Be aware that long is 32-bits on |
759 | | * 32-bit Windows and 64-bits on 64-bit Windows. |
760 | | */ |
761 | | long uuid_time[2]; |
762 | | /* |
763 | | * global_named_objects holds named objects that are independent of |
764 | | * the current namespace: {Catalog}, {DocInfo}, {Page#}, {ThisPage}, |
765 | | * {PrevPage}, {NextPage}. |
766 | | */ |
767 | | cos_dict_t *global_named_objects; |
768 | | /* |
769 | | * local_named_objects holds named objects in the current namespace. |
770 | | */ |
771 | | cos_dict_t *local_named_objects; |
772 | | /* |
773 | | * NI_stack is a last-in, first-out stack in which each element is a |
774 | | * (named) cos_stream_t object that eventually becomes the object of an |
775 | | * image XObject resource. |
776 | | */ |
777 | | cos_array_t *NI_stack; |
778 | | /* |
779 | | * Namespace_stack is a last-in, first-out stack in which each pair of |
780 | | * elements is, respectively, a saved value of local_named_objects and |
781 | | * a saved value of NI_stack. (The latter is not documented by Adobe, |
782 | | * but it was confirmed by them.) |
783 | | */ |
784 | | cos_array_t *Namespace_stack; |
785 | | pdf_font_cache_elem_t *font_cache; |
786 | | /* |
787 | | * char_width is used by pdf_text_set_cache to communicate |
788 | | * with assign_char_code around gdev_pdf_fill_mask. |
789 | | */ |
790 | | gs_point char_width; |
791 | | /* |
792 | | * We need a stable copy of clipping path to prevent writing |
793 | | * redundant clipping paths when PS document generates such ones. |
794 | | */ |
795 | | gx_path *clip_path; |
796 | | |
797 | | /* Used for preserving text rendering modes with clip. */ |
798 | | bool clipped_text_pending; |
799 | | int saved_vgstack_bottom_for_textclip; |
800 | | int saved_vgstack_depth_for_textclip; |
801 | | |
802 | | /* |
803 | | * Page labels. |
804 | | */ |
805 | | cos_array_t *PageLabels; |
806 | | int PageLabels_current_page; |
807 | | cos_dict_t *PageLabels_current_label; |
808 | | /* |
809 | | * The following is a dangerous pointer, which pdf_text_process |
810 | | * uses to communicate with assign_char_code. |
811 | | * It is a pointer from global memory to local memory. |
812 | | * The garbager must not proceess this pointer, and it must |
813 | | * not be listed in st_device_pdfwrite. |
814 | | * It's life time terminates on garbager invocation. |
815 | | */ |
816 | | gs_text_enum_t *pte; |
817 | | /* |
818 | | * The viewer's graphic state stack. |
819 | | */ |
820 | | pdf_viewer_state *vgstack; |
821 | | int vgstack_size; |
822 | | int vgstack_depth; |
823 | | int vgstack_bottom; /* Stack bottom for the current substream. */ |
824 | | pdf_viewer_state vg_initial; /* Initial values for viewer's graphic state */ |
825 | | bool vg_initial_set; |
826 | | |
827 | | /* The substream context stack. */ |
828 | | int sbstack_size; |
829 | | int sbstack_depth; |
830 | | pdf_substream_save *sbstack; |
831 | | |
832 | | /* Temporary workaround. The only way to get forms out of pdfwrite at present |
833 | | * is via a transparency group or mask operation. Ordinarily we don't care |
834 | | * much about forms, but Patterns within forms need to be scaled to the |
835 | | * CTM of the Pattern, not the default page co-ordinate system. We use |
836 | | * this value to know if we are nested inside a form or not. If we are |
837 | | * we don't undo the resolution co-ordinate transform. |
838 | | */ |
839 | | int FormDepth; |
840 | | |
841 | | /* Determine if we have a high level form. We want to do things differently |
842 | | * sometimes, if we are capturing a form |
843 | | */ |
844 | | int HighLevelForm; |
845 | | |
846 | | /* Nasty hack. OPDFread.ps resets the graphics state to the identity before |
847 | | * replaying the Pattern PaintProc, but if the Pattern is nested inside a |
848 | | * previous pattern, this doesn't work. We use this to keep track of whether |
849 | | * we are nested, and if we are (and are ps2write, not pdfwrite) we track the |
850 | | * pattern CTM below. |
851 | | */ |
852 | | int PatternDepth; |
853 | | gs_matrix AccumulatedPatternMatrix; |
854 | | |
855 | | /* Normally the PDF itnerpreter doesn't call execform to pass a From XObject to |
856 | | * pdfwrite, but it *does* create forms (and increment FormDepth) for transparent |
857 | | * Groups, which are handled as Form XObjects. Because of the way that Pattterns work, |
858 | | * the first pattern after a Form uses the Form co-ordinate system, but if the Pattern |
859 | | * itself uses Patterns, then the nested Pattern needs to use the co-ordinate system |
860 | | * of the parent Pattern. Unless, of course, we have another Form! |
861 | | * So essentially we need to know the Pattern depth, since the last form was executed. |
862 | | * If its 0, then we want to apply the current CTM, if its more than that then we want |
863 | | * to undo the pdfwrite scaling (see gdevpdfv.c, pdf_store_pattern1_params() at about line |
864 | | * 239. |
865 | | */ |
866 | | int PatternsSinceForm; |
867 | | |
868 | | /* Accessories */ |
869 | | cos_dict_t *substream_Resources; /* Substream resources */ |
870 | | gs_color_space_index pcm_color_info_index; /* Index of the ProcessColorModel space. */ |
871 | | bool skip_colors; /* Skip colors while a pattern/charproc accumulation. */ |
872 | | bool AR4_save_bug; /* See pdf_put_uncolored_pattern */ |
873 | | pdf_resource_t *font3; /* The owner of the accumulated charstring. */ |
874 | | pdf_resource_t *accumulating_substream_resource; |
875 | | gs_matrix_fixed charproc_ctm; |
876 | | bool accumulating_charproc; |
877 | | gs_rect charproc_BBox; |
878 | | bool charproc_just_accumulated; /* A flag for controlling |
879 | | the glyph variation recognition. |
880 | | Used only with uncached charprocs. */ |
881 | | bool PS_accumulator; /* A flag to determine whether a given |
882 | | accumulator is for a PostScript type 3 font or not. */ |
883 | | bool Scaled_accumulator; /* We scale teh CTM when accumulating type 3 fonts */ |
884 | | bool accumulating_a_global_object; /* ps2write only. |
885 | | Accumulating a global object (such as a named Form, |
886 | | so that resources used in it must also be global. |
887 | | Important for viewers with small memory, |
888 | | which drops resources per page. */ |
889 | | const pdf_char_glyph_pairs_t *cgp; /* A temporary pointer |
890 | | for pdf_is_same_charproc1. |
891 | | Must be NULL when the garbager is invoked, |
892 | | because it points from global to local memory. */ |
893 | | int substituted_pattern_count; |
894 | | int substituted_pattern_drop_page; |
895 | | /* Temporary data for use_image_as_pattern, |
896 | | They pass an information about a mask of a masked image, |
897 | | (which is being converted into a pattern) |
898 | | between 2 consecutive calls to pdf_image_end_image_data. */ |
899 | | gs_id image_mask_id; |
900 | | bool image_mask_is_SMask; |
901 | | bool image_mask_skip; /* A flag for pdf_begin_transparency_mask */ |
902 | | bool smask_construction; /* True when pdfwrite is constructing a soft mask */ |
903 | | uint image_with_SMask; /* A flag for pdf_begin_transparency_group. In order to |
904 | | * deal with nested groups we set/test the bit according |
905 | | * to the FormDepth |
906 | | */ |
907 | | gs_matrix converting_image_matrix; |
908 | | double image_mask_scale; |
909 | | /* Temporary data for soft mask form. */ |
910 | | pdf_resource_t *pres_soft_mask_dict; |
911 | | /* used to track duplicate stream definitions in pdfmarks */ |
912 | | bool pdfmark_dup_stream; |
913 | | /* Temporary data for pdfmark_BP. */ |
914 | | gs_const_string objname; |
915 | | int OPDFRead_procset_length; /* PS2WRITE only. */ |
916 | | void *find_resource_param; /* WARNING : not visible for garbager. */ |
917 | | int last_charpath_op; /* true or false state of last charpath */ |
918 | | bool type3charpath; |
919 | | bool SetPageSize; |
920 | | bool RotatePages; |
921 | | bool FitPages; |
922 | | bool CenterPages; |
923 | | bool DoNumCopies; |
924 | | bool PreserveSeparation; |
925 | | bool PreserveDeviceN; |
926 | | int PDFACompatibilityPolicy; |
927 | | bool DetectDuplicateImages; |
928 | | bool AllowIncrementalCFF; |
929 | | bool WantsToUnicode; |
930 | | bool PdfmarkCapable; |
931 | | bool WantsPageLabels; |
932 | | bool WantsOptionalContent; |
933 | | bool AllowPSRepeatFunctions; |
934 | | bool IsDistiller; |
935 | | bool PreserveSMask; |
936 | | bool PreserveTrMode; |
937 | | bool NoT3CCITT; /* A bug in Brother printers causes CCITTFaxDecode |
938 | | * to fail, especially with small amounts of data. |
939 | | * This parameter is present only to allow |
940 | | * ps2write output to work on those pritners. |
941 | | */ |
942 | | bool Linearise; /* Whether to Linearizse the file, the next 2 parameter |
943 | | * are only used if this is true. |
944 | | */ |
945 | | pdf_linearisation_record_t |
946 | | *ResourceUsage; /* An array, one per resource defined to date, which |
947 | | * contains either -2 (shared on multiple pages), -1 |
948 | | * (structure object, eg catalog), 0 (not used on a page |
949 | | * or the page number. This does limit us to a mere 2^31 |
950 | | * pages |
951 | | */ |
952 | | int ResourceUsageSize; /* Size of the above array, currently */ |
953 | | bool InOutputPage; /* Used when closing the file, if this is true then we were |
954 | | * called from output_page and should emit a page even if there |
955 | | * are no marks. If false, then we probably were called from |
956 | | * closedevice and, if there are no marks, we should delete |
957 | | * the last file *if* we are emitting one file per page. |
958 | | */ |
959 | | bool FlattenFonts; |
960 | | int LastFormID; |
961 | | char *ExtensionMetadata; /* If present the non-standard pdfmark Extension_Metadata has been |
962 | | * used, the content of ths string is written out as part of the |
963 | | * metadata referenced by the Catalog. |
964 | | */ |
965 | | char *PDFFormName; /* If present, we are processing (or about to process) a Form XObject |
966 | | * which we wish to handle as a Form XObject, not flatten. Currently |
967 | | * this is only the case for Annotation Appearances. This must be NULL |
968 | | * after the form is processed. The name will be used to create a |
969 | | * local named object which pdfmark can reference. |
970 | | */ |
971 | | stream *PassThroughWriter; /* A copy of the stream that the image enumerator points to, if we are |
972 | | * doing JPEG pass through we write the JPEG data here, and don't write |
973 | | * anything in the image processing routines. |
974 | | */ |
975 | | float UserUnit; |
976 | | pdf_OCR_usage UseOCR; /* Never, AsNeeded or Always */ |
977 | | gs_text_enum_t* OCRSaved; /* Saved state of the text enumerator before rendering glyph bitmaps for later OCR */ |
978 | | pdf_OCR_stage OCRStage; /* Used to control a (sort of) state machine when using OCR to get a Unicode value for a glyph */ |
979 | | int *OCRUnicode; /* Used to pass back the Unicode value from the OCR engine to the text processing */ |
980 | | gs_char OCR_char_code; /* Passes the current character code from text processing to the image processing code when rendering glyph bitmaps for OCR */ |
981 | | gs_glyph OCR_glyph; /* Passes the current glyph code from text processing to the image processing code when rendering glyph bitmaps for OCR */ |
982 | | gs_text_enum_t *OCR_enum; /* We need this to update the OCR char_code and glyph in gdev_pdf_fill_mask() when rendering a glyph for OCR, when using PDF input */ |
983 | | ocr_glyph_t *ocr_glyphs; /* Records bitmaps and other data from text processing when doing OCR */ |
984 | | gs_gstate **initial_pattern_states; |
985 | | bool OmitInfoDate; /* If true, do not emit CreationDate and ModDate in the Info dictionary and XMP Metadata (must not be true for PDF/X support) */ |
986 | | bool OmitXMP; /* If true, do not emit an XMP /Metadata block and do not reference it from the Catalog (must not be true for PDF/A output) */ |
987 | | bool OmitID; /* If true, do not emit a /ID array in the trailer dicionary (must not be true for encrypted files or PDF 2.0) */ |
988 | | bool ModifiesPageSize; /* If true, the new PDF interpreter will not preserve *Box values (the media size has been modified, they will be incorrect) */ |
989 | | bool ModifiesPageOrder; /* If true, the new PDF interpreter will not preserve Outlines or Dests, because they will refer to the wrong page number */ |
990 | | bool WriteXRefStm; /* If true, (the default) use an XRef stream rather than an xref table */ |
991 | | bool WriteObjStms; /* If true, (the default) store candidate objects in ObjStms rather than plain text in the PDF file. */ |
992 | | char *PendingOC; /* An OptionalContent object is pending, the string is the name of the (already defined) object */ |
993 | | bool ToUnicodeForStdEnc; /* Should we emit ToUnicode CMaps when a simple font has only standard glyph names. Defaults to true */ |
994 | | bool EmbedSubstituteFonts; /* When we use a substitute font to replace a missing font, should we embed it in the output */ |
995 | | bool UseBrotli; /* Use Brotli compression in place of Flate */ |
996 | | }; |
997 | | |
998 | | #define is_in_page(pdev)\ |
999 | 19.6M | ((pdev)->contents_id != 0) |
1000 | | |
1001 | | /* Enumerate the individual pointers in a gx_device_pdf. |
1002 | | I disliked this macro and so its been removed, the pointers are |
1003 | | enumerated/relocated in gdevpdf.c now. We still need the gx_device_pdf_num_ptrs |
1004 | | though, so I'm maintaining this comment just to keep track of the number |
1005 | | of pointers. |
1006 | | */ |
1007 | | /*#define gx_device_pdf_do_ptrs(m)\ |
1008 | | m(0,asides.strm) m(1,asides.strm_buf) m(2,asides.save_strm)\ |
1009 | | m(3,streams.strm) m(4,streams.strm_buf)\ |
1010 | | m(5,pictures.strm) m(6,pictures.strm_buf) m(7,pictures.save_strm)\ |
1011 | | m(8,Catalog) m(9,Info) m(10,Pages)\ |
1012 | | m(11,text) m(12,pages)\ |
1013 | | m(13,cs_Patterns[0])\ |
1014 | | m(14,cs_Patterns[1]) m(15,cs_Patterns[3]) m(16,cs_Patterns[4])\ |
1015 | | m(17,last_resource)\ |
1016 | | m(18,articles) m(19,Dests) m(20,global_named_objects)\ |
1017 | | m(21, local_named_objects) m(22,NI_stack) m(23,Namespace_stack)\ |
1018 | | m(24,font_cache) m(25,clip_path)\ |
1019 | | m(26,PageLabels) m(27,PageLabels_current_label)\ |
1020 | | m(28,sbstack) m(29,substream_Resources) m(30,font3)\ |
1021 | | m(31,accumulating_substream_resource) \ |
1022 | | m(32,pres_soft_mask_dict) m(33,PDFXTrimBoxToMediaBoxOffset.data)\ |
1023 | | m(34,PDFXBleedBoxToTrimBoxOffset.data) |
1024 | | m(35,Identity_ToUnicode_CMaps[0]) m(36,Identity_ToUnicode_CMaps[1])\ |
1025 | | m(37,vgstack)\ |
1026 | | m(38, outline_levels) |
1027 | | m(39, gx_device_pdf, EmbeddedFiles); |
1028 | | m(40, gx_device_pdf, pdf_font_dir); |
1029 | | m(41, gx_device_pdf, Extension_Metadata);*/ |
1030 | 108M | #define gx_device_pdf_num_ptrs 44 |
1031 | | #define gx_device_pdf_do_param_strings(m)\ |
1032 | 781k | m(0, OwnerPassword) m(1, UserPassword) m(2, NoEncrypt)\ |
1033 | 781k | m(3, DocumentUUID) m(4, InstanceUUID) |
1034 | 108M | #define gx_device_pdf_num_param_strings 5 |
1035 | | #define gx_device_pdf_do_const_strings(m)\ |
1036 | 781k | m(0, objname) |
1037 | | #define gx_device_pdf_num_const_strings 1 |
1038 | | |
1039 | | #define private_st_device_pdfwrite() /* in gdevpdf.c */\ |
1040 | | gs_private_st_composite_final(st_device_pdfwrite, gx_device_pdf,\ |
1041 | | "gx_device_pdf", device_pdfwrite_enum_ptrs, device_pdfwrite_reloc_ptrs,\ |
1042 | | device_pdfwrite_finalize) |
1043 | | |
1044 | | /* ================ Driver procedures ================ */ |
1045 | | |
1046 | | /* In gdevpdfb.c */ |
1047 | | dev_proc_copy_mono(gdev_pdf_copy_mono); |
1048 | | dev_proc_copy_color(gdev_pdf_copy_color); |
1049 | | dev_proc_fill_mask(gdev_pdf_fill_mask); |
1050 | | dev_proc_strip_tile_rectangle(gdev_pdf_strip_tile_rectangle); |
1051 | | /* In gdevpdfd.c */ |
1052 | | extern const gx_device_vector_procs pdf_vector_procs; |
1053 | | dev_proc_fill_rectangle(gdev_pdf_fill_rectangle); |
1054 | | dev_proc_fill_path(gdev_pdf_fill_path); |
1055 | | dev_proc_stroke_path(gdev_pdf_stroke_path); |
1056 | | dev_proc_fill_stroke_path(gdev_pdf_fill_stroke_path); |
1057 | | dev_proc_fillpage(gdev_pdf_fillpage); |
1058 | | /* In gdevpdfi.c */ |
1059 | | dev_proc_begin_typed_image(gdev_pdf_begin_typed_image); |
1060 | | /* In gdevpdfp.c */ |
1061 | | dev_proc_get_params(gdev_pdf_get_params); |
1062 | | dev_proc_put_params(gdev_pdf_put_params); |
1063 | | /* In gdevpdft.c */ |
1064 | | dev_proc_text_begin(gdev_pdf_text_begin); |
1065 | | dev_proc_fill_rectangle_hl_color(gdev_pdf_fill_rectangle_hl_color); |
1066 | | /* In gdevpdfv.c */ |
1067 | | dev_proc_include_color_space(gdev_pdf_include_color_space); |
1068 | | /* In gdevpdft.c */ |
1069 | | dev_proc_composite(gdev_pdf_composite); |
1070 | | dev_proc_begin_transparency_group(gdev_pdf_begin_transparency_group); |
1071 | | dev_proc_end_transparency_group(gdev_pdf_end_transparency_group); |
1072 | | dev_proc_begin_transparency_mask(gdev_pdf_begin_transparency_mask); |
1073 | | dev_proc_end_transparency_mask(gdev_pdf_end_transparency_mask); |
1074 | | dev_proc_dev_spec_op(gdev_pdf_dev_spec_op); |
1075 | | |
1076 | | /* ================ Utility procedures ================ */ |
1077 | | |
1078 | | /* ---------------- Exported by gdevpdf.c ---------------- */ |
1079 | | |
1080 | | /* Initialize the IDs allocated at startup. */ |
1081 | | void pdf_initialize_ids(gx_device_pdf * pdev); |
1082 | | |
1083 | | /* Update the color mapping procedures after setting ProcessColorModel. */ |
1084 | | void pdf_set_process_color_model(gx_device_pdf * pdev, int index); |
1085 | | |
1086 | | /* Reset the text state parameters to initial values. */ |
1087 | | void pdf_reset_text(gx_device_pdf *pdev); |
1088 | | |
1089 | | /* ---------------- Exported by gdevpdfu.c ---------------- */ |
1090 | | |
1091 | | /* ------ Document ------ */ |
1092 | | |
1093 | | /* Utility functions to write args into the file as comments */ |
1094 | | int pdfwrite_fwrite_args_comment(gx_device_pdf *pdev, gp_file *f); |
1095 | | int pdfwrite_write_args_comment(gx_device_pdf *pdev, stream *s); |
1096 | | |
1097 | | /* Write a DSC compliant header to the file */ |
1098 | | int ps2write_dsc_header(gx_device_pdf * pdev, int pages); |
1099 | | |
1100 | | /* Open the document if necessary. */ |
1101 | | int pdfwrite_pdf_open_document(gx_device_pdf * pdev); |
1102 | | |
1103 | | /* ------ Objects ------ */ |
1104 | | |
1105 | | /* Allocate an ID for a future object, set its pos=0 so we can tell if it is used */ |
1106 | | int64_t pdf_obj_forward_ref(gx_device_pdf * pdev); |
1107 | | |
1108 | | /* Allocate an ID for a future object. */ |
1109 | | int64_t pdf_obj_ref(gx_device_pdf * pdev); |
1110 | | |
1111 | | /* Remove an object from the xref table (mark as unused) */ |
1112 | | int64_t pdf_obj_mark_unused(gx_device_pdf *pdev, int64_t id); |
1113 | | |
1114 | | /* Read the current position in the output stream. */ |
1115 | | gs_offset_t pdf_stell(gx_device_pdf * pdev); |
1116 | | |
1117 | | /* Begin an object, optionally allocating an ID. */ |
1118 | | int64_t pdf_open_obj(gx_device_pdf * pdev, int64_t id, pdf_resource_type_t type); |
1119 | | int64_t pdf_begin_obj(gx_device_pdf * pdev, pdf_resource_type_t type); |
1120 | | |
1121 | | /* End an object. */ |
1122 | | int pdf_end_obj(gx_device_pdf * pdev, pdf_resource_type_t type); |
1123 | | |
1124 | | /* ------ Page contents ------ */ |
1125 | | |
1126 | | /* Open a page contents part. */ |
1127 | | /* Return an error if the page has too many contents parts. */ |
1128 | | int pdf_open_contents(gx_device_pdf * pdev, pdf_context_t context); |
1129 | | |
1130 | | /* Close the current contents part if we are in one. */ |
1131 | | int pdf_close_contents(gx_device_pdf * pdev, bool last); |
1132 | | |
1133 | | /* ------ Resources et al ------ */ |
1134 | | |
1135 | | extern const char *const pdf_resource_type_names[]; |
1136 | | extern const gs_memory_struct_type_t *const pdf_resource_type_structs[]; |
1137 | | |
1138 | | /* Record usage of resoruces by pages */ |
1139 | | int pdf_record_usage(gx_device_pdf *const pdev, int64_t resource_id, int page_num); |
1140 | | int pdf_record_usage_by_parent(gx_device_pdf *const pdev, int64_t resource_id, int64_t parent); |
1141 | | |
1142 | | /* |
1143 | | * Define the offset that indicates that a file position is in the |
1144 | | * asides file rather than the main (contents) file. We just use the top bit |
1145 | | * as a flag. Complexity is due to ubsan and the possibility we have 32-bit offset type. |
1146 | | */ |
1147 | | #ifdef ARCH_SIZEOF_GS_OFFSET_T |
1148 | | # if ARCH_SIZEOF_GS_OFFSET_T == 8 |
1149 | 1.05M | #define ASIDES_BASE_POSITION ((uint64_t)1 << ((sizeof(gs_offset_t) * 8) - 1)) |
1150 | | # elif ARCH_SIZEOF_GS_OFFSET_T == 4 |
1151 | | #define ASIDES_BASE_POSITION ((uint32_t)1 << ((sizeof(gs_offset_t) * 8) - 1)) |
1152 | | # else |
1153 | | UNSUPPORTED |
1154 | | # endif |
1155 | | # else |
1156 | | UNSUPPORTED |
1157 | | # endif |
1158 | | |
1159 | | /* Begin an object logically separate from the contents. */ |
1160 | | /* (I.e., an object in the resource file.) */ |
1161 | | int64_t pdf_open_separate(gx_device_pdf * pdev, int64_t id, pdf_resource_type_t type); |
1162 | | int64_t pdf_begin_separate(gx_device_pdf * pdev, pdf_resource_type_t type); |
1163 | | |
1164 | | /* functions used for ObjStm writing */ |
1165 | | int FlushObjStm(gx_device_pdf *pdev); |
1166 | | int NewObjStm(gx_device_pdf *pdev); |
1167 | | int64_t pdf_open_separate_noObjStm(gx_device_pdf * pdev, int64_t id, pdf_resource_type_t type); |
1168 | | int pdf_end_separate_noObjStm(gx_device_pdf * pdev, pdf_resource_type_t type); |
1169 | | |
1170 | | /* Reserve object id. */ |
1171 | | void pdf_reserve_object_id(gx_device_pdf * pdev, pdf_resource_t *ppres, int64_t id); |
1172 | | |
1173 | | /* Begin an aside (resource, annotation, ...). */ |
1174 | | int pdf_alloc_aside(gx_device_pdf * pdev, pdf_resource_t ** plist, |
1175 | | const gs_memory_struct_type_t * pst, pdf_resource_t **ppres, |
1176 | | int64_t id); |
1177 | | /* Begin an aside (resource, annotation, ...). */ |
1178 | | int64_t pdf_begin_aside(gx_device_pdf * pdev, pdf_resource_t **plist, |
1179 | | const gs_memory_struct_type_t * pst, |
1180 | | pdf_resource_t **ppres, pdf_resource_type_t type); |
1181 | | |
1182 | | /* Begin a resource of a given type. */ |
1183 | | int pdf_begin_resource(gx_device_pdf * pdev, pdf_resource_type_t rtype, |
1184 | | gs_id rid, pdf_resource_t **ppres); |
1185 | | |
1186 | | /* Begin a resource body of a given type. */ |
1187 | | int pdf_begin_resource_body(gx_device_pdf * pdev, pdf_resource_type_t rtype, |
1188 | | gs_id rid, pdf_resource_t **ppres); |
1189 | | |
1190 | | /* Allocate a resource, but don't open the stream. */ |
1191 | | int pdf_alloc_resource(gx_device_pdf * pdev, pdf_resource_type_t rtype, |
1192 | | gs_id rid, pdf_resource_t **ppres, int64_t id); |
1193 | | |
1194 | | /* Find same resource. */ |
1195 | | int pdf_find_same_resource(gx_device_pdf * pdev, |
1196 | | pdf_resource_type_t rtype, pdf_resource_t **ppres, |
1197 | | int (*eq)(gx_device_pdf * pdev, pdf_resource_t *pres0, pdf_resource_t *pres1)); |
1198 | | |
1199 | | /* Find resource by resource id. */ |
1200 | | pdf_resource_t *pdf_find_resource_by_resource_id(gx_device_pdf * pdev, |
1201 | | pdf_resource_type_t rtype, gs_id id); |
1202 | | |
1203 | | /* Find a resource of a given type by gs_id. */ |
1204 | | pdf_resource_t *pdf_find_resource_by_gs_id(gx_device_pdf * pdev, |
1205 | | pdf_resource_type_t rtype, |
1206 | | gs_id rid); |
1207 | | |
1208 | | /* Remove a resource from a chain of resources but do not free it. The resource will |
1209 | | * have to be listed elsewhere. This is primarily useful for moving existing resources |
1210 | | * to local named resources. |
1211 | | */ |
1212 | | void |
1213 | | pdf_drop_resource_from_chain(gx_device_pdf * pdev, pdf_resource_t *pres1, pdf_resource_type_t rtype); |
1214 | | |
1215 | | void pdf_drop_resources(gx_device_pdf * pdev, pdf_resource_type_t rtype, |
1216 | | int (*cond)(gx_device_pdf * pdev, pdf_resource_t *pres)); |
1217 | | |
1218 | | /* Print resource statistics. */ |
1219 | | void pdf_print_resource_statistics(gx_device_pdf * pdev); |
1220 | | |
1221 | | /* Cancel a resource (do not write it into PDF). */ |
1222 | | int pdf_cancel_resource(gx_device_pdf * pdev, pdf_resource_t *pres, |
1223 | | pdf_resource_type_t rtype); |
1224 | | |
1225 | | /* Remove a resource. */ |
1226 | | void pdf_forget_resource(gx_device_pdf * pdev, pdf_resource_t *pres1, |
1227 | | pdf_resource_type_t rtype); |
1228 | | |
1229 | | /* Substitute a resource with a same one. */ |
1230 | | int pdf_substitute_resource(gx_device_pdf *pdev, pdf_resource_t **ppres, |
1231 | | pdf_resource_type_t rtype, |
1232 | | int (*eq)(gx_device_pdf *pdev, pdf_resource_t *pres0, pdf_resource_t *pres1), |
1233 | | bool write); |
1234 | | |
1235 | | /* Get the object id of a resource. */ |
1236 | | int64_t pdf_resource_id(const pdf_resource_t *pres); |
1237 | | |
1238 | | /* End a separate object. */ |
1239 | | int pdf_end_separate(gx_device_pdf * pdev, pdf_resource_type_t type); |
1240 | | |
1241 | | /* End an aside. */ |
1242 | | int pdf_end_aside(gx_device_pdf * pdev, pdf_resource_type_t type); |
1243 | | |
1244 | | /* End a resource. */ |
1245 | | int pdf_end_resource(gx_device_pdf * pdev, pdf_resource_type_t type); |
1246 | | |
1247 | | /* |
1248 | | * Write the Cos objects for resources local to a content stream. |
1249 | | */ |
1250 | | int pdf_write_resource_objects(gx_device_pdf *pdev, pdf_resource_type_t rtype); |
1251 | | |
1252 | | /* |
1253 | | * Reverse resource chains. |
1254 | | * ps2write uses it with page resources. |
1255 | | * Assuming only the 0th chain contauns something. |
1256 | | */ |
1257 | | void pdf_reverse_resource_chain(gx_device_pdf *pdev, pdf_resource_type_t rtype); |
1258 | | |
1259 | | /* |
1260 | | * Free unnamed Cos objects for resources local to a content stream. |
1261 | | */ |
1262 | | int pdf_free_resource_objects(gx_device_pdf *pdev, pdf_resource_type_t rtype); |
1263 | | |
1264 | | /* |
1265 | | * Store the resource sets for a content stream (page or XObject). |
1266 | | * Sets page->{procsets, resource_ids[], fonts_id}. |
1267 | | */ |
1268 | | int pdf_store_page_resources(gx_device_pdf *pdev, pdf_page_t *page, bool clear_usage); |
1269 | | |
1270 | | /* Copy data from a temporary file to a stream. */ |
1271 | | int pdf_copy_data(stream *s, gp_file *file, gs_offset_t count, stream_arcfour_state *ss); |
1272 | | int pdf_copy_data_safe(stream *s, gp_file *file, gs_offset_t position, int64_t count); |
1273 | | |
1274 | | /* Add the encryption filter. */ |
1275 | | int pdf_begin_encrypt(gx_device_pdf * pdev, stream **s, gs_id object_id); |
1276 | | /* Remove the encryption filter. */ |
1277 | | static int inline pdf_end_encrypt(gx_device_pdf *pdev) |
1278 | 146k | { |
1279 | 146k | if (pdev->KeyLength) |
1280 | 0 | return 1; |
1281 | 146k | return 0; |
1282 | 146k | } Unexecuted instantiation: gdevpdf.c:pdf_end_encrypt Unexecuted instantiation: gdevpdfb.c:pdf_end_encrypt Unexecuted instantiation: gdevpdfc.c:pdf_end_encrypt Unexecuted instantiation: gdevpdfd.c:pdf_end_encrypt Unexecuted instantiation: gdevpdfe.c:pdf_end_encrypt Unexecuted instantiation: gdevpdfg.c:pdf_end_encrypt Unexecuted instantiation: gdevpdfi.c:pdf_end_encrypt Unexecuted instantiation: gdevpdfj.c:pdf_end_encrypt Unexecuted instantiation: gdevpdfk.c:pdf_end_encrypt Unexecuted instantiation: gdevpdfm.c:pdf_end_encrypt Unexecuted instantiation: gdevpdfo.c:pdf_end_encrypt Unexecuted instantiation: gdevpdfp.c:pdf_end_encrypt Unexecuted instantiation: gdevpdft.c:pdf_end_encrypt Unexecuted instantiation: gdevpdfr.c:pdf_end_encrypt gdevpdfu.c:pdf_end_encrypt Line | Count | Source | 1278 | 12.1k | { | 1279 | 12.1k | if (pdev->KeyLength) | 1280 | 0 | return 1; | 1281 | 12.1k | return 0; | 1282 | 12.1k | } |
Unexecuted instantiation: gdevpdfv.c:pdf_end_encrypt Unexecuted instantiation: gdevpdt.c:pdf_end_encrypt Unexecuted instantiation: gdevpdtd.c:pdf_end_encrypt Unexecuted instantiation: gdevpdtf.c:pdf_end_encrypt gdevpdti.c:pdf_end_encrypt Line | Count | Source | 1278 | 134k | { | 1279 | 134k | if (pdev->KeyLength) | 1280 | 0 | return 1; | 1281 | 134k | return 0; | 1282 | 134k | } |
Unexecuted instantiation: gdevpdts.c:pdf_end_encrypt Unexecuted instantiation: gdevpdtt.c:pdf_end_encrypt Unexecuted instantiation: gdevpdtw.c:pdf_end_encrypt Unexecuted instantiation: gdevpdtb.c:pdf_end_encrypt Unexecuted instantiation: gdevpdtc.c:pdf_end_encrypt Unexecuted instantiation: gdevpdte.c:pdf_end_encrypt |
1283 | | /* Initialize encryption. */ |
1284 | | int pdf_encrypt_init(const gx_device_pdf * pdev, gs_id object_id, stream_arcfour_state *psarc4); |
1285 | | |
1286 | | /* ------ Pages ------ */ |
1287 | | |
1288 | | /* Get or assign the ID for a page. */ |
1289 | | /* Returns 0 if the page number is out of range. */ |
1290 | | int64_t pdf_page_id(gx_device_pdf * pdev, int page_num); |
1291 | | |
1292 | | /* Get the page structure for the current page. */ |
1293 | | pdf_page_t *pdf_current_page(gx_device_pdf *pdev); |
1294 | | |
1295 | | /* Get the dictionary object for the current page. */ |
1296 | | cos_dict_t *pdf_current_page_dict(gx_device_pdf *pdev); |
1297 | | |
1298 | | /* Open a page for writing. */ |
1299 | | int pdf_open_page(gx_device_pdf * pdev, pdf_context_t context); |
1300 | | |
1301 | | /* Go to the unclipped stream context. */ |
1302 | | int pdf_unclip(gx_device_pdf * pdev); |
1303 | | |
1304 | | /* Write saved page- or document-level information. */ |
1305 | | int pdf_write_saved_string(gx_device_pdf * pdev, gs_string * pstr); |
1306 | | |
1307 | | /* ------ Path drawing ------ */ |
1308 | | |
1309 | | /* Store a copy of clipping path. */ |
1310 | | int pdf_remember_clip_path(gx_device_pdf * pdev, const gx_clip_path * pcpath); |
1311 | | |
1312 | | int pdf_check_soft_mask(gx_device_pdf * pdev, gs_gstate * pgs); |
1313 | | |
1314 | | /* Test whether the clip path needs updating. */ |
1315 | | bool pdf_must_put_clip_path(gx_device_pdf * pdev, const gx_clip_path * pcpath); |
1316 | | |
1317 | | /* Write and update the clip path. */ |
1318 | | int pdf_put_clip_path(gx_device_pdf * pdev, const gx_clip_path * pcpath); |
1319 | | |
1320 | | /* ------ Masked image convertion ------ */ |
1321 | | |
1322 | | typedef struct pdf_lcvd_s { |
1323 | | gx_device_memory mdev; |
1324 | | gx_device_memory *mask; |
1325 | | gx_device_pdf *pdev; |
1326 | | dev_t_proc_copy_color((*std_copy_color), gx_device); |
1327 | | dev_t_proc_copy_mono((*std_copy_mono), gx_device); |
1328 | | dev_t_proc_fill_rectangle((*std_fill_rectangle), gx_device); |
1329 | | dev_t_proc_close_device((*std_close_device), gx_device); |
1330 | | dev_t_proc_get_clipping_box((*std_get_clipping_box), gx_device); |
1331 | | dev_t_proc_transform_pixel_region((*std_transform_pixel_region), gx_device); |
1332 | | bool mask_is_empty; |
1333 | | bool path_is_empty; |
1334 | | bool mask_is_clean; |
1335 | | bool filled_trap; |
1336 | | bool write_matrix; |
1337 | | bool has_background; |
1338 | | int pass; |
1339 | | gs_matrix m; |
1340 | | gs_point path_offset; |
1341 | | } pdf_lcvd_t; |
1342 | | |
1343 | | #define public_st_pdf_lcvd_t()\ |
1344 | | gs_public_st_suffix_add2(st_pdf_lcvd_t, pdf_lcvd_t,\ |
1345 | | "pdf_lcvd_t", pdf_lcvd_t_enum_ptrs,\ |
1346 | | pdf_lcvd_t_reloc_ptrs, st_device_memory, mask, pdev) |
1347 | | #define pdf_lcvd_t_max_ptrs (gx_device_memory_max_ptrs + 2) |
1348 | | |
1349 | | int pdf_setup_masked_image_converter(gx_device_pdf *pdev, gs_memory_t *mem, const gs_matrix *m, pdf_lcvd_t **pcvd, |
1350 | | bool need_mask, int x, int y, int w, int h, bool write_on_close); |
1351 | | int pdf_dump_converted_image(gx_device_pdf *pdev, pdf_lcvd_t *cvd, int for_pattern); |
1352 | | void pdf_remove_masked_image_converter(gx_device_pdf *pdev, pdf_lcvd_t *cvd, bool need_mask); |
1353 | | |
1354 | | /* ------ Miscellaneous output ------ */ |
1355 | | |
1356 | 34.0k | #define PDF_MAX_PRODUCER 200 /* adhoc */ |
1357 | | /* Generate the default Producer string. */ |
1358 | | void pdf_store_default_Producer(char buf[PDF_MAX_PRODUCER]); |
1359 | | |
1360 | | /* Define the strings for filter names and parameters. */ |
1361 | | typedef struct pdf_filter_names_s { |
1362 | | const char *ASCII85Decode; |
1363 | | const char *ASCIIHexDecode; |
1364 | | const char *CCITTFaxDecode; |
1365 | | const char *DCTDecode; |
1366 | | const char *DecodeParms; |
1367 | | const char *Filter; |
1368 | | const char *FlateDecode; |
1369 | | const char *LZWDecode; |
1370 | | const char *RunLengthDecode; |
1371 | | const char *JBIG2Decode; |
1372 | | const char *JPXDecode; |
1373 | | const char *BrotliDecode; |
1374 | | } pdf_filter_names_t; |
1375 | | #define PDF_FILTER_NAMES\ |
1376 | 197k | "/ASCII85Decode", "/ASCIIHexDecode", "/CCITTFaxDecode",\ |
1377 | 197k | "/DCTDecode", "/DecodeParms", "/Filter", "/FlateDecode",\ |
1378 | 197k | "/LZWDecode", "/RunLengthDecode", "/JBIG2Decode", "/JPXDecode",\ |
1379 | 197k | "/BrotliDecode" |
1380 | | #define PDF_FILTER_NAMES_SHORT\ |
1381 | | "/A85", "/AHx", "/CCF", "/DCT", "/DP", "/F", "/Fl", "/LZW", "/RL", "/???", "/???", "/Br" |
1382 | | |
1383 | | /* Write matrix values. */ |
1384 | | void pdf_put_matrix(gx_device_pdf *pdev, const char *before, |
1385 | | const gs_matrix *pmat, const char *after); |
1386 | | |
1387 | | /* Write a name, with escapes for unusual characters. */ |
1388 | | typedef int (*pdf_put_name_chars_proc_t)(stream *, const byte *, uint); |
1389 | | pdf_put_name_chars_proc_t |
1390 | | pdf_put_name_chars_proc(const gx_device_pdf *pdev); |
1391 | | int pdf_put_name_chars(const gx_device_pdf *pdev, const byte *nstr, |
1392 | | uint size); |
1393 | | int pdf_put_name(const gx_device_pdf *pdev, const byte *nstr, uint size); |
1394 | | |
1395 | | /* Write a string in its shortest form ( () or <> ). */ |
1396 | | int pdf_put_string(const gx_device_pdf *pdev, const byte *str, uint size); |
1397 | | |
1398 | | /* Write a value, treating names specially. */ |
1399 | | int pdf_write_value(const gx_device_pdf *pdev, const byte *vstr, uint size, gs_id object_id); |
1400 | | |
1401 | | /* Store filters for a stream. */ |
1402 | | int pdf_put_filters(cos_dict_t *pcd, gx_device_pdf *pdev, stream *s, |
1403 | | const pdf_filter_names_t *pfn); |
1404 | | |
1405 | | /* Define a possibly encoded and compressed data stream. */ |
1406 | | typedef struct pdf_data_writer_s { |
1407 | | psdf_binary_writer binary; |
1408 | | gs_offset_t start; |
1409 | | gs_offset_t length_pos; |
1410 | | pdf_resource_t *pres; |
1411 | | gx_device_pdf *pdev; /* temporary for backward compatibility of pdf_end_data prototype. */ |
1412 | | int64_t length_id; |
1413 | | bool encrypted; |
1414 | | } pdf_data_writer_t; |
1415 | | /* |
1416 | | * Begin a data stream. The client has opened the object and written |
1417 | | * the << and any desired dictionary keys. |
1418 | | */ |
1419 | 11.8k | #define DATA_STREAM_NOT_BINARY 0 /* data are text, not binary */ |
1420 | 526k | #define DATA_STREAM_BINARY 1 /* data are binary */ |
1421 | 316k | #define DATA_STREAM_COMPRESS 2 /* OK to compress data */ |
1422 | 358k | #define DATA_STREAM_NOLENGTH 4 /* Skip the length reference and filter names writing. */ |
1423 | 188k | #define DATA_STREAM_ENCRYPT 8 /* Encrypt data. */ |
1424 | | int pdf_begin_data_stream(gx_device_pdf *pdev, pdf_data_writer_t *pdw, |
1425 | | int options, gs_id object_id); |
1426 | | int pdf_append_data_stream_filters(gx_device_pdf *pdev, pdf_data_writer_t *pdw, |
1427 | | int orig_options, gs_id object_id); |
1428 | | /* begin_data = begin_data_binary with both options = true. */ |
1429 | | int pdf_begin_data(gx_device_pdf *pdev, pdf_data_writer_t *pdw); |
1430 | | |
1431 | | /* End a data stream. */ |
1432 | | int pdf_end_data(pdf_data_writer_t *pdw); |
1433 | | |
1434 | | /* ------ Functions ------ */ |
1435 | | |
1436 | | /* Define the maximum size of a Function reference. */ |
1437 | | #define MAX_REF_CHARS ((sizeof(int64_t) * 8 + 2) / 3) |
1438 | | |
1439 | | /* |
1440 | | * Create a Function object with or without range scaling. Scaling means |
1441 | | * that if x[i] is the i'th output value from the original Function, |
1442 | | * the i'th output value from the Function object will be (x[i] - |
1443 | | * ranges[i].rmin) / (ranges[i].rmax - ranges[i].rmin). Note that this is |
1444 | | * the inverse of the scaling convention for Functions per se. |
1445 | | */ |
1446 | | int pdf_function(gx_device_pdf *pdev, const gs_function_t *pfn, |
1447 | | cos_value_t *pvalue); |
1448 | | int pdf_function_scaled(gx_device_pdf *pdev, const gs_function_t *pfn, |
1449 | | const gs_range_t *pranges, cos_value_t *pvalue); |
1450 | | |
1451 | | /* Write a Function object, returning its object ID. */ |
1452 | | int pdf_write_function(gx_device_pdf *pdev, const gs_function_t *pfn, |
1453 | | int64_t *pid); |
1454 | | |
1455 | | /* If a stitching function references an array of other functions, we need |
1456 | | * to 'unreference' those before freeing the function. otherwise we end up |
1457 | | * trying to free the referenced functions twice. |
1458 | | */ |
1459 | | int free_function_refs(gx_device_pdf *pdev, cos_object_t *pco); |
1460 | | /* ------ Fonts ------ */ |
1461 | | |
1462 | | /* Write a FontBBox dictionary element. */ |
1463 | | int pdf_write_font_bbox(gx_device_pdf *pdev, const gs_int_rect *pbox); |
1464 | | int pdf_write_font_bbox_float(gx_device_pdf *pdev, const gs_rect *pbox); |
1465 | | |
1466 | | /* ---------------- Exported by gdevpdfm.c ---------------- */ |
1467 | | |
1468 | | /* |
1469 | | * Define the type for a pdfmark-processing procedure. |
1470 | | * If nameable is false, the objname argument is always NULL. |
1471 | | */ |
1472 | | #define pdfmark_proc(proc)\ |
1473 | | int proc(gx_device_pdf *pdev, gs_param_string *pairs, uint count,\ |
1474 | | const gs_matrix *pctm, const gs_param_string *objname) |
1475 | | |
1476 | | /* Compare a C string and a gs_param_string. */ |
1477 | | bool pdf_key_eq(const gs_param_string * pcs, const char *str); |
1478 | | |
1479 | | /* Scan an integer out of a parameter string. */ |
1480 | | int pdfmark_scan_int(const gs_param_string * pstr, int *pvalue); |
1481 | | |
1482 | | /* Process a pdfmark (called from pdf_put_params). */ |
1483 | | int pdfmark_process(gx_device_pdf * pdev, const gs_param_string_array * pma); |
1484 | | |
1485 | | /* Close the current level of the outline tree. */ |
1486 | | int pdfmark_close_outline(gx_device_pdf * pdev); |
1487 | | |
1488 | | /* Close the pagelabel numtree. */ |
1489 | | int pdfmark_end_pagelabels(gx_device_pdf * pdev); |
1490 | | |
1491 | | /* Finish writing an article. */ |
1492 | | int pdfmark_write_article(gx_device_pdf * pdev, const pdf_article_t * part); |
1493 | | |
1494 | | /* ---------------- Exported by gdevpdfr.c ---------------- */ |
1495 | | |
1496 | | /* Test whether an object name has valid syntax, {name}. */ |
1497 | | bool pdf_objname_is_valid(const byte *data, uint size); |
1498 | | |
1499 | | /* |
1500 | | * Look up a named object. Return_error(gs_error_rangecheck if the syntax is invalid, |
1501 | | * gs_error_undefined if no object by that name exists. |
1502 | | */ |
1503 | | int pdf_find_named(gx_device_pdf * pdev, const gs_param_string * pname, |
1504 | | cos_object_t **ppco); |
1505 | | |
1506 | | /* |
1507 | | * Create a named object. id = -1L means do not assign an id. pname = 0 |
1508 | | * means just create the object, do not name it. |
1509 | | */ |
1510 | | int pdf_create_named(gx_device_pdf *pdev, const gs_param_string *pname, |
1511 | | cos_type_t cotype, cos_object_t **ppco, int64_t id); |
1512 | | int pdf_create_named_dict(gx_device_pdf *pdev, const gs_param_string *pname, |
1513 | | cos_dict_t **ppcd, int64_t id); |
1514 | | |
1515 | | /* |
1516 | | * Look up a named object as for pdf_find_named. If the object does not |
1517 | | * exist, create it (as a dictionary if it is one of the predefined names |
1518 | | * {ThisPage}, {NextPage}, {PrevPage}, or {Page<#>}, otherwise as a |
1519 | | * generic object) and return 1. |
1520 | | */ |
1521 | | int pdf_refer_named(gx_device_pdf *pdev, const gs_param_string *pname, |
1522 | | cos_object_t **ppco); |
1523 | | |
1524 | | /* |
1525 | | * Look up a named object as for pdf_refer_named. If the object already |
1526 | | * exists and is not simply a forward reference, return_error(gs_error_rangecheck); |
1527 | | * if it exists as a forward reference, set its type and return 0; |
1528 | | * otherwise, create the object with the given type and return 1. |
1529 | | * pname = 0 is allowed: in this case, simply create the object. |
1530 | | */ |
1531 | | int pdf_make_named(gx_device_pdf * pdev, const gs_param_string * pname, |
1532 | | cos_type_t cotype, cos_object_t **ppco, bool assign_id); |
1533 | | int pdf_make_named_dict(gx_device_pdf * pdev, const gs_param_string * pname, |
1534 | | cos_dict_t **ppcd, bool assign_id); |
1535 | | |
1536 | | /* |
1537 | | * Look up a named object as for pdf_refer_named. If the object does not |
1538 | | * exist, or is a forward reference, return gs_error_undefined; if the object |
1539 | | * exists has the wrong type, return gs_error_typecheck. |
1540 | | */ |
1541 | | int pdf_get_named(gx_device_pdf * pdev, const gs_param_string * pname, |
1542 | | cos_type_t cotype, cos_object_t **ppco); |
1543 | | |
1544 | | /* |
1545 | | * Push the current local namespace onto the namespace stack, and reset it |
1546 | | * to an empty namespace. |
1547 | | */ |
1548 | | int pdf_push_namespace(gx_device_pdf *pdev); |
1549 | | |
1550 | | /* |
1551 | | * Pop the top local namespace from the namespace stack. Return an error if |
1552 | | * the stack is empty. |
1553 | | */ |
1554 | | int pdf_pop_namespace(gx_device_pdf *pdev); |
1555 | | |
1556 | | /* |
1557 | | * Scan a string for a token. <<, >>, [, and ] are treated as tokens. |
1558 | | * Return 1 if a token was scanned, 0 if we reached the end of the string, |
1559 | | * or an error. On a successful return, the token extends from *ptoken up |
1560 | | * to but not including *pscan. |
1561 | | */ |
1562 | | int pdf_scan_token(const byte **pscan, const byte * end, const byte **ptoken); |
1563 | | |
1564 | | /* |
1565 | | * Scan a possibly composite token: arrays and dictionaries are treated as |
1566 | | * single tokens. |
1567 | | */ |
1568 | | int pdf_scan_token_composite(const byte **pscan, const byte * end, |
1569 | | const byte **ptoken); |
1570 | | |
1571 | | /* Replace object names with object references in a (parameter) string. */ |
1572 | | int pdf_replace_names(gx_device_pdf *pdev, const gs_param_string *from, |
1573 | | gs_param_string *to); |
1574 | | |
1575 | | /* ================ Text module procedures ================ */ |
1576 | | |
1577 | | /* ---------------- Exported by gdevpdfw.c ---------------- */ |
1578 | | |
1579 | | /* For gdevpdf.c */ |
1580 | | |
1581 | | int write_font_resources(gx_device_pdf *pdev, pdf_resource_list_t *prlist); |
1582 | | |
1583 | | /* ---------------- Exported by gdevpdft.c ---------------- */ |
1584 | | |
1585 | | /* For gdevpdf.c */ |
1586 | | |
1587 | | pdf_text_data_t *pdf_text_data_alloc(gs_memory_t *mem); |
1588 | | void pdf_set_text_state_default(pdf_text_state_t *pts); |
1589 | | void pdf_text_state_copy(pdf_text_state_t *pts_to, pdf_text_state_t *pts_from); |
1590 | | void pdf_reset_text_page(pdf_text_data_t *ptd); |
1591 | | void pdf_reset_text_state(pdf_text_data_t *ptd); |
1592 | | void pdf_close_text_page(gx_device_pdf *pdev); |
1593 | | |
1594 | | /* For gdevpdfb.c */ |
1595 | | |
1596 | | int pdf_char_image_y_offset(const gx_device_pdf *pdev, int x, int y, int h); |
1597 | | |
1598 | | /* Begin a CharProc for an embedded (bitmap) font. */ |
1599 | | int pdf_begin_char_proc(gx_device_pdf * pdev, int w, int h, int x_width, |
1600 | | int y_offset, int x_offset, gs_id id, pdf_char_proc_t **ppcp, |
1601 | | pdf_stream_position_t * ppos); |
1602 | | |
1603 | | /* End a CharProc. */ |
1604 | | int pdf_end_char_proc(gx_device_pdf * pdev, pdf_stream_position_t * ppos); |
1605 | | |
1606 | | /* Put out a reference to an image as a character in an embedded font. */ |
1607 | | int pdf_do_char_image(gx_device_pdf * pdev, const pdf_char_proc_t * pcp, |
1608 | | const gs_matrix * pimat); |
1609 | | |
1610 | | /* Start charproc accumulation for a Type 3 font. */ |
1611 | | int pdf_start_charproc_accum(gx_device_pdf *pdev); |
1612 | | /* Install charproc accumulator for a Type 3 font. */ |
1613 | | int pdf_set_charproc_attrs(gx_device_pdf *pdev, gs_font *font, double *pw, int narg, |
1614 | | gs_text_cache_control_t control, gs_char ch, bool scale_100); |
1615 | | /* Complete charproc accumulation for aType 3 font. */ |
1616 | | int pdf_end_charproc_accum(gx_device_pdf *pdev, gs_font *font, const pdf_char_glyph_pairs_t *cgp, |
1617 | | gs_glyph glyph, gs_char output_char_code, const gs_const_string *gnstr); |
1618 | | /* Open a stream object in the temporary file. */ |
1619 | | int pdf_open_aside(gx_device_pdf *pdev, pdf_resource_type_t rtype, |
1620 | | gs_id id, pdf_resource_t **ppres, bool reserve_object_id, int options); |
1621 | | |
1622 | | /* Close a stream object in the temporary file. */ |
1623 | | int pdf_close_aside(gx_device_pdf *pdev); |
1624 | | |
1625 | | /* Enter the substream accumulation mode. */ |
1626 | | int pdf_enter_substream(gx_device_pdf *pdev, pdf_resource_type_t rtype, |
1627 | | gs_id id, pdf_resource_t **ppres, bool reserve_object_id, bool compress); |
1628 | | |
1629 | | /* Exit the substream accumulation mode. */ |
1630 | | int pdf_exit_substream(gx_device_pdf *pdev); |
1631 | | /* Add procsets to substream Resources. */ |
1632 | | int pdf_add_procsets(cos_dict_t *pcd, pdf_procset_t procsets); |
1633 | | /* Add a resource to substream Resources. */ |
1634 | | int pdf_add_resource(gx_device_pdf *pdev, cos_dict_t *pcd, const char *key, pdf_resource_t *pres); |
1635 | | |
1636 | | /* For gdevpdfu.c */ |
1637 | | |
1638 | | int pdf_from_stream_to_text(gx_device_pdf *pdev); |
1639 | | int pdf_from_string_to_text(gx_device_pdf *pdev); |
1640 | | void pdf_close_text_contents(gx_device_pdf *pdev); |
1641 | | |
1642 | | int gdev_pdf_get_param(gx_device *dev, char *Param, void *list); |
1643 | | |
1644 | | int pdf_open_temp_file(gx_device_pdf *pdev, pdf_temp_file_t *ptf); |
1645 | | int pdf_open_temp_stream(gx_device_pdf *pdev, pdf_temp_file_t *ptf); |
1646 | | int pdf_close_temp_file(gx_device_pdf *pdev, pdf_temp_file_t *ptf, int code); |
1647 | | |
1648 | | /* exported by gdevpdfe.c */ |
1649 | | |
1650 | | int pdf_xmp_write_translated(gx_device_pdf* pdev, stream* s, const byte* data, int data_length, |
1651 | | void(*write)(stream* s, const byte* data, int data_length)); |
1652 | | |
1653 | | #endif /* gdevpdfx_INCLUDED */ |