1 /* Copyright (C) 2001-2006 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, modified
8    or distributed except as expressly authorized under the terms of that
9    license.  Refer to licensing information at http://www.artifex.com/
10    or contact Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134,
11    San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
12 */
13 
14 /* $Id: gdevpdfu.c 9987 2009-08-13 14:58:04Z ken $ */
15 /* Output utilities for PDF-writing driver */
16 #include "memory_.h"
17 #include "jpeglib_.h"		/* for sdct.h */
18 #include "gx.h"
19 #include "gserrors.h"
20 #include "gscdefs.h"
21 #include "gsdsrc.h"
22 #include "gsfunc.h"
23 #include "gsfunc3.h"
24 #include "gdevpdfx.h"
25 #include "gdevpdfo.h"
26 #include "gdevpdfg.h"
27 #include "gdevpdtd.h"
28 #include "strimpl.h"
29 #include "sa85x.h"
30 #include "scfx.h"
31 #include "sdct.h"
32 #include "slzwx.h"
33 #include "spngpx.h"
34 #include "srlx.h"
35 #include "sarc4.h"
36 #include "smd5.h"
37 #include "sstring.h"
38 #include "strmio.h"
39 #include "szlibx.h"
40 #ifdef USE_LDF_JB2
41 #include "sjbig2_luratech.h"
42 #endif
43 #ifdef USE_LWF_JP2
44 #include "sjpx_luratech.h"
45 #endif
46 
47 /* Define the size of internal stream buffers. */
48 /* (This is not a limitation, it only affects performance.) */
49 #define sbuf_size 512
50 
51 /* Optionally substitute other filters for FlateEncode for debugging. */
52 #if 1
53 #  define compression_filter_name "FlateDecode"
54 #  define compression_filter_template s_zlibE_template
55 #  define compression_filter_state stream_zlib_state
56 #else
57 #  define compression_filter_name "LZWDecode"
58 #  define compression_filter_template s_LZWE_template
59 #  define compression_filter_state stream_LZW_state
60 #endif
61 
62 /* Import procedures for writing filter parameters. */
63 extern stream_state_proc_get_params(s_DCTE_get_params, stream_DCT_state);
64 extern stream_state_proc_get_params(s_CF_get_params, stream_CF_state);
65 
66 #define CHECK(expr)\
67   BEGIN if ((code = (expr)) < 0) return code; END
68 
69 /* GC descriptors */
70 extern_st(st_pdf_color_space);
71 extern_st(st_pdf_font_resource);
72 extern_st(st_pdf_char_proc);
73 extern_st(st_pdf_font_descriptor);
74 public_st_pdf_resource();
75 private_st_pdf_x_object();
76 private_st_pdf_pattern();
77 
78 /* ---------------- Utilities ---------------- */
79 
80 /*
81  * Strip whitespace and comments from a line of PostScript code as possible.
82  * Return a pointer to any string that remains, or NULL if none.
83  * Note that this may store into the string.
84  */
85 /* This function copied from geninit.c . */
86 static char *
doit(char * line,bool intact)87 doit(char *line, bool intact)
88 {
89     char *str = line;
90     char *from;
91     char *to;
92     int in_string = 0;
93 
94     if (intact)
95 	return str;
96     while (*str == ' ' || *str == '\t')		/* strip leading whitespace */
97 	++str;
98     if (*str == 0)		/* all whitespace */
99 	return NULL;
100     if (!strncmp(str, "%END", 4))	/* keep these for .skipeof */
101 	return str;
102     if (str[0] == '%')    /* comment line */
103 	return NULL;
104     /*
105      * Copy the string over itself removing:
106      *  - All comments not within string literals;
107      *  - Whitespace adjacent to '[' ']' '{' '}';
108      *  - Whitespace before '/' '(' '<';
109      *  - Whitespace after ')' '>'.
110      */
111     for (to = from = str; (*to = *from) != 0; ++from, ++to) {
112 	switch (*from) {
113 	    case '%':
114 		if (!in_string)
115 		    break;
116 		continue;
117 	    case ' ':
118 	    case '\t':
119 		if (to > str && !in_string && strchr(" \t>[]{})", to[-1]))
120 		    --to;
121 		continue;
122 	    case '(':
123 	    case '<':
124 	    case '/':
125 	    case '[':
126 	    case ']':
127 	    case '{':
128 	    case '}':
129 		if (to > str && !in_string && strchr(" \t", to[-1]))
130 		    *--to = *from;
131                 if (*from == '(')
132                     ++in_string;
133               	continue;
134 	    case ')':
135 		--in_string;
136 		continue;
137 	    case '\\':
138 		if (from[1] == '\\' || from[1] == '(' || from[1] == ')')
139 		    *++to = *++from;
140 		continue;
141 	    default:
142 		continue;
143 	}
144 	break;
145     }
146     /* Strip trailing whitespace. */
147     while (to > str && (to[-1] == ' ' || to[-1] == '\t'))
148 	--to;
149     *to = 0;
150     return str;
151 }
152 
153 
154 static int
copy_ps_file_stripping(stream * s,const char * fname,bool HaveTrueTypes)155 copy_ps_file_stripping(stream *s, const char *fname, bool HaveTrueTypes)
156 {
157     stream *f;
158     char buf[1024], *p, *q  = buf;
159     int n, l = 0, m = sizeof(buf) - 1, outl = 0;
160     bool skipping = false;
161 
162     f = sfopen(fname, "rb", s->memory);
163     if (f == NULL)
164 	return_error(gs_error_undefinedfilename);
165     n = sfread(buf, 1, m, f);
166     buf[n] = 0;
167     do {
168 	if (*q == '\r' || *q == '\n') {
169 	    q++;
170 	    continue;
171 	}
172 	p = strchr(q, '\r');
173 	if (p == NULL)
174 	    p = strchr(q, '\n');
175 	if (p == NULL) {
176 	    if (n < m)
177 		p = buf + n;
178 	    else {
179 		strcpy(buf, q);
180 		l = strlen(buf);
181 		m = sizeof(buf) - 1 - l;
182 		if (!m) {
183 		    sfclose(f);
184 		    eprintf1("The procset %s contains a too long line.", fname);
185 		    return_error(gs_error_ioerror);
186 		}
187 		n = sfread(buf + l, 1, m, f);
188 		n += l;
189 		m += l;
190 		buf[n] = 0;
191 		q = buf;
192 		continue;
193 	    }
194 	}
195 	*p = 0;
196 	if (q[0] == '%')
197 	    l = 0;
198 	else {
199 	    q = doit(q, false);
200 	    if (q == NULL)
201 		l = 0;
202 	    else
203 		l = strlen(q);
204 	}
205 	if (l) {
206 	    if (!HaveTrueTypes && !strcmp("%%beg TrueType", q))
207 		skipping = true;
208 	    if (!skipping) {
209 		outl += l + 1;
210 		if (outl > 100) {
211 		    q[l] = '\r';
212 		    outl = 0;
213 		} else
214 		    q[l] = ' ';
215 		stream_write(s, q, l + 1);
216 	    }
217 	    if (!HaveTrueTypes && !strcmp("%%end TrueType", q))
218 		skipping = false;
219 	}
220 	q = p + 1;
221     } while (n == m || q < buf + n);
222     if (outl)
223 	stream_write(s, "\r", 1);
224     sfclose(f);
225     return 0;
226 }
227 
228 static int
copy_procsets(stream * s,const gs_param_string * path,bool HaveTrueTypes)229 copy_procsets(stream *s, const gs_param_string *path, bool HaveTrueTypes)
230 {
231     char fname[gp_file_name_sizeof];
232     const byte *p = path->data, *e = path->data + path->size;
233     int l, i = 0, code;
234     const char *tt_encs[] = {"gs_agl.ps", "gs_mgl_e.ps"};
235 
236     if (p != NULL) {
237 	for (;; i++) {
238 	    const byte *c = memchr(p, gp_file_name_list_separator, e - p);
239 	    int k = 0; /* Initializing against a compiler warning only. */
240 
241 	    if (c == NULL)
242 		c = e;
243 	    l = c - p;
244 	    if (l > 0) {
245 		if (l > sizeof(fname) - 1)
246 		    return_error(gs_error_limitcheck);
247 		memcpy(fname, p, l);
248 		fname[l] = 0;
249 		if (!HaveTrueTypes) {
250 		    for (k = count_of(tt_encs) - 1; k >= 0; k--) {
251 			int L = strlen(tt_encs[k]);
252 
253 			if (!strcmp(fname + strlen(fname) - L, tt_encs[k]))
254 			    break;
255 		    }
256 		}
257 		if (HaveTrueTypes || k < 0) {
258 		    code = copy_ps_file_stripping(s, fname, HaveTrueTypes);
259 		    if (code < 0)
260 			return code;
261 		}
262 	    }
263 	    if (c == e)
264 		break;
265 	    p = c + 1;
266 	}
267     }
268     if (!i)
269 	return_error(gs_error_undefinedfilename);
270     return 0;
271 }
272 
273 static int
encode(stream ** s,const stream_template * t,gs_memory_t * mem)274 encode(stream **s, const stream_template *t, gs_memory_t *mem)
275 {
276     stream_state *st = s_alloc_state(mem, t->stype, "pdf_open_document.encode");
277 
278     if (st == 0)
279 	return_error(gs_error_VMerror);
280     if (t->set_defaults)
281 	t->set_defaults(st);
282     if (s_add_filter(s, t, st, mem) == 0) {
283 	gs_free_object(mem, st, "pdf_open_document.encode");
284 	return_error(gs_error_VMerror);
285     }
286     return 0;
287 }
288 
289 /* ------ Document ------ */
290 
291 /* Open the document if necessary. */
292 int
pdf_open_document(gx_device_pdf * pdev)293 pdf_open_document(gx_device_pdf * pdev)
294 {
295     if (!is_in_page(pdev) && pdf_stell(pdev) == 0) {
296 	stream *s = pdev->strm;
297 	int level = (int)(pdev->CompatibilityLevel * 10 + 0.5);
298 
299 	pdev->binary_ok = !pdev->params.ASCII85EncodePages;
300 	if (pdev->ForOPDFRead && pdev->OPDFReadProcsetPath.size) {
301 	    int code, status;
302 	    char BBox[256];
303 	    int width = (int)(pdev->width * 72.0 / pdev->HWResolution[0] + 0.5);
304 	    int height = (int)(pdev->height * 72.0 / pdev->HWResolution[1] + 0.5);
305 
306 	    stream_write(s, (byte *)"%!\r", 3);
307 	    sprintf(BBox, "%%%%BoundingBox: 0 0 %d %d\r", width, height);
308 	    stream_write(s, (byte *)BBox, strlen(BBox));
309 	    if(pdev->SetPageSize)
310 		stream_puts(s, "/SetPageSize true def\n");
311 	    if(pdev->RotatePages)
312 		stream_puts(s, "/RotatePages true def\n");
313 	    if(pdev->FitPages)
314 		stream_puts(s, "/FitPages true def\n");
315 	    if(pdev->CenterPages)
316 		stream_puts(s, "/CenterPages true def\n");
317 	    if (pdev->params.CompressPages || pdev->CompressEntireFile) {
318 		/*  When CompressEntireFile is true and ASCII85EncodePages is false,
319 		    the ASCII85Encode filter is applied, rather one may expect the opposite.
320 		    Keeping it so due to no demand for this mode.
321 		    A right implementation should compute the length of the compressed procset,
322 		    write out an invocation of SubFileDecode filter, and write the length to
323 		    there assuming the output file is positionable. */
324 		stream_write(s, (byte *)"currentfile /ASCII85Decode filter /LZWDecode filter cvx exec\r", 61);
325 		code = encode(&s, &s_A85E_template, pdev->pdf_memory);
326 		if (code < 0)
327 		    return code;
328 		code = encode(&s, &s_LZWE_template, pdev->pdf_memory);
329 		if (code < 0)
330 		    return code;
331 	    }
332 	    code = copy_procsets(s, &pdev->OPDFReadProcsetPath, pdev->HaveTrueTypes);
333 	    if (code < 0)
334 		return code;
335 	    if (!pdev->CompressEntireFile) {
336 		status = s_close_filters(&s, pdev->strm);
337 		if (status < 0)
338 		    return_error(gs_error_ioerror);
339 	    } else
340 		pdev->strm = s;
341 	    pdev->OPDFRead_procset_length = stell(s);
342 	}
343 	pprintd2(s, "%%PDF-%d.%d\n", level / 10, level % 10);
344 	if (pdev->binary_ok)
345 	    stream_puts(s, "%\307\354\217\242\n");
346     }
347     /*
348      * Determine the compression method.  Currently this does nothing.
349      * It also isn't clear whether the compression method can now be
350      * changed in the course of the document.
351      *
352      * Flate compression is available starting in PDF 1.2.  Since we no
353      * longer support any older PDF versions, we ignore UseFlateCompression
354      * and always use Flate compression.
355      */
356     if (!pdev->params.CompressPages)
357 	pdev->compression = pdf_compress_none;
358     else
359 	pdev->compression = pdf_compress_Flate;
360     return 0;
361 }
362 
363 /* ------ Objects ------ */
364 
365 /* Allocate an object ID. */
366 static long
pdf_next_id(gx_device_pdf * pdev)367 pdf_next_id(gx_device_pdf * pdev)
368 {
369     return (pdev->next_id)++;
370 }
371 
372 /*
373  * Return the current position in the output.  Note that this may be in the
374  * main output file, the asides file, or the pictures file.  If the current
375  * file is the pictures file, positions returned by pdf_stell must only be
376  * used locally (for computing lengths or patching), since there is no way
377  * to map them later to the eventual position in the output file.
378  */
379 long
pdf_stell(gx_device_pdf * pdev)380 pdf_stell(gx_device_pdf * pdev)
381 {
382     stream *s = pdev->strm;
383     long pos = stell(s);
384 
385     if (s == pdev->asides.strm)
386 	pos += ASIDES_BASE_POSITION;
387     return pos;
388 }
389 
390 /* Allocate an ID for a future object. */
391 long
pdf_obj_ref(gx_device_pdf * pdev)392 pdf_obj_ref(gx_device_pdf * pdev)
393 {
394     long id = pdf_next_id(pdev);
395     long pos = pdf_stell(pdev);
396 
397     fwrite(&pos, sizeof(pos), 1, pdev->xref.file);
398     return id;
399 }
400 
401 /* Begin an object, optionally allocating an ID. */
402 long
pdf_open_obj(gx_device_pdf * pdev,long id)403 pdf_open_obj(gx_device_pdf * pdev, long id)
404 {
405     stream *s = pdev->strm;
406 
407     if (id <= 0) {
408 	id = pdf_obj_ref(pdev);
409     } else {
410 	long pos = pdf_stell(pdev);
411 	FILE *tfile = pdev->xref.file;
412 	long tpos = ftell(tfile);
413 
414 	fseek(tfile, (id - pdev->FirstObjectNumber) * sizeof(pos),
415 	      SEEK_SET);
416 	fwrite(&pos, sizeof(pos), 1, tfile);
417 	fseek(tfile, tpos, SEEK_SET);
418     }
419     pprintld1(s, "%ld 0 obj\n", id);
420     return id;
421 }
422 long
pdf_begin_obj(gx_device_pdf * pdev)423 pdf_begin_obj(gx_device_pdf * pdev)
424 {
425     return pdf_open_obj(pdev, 0L);
426 }
427 
428 /* End an object. */
429 int
pdf_end_obj(gx_device_pdf * pdev)430 pdf_end_obj(gx_device_pdf * pdev)
431 {
432     stream_puts(pdev->strm, "endobj\n");
433     return 0;
434 }
435 
436 /* ------ Page contents ------ */
437 
438 /* Handle transitions between contexts. */
439 static int
440     none_to_stream(gx_device_pdf *), stream_to_text(gx_device_pdf *),
441     string_to_text(gx_device_pdf *), text_to_stream(gx_device_pdf *),
442     stream_to_none(gx_device_pdf *);
443 typedef int (*context_proc) (gx_device_pdf *);
444 static const context_proc context_procs[4][4] =
445 {
446     {0, none_to_stream, none_to_stream, none_to_stream},
447     {stream_to_none, 0, stream_to_text, stream_to_text},
448     {text_to_stream, text_to_stream, 0, 0},
449     {string_to_text, string_to_text, string_to_text, 0}
450 };
451 
452 /* Compute an object encryption key. */
453 static int
pdf_object_key(const gx_device_pdf * pdev,gs_id object_id,byte key[16])454 pdf_object_key(const gx_device_pdf * pdev, gs_id object_id, byte key[16])
455 {
456     gs_md5_state_t md5;
457     gs_md5_byte_t zero[2] = {0, 0}, t;
458     int KeySize = pdev->KeyLength / 8;
459 
460     gs_md5_init(&md5);
461     gs_md5_append(&md5, pdev->EncryptionKey, KeySize);
462     t = (byte)(object_id >>  0);  gs_md5_append(&md5, &t, 1);
463     t = (byte)(object_id >>  8);  gs_md5_append(&md5, &t, 1);
464     t = (byte)(object_id >> 16);  gs_md5_append(&md5, &t, 1);
465     gs_md5_append(&md5, zero, 2);
466     gs_md5_finish(&md5, key);
467     return min(KeySize + 5, 16);
468 }
469 
470 /* Initialize encryption. */
471 int
pdf_encrypt_init(const gx_device_pdf * pdev,gs_id object_id,stream_arcfour_state * psarc4)472 pdf_encrypt_init(const gx_device_pdf * pdev, gs_id object_id, stream_arcfour_state *psarc4)
473 {
474     byte key[16];
475 
476     return s_arcfour_set_key(psarc4, key, pdf_object_key(pdev, object_id, key));
477 }
478 
479 
480 /* Add the encryption filter. */
481 int
pdf_begin_encrypt(gx_device_pdf * pdev,stream ** s,gs_id object_id)482 pdf_begin_encrypt(gx_device_pdf * pdev, stream **s, gs_id object_id)
483 {
484     gs_memory_t *mem = pdev->v_memory;
485     stream_arcfour_state *ss;
486     gs_md5_byte_t key[16];
487     int code, keylength;
488 
489     if (!pdev->KeyLength)
490 	return 0;
491     keylength = pdf_object_key(pdev, object_id, key);
492     ss = gs_alloc_struct(mem, stream_arcfour_state,
493 		    s_arcfour_template.stype, "psdf_encrypt");
494     if (ss == NULL)
495 	return_error(gs_error_VMerror);
496     code = s_arcfour_set_key(ss, key, keylength);
497     if (code < 0)
498 	return code;
499     if (s_add_filter(s, &s_arcfour_template, (stream_state *)ss, mem) == 0)
500 	return_error(gs_error_VMerror);
501     return 0;
502     /* IMPORTANT NOTE :
503        We don't encrypt streams written into temporary files,
504        because they can be used for comparizon
505        (for example, for merging equal images).
506        Instead that the encryption is applied in pdf_copy_data,
507        when the stream is copied to the output file.
508      */
509 }
510 
511 /* Remove the encryption filter. */
512 void
pdf_end_encrypt(gx_device_pdf * pdev)513 pdf_end_encrypt(gx_device_pdf * pdev)
514 {
515     if (pdev->KeyLength) {
516 	stream *s = pdev->strm;
517 	stream *fs = s->strm;
518 
519 	sclose(s);
520 	gs_free_object(pdev->pdf_memory, s->cbuf, "encrypt buffer");
521 	gs_free_object(pdev->pdf_memory, s, "encrypt stream");
522 	pdev->strm = fs;
523     }
524 }
525 
526 /* Enter stream context. */
527 static int
none_to_stream(gx_device_pdf * pdev)528 none_to_stream(gx_device_pdf * pdev)
529 {
530     stream *s;
531     int code;
532 
533     if (pdev->contents_id != 0)
534 	return_error(gs_error_Fatal);	/* only 1 contents per page */
535     pdev->compression_at_page_start = pdev->compression;
536     if (pdev->ResourcesBeforeUsage) {
537 	pdf_resource_t *pres;
538 
539 	code = pdf_enter_substream(pdev, resourcePage, gs_no_id, &pres,
540 		    true, pdev->params.CompressPages);
541 	if (code < 0)
542 	    return code;
543 	pdev->contents_id = pres->object->id;
544 	pdev->contents_length_id = gs_no_id; /* inapplicable */
545 	pdev->contents_pos = -1; /* inapplicable */
546 	s = pdev->strm;
547     } else {
548     	pdev->contents_id = pdf_begin_obj(pdev);
549 	pdev->contents_length_id = pdf_obj_ref(pdev);
550 	s = pdev->strm;
551 	pprintld1(s, "<</Length %ld 0 R", pdev->contents_length_id);
552 	if (pdev->compression == pdf_compress_Flate) {
553 	    if (pdev->binary_ok)
554 		pprints1(s, "/Filter /%s", compression_filter_name);
555 	    else
556 		pprints1(s, "/Filter [/ASCII85Decode /%s]", compression_filter_name);
557 	}
558 	stream_puts(s, ">>\nstream\n");
559 	pdev->contents_pos = pdf_stell(pdev);
560 	code = pdf_begin_encrypt(pdev, &s, pdev->contents_id);
561 	if (code < 0)
562 	    return code;
563 	pdev->strm = s;
564 	if (pdev->compression == pdf_compress_Flate) {	/* Set up the Flate filter. */
565 	    const stream_template *template;
566 	    stream *es;
567 	    byte *buf;
568 	    compression_filter_state *st;
569 
570 	    if (!pdev->binary_ok) {	/* Set up the A85 filter */
571 		const stream_template *template = &s_A85E_template;
572 		stream *as = s_alloc(pdev->pdf_memory, "PDF contents stream");
573 		byte *buf = gs_alloc_bytes(pdev->pdf_memory, sbuf_size,
574 					   "PDF contents buffer");
575 		stream_A85E_state *ast = gs_alloc_struct(pdev->pdf_memory, stream_A85E_state,
576 				template->stype, "PDF contents state");
577 		if (as == 0 || ast == 0 || buf == 0)
578 		    return_error(gs_error_VMerror);
579 		s_std_init(as, buf, sbuf_size, &s_filter_write_procs,
580 			   s_mode_write);
581 		ast->memory = pdev->pdf_memory;
582 		ast->template = template;
583 		as->state = (stream_state *) ast;
584 		as->procs.process = template->process;
585 		as->strm = s;
586 		(*template->init) ((stream_state *) ast);
587 		pdev->strm = s = as;
588 	    }
589 	    template = &compression_filter_template;
590 	    es = s_alloc(pdev->pdf_memory, "PDF compression stream");
591 	    buf = gs_alloc_bytes(pdev->pdf_memory, sbuf_size,
592 				       "PDF compression buffer");
593 	    st = gs_alloc_struct(pdev->pdf_memory, compression_filter_state,
594 				template->stype, "PDF compression state");
595 	    if (es == 0 || st == 0 || buf == 0)
596 		return_error(gs_error_VMerror);
597 	    s_std_init(es, buf, sbuf_size, &s_filter_write_procs,
598 		       s_mode_write);
599 	    st->memory = pdev->pdf_memory;
600 	    st->template = template;
601 	    es->state = (stream_state *) st;
602 	    es->procs.process = template->process;
603 	    es->strm = s;
604 	    (*template->set_defaults) ((stream_state *) st);
605 	    (*template->init) ((stream_state *) st);
606 	    pdev->strm = s = es;
607 	}
608     }
609     /*
610      * Scale the coordinate system.  Use an extra level of q/Q for the
611      * sake of poorly designed PDF tools that assume that the contents
612      * stream restores the CTM.
613      */
614     pprintg2(s, "q %g 0 0 %g 0 0 cm\n",
615 	     72.0 / pdev->HWResolution[0], 72.0 / pdev->HWResolution[1]);
616     if (pdev->CompatibilityLevel >= 1.3) {
617 	/* Set the default rendering intent. */
618 	if (pdev->params.DefaultRenderingIntent != ri_Default) {
619 	    static const char *const ri_names[] = { psdf_ri_names };
620 
621 	    pprints1(s, "/%s ri\n",
622 		     ri_names[(int)pdev->params.DefaultRenderingIntent]);
623 	}
624     }
625     pdev->AR4_save_bug = false;
626     return PDF_IN_STREAM;
627 }
628 /* Enter text context from stream context. */
629 static int
stream_to_text(gx_device_pdf * pdev)630 stream_to_text(gx_device_pdf * pdev)
631 {
632     int code;
633 
634     /*
635      * Bizarrely enough, Acrobat Reader cares how the final font size is
636      * obtained -- the CTM (cm), text matrix (Tm), and font size (Tf)
637      * are *not* all equivalent.  In particular, it seems to use the
638      * product of the text matrix and font size to decide how to
639      * anti-alias characters.  Therefore, we have to temporarily patch
640      * the CTM so that the scale factors are unity.  What a nuisance!
641      */
642     code = pdf_save_viewer_state(pdev, pdev->strm);
643     if (code < 0)
644 	return 0;
645     pprintg2(pdev->strm, "%g 0 0 %g 0 0 cm BT\n",
646 	     pdev->HWResolution[0] / 72.0, pdev->HWResolution[1] / 72.0);
647     pdev->procsets |= Text;
648     code = pdf_from_stream_to_text(pdev);
649     return (code < 0 ? code : PDF_IN_TEXT);
650 }
651 /* Exit string context to text context. */
652 static int
string_to_text(gx_device_pdf * pdev)653 string_to_text(gx_device_pdf * pdev)
654 {
655     int code = pdf_from_string_to_text(pdev);
656 
657     return (code < 0 ? code : PDF_IN_TEXT);
658 }
659 /* Exit text context to stream context. */
660 static int
text_to_stream(gx_device_pdf * pdev)661 text_to_stream(gx_device_pdf * pdev)
662 {
663     int code;
664 
665     stream_puts(pdev->strm, "ET\n");
666     code = pdf_restore_viewer_state(pdev, pdev->strm);
667     if (code < 0)
668 	return code;
669     pdf_reset_text(pdev);	/* because of Q */
670     return PDF_IN_STREAM;
671 }
672 /* Exit stream context. */
673 static int
stream_to_none(gx_device_pdf * pdev)674 stream_to_none(gx_device_pdf * pdev)
675 {
676     stream *s = pdev->strm;
677     long length;
678     int code;
679 
680     if (pdev->ResourcesBeforeUsage) {
681 	int code = pdf_exit_substream(pdev);
682 
683 	if (code < 0)
684 	    return code;
685     } else {
686 	if (pdev->vgstack_depth) {
687 	    code = pdf_restore_viewer_state(pdev, s);
688 	    if (code < 0)
689 		return code;
690 	}
691 	if (pdev->compression_at_page_start == pdf_compress_Flate) {	/* Terminate the filters. */
692 	    stream *fs = s->strm;
693 
694 	    if (!pdev->binary_ok) {
695 		sclose(s);	/* Terminate the ASCII85 filter. */
696 		gs_free_object(pdev->pdf_memory, s->cbuf, "A85E contents buffer");
697 		gs_free_object(pdev->pdf_memory, s, "A85E contents stream");
698 		pdev->strm = s = fs;
699 		fs = s->strm;
700 	    }
701 	    sclose(s);		/* Next terminate the compression filter */
702 	    gs_free_object(pdev->pdf_memory, s->cbuf, "zlib buffer");
703 	    gs_free_object(pdev->pdf_memory, s, "zlib stream");
704 	    pdev->strm = s = fs;
705 	}
706 	pdf_end_encrypt(pdev);
707     	s = pdev->strm;
708 	length = pdf_stell(pdev) - pdev->contents_pos;
709 	if (pdev->PDFA)
710 	    stream_puts(s, "\n");
711 	stream_puts(s, "endstream\n");
712 	pdf_end_obj(pdev);
713 	pdf_open_obj(pdev, pdev->contents_length_id);
714 	pprintld1(s, "%ld\n", length);
715 	pdf_end_obj(pdev);
716     }
717     return PDF_IN_NONE;
718 }
719 
720 /* Begin a page contents part. */
721 int
pdf_open_contents(gx_device_pdf * pdev,pdf_context_t context)722 pdf_open_contents(gx_device_pdf * pdev, pdf_context_t context)
723 {
724     int (*proc) (gx_device_pdf *);
725 
726     while ((proc = context_procs[pdev->context][context]) != 0) {
727 	int code = (*proc) (pdev);
728 
729 	if (code < 0)
730 	    return code;
731 	pdev->context = (pdf_context_t) code;
732     }
733     pdev->context = context;
734     return 0;
735 }
736 
737 /* Close the current contents part if we are in one. */
738 int
pdf_close_contents(gx_device_pdf * pdev,bool last)739 pdf_close_contents(gx_device_pdf * pdev, bool last)
740 {
741     if (pdev->context == PDF_IN_NONE)
742 	return 0;
743     if (last) {			/* Exit from the clipping path gsave. */
744 	int code = pdf_open_contents(pdev, PDF_IN_STREAM);
745 
746 	if (code < 0)
747 	    return code;
748 	stream_puts(pdev->strm, "Q\n");	/* See none_to_stream. */
749 	pdf_close_text_contents(pdev);
750     }
751     return pdf_open_contents(pdev, PDF_IN_NONE);
752 }
753 
754 /* ------ Resources et al ------ */
755 
756 /* Define the allocator descriptors for the resource types. */
757 const char *const pdf_resource_type_names[] = {
758     PDF_RESOURCE_TYPE_NAMES
759 };
760 const gs_memory_struct_type_t *const pdf_resource_type_structs[] = {
761     PDF_RESOURCE_TYPE_STRUCTS
762 };
763 
764 /* Cancel a resource (do not write it into PDF). */
765 int
pdf_cancel_resource(gx_device_pdf * pdev,pdf_resource_t * pres,pdf_resource_type_t rtype)766 pdf_cancel_resource(gx_device_pdf * pdev, pdf_resource_t *pres, pdf_resource_type_t rtype)
767 {
768     /* fixme : remove *pres from resource chain. */
769     pres->where_used = 0;
770     pres->object->written = true;
771     if (rtype == resourceXObject || rtype == resourceCharProc || rtype == resourceOther
772 	) {
773 	int code = cos_stream_release_pieces((cos_stream_t *)pres->object);
774 
775 	if (code < 0)
776 	    return code;
777     }
778     cos_release(pres->object, "pdf_cancel_resource");
779     return 0;
780 }
781 
782 /* Remove a resource. */
783 void
pdf_forget_resource(gx_device_pdf * pdev,pdf_resource_t * pres1,pdf_resource_type_t rtype)784 pdf_forget_resource(gx_device_pdf * pdev, pdf_resource_t *pres1, pdf_resource_type_t rtype)
785 {   /* fixme : optimize. */
786     pdf_resource_t **pchain = pdev->resources[rtype].chains;
787     pdf_resource_t *pres;
788     pdf_resource_t **pprev = &pdev->last_resource;
789     int i;
790 
791     for (; (pres = *pprev) != 0; pprev = &pres->prev)
792 	if (pres == pres1) {
793 	    *pprev = pres->prev;
794 	    break;
795 	}
796     for (i = 0; i < NUM_RESOURCE_CHAINS; i++) {
797 	pprev = pchain + i;
798 	for (; (pres = *pprev) != 0; pprev = &pres->next)
799 	    if (pres == pres1) {
800 		*pprev = pres->next;
801 		COS_RELEASE(pres->object, "pdf_forget_resource");
802 		gs_free_object(pdev->pdf_memory, pres->object, "pdf_forget_resource");
803 		gs_free_object(pdev->pdf_memory, pres, "pdf_forget_resource");
804 		break;
805 	    }
806     }
807 }
808 
809 static int
nocheck(gx_device_pdf * pdev,pdf_resource_t * pres0,pdf_resource_t * pres1)810 nocheck(gx_device_pdf * pdev, pdf_resource_t *pres0, pdf_resource_t *pres1)
811 {
812     return 1;
813 }
814 
815 
816 /* Substitute a resource with a same one. */
817 int
pdf_substitute_resource(gx_device_pdf * pdev,pdf_resource_t ** ppres,pdf_resource_type_t rtype,int (* eq)(gx_device_pdf * pdev,pdf_resource_t * pres0,pdf_resource_t * pres1),bool write)818 pdf_substitute_resource(gx_device_pdf *pdev, pdf_resource_t **ppres,
819 	pdf_resource_type_t rtype,
820 	int (*eq)(gx_device_pdf * pdev, pdf_resource_t *pres0, pdf_resource_t *pres1),
821 	bool write)
822 {
823     pdf_resource_t *pres1 = *ppres;
824     int code;
825 
826     code = pdf_find_same_resource(pdev, rtype, ppres, (eq ? eq : nocheck));
827     if (code < 0)
828 	return code;
829     if (code != 0) {
830 	code = pdf_cancel_resource(pdev, (pdf_resource_t *)pres1, rtype);
831 	if (code < 0)
832 	    return code;
833 	pdf_forget_resource(pdev, pres1, rtype);
834 	return 0;
835     } else {
836 	pdf_reserve_object_id(pdev, pres1, gs_no_id);
837 	if (write) {
838 	    code = cos_write_object(pres1->object, pdev);
839 	    if (code < 0)
840 		return code;
841 	    pres1->object->written = 1;
842 	}
843 	return 1;
844     }
845 }
846 
847 /* Find a resource of a given type by gs_id. */
848 pdf_resource_t *
pdf_find_resource_by_gs_id(gx_device_pdf * pdev,pdf_resource_type_t rtype,gs_id rid)849 pdf_find_resource_by_gs_id(gx_device_pdf * pdev, pdf_resource_type_t rtype,
850 			   gs_id rid)
851 {
852     pdf_resource_t **pchain = PDF_RESOURCE_CHAIN(pdev, rtype, rid);
853     pdf_resource_t **pprev = pchain;
854     pdf_resource_t *pres;
855 
856     for (; (pres = *pprev) != 0; pprev = &pres->next)
857 	if (pres->rid == rid) {
858 	    if (pprev != pchain) {
859 		*pprev = pres->next;
860 		pres->next = *pchain;
861 		*pchain = pres;
862 	    }
863 	    return pres;
864 	}
865     return 0;
866 }
867 
868 /* Find resource by resource id. */
869 pdf_resource_t *
pdf_find_resource_by_resource_id(gx_device_pdf * pdev,pdf_resource_type_t rtype,gs_id id)870 pdf_find_resource_by_resource_id(gx_device_pdf * pdev, pdf_resource_type_t rtype, gs_id id)
871 {
872     pdf_resource_t **pchain = pdev->resources[rtype].chains;
873     pdf_resource_t *pres;
874     int i;
875 
876     for (i = 0; i < NUM_RESOURCE_CHAINS; i++) {
877 	for (pres = pchain[i]; pres != 0; pres = pres->next) {
878 	    if (pres->object->id == id)
879 		return pres;
880 	}
881     }
882     return 0;
883 }
884 
885 
886 /* Find same resource. */
887 int
pdf_find_same_resource(gx_device_pdf * pdev,pdf_resource_type_t rtype,pdf_resource_t ** ppres,int (* eq)(gx_device_pdf * pdev,pdf_resource_t * pres0,pdf_resource_t * pres1))888 pdf_find_same_resource(gx_device_pdf * pdev, pdf_resource_type_t rtype, pdf_resource_t **ppres,
889 	int (*eq)(gx_device_pdf * pdev, pdf_resource_t *pres0, pdf_resource_t *pres1))
890 {
891     pdf_resource_t **pchain = pdev->resources[rtype].chains;
892     pdf_resource_t *pres;
893     cos_object_t *pco0 = (*ppres)->object;
894     int i;
895 
896     for (i = 0; i < NUM_RESOURCE_CHAINS; i++) {
897 	for (pres = pchain[i]; pres != 0; pres = pres->next) {
898 	    if (*ppres != pres) {
899 		int code;
900 		cos_object_t *pco1 = pres->object;
901 
902 		if (cos_type(pco0) != cos_type(pco1))
903 		    continue;	    /* don't compare different types */
904 		code = pco0->cos_procs->equal(pco0, pco1, pdev);
905 		if (code < 0)
906 		    return code;
907 		if (code > 0) {
908 		    code = eq(pdev, *ppres, pres);
909 		    if (code < 0)
910 			return code;
911 		    if (code > 0) {
912 			*ppres = pres;
913 			return 1;
914 		    }
915 		}
916 	    }
917 	}
918     }
919     return 0;
920 }
921 
922 /* Drop resources by a condition. */
923 void
pdf_drop_resources(gx_device_pdf * pdev,pdf_resource_type_t rtype,int (* cond)(gx_device_pdf * pdev,pdf_resource_t * pres))924 pdf_drop_resources(gx_device_pdf * pdev, pdf_resource_type_t rtype,
925 	int (*cond)(gx_device_pdf * pdev, pdf_resource_t *pres))
926 {
927     pdf_resource_t **pchain = pdev->resources[rtype].chains;
928     pdf_resource_t **pprev;
929     pdf_resource_t *pres;
930     int i;
931 
932     for (i = 0; i < NUM_RESOURCE_CHAINS; i++) {
933 	pprev = pchain + i;
934 	for (; (pres = *pprev) != 0; ) {
935 	    if (cond(pdev, pres)) {
936 		*pprev = pres->next;
937 		pres->next = pres; /* A temporary mark - see below */
938 	    } else
939 		pprev = &pres->next;
940 	}
941     }
942     pprev = &pdev->last_resource;
943     for (; (pres = *pprev) != 0; )
944 	if (pres->next == pres) {
945 	    *pprev = pres->prev;
946 	    COS_RELEASE(pres->object, "pdf_drop_resources");
947 	    gs_free_object(pdev->pdf_memory, pres->object, "pdf_drop_resources");
948 	    gs_free_object(pdev->pdf_memory, pres, "pdf_drop_resources");
949 	} else
950 	    pprev = &pres->prev;
951 }
952 
953 /* Print resource statistics. */
954 void
pdf_print_resource_statistics(gx_device_pdf * pdev)955 pdf_print_resource_statistics(gx_device_pdf * pdev)
956 {
957 
958     int rtype;
959 
960     for (rtype = 0; rtype < NUM_RESOURCE_TYPES; rtype++) {
961 	pdf_resource_t **pchain = pdev->resources[rtype].chains;
962 	pdf_resource_t *pres;
963 	const char *name = pdf_resource_type_names[rtype];
964 	int i, n = 0;
965 
966 	for (i = 0; i < NUM_RESOURCE_CHAINS; i++) {
967 	    for (pres = pchain[i]; pres != 0; pres = pres->next, n++);
968 	}
969 	dprintf3("Resource type %d (%s) has %d instances.\n", rtype,
970 		(name ? name : ""), n);
971     }
972 }
973 
974 
975 /* Begin an object logically separate from the contents. */
976 long
pdf_open_separate(gx_device_pdf * pdev,long id)977 pdf_open_separate(gx_device_pdf * pdev, long id)
978 {
979     int code;
980     code = pdf_open_document(pdev);
981     if (code < 0)
982 	return code;
983     pdev->asides.save_strm = pdev->strm;
984     pdev->strm = pdev->asides.strm;
985     return pdf_open_obj(pdev, id);
986 }
987 long
pdf_begin_separate(gx_device_pdf * pdev)988 pdf_begin_separate(gx_device_pdf * pdev)
989 {
990     return pdf_open_separate(pdev, 0L);
991 }
992 
993 void
pdf_reserve_object_id(gx_device_pdf * pdev,pdf_resource_t * pres,long id)994 pdf_reserve_object_id(gx_device_pdf * pdev, pdf_resource_t *pres, long id)
995 {
996     pres->object->id = (id == 0 ? pdf_obj_ref(pdev) : id);
997     sprintf(pres->rname, "R%ld", pres->object->id);
998 }
999 
1000 /* Begin an aside (resource, annotation, ...). */
1001 int
pdf_alloc_aside(gx_device_pdf * pdev,pdf_resource_t ** plist,const gs_memory_struct_type_t * pst,pdf_resource_t ** ppres,long id)1002 pdf_alloc_aside(gx_device_pdf * pdev, pdf_resource_t ** plist,
1003 		const gs_memory_struct_type_t * pst, pdf_resource_t **ppres,
1004 		long id)
1005 {
1006     pdf_resource_t *pres;
1007     cos_object_t *object;
1008 
1009     if (pst == NULL)
1010 	pst = &st_pdf_resource;
1011     pres = gs_alloc_struct(pdev->pdf_memory, pdf_resource_t, pst,
1012 			   "pdf_alloc_aside(resource)");
1013     if (pres == 0)
1014 	return_error(gs_error_VMerror);
1015     object = cos_object_alloc(pdev, "pdf_alloc_aside(object)");
1016     if (object == 0)
1017 	return_error(gs_error_VMerror);
1018     memset(pres + 1, 0, pst->ssize - sizeof(*pres));
1019     pres->object = object;
1020     if (id < 0) {
1021 	object->id = -1L;
1022 	pres->rname[0] = 0;
1023     } else
1024 	pdf_reserve_object_id(pdev, pres, id);
1025     pres->next = *plist;
1026     pres->rid = 0;
1027     *plist = pres;
1028     pres->prev = pdev->last_resource;
1029     pdev->last_resource = pres;
1030     pres->named = false;
1031     pres->global = false;
1032     pres->where_used = pdev->used_mask;
1033     *ppres = pres;
1034     return 0;
1035 }
1036 int
pdf_begin_aside(gx_device_pdf * pdev,pdf_resource_t ** plist,const gs_memory_struct_type_t * pst,pdf_resource_t ** ppres)1037 pdf_begin_aside(gx_device_pdf * pdev, pdf_resource_t ** plist,
1038 		const gs_memory_struct_type_t * pst, pdf_resource_t ** ppres)
1039 {
1040     long id = pdf_begin_separate(pdev);
1041 
1042     if (id < 0)
1043 	return (int)id;
1044     return pdf_alloc_aside(pdev, plist, pst, ppres, id);
1045 }
1046 
1047 /* Begin a resource of a given type. */
1048 int
pdf_begin_resource_body(gx_device_pdf * pdev,pdf_resource_type_t rtype,gs_id rid,pdf_resource_t ** ppres)1049 pdf_begin_resource_body(gx_device_pdf * pdev, pdf_resource_type_t rtype,
1050 			gs_id rid, pdf_resource_t ** ppres)
1051 {
1052     int code = pdf_begin_aside(pdev, PDF_RESOURCE_CHAIN(pdev, rtype, rid),
1053 			       pdf_resource_type_structs[rtype], ppres);
1054 
1055     if (code >= 0)
1056 	(*ppres)->rid = rid;
1057     return code;
1058 }
1059 int
pdf_begin_resource(gx_device_pdf * pdev,pdf_resource_type_t rtype,gs_id rid,pdf_resource_t ** ppres)1060 pdf_begin_resource(gx_device_pdf * pdev, pdf_resource_type_t rtype, gs_id rid,
1061 		   pdf_resource_t ** ppres)
1062 {
1063     int code = pdf_begin_resource_body(pdev, rtype, rid, ppres);
1064 
1065     if (code >= 0 && pdf_resource_type_names[rtype] != 0) {
1066 	stream *s = pdev->strm;
1067 
1068 	pprints1(s, "<</Type%s", pdf_resource_type_names[rtype]);
1069 	pprintld1(s, "/Name/R%ld", (*ppres)->object->id);
1070     }
1071     return code;
1072 }
1073 
1074 /* Allocate a resource, but don't open the stream. */
1075 int
pdf_alloc_resource(gx_device_pdf * pdev,pdf_resource_type_t rtype,gs_id rid,pdf_resource_t ** ppres,long id)1076 pdf_alloc_resource(gx_device_pdf * pdev, pdf_resource_type_t rtype, gs_id rid,
1077 		   pdf_resource_t ** ppres, long id)
1078 {
1079     int code = pdf_alloc_aside(pdev, PDF_RESOURCE_CHAIN(pdev, rtype, rid),
1080 			       pdf_resource_type_structs[rtype], ppres, id);
1081 
1082     if (code >= 0)
1083 	(*ppres)->rid = rid;
1084     return code;
1085 }
1086 
1087 /* Get the object id of a resource. */
1088 long
pdf_resource_id(const pdf_resource_t * pres)1089 pdf_resource_id(const pdf_resource_t *pres)
1090 {
1091     return pres->object->id;
1092 }
1093 
1094 /* End an aside or other separate object. */
1095 int
pdf_end_separate(gx_device_pdf * pdev)1096 pdf_end_separate(gx_device_pdf * pdev)
1097 {
1098     int code = pdf_end_obj(pdev);
1099 
1100     pdev->strm = pdev->asides.save_strm;
1101     pdev->asides.save_strm = 0;
1102     return code;
1103 }
1104 int
pdf_end_aside(gx_device_pdf * pdev)1105 pdf_end_aside(gx_device_pdf * pdev)
1106 {
1107     return pdf_end_separate(pdev);
1108 }
1109 
1110 /* End a resource. */
1111 int
pdf_end_resource(gx_device_pdf * pdev)1112 pdf_end_resource(gx_device_pdf * pdev)
1113 {
1114     return pdf_end_aside(pdev);
1115 }
1116 
1117 /*
1118  * Write the Cos objects for resources local to a content stream.  Formerly,
1119  * this procedure also freed such objects, but this doesn't work, because
1120  * resources of one type might refer to resources of another type.
1121  */
1122 int
pdf_write_resource_objects(gx_device_pdf * pdev,pdf_resource_type_t rtype)1123 pdf_write_resource_objects(gx_device_pdf *pdev, pdf_resource_type_t rtype)
1124 {
1125     int j, code = 0;
1126 
1127     for (j = 0; j < NUM_RESOURCE_CHAINS && code >= 0; ++j) {
1128 	pdf_resource_t *pres = pdev->resources[rtype].chains[j];
1129 
1130 	for (; pres != 0; pres = pres->next)
1131 	    if ((!pres->named || pdev->ForOPDFRead)
1132 		&& !pres->object->written)
1133 		code = cos_write_object(pres->object, pdev);
1134 
1135     }
1136     return code;
1137 }
1138 
1139 /*
1140  * Reverse resource chains.
1141  * ps2write uses it with page resources.
1142  * Assuming only the 0th chain contauns something.
1143  */
1144 void
pdf_reverse_resource_chain(gx_device_pdf * pdev,pdf_resource_type_t rtype)1145 pdf_reverse_resource_chain(gx_device_pdf *pdev, pdf_resource_type_t rtype)
1146 {
1147     pdf_resource_t *pres = pdev->resources[rtype].chains[0];
1148     pdf_resource_t *pres1, *pres0 = pres, *pres2;
1149 
1150     if (pres == NULL)
1151 	return;
1152     pres1 = pres->next;
1153     for (;;) {
1154 	if (pres1 == NULL)
1155 	    break;
1156 	pres2 = pres1->next;
1157 	pres1->next = pres;
1158 	pres = pres1;
1159 	pres1 = pres2;
1160     }
1161     pres0->next = NULL;
1162     pdev->resources[rtype].chains[0] = pres;
1163 }
1164 
1165 
1166 /*
1167  * Free unnamed Cos objects for resources local to a content stream,
1168  * since they can't be used again.
1169  */
1170 int
pdf_free_resource_objects(gx_device_pdf * pdev,pdf_resource_type_t rtype)1171 pdf_free_resource_objects(gx_device_pdf *pdev, pdf_resource_type_t rtype)
1172 {
1173     int j;
1174 
1175     for (j = 0; j < NUM_RESOURCE_CHAINS; ++j) {
1176 	pdf_resource_t **prev = &pdev->resources[rtype].chains[j];
1177 	pdf_resource_t *pres;
1178 
1179 	while ((pres = *prev) != 0) {
1180 	    if (pres->named) {	/* named, don't free */
1181 		prev = &pres->next;
1182 	    } else {
1183 		cos_free(pres->object, "pdf_free_resource_objects");
1184 		pres->object = 0;
1185 		*prev = pres->next;
1186 	    }
1187 	}
1188     }
1189     return 0;
1190 }
1191 
1192 /* Write and free all resource objects. */
1193 
1194 int
pdf_write_and_free_all_resource_objects(gx_device_pdf * pdev)1195 pdf_write_and_free_all_resource_objects(gx_device_pdf *pdev)
1196 {
1197     int i, code = 0, code1;
1198 
1199     for (i = 0; i < NUM_RESOURCE_TYPES; ++i) {
1200 	code1 = pdf_write_resource_objects(pdev, i);
1201 	if (code >= 0)
1202 	    code = code1;
1203     }
1204     code1 = pdf_finish_resources(pdev, resourceFontDescriptor,
1205 			pdf_release_FontDescriptor_components);
1206     if (code >= 0)
1207 	code = code1;
1208     for (i = 0; i < NUM_RESOURCE_TYPES; ++i) {
1209 	code1 = pdf_free_resource_objects(pdev, i);
1210 	if (code >= 0)
1211 	    code = code1;
1212     }
1213     return code;
1214 }
1215 
1216 /*
1217  * Store the resource sets for a content stream (page or XObject).
1218  * Sets page->{procsets, resource_ids[]}.
1219  */
1220 int
pdf_store_page_resources(gx_device_pdf * pdev,pdf_page_t * page,bool clear_usage)1221 pdf_store_page_resources(gx_device_pdf *pdev, pdf_page_t *page, bool clear_usage)
1222 {
1223     int i;
1224 
1225     /* Write any resource dictionaries. */
1226 
1227     for (i = 0; i <= resourceFont; ++i) {
1228 	stream *s = 0;
1229 	int j;
1230 
1231 	if (i == resourceOther)
1232 	    continue;
1233 	page->resource_ids[i] = 0;
1234 	for (j = 0; j < NUM_RESOURCE_CHAINS; ++j) {
1235 	    pdf_resource_t *pres = pdev->resources[i].chains[j];
1236 
1237 	    for (; pres != 0; pres = pres->next) {
1238 		if (pres->where_used & pdev->used_mask) {
1239 		    long id = pdf_resource_id(pres);
1240 
1241 		    if (id == -1L)
1242 			continue;
1243 		    if (s == 0) {
1244 			page->resource_ids[i] = pdf_begin_separate(pdev);
1245 			s = pdev->strm;
1246 			stream_puts(s, "<<");
1247 		    }
1248 		    pprints1(s, "/%s\n", pres->rname);
1249 		    pprintld1(s, "%ld 0 R", id);
1250 		    if (clear_usage)
1251 			pres->where_used -= pdev->used_mask;
1252 		}
1253 	    }
1254 	}
1255 	if (s) {
1256 	    stream_puts(s, ">>\n");
1257 	    pdf_end_separate(pdev);
1258 	    if (i != resourceFont)
1259 		pdf_write_resource_objects(pdev, i);
1260 	}
1261     }
1262     page->procsets = pdev->procsets;
1263     return 0;
1264 }
1265 
1266 /* Copy data from a temporary file to a stream. */
1267 void
pdf_copy_data(stream * s,FILE * file,long count,stream_arcfour_state * ss)1268 pdf_copy_data(stream *s, FILE *file, long count, stream_arcfour_state *ss)
1269 {
1270     long left = count;
1271     byte buf[sbuf_size];
1272 
1273     while (left > 0) {
1274 	uint copy = min(left, sbuf_size);
1275 
1276 	fread(buf, 1, copy, file);
1277 	if (ss)
1278 	    s_arcfour_process_buffer(ss, buf, copy);
1279 	stream_write(s, buf, copy);
1280 	left -= copy;
1281     }
1282 }
1283 
1284 
1285 /* Copy data from a temporary file to a stream,
1286    which may be targetted to the same file. */
1287 void
pdf_copy_data_safe(stream * s,FILE * file,long position,long count)1288 pdf_copy_data_safe(stream *s, FILE *file, long position, long count)
1289 {
1290     long left = count;
1291 
1292     while (left > 0) {
1293 	byte buf[sbuf_size];
1294 	long copy = min(left, (long)sbuf_size);
1295 	long end_pos = ftell(file);
1296 
1297 	fseek(file, position + count - left, SEEK_SET);
1298 	fread(buf, 1, copy, file);
1299 	fseek(file, end_pos, SEEK_SET);
1300 	stream_write(s, buf, copy);
1301 	sflush(s);
1302 	left -= copy;
1303     }
1304 }
1305 
1306 /* ------ Pages ------ */
1307 
1308 /* Get or assign the ID for a page. */
1309 /* Returns 0 if the page number is out of range. */
1310 long
pdf_page_id(gx_device_pdf * pdev,int page_num)1311 pdf_page_id(gx_device_pdf * pdev, int page_num)
1312 {
1313     cos_dict_t *Page;
1314 
1315     if (page_num < 1)
1316 	return 0;
1317     if (page_num >= pdev->num_pages) {	/* Grow the pages array. */
1318 	uint new_num_pages =
1319 	    max(page_num + 10, pdev->num_pages << 1);
1320 	pdf_page_t *new_pages =
1321 	    gs_resize_object(pdev->pdf_memory, pdev->pages, new_num_pages,
1322 			     "pdf_page_id(resize pages)");
1323 
1324 	if (new_pages == 0)
1325 	    return 0;
1326 	memset(&new_pages[pdev->num_pages], 0,
1327 	       (new_num_pages - pdev->num_pages) * sizeof(pdf_page_t));
1328 	pdev->pages = new_pages;
1329 	pdev->num_pages = new_num_pages;
1330     }
1331     if ((Page = pdev->pages[page_num - 1].Page) == 0) {
1332 	pdev->pages[page_num - 1].Page = Page =
1333 	    cos_dict_alloc(pdev, "pdf_page_id");
1334 	Page->id = pdf_obj_ref(pdev);
1335     }
1336     return Page->id;
1337 }
1338 
1339 /* Get the page structure for the current page. */
1340 pdf_page_t *
pdf_current_page(gx_device_pdf * pdev)1341 pdf_current_page(gx_device_pdf *pdev)
1342 {
1343     return &pdev->pages[pdev->next_page];
1344 }
1345 
1346 /* Get the dictionary object for the current page. */
1347 cos_dict_t *
pdf_current_page_dict(gx_device_pdf * pdev)1348 pdf_current_page_dict(gx_device_pdf *pdev)
1349 {
1350     if (pdf_page_id(pdev, pdev->next_page + 1) <= 0)
1351 	return 0;
1352     return pdev->pages[pdev->next_page].Page;
1353 }
1354 
1355 /* Write saved page- or document-level information. */
1356 int
pdf_write_saved_string(gx_device_pdf * pdev,gs_string * pstr)1357 pdf_write_saved_string(gx_device_pdf * pdev, gs_string * pstr)
1358 {
1359     if (pstr->data != 0) {
1360 	stream_write(pdev->strm, pstr->data, pstr->size);
1361 	gs_free_string(pdev->pdf_memory, pstr->data, pstr->size,
1362 		       "pdf_write_saved_string");
1363 	pstr->data = 0;
1364     }
1365     return 0;
1366 }
1367 
1368 /* Open a page for writing. */
1369 int
pdf_open_page(gx_device_pdf * pdev,pdf_context_t context)1370 pdf_open_page(gx_device_pdf * pdev, pdf_context_t context)
1371 {
1372     if (!is_in_page(pdev)) {
1373 	int code;
1374 
1375 	if (pdf_page_id(pdev, pdev->next_page + 1) == 0)
1376 	    return_error(gs_error_VMerror);
1377 	code = pdf_open_document(pdev);
1378 	if (code < 0)
1379 	    return code;
1380     }
1381     /* Note that context may be PDF_IN_NONE here. */
1382     return pdf_open_contents(pdev, context);
1383 }
1384 
1385 
1386 /*  Go to the unclipped stream context. */
1387 int
pdf_unclip(gx_device_pdf * pdev)1388 pdf_unclip(gx_device_pdf * pdev)
1389 {
1390     const int bottom = (pdev->ResourcesBeforeUsage ? 1 : 0);
1391     /* When ResourcesBeforeUsage != 0, one sbstack element
1392        appears from the page contents stream. */
1393 
1394     if (pdev->sbstack_depth <= bottom) {
1395 	int code = pdf_open_page(pdev, PDF_IN_STREAM);
1396 
1397 	if (code < 0)
1398 	    return code;
1399     }
1400     if (pdev->context > PDF_IN_STREAM) {
1401 	int code = pdf_open_contents(pdev, PDF_IN_STREAM);
1402 
1403 	if (code < 0)
1404 	    return code;
1405     }
1406     if (pdev->vgstack_depth > pdev->vgstack_bottom) {
1407 	int code = pdf_restore_viewer_state(pdev, pdev->strm);
1408 
1409 	if (code < 0)
1410 	    return code;
1411 	code = pdf_remember_clip_path(pdev, NULL);
1412 	if (code < 0)
1413 	    return code;
1414 	pdev->clip_path_id = pdev->no_clip_path_id;
1415     }
1416     return 0;
1417 }
1418 
1419 
1420 /* ------ Miscellaneous output ------ */
1421 
1422 /* Generate the default Producer string. */
1423 void
pdf_store_default_Producer(char buf[PDF_MAX_PRODUCER])1424 pdf_store_default_Producer(char buf[PDF_MAX_PRODUCER])
1425 {
1426     if ((gs_revision % 100) == 0)
1427 	sprintf(buf, "(%s %1.1f)", gs_product, gs_revision / 100.0);
1428     else
1429 	sprintf(buf, "(%s %1.2f)", gs_product, gs_revision / 100.0);
1430 }
1431 
1432 /* Write matrix values. */
1433 void
pdf_put_matrix(gx_device_pdf * pdev,const char * before,const gs_matrix * pmat,const char * after)1434 pdf_put_matrix(gx_device_pdf * pdev, const char *before,
1435 	       const gs_matrix * pmat, const char *after)
1436 {
1437     stream *s = pdev->strm;
1438 
1439     if (before)
1440 	stream_puts(s, before);
1441     pprintg6(s, "%g %g %g %g %g %g ",
1442 	     pmat->xx, pmat->xy, pmat->yx, pmat->yy, pmat->tx, pmat->ty);
1443     if (after)
1444 	stream_puts(s, after);
1445 }
1446 
1447 /*
1448  * Write a name, with escapes for unusual characters.  Since we only support
1449  * PDF 1.2 and above, we can use an escape sequence for anything except a
1450  * null <00>, and the machinery for selecting the put_name_chars procedure
1451  * depending on CompatibilityLevel is no longer needed.
1452  */
1453 static int
pdf_put_name_chars_1_2(stream * s,const byte * nstr,uint size)1454 pdf_put_name_chars_1_2(stream *s, const byte *nstr, uint size)
1455 {
1456     uint i;
1457 
1458     for (i = 0; i < size; ++i) {
1459 	uint c = nstr[i];
1460 	char hex[4];
1461 
1462 	switch (c) {
1463 	    default:
1464 		if (c >= 0x21 && c <= 0x7e) {
1465 		    stream_putc(s, (byte)c);
1466 		    break;
1467 		}
1468 		/* falls through */
1469 	    case '#':
1470 	    case '%':
1471 	    case '(': case ')':
1472 	    case '<': case '>':
1473 	    case '[': case ']':
1474 	    case '{': case '}':
1475 	    case '/':
1476 		sprintf(hex, "#%02x", c);
1477 		stream_puts(s, hex);
1478 		break;
1479 	    case 0:
1480 		stream_puts(s, "BnZr"); /* arbitrary */
1481 	}
1482     }
1483     return 0;
1484 }
1485 pdf_put_name_chars_proc_t
pdf_put_name_chars_proc(const gx_device_pdf * pdev)1486 pdf_put_name_chars_proc(const gx_device_pdf *pdev)
1487 {
1488     return &pdf_put_name_chars_1_2;
1489 }
1490 int
pdf_put_name_chars(const gx_device_pdf * pdev,const byte * nstr,uint size)1491 pdf_put_name_chars(const gx_device_pdf *pdev, const byte *nstr, uint size)
1492 {
1493     return pdf_put_name_chars_proc(pdev)(pdev->strm, nstr, size);
1494 }
1495 int
pdf_put_name(const gx_device_pdf * pdev,const byte * nstr,uint size)1496 pdf_put_name(const gx_device_pdf *pdev, const byte *nstr, uint size)
1497 {
1498     stream_putc(pdev->strm, '/');
1499     return pdf_put_name_chars(pdev, nstr, size);
1500 }
1501 
1502 /* Write an encoded string with encryption. */
1503 static int
pdf_encrypt_encoded_string(const gx_device_pdf * pdev,const byte * str,uint size,gs_id object_id)1504 pdf_encrypt_encoded_string(const gx_device_pdf *pdev, const byte *str, uint size, gs_id object_id)
1505 {
1506     stream sinp, sstr, sout;
1507     stream_PSSD_state st;
1508     stream_state so;
1509     byte buf[100], bufo[100];
1510     stream_arcfour_state sarc4;
1511 
1512     if (pdf_encrypt_init(pdev, object_id, &sarc4) < 0) {
1513 	/* The interface can't pass an error. */
1514 	stream_write(pdev->strm, str, size);
1515 	return size;
1516     }
1517     s_init(&sinp, NULL);
1518     sread_string(&sinp, str + 1, size);
1519     s_init(&sstr, NULL);
1520     sstr.close_at_eod = false;
1521     s_init_state((stream_state *)&st, &s_PSSD_template, NULL);
1522     s_init_filter(&sstr, (stream_state *)&st, buf, sizeof(buf), &sinp);
1523     s_init(&sout, NULL);
1524     s_init_state(&so, &s_PSSE_template, NULL);
1525     s_init_filter(&sout, &so, bufo, sizeof(bufo), pdev->strm);
1526     stream_putc(pdev->strm, '(');
1527     for (;;) {
1528 	uint n;
1529 	int code = sgets(&sstr, buf, sizeof(buf), &n);
1530 
1531 	if (n > 0) {
1532 	    s_arcfour_process_buffer(&sarc4, buf, n);
1533 	    stream_write(&sout, buf, n);
1534 	}
1535 	if (code == EOFC)
1536 	    break;
1537 	if (code < 0 || n < sizeof(buf)) {
1538 	    /* The interface can't pass an error. */
1539 	    break;
1540 	}
1541     }
1542     sclose(&sout); /* Writes ')'. */
1543     return stell(&sinp) + 1;
1544 }
1545 
1546 /* Write an encoded string with possible encryption. */
1547 static int
pdf_put_encoded_string(const gx_device_pdf * pdev,const byte * str,uint size,gs_id object_id)1548 pdf_put_encoded_string(const gx_device_pdf *pdev, const byte *str, uint size, gs_id object_id)
1549 {
1550     if (!pdev->KeyLength || object_id == (gs_id)-1) {
1551 	stream_write(pdev->strm, str, size);
1552 	return 0;
1553     } else
1554 	return pdf_encrypt_encoded_string(pdev, str, size, object_id);
1555 }
1556 /* Write an encoded hexadecimal string with possible encryption. */
1557 static int
pdf_put_encoded_hex_string(const gx_device_pdf * pdev,const byte * str,uint size,gs_id object_id)1558 pdf_put_encoded_hex_string(const gx_device_pdf *pdev, const byte *str, uint size, gs_id object_id)
1559 {
1560     eprintf("Unimplemented function : pdf_put_encoded_hex_string\n");
1561     stream_write(pdev->strm, str, size);
1562     return_error(gs_error_unregistered);
1563 }
1564 /*  Scan an item in a serialized array or dictionary.
1565     This is a very simplified Postscript lexical scanner.
1566     It assumes the serialization with pdf===only defined in gs/lib/gs_pdfwr.ps .
1567     We only need to select strings and encrypt them.
1568     Other items are passed identically.
1569     Note we don't reconstruct the nesting of arrays|dictionaries.
1570 */
1571 static int
pdf_scan_item(const gx_device_pdf * pdev,const byte * p,uint l,gs_id object_id)1572 pdf_scan_item(const gx_device_pdf * pdev, const byte * p, uint l, gs_id object_id)
1573 {
1574     const byte *q = p;
1575     int n = l;
1576 
1577     if (*q == ' ' || *q == 't' || *q == '\r' || *q == '\n')
1578 	return (l > 0 ? 1 : 0);
1579     for (q++, n--; n; q++, n--) {
1580 	if (*q == ' ' || *q == 't' || *q == '\r' || *q == '\n')
1581 	    return q - p;
1582 	if (*q == '/' || *q == '[' || *q == ']' || *q == '{' || *q == '}' || *q == '(' || *q == '<')
1583 	    return q - p;
1584 	/* Note : immediate names are not allowed in PDF. */
1585     }
1586     return l;
1587 }
1588 
1589 /* Write a serialized array or dictionary with possible encryption. */
1590 static int
pdf_put_composite(const gx_device_pdf * pdev,const byte * vstr,uint size,gs_id object_id)1591 pdf_put_composite(const gx_device_pdf * pdev, const byte * vstr, uint size, gs_id object_id)
1592 {
1593     if (!pdev->KeyLength || object_id == (gs_id)-1) {
1594 	stream_write(pdev->strm, vstr, size);
1595     } else {
1596 	const byte *p = vstr;
1597 	int l = size, n;
1598 
1599 	for (;l > 0 ;) {
1600 	    if (*p == '(')
1601 		n = pdf_encrypt_encoded_string(pdev, p, l, object_id);
1602 	    else {
1603 		n = pdf_scan_item(pdev, p, l, object_id);
1604 		stream_write(pdev->strm, p, n);
1605 	    }
1606 	    l -= n;
1607 	    p += n;
1608 	}
1609     }
1610     return 0;
1611 }
1612 
1613 /*
1614  * Write a string in its shortest form ( () or <> ).  Note that
1615  * this form is different depending on whether binary data are allowed.
1616  * We wish PDF supported ASCII85 strings ( <~ ~> ), but it doesn't.
1617  */
1618 int
pdf_put_string(const gx_device_pdf * pdev,const byte * str,uint size)1619 pdf_put_string(const gx_device_pdf * pdev, const byte * str, uint size)
1620 {
1621     psdf_write_string(pdev->strm, str, size,
1622 		      (pdev->binary_ok ? PRINT_BINARY_OK : 0));
1623     return 0;
1624 }
1625 
1626 /* Write a value, treating names specially. */
1627 int
pdf_write_value(const gx_device_pdf * pdev,const byte * vstr,uint size,gs_id object_id)1628 pdf_write_value(const gx_device_pdf * pdev, const byte * vstr, uint size, gs_id object_id)
1629 {
1630     if (size > 0 && vstr[0] == '/')
1631 	return pdf_put_name(pdev, vstr + 1, size - 1);
1632     else if (size > 3 && vstr[0] == 0 && vstr[1] == 0 && vstr[size - 1] == 0)
1633 	return pdf_put_name(pdev, vstr + 3, size - 4);
1634     else if (size > 1 && (vstr[0] == '[' || vstr[0] == '{'))
1635 	return pdf_put_composite(pdev, vstr, size, object_id);
1636     else if (size > 2 && vstr[0] == '<' && vstr[1] == '<')
1637 	return pdf_put_composite(pdev, vstr, size, object_id);
1638     else if (size > 1 && vstr[0] == '(')
1639 	return pdf_put_encoded_string(pdev, vstr, size, object_id);
1640     else if (size > 1 && vstr[0] == '<')
1641 	return pdf_put_encoded_hex_string(pdev, vstr, size, object_id);
1642     stream_write(pdev->strm, vstr, size);
1643     return 0;
1644 }
1645 
1646 /* Store filters for a stream. */
1647 /* Currently this only saves parameters for CCITTFaxDecode. */
1648 int
pdf_put_filters(cos_dict_t * pcd,gx_device_pdf * pdev,stream * s,const pdf_filter_names_t * pfn)1649 pdf_put_filters(cos_dict_t *pcd, gx_device_pdf *pdev, stream *s,
1650 		const pdf_filter_names_t *pfn)
1651 {
1652     const char *filter_name = 0;
1653     bool binary_ok = true;
1654     stream *fs = s;
1655     cos_dict_t *decode_parms = 0;
1656     int code;
1657 
1658     for (; fs != 0; fs = fs->strm) {
1659 	const stream_state *st = fs->state;
1660 	const stream_template *template = st->template;
1661 
1662 #define TEMPLATE_IS(atemp)\
1663   (template->process == (atemp).process)
1664 	if (TEMPLATE_IS(s_A85E_template))
1665 	    binary_ok = false;
1666 	else if (TEMPLATE_IS(s_CFE_template)) {
1667 	    cos_param_list_writer_t writer;
1668 	    stream_CF_state cfs;
1669 
1670 	    decode_parms =
1671 		cos_dict_alloc(pdev, "pdf_put_image_filters(decode_parms)");
1672 	    if (decode_parms == 0)
1673 		return_error(gs_error_VMerror);
1674 	    CHECK(cos_param_list_writer_init(&writer, decode_parms, 0));
1675 	    /*
1676 	     * If EndOfBlock is true, we mustn't write a Rows value.
1677 	     * This is a hack....
1678 	     */
1679 	    cfs = *(const stream_CF_state *)st;
1680 	    if (cfs.EndOfBlock)
1681 		cfs.Rows = 0;
1682 	    CHECK(s_CF_get_params((gs_param_list *)&writer, &cfs, false));
1683 	    filter_name = pfn->CCITTFaxDecode;
1684 	} else if (TEMPLATE_IS(s_DCTE_template))
1685 	    filter_name = pfn->DCTDecode;
1686 	else if (TEMPLATE_IS(s_zlibE_template))
1687 	    filter_name = pfn->FlateDecode;
1688 	else if (TEMPLATE_IS(s_LZWE_template))
1689 	    filter_name = pfn->LZWDecode;
1690 #ifdef USE_LDF_JB2
1691 	else if (TEMPLATE_IS(s_jbig2encode_template))
1692 	    filter_name = pfn->JBIG2Decode;
1693 #endif
1694 #ifdef USE_LWF_JP2
1695 	else if (TEMPLATE_IS(s_jpxe_template))
1696 	    filter_name = pfn->JPXDecode;
1697 #endif
1698 	else if (TEMPLATE_IS(s_PNGPE_template)) {
1699 	    /* This is a predictor for FlateDecode or LZWEncode. */
1700 	    const stream_PNGP_state *const ss =
1701 		(const stream_PNGP_state *)st;
1702 
1703 	    decode_parms =
1704 		cos_dict_alloc(pdev, "pdf_put_image_filters(decode_parms)");
1705 	    if (decode_parms == 0)
1706 		return_error(gs_error_VMerror);
1707 	    CHECK(cos_dict_put_c_key_int(decode_parms, "/Predictor",
1708 					 ss->Predictor));
1709 	    CHECK(cos_dict_put_c_key_int(decode_parms, "/Columns",
1710 					 ss->Columns));
1711 	    if (ss->Colors != 1)
1712 		CHECK(cos_dict_put_c_key_int(decode_parms, "/Colors",
1713 					     ss->Colors));
1714 	    if (ss->BitsPerComponent != 8)
1715 		CHECK(cos_dict_put_c_key_int(decode_parms,
1716 					     "/BitsPerComponent",
1717 					     ss->BitsPerComponent));
1718 	} else if (TEMPLATE_IS(s_RLE_template))
1719 	    filter_name = pfn->RunLengthDecode;
1720 #undef TEMPLATE_IS
1721     }
1722     if (filter_name) {
1723 	if (binary_ok) {
1724 	    CHECK(cos_dict_put_c_strings(pcd, pfn->Filter, filter_name));
1725 	    if (decode_parms)
1726 		CHECK(cos_dict_put_c_key_object(pcd, pfn->DecodeParms,
1727 						COS_OBJECT(decode_parms)));
1728 	} else {
1729 	    cos_array_t *pca =
1730 		cos_array_alloc(pdev, "pdf_put_image_filters(Filters)");
1731 
1732 	    if (pca == 0)
1733 		return_error(gs_error_VMerror);
1734 	    CHECK(cos_array_add_c_string(pca, pfn->ASCII85Decode));
1735 	    CHECK(cos_array_add_c_string(pca, filter_name));
1736 	    CHECK(cos_dict_put_c_key_object(pcd, pfn->Filter,
1737 					    COS_OBJECT(pca)));
1738 	    if (decode_parms) {
1739 		pca = cos_array_alloc(pdev,
1740 				      "pdf_put_image_filters(DecodeParms)");
1741 		if (pca == 0)
1742 		    return_error(gs_error_VMerror);
1743 		CHECK(cos_array_add_c_string(pca, "null"));
1744 		CHECK(cos_array_add_object(pca, COS_OBJECT(decode_parms)));
1745 		CHECK(cos_dict_put_c_key_object(pcd, pfn->DecodeParms,
1746 						COS_OBJECT(pca)));
1747 	    }
1748 	}
1749     } else if (!binary_ok)
1750 	CHECK(cos_dict_put_c_strings(pcd, pfn->Filter, pfn->ASCII85Decode));
1751     return 0;
1752 }
1753 
1754 /* Add a Flate compression filter to a binary writer. */
1755 static int
pdf_flate_binary(gx_device_pdf * pdev,psdf_binary_writer * pbw)1756 pdf_flate_binary(gx_device_pdf *pdev, psdf_binary_writer *pbw)
1757 {
1758     const stream_template *template = (pdev->CompatibilityLevel < 1.3 ?
1759 		    &s_LZWE_template : &s_zlibE_template);
1760     stream_state *st = s_alloc_state(pdev->pdf_memory, template->stype,
1761 				     "pdf_write_function");
1762 
1763     if (st == 0)
1764 	return_error(gs_error_VMerror);
1765     if (template->set_defaults)
1766 	template->set_defaults(st);
1767     return psdf_encode_binary(pbw, template, st);
1768 }
1769 
1770 /*
1771  * Begin a data stream.  The client has opened the object and written
1772  * the << and any desired dictionary keys.
1773  */
1774 int
pdf_begin_data(gx_device_pdf * pdev,pdf_data_writer_t * pdw)1775 pdf_begin_data(gx_device_pdf *pdev, pdf_data_writer_t *pdw)
1776 {
1777     return pdf_begin_data_stream(pdev, pdw,
1778 				 DATA_STREAM_BINARY | DATA_STREAM_COMPRESS, 0);
1779 }
1780 
1781 int
pdf_append_data_stream_filters(gx_device_pdf * pdev,pdf_data_writer_t * pdw,int orig_options,gs_id object_id)1782 pdf_append_data_stream_filters(gx_device_pdf *pdev, pdf_data_writer_t *pdw,
1783 		      int orig_options, gs_id object_id)
1784 {
1785     stream *s = pdev->strm;
1786     int options = orig_options;
1787 #define USE_ASCII85 1
1788 #define USE_FLATE 2
1789     static const char *const fnames[4] = {
1790 	"", "/Filter/ASCII85Decode", "/Filter/FlateDecode",
1791 	"/Filter[/ASCII85Decode/FlateDecode]"
1792     };
1793     static const char *const fnames1_2[4] = {
1794 	"", "/Filter/ASCII85Decode", "/Filter/LZWDecode",
1795 	"/Filter[/ASCII85Decode/LZWDecode]"
1796     };
1797     int filters = 0;
1798     int code;
1799 
1800     if (options & DATA_STREAM_COMPRESS) {
1801 	filters |= USE_FLATE;
1802 	options |= DATA_STREAM_BINARY;
1803     }
1804     if ((options & DATA_STREAM_BINARY) && !pdev->binary_ok)
1805 	filters |= USE_ASCII85;
1806     if (!(options & DATA_STREAM_NOLENGTH)) {
1807 	stream_puts(s, (pdev->CompatibilityLevel < 1.3 ?
1808 	    fnames1_2[filters] : fnames[filters]));
1809 	if (pdev->ResourcesBeforeUsage) {
1810 	    pdw->length_pos = stell(s) + 8;
1811 	    stream_puts(s, "/Length             >>stream\n");
1812 	    pdw->length_id = -1;
1813 	} else {
1814 	    pdw->length_pos = -1;
1815 	    pdw->length_id = pdf_obj_ref(pdev);
1816 	    pprintld1(s, "/Length %ld 0 R>>stream\n", pdw->length_id);
1817 	}
1818     }
1819     if (options & DATA_STREAM_ENCRYPT) {
1820 	code = pdf_begin_encrypt(pdev, &s, object_id);
1821 	if (code < 0)
1822 	    return code;
1823 	pdev->strm = s;
1824 	pdw->encrypted = true;
1825     } else
1826     	pdw->encrypted = false;
1827     if (options & DATA_STREAM_BINARY) {
1828 	code = psdf_begin_binary((gx_device_psdf *)pdev, &pdw->binary);
1829 	if (code < 0)
1830 	    return code;
1831     } else {
1832 	code = 0;
1833 	pdw->binary.target = pdev->strm;
1834 	pdw->binary.dev = (gx_device_psdf *)pdev;
1835 	pdw->binary.strm = pdev->strm;
1836     }
1837     pdw->start = stell(s);
1838     if (filters & USE_FLATE)
1839 	code = pdf_flate_binary(pdev, &pdw->binary);
1840     return code;
1841 #undef USE_ASCII85
1842 #undef USE_FLATE
1843 }
1844 
1845 int
pdf_begin_data_stream(gx_device_pdf * pdev,pdf_data_writer_t * pdw,int options,gs_id object_id)1846 pdf_begin_data_stream(gx_device_pdf *pdev, pdf_data_writer_t *pdw,
1847 		      int options, gs_id object_id)
1848 {   int code;
1849     /* object_id is an unused rudiment from the old code,
1850        when the encription was applied when creating the stream.
1851        The new code encrypts than copying stream from the temporary file. */
1852     pdw->pdev = pdev;  /* temporary for backward compatibility of pdf_end_data prototype. */
1853     pdw->binary.target = pdev->strm;
1854     pdw->binary.dev = (gx_device_psdf *)pdev;
1855     pdw->binary.strm = 0;		/* for GC in case of failure */
1856     code = pdf_open_aside(pdev, resourceOther, gs_no_id, &pdw->pres, !object_id,
1857 		options);
1858     if (object_id != 0)
1859 	pdf_reserve_object_id(pdev, pdw->pres, object_id);
1860     pdw->binary.strm = pdev->strm;
1861     return code;
1862 }
1863 
1864 /* End a data stream. */
1865 int
pdf_end_data(pdf_data_writer_t * pdw)1866 pdf_end_data(pdf_data_writer_t *pdw)
1867 {   int code;
1868 
1869     code = pdf_close_aside(pdw->pdev);
1870     if (code < 0)
1871 	return code;
1872     code = COS_WRITE_OBJECT(pdw->pres->object, pdw->pdev);
1873     if (code < 0)
1874 	return code;
1875     return 0;
1876 }
1877 
1878 /* Create a Function object. */
1879 static int pdf_function_array(gx_device_pdf *pdev, cos_array_t *pca,
1880 			       const gs_function_info_t *pinfo);
1881 int
pdf_function_scaled(gx_device_pdf * pdev,const gs_function_t * pfn,const gs_range_t * pranges,cos_value_t * pvalue)1882 pdf_function_scaled(gx_device_pdf *pdev, const gs_function_t *pfn,
1883 		    const gs_range_t *pranges, cos_value_t *pvalue)
1884 {
1885     if (pranges == NULL)
1886 	return pdf_function(pdev, pfn, pvalue);
1887     {
1888 	/*
1889 	 * Create a temporary scaled function.  Note that the ranges
1890 	 * represent the inverse scaling from what gs_function_make_scaled
1891 	 * expects.
1892 	 */
1893 	gs_memory_t *mem = pdev->pdf_memory;
1894 	gs_function_t *psfn;
1895 	gs_range_t *ranges = (gs_range_t *)
1896 	    gs_alloc_byte_array(mem, pfn->params.n, sizeof(gs_range_t),
1897 				"pdf_function_scaled");
1898 	int i, code;
1899 
1900 	if (ranges == 0)
1901 	    return_error(gs_error_VMerror);
1902 	for (i = 0; i < pfn->params.n; ++i) {
1903 	    double rbase = pranges[i].rmin;
1904 	    double rdiff = pranges[i].rmax - rbase;
1905 	    double invbase = -rbase / rdiff;
1906 
1907 	    ranges[i].rmin = invbase;
1908 	    ranges[i].rmax = invbase + 1.0 / rdiff;
1909 	}
1910 	code = gs_function_make_scaled(pfn, &psfn, ranges, mem);
1911 	if (code >= 0) {
1912 	    code = pdf_function(pdev, psfn, pvalue);
1913 	    gs_function_free(psfn, true, mem);
1914 	}
1915 	gs_free_object(mem, ranges, "pdf_function_scaled");
1916 	return code;
1917     }
1918 }
1919 static int
pdf_function_aux(gx_device_pdf * pdev,const gs_function_t * pfn,pdf_resource_t ** ppres)1920 pdf_function_aux(gx_device_pdf *pdev, const gs_function_t *pfn,
1921 	     pdf_resource_t **ppres)
1922 {
1923     gs_function_info_t info;
1924     cos_param_list_writer_t rlist;
1925     pdf_resource_t *pres;
1926     cos_object_t *pcfn;
1927     cos_dict_t *pcd;
1928     int code = pdf_alloc_resource(pdev, resourceFunction, gs_no_id, &pres, -1);
1929 
1930     if (code < 0) {
1931 	*ppres = 0;
1932 	return code;
1933     }
1934     *ppres = pres;
1935     pcfn = pres->object;
1936     gs_function_get_info(pfn, &info);
1937     if (FunctionType(pfn) == function_type_ArrayedOutput) {
1938 	/*
1939 	 * Arrayed Output Functions are used internally to represent
1940 	 * Shading Function entries that are arrays of Functions.
1941 	 * They require special handling.
1942 	 */
1943 	cos_array_t *pca;
1944 
1945 	cos_become(pcfn, cos_type_array);
1946 	pca = (cos_array_t *)pcfn;
1947 	return pdf_function_array(pdev, pca, &info);
1948     }
1949     if (info.DataSource != 0) {
1950 	psdf_binary_writer writer;
1951 	stream *save = pdev->strm;
1952 	cos_stream_t *pcos;
1953 	stream *s;
1954 
1955 	cos_become(pcfn, cos_type_stream);
1956 	pcos = (cos_stream_t *)pcfn;
1957 	pcd = cos_stream_dict(pcos);
1958 	s = cos_write_stream_alloc(pcos, pdev, "pdf_function");
1959 	if (s == 0)
1960 	    return_error(gs_error_VMerror);
1961 	pdev->strm = s;
1962 	code = psdf_begin_binary((gx_device_psdf *)pdev, &writer);
1963 	if (code >= 0 && info.data_size > 30	/* 30 is arbitrary */
1964 	    )
1965 	    code = pdf_flate_binary(pdev, &writer);
1966 	if (code >= 0) {
1967 	    static const pdf_filter_names_t fnames = {
1968 		PDF_FILTER_NAMES
1969 	    };
1970 
1971 	    code = pdf_put_filters(pcd, pdev, writer.strm, &fnames);
1972 	}
1973 	if (code >= 0) {
1974 	    byte buf[100];		/* arbitrary */
1975 	    ulong pos;
1976 	    uint count;
1977 	    const byte *ptr;
1978 
1979 	    for (pos = 0; pos < info.data_size; pos += count) {
1980 		count = min(sizeof(buf), info.data_size - pos);
1981 		data_source_access_only(info.DataSource, pos, count, buf,
1982 					&ptr);
1983 		stream_write(writer.strm, ptr, count);
1984 	    }
1985 	    code = psdf_end_binary(&writer);
1986 	    sclose(s);
1987 	}
1988 	pdev->strm = save;
1989 	if (code < 0)
1990 	    return code;
1991     } else {
1992 	cos_become(pcfn, cos_type_dict);
1993 	pcd = (cos_dict_t *)pcfn;
1994     }
1995     if (info.Functions != 0) {
1996 	cos_array_t *functions =
1997 	    cos_array_alloc(pdev, "pdf_function(Functions)");
1998 	cos_value_t v;
1999 
2000 	if (functions == 0)
2001 	    return_error(gs_error_VMerror);
2002 	if ((code = pdf_function_array(pdev, functions, &info)) < 0 ||
2003 	    (code = cos_dict_put_c_key(pcd, "/Functions",
2004 				       COS_OBJECT_VALUE(&v, functions))) < 0
2005 	    ) {
2006 	    COS_FREE(functions, "pdf_function(Functions)");
2007 	    return code;
2008 	}
2009     }
2010     code = cos_param_list_writer_init(&rlist, pcd, PRINT_BINARY_OK);
2011     if (code < 0)
2012 	return code;
2013     return gs_function_get_params(pfn, (gs_param_list *)&rlist);
2014 }
2015 static int
functions_equal(gx_device_pdf * pdev,pdf_resource_t * pres0,pdf_resource_t * pres1)2016 functions_equal(gx_device_pdf * pdev, pdf_resource_t *pres0, pdf_resource_t *pres1)
2017 {
2018     return true;
2019 }
2020 int
pdf_function(gx_device_pdf * pdev,const gs_function_t * pfn,cos_value_t * pvalue)2021 pdf_function(gx_device_pdf *pdev, const gs_function_t *pfn, cos_value_t *pvalue)
2022 {
2023     pdf_resource_t *pres;
2024     int code = pdf_function_aux(pdev, pfn, &pres);
2025 
2026     if (code < 0)
2027 	return code;
2028     code = pdf_substitute_resource(pdev, &pres, resourceFunction, functions_equal, false);
2029     if (code < 0)
2030 	return code;
2031     pres->where_used |= pdev->used_mask;
2032     COS_OBJECT_VALUE(pvalue, pres->object);
2033     return 0;
2034 }
pdf_function_array(gx_device_pdf * pdev,cos_array_t * pca,const gs_function_info_t * pinfo)2035 static int pdf_function_array(gx_device_pdf *pdev, cos_array_t *pca,
2036 			       const gs_function_info_t *pinfo)
2037 {
2038     int i, code = 0;
2039     cos_value_t v;
2040 
2041     for (i = 0; i < pinfo->num_Functions; ++i) {
2042 	if ((code = pdf_function(pdev, pinfo->Functions[i], &v)) < 0 ||
2043 	    (code = cos_array_add(pca, &v)) < 0
2044 	    ) {
2045 	    break;
2046 	}
2047     }
2048     return code;
2049 }
2050 
2051 
2052 /* Write a Function object. */
2053 int
pdf_write_function(gx_device_pdf * pdev,const gs_function_t * pfn,long * pid)2054 pdf_write_function(gx_device_pdf *pdev, const gs_function_t *pfn, long *pid)
2055 {
2056     cos_value_t value;
2057     int code = pdf_function(pdev, pfn, &value);
2058 
2059     if (code < 0)
2060 	return code;
2061     *pid = value.contents.object->id;
2062     return 0;
2063 }
2064 
2065 /* Write a FontBBox dictionary element. */
2066 int
pdf_write_font_bbox(gx_device_pdf * pdev,const gs_int_rect * pbox)2067 pdf_write_font_bbox(gx_device_pdf *pdev, const gs_int_rect *pbox)
2068 {
2069     stream *s = pdev->strm;
2070     /*
2071      * AR 4 doesn't like fonts with empty FontBBox, which
2072      * happens when the font contains only space characters.
2073      * Small bbox causes AR 4 to display a hairline. So we use
2074      * the full BBox.
2075      */
2076     int x = pbox->q.x + ((pbox->p.x == pbox->q.x) ? 1000 : 0);
2077     int y = pbox->q.y + ((pbox->p.y == pbox->q.y) ? 1000 : 0);
2078 
2079     pprintd4(s, "/FontBBox[%d %d %d %d]",
2080 	     pbox->p.x, pbox->p.y, x, y);
2081     return 0;
2082 }
2083 
2084 /* Write a FontBBox dictionary element using floats for the values. */
2085 int
pdf_write_font_bbox_float(gx_device_pdf * pdev,const gs_rect * pbox)2086 pdf_write_font_bbox_float(gx_device_pdf *pdev, const gs_rect *pbox)
2087 {
2088     stream *s = pdev->strm;
2089     /*
2090      * AR 4 doesn't like fonts with empty FontBBox, which
2091      * happens when the font contains only space characters.
2092      * Small bbox causes AR 4 to display a hairline. So we use
2093      * the full BBox.
2094      */
2095     float x = pbox->q.x + ((pbox->p.x == pbox->q.x) ? 1000 : 0);
2096     float y = pbox->q.y + ((pbox->p.y == pbox->q.y) ? 1000 : 0);
2097 
2098     pprintg4(s, "/FontBBox[%g %g %g %g]",
2099 	     pbox->p.x, pbox->p.y, x, y);
2100     return 0;
2101 }
2102