~ubuntu-branches/ubuntu/natty/luatex/natty

« back to all changes in this revision

Viewing changes to source/texk/web2c/luatexdir/pdf/pdfgen.c

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Preining
  • Date: 2009-12-25 09:47:05 UTC
  • mfrom: (1.1.9 upstream) (4.2.3 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091225094705-y33rpflo8t4u9nag
Tags: 0.50.0-1
* new upstream release
* disable fix-hurd-ftbfs patch, included upstream
* disable upstram-fixes, included upstream
* disable ubuntu_libpoppler-0.11, not needed anymore

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* pdfgen.c
 
2
 
 
3
   Copyright 2009 Taco Hoekwater <taco@luatex.org>
 
4
 
 
5
   This file is part of LuaTeX.
 
6
 
 
7
   LuaTeX is free software; you can redistribute it and/or modify it under
 
8
   the terms of the GNU General Public License as published by the Free
 
9
   Software Foundation; either version 2 of the License, or (at your
 
10
   option) any later version.
 
11
 
 
12
   LuaTeX is distributed in the hope that it will be useful, but WITHOUT
 
13
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
14
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 
15
   License for more details.
 
16
 
 
17
   You should have received a copy of the GNU General Public License along
 
18
   with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */
 
19
 
 
20
static const char __svn_version[] =
 
21
    "$Id: pdfgen.c 3261 2009-12-18 11:38:21Z taco $"
 
22
    "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.50.0/source/texk/web2c/luatexdir/pdf/pdfgen.c $";
 
23
 
 
24
#include "ptexlib.h"
 
25
#include <ctype.h>
 
26
#include "md5.h"
 
27
 
 
28
/* for tokenlist_to_cstring */
 
29
 
 
30
#define is_hex_char isxdigit
 
31
 
 
32
#define check_nprintf(size_get, size_want) \
 
33
    if ((unsigned)(size_get) >= (unsigned)(size_want)) \
 
34
        pdftex_fail ("snprintf failed: file %s, line %d", __FILE__, __LINE__);
 
35
 
 
36
PDF static_pdf = NULL;
 
37
 
 
38
static char *jobname_cstr = NULL;
 
39
 
 
40
/* commandline interface */
 
41
int pdf_output_option;
 
42
int pdf_output_value;
 
43
int pdf_draftmode_option;
 
44
int pdf_draftmode_value;
 
45
 
 
46
halfword pdf_info_toks;         /* additional keys of Info dictionary */
 
47
halfword pdf_catalog_toks;      /* additional keys of Catalog dictionary */
 
48
halfword pdf_catalog_openaction;
 
49
halfword pdf_names_toks;        /* additional keys of Names dictionary */
 
50
halfword pdf_trailer_toks;      /* additional keys of Trailer dictionary */
 
51
boolean is_shipping_page;       /* set to |shipping_page| when |ship_out| starts */
 
52
 
 
53
/* init_pdf_struct() is called early, only once, from maincontrol.c */
 
54
 
 
55
PDF init_pdf_struct(PDF pdf)
 
56
{
 
57
    assert(pdf == NULL);
 
58
    pdf = xmalloc(sizeof(pdf_output_file));
 
59
    memset(pdf, 0, sizeof(pdf_output_file));
 
60
 
 
61
    pdf->o_mode = OMODE_NONE;   /* will be set by fix_o_mode() */
 
62
    pdf->o_state = ST_INITIAL;
 
63
 
 
64
    pdf->os_obj = xmalloc(pdf_os_max_objs * sizeof(os_obj_data));
 
65
    pdf->os_buf_size = inf_pdf_os_buf_size;
 
66
    pdf->os_buf = xmalloc(pdf->os_buf_size * sizeof(unsigned char));
 
67
    pdf->op_buf_size = inf_pdf_op_buf_size;
 
68
    pdf->op_buf = xmalloc(pdf->op_buf_size * sizeof(unsigned char));
 
69
 
 
70
    pdf->buf_size = pdf->op_buf_size;
 
71
    pdf->buf = pdf->op_buf;
 
72
 
 
73
    /* Sometimes it is neccesary to allocate memory for PDF output that cannot
 
74
       be deallocated then, so we use |mem| for this purpose. */
 
75
    pdf->mem_size = inf_pdf_mem_size;   /* allocated size of |mem| array */
 
76
    pdf->mem = xmalloc(pdf->mem_size * sizeof(int));
 
77
    pdf->mem_ptr = 1;           /* the first word is not used so we can use zero as a value for testing
 
78
                                   whether a pointer to |mem| is valid  */
 
79
    pdf->pstruct = NULL;
 
80
 
 
81
    pdf->posstruct = xmalloc(sizeof(posstructure));
 
82
    pdf->posstruct->pos.h = 0;
 
83
    pdf->posstruct->pos.v = 0;
 
84
    pdf->posstruct->dir = dir_TLT;
 
85
 
 
86
    pdf->obj_tab_size = inf_obj_tab_size;       /* allocated size of |obj_tab| array */
 
87
    pdf->obj_tab = xmalloc((pdf->obj_tab_size + 1) * sizeof(obj_entry));
 
88
    memset(pdf->obj_tab, 0, sizeof(obj_entry));
 
89
 
 
90
    pdf->minor_version = -1;    /* unset */
 
91
    pdf->decimal_digits = 4;
 
92
    pdf->gamma = 65536;
 
93
    pdf->image_gamma = 65536;
 
94
    pdf->image_hicolor = 1;
 
95
    pdf->image_apply_gamma = 0;
 
96
    pdf->objcompresslevel = 0;
 
97
    pdf->compress_level = 0;
 
98
    pdf->draftmode = 0;
 
99
    pdf->inclusion_copy_font = 1;
 
100
    pdf->replace_font = 0;
 
101
    pdf->pk_resolution = 0;
 
102
    pdf->pk_scale_factor = 0;
 
103
 
 
104
    init_dest_names(pdf);
 
105
    pdf->resources = NULL;
 
106
 
 
107
    init_pdf_pagecalculations(pdf);
 
108
 
 
109
    return pdf;
 
110
}
 
111
 
 
112
static void pdf_shipout_begin(boolean shipping_page)
 
113
{
 
114
    pos_stack_used = 0;         /* start with empty stack */
 
115
 
 
116
    page_mode = shipping_page;
 
117
    if (shipping_page) {
 
118
        colorstackpagestart();
 
119
    }
 
120
}
 
121
 
 
122
static void pdf_shipout_end(boolean shipping_page)
 
123
{
 
124
    if (pos_stack_used > 0) {
 
125
        pdftex_fail("%u unmatched \\pdfsave after %s shipout",
 
126
                    (unsigned int) pos_stack_used,
 
127
                    ((shipping_page) ? "page" : "form"));
 
128
    }
 
129
}
 
130
 
 
131
/*
 
132
  We use |pdf_get_mem| to allocate memory in |mem|
 
133
*/
 
134
 
 
135
int pdf_get_mem(PDF pdf, int s)
 
136
{                               /* allocate |s| words in |mem| */
 
137
    int a;
 
138
    int ret;
 
139
    if (s > sup_pdf_mem_size - pdf->mem_ptr)
 
140
        overflow("PDF memory size (pdf_mem_size)", pdf->mem_size);
 
141
    if (pdf->mem_ptr + s > pdf->mem_size) {
 
142
        a = 0.2 * pdf->mem_size;
 
143
        if (pdf->mem_ptr + s > pdf->mem_size + a) {
 
144
            pdf->mem_size = pdf->mem_ptr + s;
 
145
        } else if (pdf->mem_size < sup_pdf_mem_size - a) {
 
146
            pdf->mem_size = pdf->mem_size + a;
 
147
        } else {
 
148
            pdf->mem_size = sup_pdf_mem_size;
 
149
        }
 
150
        pdf->mem = xreallocarray(pdf->mem, int, pdf->mem_size);
 
151
    }
 
152
    ret = pdf->mem_ptr;
 
153
    pdf->mem_ptr = pdf->mem_ptr + s;
 
154
    return ret;
 
155
}
 
156
 
 
157
/*
 
158
|fix_o_mode| freezes |pdf->o_mode| as soon as anything goes through
 
159
the backend, be it \.{PDF}, \.{DVI}, or \.{Lua}.
 
160
*/
 
161
 
 
162
#define pdf_output int_par(pdf_output_code)
 
163
 
 
164
void fix_o_mode(PDF pdf)
 
165
{
 
166
    static int fixed_pdf_output = 0;
 
167
    if (pdf->o_mode == OMODE_NONE) {
 
168
        if (pdf_output > 0) {
 
169
            if (pdf_output == 2009)
 
170
                pdf->o_mode = OMODE_LUA;
 
171
            else
 
172
                pdf->o_mode = OMODE_PDF;
 
173
        } else
 
174
            pdf->o_mode = OMODE_DVI;
 
175
        fixed_pdf_output = pdf_output;
 
176
    } else if (pdf_output != fixed_pdf_output) {
 
177
        pdf_error("setup",
 
178
                  "\\pdfoutput can only be changed before anything is written to the output");
 
179
    }
 
180
}
 
181
 
 
182
/*
 
183
This ensures that |pdfminorversion| is set only before any bytes have
 
184
been written to the generated \.{PDF} file. Here also all variables for
 
185
\.{PDF} output are initialized, the \.{PDF} file is opened by |ensure_pdf_open|,
 
186
and the \.{PDF} header is written.
 
187
*/
 
188
 
 
189
void fix_pdf_minorversion(PDF pdf)
 
190
{
 
191
    if (pdf->minor_version < 0) {       /* unset */
 
192
        if ((pdf_minor_version < 0) || (pdf_minor_version > 9)) {
 
193
            char *hlp[] = { "The pdfminorversion must be between 0 and 9.",
 
194
                "I changed this to 4.", NULL
 
195
            };
 
196
            char msg[256];
 
197
            (void) snprintf(msg, 255,
 
198
                            "LuaTeX error (illegal pdfminorversion %d)",
 
199
                            (int) pdf_minor_version);
 
200
            tex_error(msg, hlp);
 
201
            pdf_minor_version = 4;
 
202
        }
 
203
        pdf->minor_version = pdf_minor_version;
 
204
    } else {
 
205
        /* Check that variables for \.{PDF} output are unchanged */
 
206
        if (pdf->minor_version != int_par(pdf_minor_version_code))
 
207
            pdf_error("setup",
 
208
                      "\\pdfminorversion cannot be changed after data is written to the PDF file");
 
209
        if (pdf->draftmode != int_par(pdf_draftmode_code))
 
210
            pdf_error("setup",
 
211
                      "\\pdfdraftmode cannot be changed after data is written to the PDF file");
 
212
    }
 
213
    if (pdf->draftmode != 0) {
 
214
        pdf->compress_level = 0;        /* re-fix it, might have been changed inbetween */
 
215
        pdf->objcompresslevel = 0;
 
216
    }
 
217
}
 
218
 
 
219
/*
 
220
The PDF buffer is flushed by calling |pdf_flush|, which checks the
 
221
variable |zip_write_state| and will compress the buffer before flushing if
 
222
neccesary. We call |pdf_begin_stream| to begin a stream  and |pdf_end_stream|
 
223
to finish it. The stream contents will be compressed if compression is turn on.
 
224
*/
 
225
 
 
226
/* writepdf() always writes by fwrite() */
 
227
 
 
228
static void write_pdf(PDF pdf, int a, int b)
 
229
{
 
230
    (void) fwrite((char *) &pdf->buf[a], sizeof(pdf->buf[a]),
 
231
                  (int) ((b) - (a) + 1), pdf->file);
 
232
}
 
233
 
 
234
void pdf_flush(PDF pdf)
 
235
{                               /* flush out the |pdf_buf| */
 
236
 
 
237
    off_t saved_pdf_gone;
 
238
    if (!pdf->os_mode) {
 
239
        saved_pdf_gone = pdf->gone;
 
240
        switch (pdf->zip_write_state) {
 
241
        case no_zip:
 
242
            if (pdf->ptr > 0) {
 
243
                if (pdf->draftmode == 0)
 
244
                    write_pdf(pdf, 0, pdf->ptr - 1);
 
245
                pdf->gone += pdf->ptr;
 
246
                pdf->last_byte = pdf->buf[pdf->ptr - 1];
 
247
            }
 
248
            break;
 
249
        case zip_writing:
 
250
            if (pdf->draftmode == 0)
 
251
                write_zip(pdf, false);
 
252
            break;
 
253
        case zip_finish:
 
254
            if (pdf->draftmode == 0)
 
255
                write_zip(pdf, true);
 
256
            pdf->zip_write_state = no_zip;
 
257
            break;
 
258
        }
 
259
        pdf->ptr = 0;
 
260
        if (saved_pdf_gone > pdf->gone)
 
261
            pdf_error("file size",
 
262
                      "File size exceeds architectural limits (pdf_gone wraps around)");
 
263
    }
 
264
}
 
265
 
 
266
 
 
267
/* switch between PDF stream and object stream mode */
 
268
void pdf_os_switch(PDF pdf, boolean pdf_os)
 
269
{
 
270
    if (pdf_os && pdf->os_enable) {
 
271
        if (!pdf->os_mode) {    /* back up PDF stream variables */
 
272
            pdf->op_ptr = pdf->ptr;
 
273
            pdf->ptr = pdf->os_ptr;
 
274
            pdf->buf = pdf->os_buf;
 
275
            pdf->buf_size = pdf->os_buf_size;
 
276
            pdf->os_mode = true;        /* switch to object stream */
 
277
        }
 
278
    } else {
 
279
        if (pdf->os_mode) {     /* back up object stream variables */
 
280
            pdf->os_ptr = pdf->ptr;
 
281
            pdf->ptr = pdf->op_ptr;
 
282
            pdf->buf = pdf->op_buf;
 
283
            pdf->buf_size = pdf->op_buf_size;
 
284
            pdf->os_mode = false;       /* switch to PDF stream */
 
285
        }
 
286
    }
 
287
}
 
288
 
 
289
/* create new \.{/ObjStm} object if required, and set up cross reference info */
 
290
void pdf_os_prepare_obj(PDF pdf, int i, int pdf_os_level)
 
291
{
 
292
    pdf_os_switch(pdf, ((pdf_os_level > 0)
 
293
                        && (pdf->objcompresslevel >= pdf_os_level)));
 
294
    if (pdf->os_mode) {
 
295
        if (pdf->os_cur_objnum == 0) {
 
296
            pdf_create_obj(pdf, obj_type_objstm, pdf->sys_obj_ptr + 1);
 
297
            pdf->os_cur_objnum = pdf->sys_obj_ptr;
 
298
            pdf->obj_ptr--;     /* object stream is not accessible to user */
 
299
            pdf->os_cntr++;     /* only for statistics */
 
300
            pdf->os_idx = 0;
 
301
            pdf->ptr = 0;       /* start fresh object stream */
 
302
        } else {
 
303
            pdf->os_idx++;
 
304
        }
 
305
        obj_os_idx(pdf, i) = pdf->os_idx;
 
306
        obj_offset(pdf, i) = pdf->os_cur_objnum;
 
307
        pdf->os_obj[pdf->os_idx].num = i;
 
308
        pdf->os_obj[pdf->os_idx].off = pdf->ptr;
 
309
    } else {
 
310
        obj_offset(pdf, i) = pdf_offset(pdf);
 
311
        obj_os_idx(pdf, i) = -1;        /* mark it as not included in object stream */
 
312
    }
 
313
}
 
314
 
 
315
/* low-level buffer checkers */
 
316
 
 
317
/* check that |s| bytes more fit into |pdf_os_buf|; increase it if required */
 
318
static void pdf_os_get_os_buf(PDF pdf, int s)
 
319
{
 
320
    int a;
 
321
    if (s > sup_pdf_os_buf_size - pdf->ptr)
 
322
        overflow("PDF object stream buffer", pdf->os_buf_size);
 
323
    if (pdf->ptr + s > pdf->os_buf_size) {
 
324
        a = 0.2 * pdf->os_buf_size;
 
325
        if (pdf->ptr + s > pdf->os_buf_size + a)
 
326
            pdf->os_buf_size = pdf->ptr + s;
 
327
        else if (pdf->os_buf_size < sup_pdf_os_buf_size - a)
 
328
            pdf->os_buf_size = pdf->os_buf_size + a;
 
329
        else
 
330
            pdf->os_buf_size = sup_pdf_os_buf_size;
 
331
        pdf->os_buf =
 
332
            xreallocarray(pdf->os_buf, unsigned char, pdf->os_buf_size);
 
333
        pdf->buf = pdf->os_buf;
 
334
        pdf->buf_size = pdf->os_buf_size;
 
335
    }
 
336
}
 
337
 
 
338
/* make sure that there are at least |n| bytes free in PDF buffer */
 
339
void pdf_room(PDF pdf, int n)
 
340
{
 
341
    if (pdf->os_mode && (n + pdf->ptr > pdf->buf_size))
 
342
        pdf_os_get_os_buf(pdf, n);
 
343
    else if ((!pdf->os_mode) && (n > pdf->buf_size))
 
344
        overflow("PDF output buffer", pdf->op_buf_size);
 
345
    else if ((!pdf->os_mode) && (n + pdf->ptr > pdf->buf_size))
 
346
        pdf_flush(pdf);
 
347
}
 
348
 
 
349
 
 
350
/* print out a character to PDF buffer; the character will be printed in octal
 
351
 * form in the following cases: chars <= 32, backslash (92), left parenthesis
 
352
 * (40) and  right parenthesis (41)
 
353
 */
 
354
 
 
355
#define pdf_print_escaped(c)                                  \
 
356
  if ((c)<=32||(c)=='\\'||(c)=='('||(c)==')'||(c)>127) {      \
 
357
    pdf_room(pdf,4);                                          \
 
358
    pdf_quick_out(pdf,'\\');                                  \
 
359
    pdf_quick_out(pdf,'0' + (((c)>>6) & 0x3));                \
 
360
    pdf_quick_out(pdf,'0' + (((c)>>3) & 0x7));                \
 
361
    pdf_quick_out(pdf,'0' + ( (c)     & 0x7));                \
 
362
  } else {                                                    \
 
363
    pdf_out(pdf,(c));                                         \
 
364
  }
 
365
 
 
366
void pdf_print_char(PDF pdf, int c)
 
367
{
 
368
    if (c > 255)
 
369
        return;
 
370
    pdf_print_escaped(c);
 
371
}
 
372
 
 
373
void pdf_print_wide_char(PDF pdf, int c)
 
374
{
 
375
    char hex[5];
 
376
    snprintf(hex, 5, "%04X", c);
 
377
    pdf_room(pdf, 4);
 
378
    pdf_quick_out(pdf, hex[0]);
 
379
    pdf_quick_out(pdf, hex[1]);
 
380
    pdf_quick_out(pdf, hex[2]);
 
381
    pdf_quick_out(pdf, hex[3]);
 
382
}
 
383
 
 
384
void pdf_puts(PDF pdf, const char *s)
 
385
{
 
386
 
 
387
    size_t l = strlen(s);
 
388
    if (l < (size_t) pdf->buf_size) {
 
389
        pdf_room(pdf, l);
 
390
        while (*s != '\0')
 
391
            pdf_quick_out(pdf, *s++);
 
392
    } else {
 
393
        while (*s != '\0')
 
394
            pdf_out(pdf, *s++);
 
395
    }
 
396
}
 
397
 
 
398
__attribute__ ((format(printf, 2, 3)))
 
399
void pdf_printf(PDF pdf, const char *fmt, ...)
 
400
{
 
401
    va_list args;
 
402
    va_start(args, fmt);
 
403
    if (pdf->printf_buf == NULL) {
 
404
        pdf->printf_buf = xtalloc(PRINTF_BUF_SIZE, char);
 
405
    }
 
406
    (void) vsnprintf(pdf->printf_buf, PRINTF_BUF_SIZE, fmt, args);
 
407
    pdf_puts(pdf, pdf->printf_buf);
 
408
    va_end(args);
 
409
}
 
410
 
 
411
/* print out a string to PDF buffer */
 
412
 
 
413
void pdf_print(PDF pdf, str_number s)
 
414
{
 
415
    if (s < number_chars) {
 
416
        assert(s < 256);
 
417
        pdf_out(pdf, s);
 
418
    } else {
 
419
        unsigned char *k, *j;
 
420
        j = str_string(s) + str_length(s);
 
421
        for (k = str_string(s); k < j; k++) {
 
422
            pdf_out(pdf, *k);
 
423
        }
 
424
    }
 
425
}
 
426
 
 
427
/* print out a integer to PDF buffer */
 
428
 
 
429
void pdf_print_int(PDF pdf, longinteger n)
 
430
{
 
431
    register int k = 0;         /*  current digit; we assume that $|n|<10^{23}$ */
 
432
    int dig[24];
 
433
    if (n < 0) {
 
434
        pdf_out(pdf, '-');
 
435
        if (n < -0x7FFFFFFF) {  /* need to negate |n| more carefully */
 
436
            register longinteger m;
 
437
            k++;
 
438
            m = -1 - n;
 
439
            n = m / 10;
 
440
            m = (m % 10) + 1;
 
441
            if (m < 10) {
 
442
                dig[0] = m;
 
443
            } else {
 
444
                dig[0] = 0;
 
445
                n++;
 
446
            }
 
447
        } else {
 
448
            n = -n;
 
449
        }
 
450
    }
 
451
    do {
 
452
        dig[k++] = n % 10;
 
453
        n = n / 10;
 
454
    } while (n != 0);
 
455
    pdf_room(pdf, k);
 
456
    while (k-- > 0) {
 
457
        pdf_quick_out(pdf, '0' + dig[k]);
 
458
    }
 
459
}
 
460
 
 
461
/* print $m/10^d$ as real */
 
462
 
 
463
void pdf_print_real(PDF pdf, int m, int d)
 
464
{
 
465
    if (m < 0) {
 
466
        pdf_out(pdf, '-');
 
467
        m = -m;
 
468
    };
 
469
    pdf_print_int(pdf, m / ten_pow[d]);
 
470
    m = m % ten_pow[d];
 
471
    if (m > 0) {
 
472
        pdf_out(pdf, '.');
 
473
        d--;
 
474
        while (m < ten_pow[d]) {
 
475
            pdf_out(pdf, '0');
 
476
            d--;
 
477
        }
 
478
        while (m % 10 == 0)
 
479
            m = m / 10;
 
480
        pdf_print_int(pdf, m);
 
481
    }
 
482
}
 
483
 
 
484
/* print out |s| as string in PDF output */
 
485
 
 
486
void pdf_print_str(PDF pdf, char *s)
 
487
{
 
488
    char *orig = s;
 
489
    int l = strlen(s) - 1;      /* last string index */
 
490
    if (l < 0) {
 
491
        pdf_puts(pdf, "()");
 
492
        return;
 
493
    }
 
494
    /* the next is not really safe, the string could be "(a)xx(b)" */
 
495
    if ((s[0] == '(') && (s[l] == ')')) {
 
496
        pdf_puts(pdf, s);
 
497
        return;
 
498
    }
 
499
    if ((s[0] != '<') || (s[l] != '>') || odd((l + 1))) {
 
500
        pdf_out(pdf, '(');
 
501
        pdf_puts(pdf, s);
 
502
        pdf_out(pdf, ')');
 
503
        return;
 
504
    }
 
505
    s++;
 
506
    while (is_hex_char(*s))
 
507
        s++;
 
508
    if (s != orig + l) {
 
509
        pdf_out(pdf, '(');
 
510
        pdf_puts(pdf, orig);
 
511
        pdf_out(pdf, ')');
 
512
        return;
 
513
    }
 
514
    pdf_puts(pdf, orig);        /* it was a hex string after all  */
 
515
}
 
516
 
 
517
/* begin a stream */
 
518
 
 
519
void pdf_begin_stream(PDF pdf)
 
520
{
 
521
    assert(pdf->os_mode == false);
 
522
    pdf_puts(pdf, "/Length           \n");
 
523
    pdf->seek_write_length = true;      /* fill in length at |pdf_end_stream| call */
 
524
    pdf->stream_length_offset = pdf_offset(pdf) - 11;
 
525
    pdf->stream_length = 0;
 
526
    pdf->last_byte = 0;
 
527
    if (pdf->compress_level > 0) {
 
528
        pdf_puts(pdf, "/Filter /FlateDecode\n");
 
529
        pdf_puts(pdf, ">>\n");
 
530
        pdf_puts(pdf, "stream\n");
 
531
        pdf_flush(pdf);
 
532
        pdf->zip_write_state = zip_writing;
 
533
    } else {
 
534
        pdf_puts(pdf, ">>\n");
 
535
        pdf_puts(pdf, "stream\n");
 
536
        pdf_save_offset(pdf);
 
537
    }
 
538
}
 
539
 
 
540
/* end a stream */
 
541
 
 
542
void pdf_end_stream(PDF pdf)
 
543
{
 
544
    if (pdf->zip_write_state == zip_writing)
 
545
        pdf->zip_write_state = zip_finish;
 
546
    else
 
547
        pdf->stream_length = pdf_offset(pdf) - pdf_saved_offset(pdf);
 
548
    pdf_flush(pdf);
 
549
    if (pdf->seek_write_length)
 
550
        write_stream_length(pdf, pdf->stream_length, pdf->stream_length_offset);
 
551
    pdf->seek_write_length = false;
 
552
    if (pdf->last_byte != pdf_new_line_char)
 
553
        pdf_out(pdf, pdf_new_line_char);
 
554
    pdf_puts(pdf, "endstream\n");
 
555
    pdf_end_obj(pdf);
 
556
}
 
557
 
 
558
void pdf_remove_last_space(PDF pdf)
 
559
{
 
560
    if ((pdf->ptr > 0) && (pdf->buf[pdf->ptr - 1] == ' '))
 
561
        pdf->ptr--;
 
562
}
 
563
 
 
564
/*
 
565
To print |scaled| value to PDF output we need some subroutines to ensure
 
566
accurary.
 
567
*/
 
568
 
 
569
#define max_integer 0x7FFFFFFF  /* $2^{31}-1$ */
 
570
 
 
571
/* scaled value corresponds to 100in, exact, 473628672 */
 
572
scaled one_hundred_inch = 7227 * 65536;
 
573
 
 
574
/* scaled value corresponds to 1in (rounded to 4736287) */
 
575
scaled one_inch = (7227 * 65536 + 50) / 100;
 
576
 
 
577
    /* scaled value corresponds to 1truein (rounded!) */
 
578
scaled one_true_inch = (7227 * 65536 + 50) / 100;
 
579
 
 
580
/* scaled value corresponds to 100bp */
 
581
scaled one_hundred_bp = (7227 * 65536) / 72;
 
582
 
 
583
/* scaled value corresponds to 1bp (rounded to 65782) */
 
584
scaled one_bp = ((7227 * 65536) / 72 + 50) / 100;
 
585
 
 
586
/* $10^0..10^9$ */
 
587
int ten_pow[10] = {
 
588
    1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000
 
589
};
 
590
 
 
591
/*
 
592
The function |divide_scaled| divides |s| by |m| using |dd| decimal
 
593
digits of precision. It is defined in C because it is a good candidate
 
594
for optimizations that are not possible in pascal.
 
595
*/
 
596
 
 
597
scaled round_xn_over_d(scaled x, int n, int d)
 
598
{
 
599
    boolean positive;           /* was |x>=0|? */
 
600
    unsigned t, u, v;           /* intermediate quantities */
 
601
    if (x >= 0) {
 
602
        positive = true;
 
603
    } else {
 
604
        x = -(x);
 
605
        positive = false;
 
606
    }
 
607
    t = (x % 0100000) * n;
 
608
    u = (x / 0100000) * n + (t / 0100000);
 
609
    v = (u % d) * 0100000 + (t % 0100000);
 
610
    if (u / d >= 0100000)
 
611
        arith_error = true;
 
612
    else
 
613
        u = 0100000 * (u / d) + (v / d);
 
614
    v = v % d;
 
615
    if (2 * v >= (unsigned) d)
 
616
        u++;
 
617
    if (positive)
 
618
        return u;
 
619
    else
 
620
        return (-u);
 
621
}
 
622
 
 
623
#define lround(a) (long) floor((a) + 0.5)
 
624
 
 
625
void pdf_print_bp(PDF pdf, scaled s)
 
626
{                               /* print scaled as |bp| */
 
627
    pdffloat a;
 
628
    pdfstructure *p = pdf->pstruct;
 
629
    assert(p != NULL);
 
630
    a.m = lround(s * p->k1);
 
631
    a.e = pdf->decimal_digits;
 
632
    print_pdffloat(pdf, a);
 
633
}
 
634
 
 
635
void pdf_print_mag_bp(PDF pdf, scaled s)
 
636
{                               /* take |mag| into account */
 
637
    pdffloat a;
 
638
    pdfstructure *p = pdf->pstruct;
 
639
    prepare_mag();
 
640
    if (int_par(mag_code) != 1000)
 
641
        a.m = lround(s * (long) int_par(mag_code) / 1000.0 * p->k1);
 
642
    else
 
643
        a.m = lround(s * p->k1);
 
644
    a.e = pdf->decimal_digits;
 
645
    print_pdffloat(pdf, a);
 
646
}
 
647
 
 
648
#define set_p_or_return(a) do {                 \
 
649
        p = a;                                  \
 
650
        if (p==NULL) {                          \
 
651
            a = item;                           \
 
652
            return;                             \
 
653
        }                                       \
 
654
    } while (0)
 
655
 
 
656
 
 
657
/**********************************************************************/
 
658
 
 
659
void reset_resource_lists(pdf_resource_struct * p)
 
660
{
 
661
    p->obj_list = NULL;
 
662
    p->font_list = NULL;
 
663
    p->xform_list = NULL;
 
664
    p->ximage_list = NULL;
 
665
    p->dest_list = NULL;
 
666
    p->link_list = NULL;
 
667
    p->annot_list = NULL;
 
668
    p->bead_list = NULL;
 
669
    p->text_procset = false;
 
670
    p->image_procset = 0;
 
671
}
 
672
 
 
673
void append_object_list(PDF pdf, pdf_obj_type t, int objnum)
 
674
{
 
675
    pdf_object_list *p;
 
676
    pdf_object_list *item = xmalloc(sizeof(pdf_object_list));
 
677
    item->link = NULL;
 
678
    item->info = objnum;
 
679
    switch (t) {
 
680
    /* *INDENT-OFF* */
 
681
    case obj_type_obj:    set_p_or_return(pdf->resources->obj_list);    break;
 
682
    case obj_type_font:   set_p_or_return(pdf->resources->font_list);   break;
 
683
    case obj_type_xform:  set_p_or_return(pdf->resources->xform_list);  break;
 
684
    case obj_type_ximage: set_p_or_return(pdf->resources->ximage_list); break;
 
685
    case obj_type_dest:   set_p_or_return(pdf->resources->dest_list);   break;
 
686
    case obj_type_link:   set_p_or_return(pdf->resources->link_list);   break;
 
687
    case obj_type_annot:  set_p_or_return(pdf->resources->annot_list);  break;
 
688
    case obj_type_bead:   set_p_or_return(pdf->resources->bead_list);   break;
 
689
    default:              assert(0);                         break;
 
690
    /* *INDENT-ON* */
 
691
    }
 
692
    while (p->link != NULL)
 
693
        p = p->link;
 
694
    p->link = item;
 
695
    set_obj_scheduled(pdf, objnum);
 
696
    return;
 
697
}
 
698
 
 
699
/* return zero on failure, or the object  */
 
700
pdf_object_list *lookup_object_list(PDF pdf, pdf_obj_type t, int f)
 
701
{
 
702
    pdf_object_list *p;
 
703
    switch (t) {
 
704
    /* *INDENT-OFF* */
 
705
    case obj_type_obj:    p = pdf->resources->obj_list; break;
 
706
    case obj_type_font:   p = pdf->resources->font_list; break;
 
707
    case obj_type_xform:  p = pdf->resources->xform_list; break;
 
708
    case obj_type_ximage: p = pdf->resources->ximage_list; break;
 
709
    case obj_type_dest:   p = pdf->resources->dest_list; break;
 
710
    case obj_type_link:   p = pdf->resources->link_list; break;
 
711
    case obj_type_annot:  p = pdf->resources->annot_list; break;
 
712
    case obj_type_bead:   p = pdf->resources->bead_list; break;
 
713
    default:              return NULL;  break;  /* shouldnt happen */
 
714
    /* *INDENT-ON* */
 
715
    }
 
716
    while (p != NULL) {
 
717
        if (p->info == f)
 
718
            return p;
 
719
        p = p->link;
 
720
    }
 
721
    return NULL;
 
722
}
 
723
 
 
724
static void flush_object_list(PDF pdf, pdf_obj_type t)
 
725
{
 
726
    pdf_object_list *q, *p;
 
727
    switch (t) {
 
728
    /* *INDENT-OFF* */
 
729
    case obj_type_obj:    p = pdf->resources->obj_list; break;
 
730
    case obj_type_font:   p = pdf->resources->font_list; break;
 
731
    case obj_type_xform:  p = pdf->resources->xform_list; break;
 
732
    case obj_type_ximage: p = pdf->resources->ximage_list; break;
 
733
    case obj_type_dest:   p = pdf->resources->dest_list; break;
 
734
    case obj_type_link:   p = pdf->resources->link_list; break;
 
735
    case obj_type_annot:  p = pdf->resources->annot_list; break;
 
736
    case obj_type_bead:   p = pdf->resources->bead_list; break;
 
737
    default:              return;  break;
 
738
    /* *INDENT-ON* */
 
739
    }
 
740
    while (p != NULL) {
 
741
        q = p;
 
742
        p = p->link;
 
743
        free(q);
 
744
    }
 
745
    switch (t) {
 
746
    /* *INDENT-OFF* */
 
747
    case obj_type_obj:    pdf->resources->obj_list = NULL; break;
 
748
    case obj_type_font:   pdf->resources->font_list = NULL; break;
 
749
    case obj_type_xform:  pdf->resources->xform_list = NULL; break;
 
750
    case obj_type_ximage: pdf->resources->ximage_list = NULL; break;
 
751
    case obj_type_dest:   pdf->resources->dest_list = NULL; break;
 
752
    case obj_type_link:   pdf->resources->link_list = NULL; break;
 
753
    case obj_type_annot:  pdf->resources->annot_list = NULL; break;
 
754
    case obj_type_bead:   pdf->resources->bead_list = NULL; break;
 
755
    default:              break; /* cant happen */
 
756
    /* *INDENT-ON* */
 
757
    }
 
758
}
 
759
 
 
760
void flush_resource_lists(PDF pdf)
 
761
{
 
762
    flush_object_list(pdf, obj_type_font);
 
763
    flush_object_list(pdf, obj_type_obj);
 
764
    flush_object_list(pdf, obj_type_xform);
 
765
    flush_object_list(pdf, obj_type_ximage);
 
766
    /* the following lists are nonzero only if shipping_page */
 
767
    flush_object_list(pdf, obj_type_annot);
 
768
    flush_object_list(pdf, obj_type_link);
 
769
    flush_object_list(pdf, obj_type_dest);
 
770
    flush_object_list(pdf, obj_type_bead);
 
771
}
 
772
 
 
773
/**********************************************************************/
 
774
 
 
775
/* Subroutines to print out various PDF objects */
 
776
 
 
777
/* print out an integer with fixed width; used for outputting cross-reference table */
 
778
void pdf_print_fw_int(PDF pdf, longinteger n, int w)
 
779
{
 
780
    int k;                      /* $0\le k\le23$ */
 
781
    int dig[24];
 
782
    k = 0;
 
783
    do {
 
784
        dig[k] = n % 10;
 
785
        n = n / 10;
 
786
        k++;
 
787
    } while (k != w);
 
788
    pdf_room(pdf, k);
 
789
    while (k-- > 0)
 
790
        pdf_quick_out(pdf, '0' + dig[k]);
 
791
}
 
792
 
 
793
/* print out an integer as a number of bytes; used for outputting \.{/XRef} cross-reference stream */
 
794
void pdf_out_bytes(PDF pdf, longinteger n, int w)
 
795
{
 
796
    int k;
 
797
    int bytes[8];               /* digits in a number being output */
 
798
    k = 0;
 
799
    do {
 
800
        bytes[k] = n % 256;
 
801
        n = n / 256;
 
802
        k++;
 
803
    } while (k != w);
 
804
    pdf_room(pdf, k);
 
805
    while (k-- > 0)
 
806
        pdf_quick_out(pdf, bytes[k]);
 
807
}
 
808
 
 
809
/* print out an entry in dictionary with integer value to PDF buffer */
 
810
 
 
811
void pdf_int_entry(PDF pdf, char *s, int v)
 
812
{
 
813
    pdf_printf(pdf, "/%s ", s);
 
814
    pdf_print_int(pdf, v);
 
815
} void pdf_int_entry_ln(PDF pdf, char *s, int v)
 
816
{
 
817
 
 
818
    pdf_int_entry(pdf, s, v);
 
819
    pdf_print_nl(pdf);
 
820
}
 
821
 
 
822
/* print out an indirect entry in dictionary */
 
823
void pdf_indirect(PDF pdf, char *s, int o)
 
824
{
 
825
    pdf_printf(pdf, "/%s %d 0 R", s, (int) o);
 
826
} void pdf_indirect_ln(PDF pdf, char *s, int o)
 
827
{
 
828
 
 
829
    pdf_indirect(pdf, s, o);
 
830
    pdf_print_nl(pdf);
 
831
}
 
832
 
 
833
/* print out |s| as string in PDF output */
 
834
void pdf_print_str_ln(PDF pdf, char *s)
 
835
{
 
836
    pdf_print_str(pdf, s);
 
837
    pdf_print_nl(pdf);
 
838
}
 
839
 
 
840
/* print out an entry in dictionary with string value to PDF buffer */
 
841
void pdf_str_entry(PDF pdf, char *s, char *v)
 
842
{
 
843
    if (v == 0)
 
844
        return;
 
845
    pdf_printf(pdf, "/%s ", s);
 
846
    pdf_print_str(pdf, v);
 
847
}
 
848
 
 
849
void pdf_str_entry_ln(PDF pdf, char *s, char *v)
 
850
{
 
851
    if (v == 0)
 
852
        return;
 
853
    pdf_str_entry(pdf, s, v);
 
854
    pdf_print_nl(pdf);
 
855
}
 
856
 
 
857
void pdf_print_toks(PDF pdf, halfword p)
 
858
{
 
859
    int len = 0;
 
860
    char *s = tokenlist_to_cstring(p, true, &len);
 
861
    if (len > 0)
 
862
        pdf_puts(pdf, s);
 
863
    xfree(s);
 
864
}
 
865
 
 
866
 
 
867
void pdf_print_toks_ln(PDF pdf, halfword p)
 
868
{
 
869
    int len = 0;
 
870
    char *s = tokenlist_to_cstring(p, true, &len);
 
871
    if (len > 0) {
 
872
        pdf_puts(pdf, s);
 
873
        pdf_print_nl(pdf);
 
874
    }
 
875
    xfree(s);
 
876
}
 
877
 
 
878
/* prints a rect spec */
 
879
void pdf_print_rect_spec(PDF pdf, halfword r)
 
880
{
 
881
    pdf_print_mag_bp(pdf, pdf_ann_left(r));
 
882
    pdf_out(pdf, ' ');
 
883
    pdf_print_mag_bp(pdf, pdf_ann_bottom(r));
 
884
    pdf_out(pdf, ' ');
 
885
    pdf_print_mag_bp(pdf, pdf_ann_right(r));
 
886
    pdf_out(pdf, ' ');
 
887
    pdf_print_mag_bp(pdf, pdf_ann_top(r));
 
888
}
 
889
 
 
890
/* output a rectangle specification to PDF file */
 
891
void pdf_rectangle(PDF pdf, halfword r)
 
892
{
 
893
    prepare_mag();
 
894
    pdf_puts(pdf, "/Rect [");
 
895
    pdf_print_rect_spec(pdf, r);
 
896
    pdf_puts(pdf, "]\n");
 
897
}
 
898
 
 
899
static void init_pdf_outputparameters(PDF pdf)
 
900
{
 
901
    assert(pdf->o_mode == OMODE_PDF);
 
902
    pdf->draftmode = fix_int(pdf_draftmode, 0, 1);
 
903
    pdf->compress_level = fix_int(pdf_compress_level, 0, 9);
 
904
    pdf->decimal_digits = fix_int(pdf_decimal_digits, 0, 4);
 
905
    pdf->gamma = fix_int(pdf_gamma, 0, 1000000);
 
906
    pdf->image_gamma = fix_int(pdf_image_gamma, 0, 1000000);
 
907
    pdf->image_hicolor = fix_int(pdf_image_hicolor, 0, 1);
 
908
    pdf->image_apply_gamma = fix_int(pdf_image_apply_gamma, 0, 1);
 
909
    pdf->objcompresslevel = fix_int(pdf_objcompresslevel, 0, 3);
 
910
    pdf->inclusion_copy_font = fix_int(pdf_inclusion_copy_font, 0, 1);
 
911
    pdf->replace_font = fix_int(pdf_replace_font, 0, 1);
 
912
    pdf->pk_resolution = fix_int(pdf_pk_resolution, 72, 8000);
 
913
    if ((pdf->minor_version >= 5) && (pdf->objcompresslevel > 0)) {
 
914
        pdf->os_enable = true;
 
915
    } else {
 
916
        if (pdf->objcompresslevel > 0) {
 
917
            pdf_warning("Object streams",
 
918
                        "\\pdfobjcompresslevel > 0 requires \\pdfminorversion > 4. Object streams disabled now.",
 
919
                        true, true);
 
920
            pdf->objcompresslevel = 0;
 
921
        }
 
922
        pdf->os_enable = false;
 
923
    }
 
924
    if (pdf->pk_resolution == 0)        /* if not set from format file or by user */
 
925
        pdf->pk_resolution = pk_dpi;    /* take it from \.{texmf.cnf} */
 
926
    pdf->pk_scale_factor =
 
927
        divide_scaled(72, pdf->pk_resolution, 5 + pdf->decimal_digits);
 
928
    if (!callback_defined(read_pk_file_callback)) {
 
929
        if (pdf_pk_mode != null) {
 
930
            char *s = tokenlist_to_cstring(pdf_pk_mode, true, NULL);
 
931
            kpseinitprog("PDFTEX", pdf->pk_resolution, s, nil);
 
932
            xfree(s);
 
933
        } else {
 
934
            kpseinitprog("PDFTEX", pdf->pk_resolution, nil, nil);
 
935
        }
 
936
        if (!kpsevarvalue("MKTEXPK"))
 
937
            kpsesetprogramenabled(kpsepkformat, 1, kpsesrccmdline);
 
938
    }
 
939
    set_job_id(pdf, int_par(year_code),
 
940
               int_par(month_code), int_par(day_code), int_par(time_code));
 
941
    if ((pdf_unique_resname > 0) && (pdf->resname_prefix == NULL))
 
942
        pdf->resname_prefix = get_resname_prefix(pdf);
 
943
}
 
944
 
 
945
/**********************************************************************/
 
946
 
 
947
/* Checks that we have a name for the generated PDF file and that it's open. */
 
948
 
 
949
static void ensure_output_file_open(PDF pdf, char *ext)
 
950
{
 
951
    char *fn;
 
952
    if (pdf->file_name != NULL)
 
953
        return;
 
954
    if (job_name == 0)
 
955
        open_log_file();
 
956
    fn = pack_job_name(ext);
 
957
    if (pdf->draftmode == 0 || pdf->o_mode == OMODE_DVI) {
 
958
        while (!lua_b_open_out(&pdf->file, fn))
 
959
            fn = prompt_file_name("file name for output", ext);
 
960
    }
 
961
    pdf->file_name = fn;
 
962
}
 
963
 
 
964
static void ensure_pdf_header_written(PDF pdf)
 
965
{
 
966
    assert(pdf->o_state == ST_FILE_OPEN);
 
967
    assert(pdf->o_mode == OMODE_PDF);
 
968
    /* Initialize variables for \.{PDF} output */
 
969
    fix_pdf_minorversion(pdf);
 
970
    init_pdf_outputparameters(pdf);
 
971
    /* Write \.{PDF} header */
 
972
    pdf_printf(pdf, "%%PDF-1.%d\n", pdf->minor_version);
 
973
    pdf_out(pdf, '%');
 
974
    pdf_out(pdf, 'P' + 128);
 
975
    pdf_out(pdf, 'T' + 128);
 
976
    pdf_out(pdf, 'E' + 128);
 
977
    pdf_out(pdf, 'X' + 128);
 
978
    pdf_print_nl(pdf);
 
979
}
 
980
 
 
981
void ensure_output_state(PDF pdf, output_state s)
 
982
{
 
983
    if (pdf->o_state < s) {
 
984
        if (s > ST_INITIAL)
 
985
            ensure_output_state(pdf, s - 1);
 
986
        switch (s - 1) {
 
987
        case ST_INITIAL:
 
988
            fix_o_mode(pdf);
 
989
            break;
 
990
        case ST_OMODE_FIX:
 
991
            switch (pdf->o_mode) {
 
992
            case OMODE_DVI:
 
993
                ensure_output_file_open(pdf, ".dvi");
 
994
                break;
 
995
            case OMODE_PDF:
 
996
                ensure_output_file_open(pdf, ".pdf");
 
997
                break;
 
998
            case OMODE_LUA:
 
999
                break;
 
1000
            default:
 
1001
                assert(0);
 
1002
            }
 
1003
            break;
 
1004
        case ST_FILE_OPEN:
 
1005
            switch (pdf->o_mode) {
 
1006
            case OMODE_DVI:
 
1007
                ensure_dvi_header_written(pdf);
 
1008
                break;
 
1009
            case OMODE_PDF:
 
1010
                ensure_pdf_header_written(pdf);
 
1011
                break;
 
1012
            case OMODE_LUA:
 
1013
                break;
 
1014
            default:
 
1015
                assert(0);
 
1016
            }
 
1017
            break;
 
1018
        case ST_HEADER_WRITTEN:
 
1019
            break;
 
1020
        case ST_FILE_CLOSED:
 
1021
            break;
 
1022
        default:
 
1023
            assert(0);
 
1024
        }
 
1025
        pdf->o_state++;
 
1026
    }
 
1027
}
 
1028
 
 
1029
/**********************************************************************/
 
1030
 
 
1031
/* begin a PDF dictionary object */
 
1032
void pdf_begin_dict(PDF pdf, int i, int pdf_os_level)
 
1033
{
 
1034
    ensure_output_state(pdf, ST_HEADER_WRITTEN);
 
1035
    pdf_os_prepare_obj(pdf, i, pdf_os_level);
 
1036
    if (!pdf->os_mode) {
 
1037
        pdf_printf(pdf, "%d 0 obj <<\n", (int) i);
 
1038
    } else {
 
1039
        if (pdf->compress_level == 0)
 
1040
            pdf_printf(pdf, "%% %d 0 obj\n", (int) i);  /* debugging help */
 
1041
        pdf_puts(pdf, "<<\n");
 
1042
    }
 
1043
}
 
1044
 
 
1045
/* begin a new PDF dictionary object */
 
1046
void pdf_new_dict(PDF pdf, int t, int i, int pdf_os)
 
1047
{
 
1048
    pdf_create_obj(pdf, t, i);
 
1049
    pdf_begin_dict(pdf, pdf->obj_ptr, pdf_os);
 
1050
}
 
1051
 
 
1052
/* end a PDF dictionary object */
 
1053
void pdf_end_dict(PDF pdf)
 
1054
{
 
1055
    if (pdf->os_mode) {
 
1056
        pdf_puts(pdf, ">>\n");
 
1057
        if (pdf->os_idx == pdf_os_max_objs - 1)
 
1058
            pdf_os_write_objstream(pdf);
 
1059
    } else {
 
1060
        pdf_puts(pdf, ">> endobj\n");
 
1061
    }
 
1062
}
 
1063
 
 
1064
 
 
1065
/*
 
1066
Write out an accumulated object stream.
 
1067
First the object number and byte offset pairs are generated
 
1068
and appended to the ready buffered object stream.
 
1069
By this the value of \.{/First} can be calculated.
 
1070
Then a new \.{/ObjStm} object is generated, and everything is
 
1071
copied to the PDF output buffer, where also compression is done.
 
1072
When calling this procedure, |pdf_os_mode| must be |true|.
 
1073
*/
 
1074
 
 
1075
void pdf_os_write_objstream(PDF pdf)
 
1076
{
 
1077
    halfword i, j, p, q;
 
1078
    if (pdf->os_cur_objnum == 0)        /* no object stream started */
 
1079
        return;
 
1080
    p = pdf->ptr;
 
1081
    i = 0;
 
1082
    j = 0;
 
1083
    while (i <= pdf->os_idx) {  /* assemble object number and byte offset pairs */
 
1084
        pdf_printf(pdf, "%d %d", (int) pdf->os_obj[i].num,
 
1085
                   (int) pdf->os_obj[i].off);
 
1086
        if (j == 9) {           /* print out in groups of ten for better readability */
 
1087
            pdf_out(pdf, pdf_new_line_char);
 
1088
            j = 0;
 
1089
        } else {
 
1090
            pdf_out(pdf, ' ');
 
1091
            j++;
 
1092
        }
 
1093
        i++;
 
1094
    }
 
1095
    pdf->buf[pdf->ptr - 1] = pdf_new_line_char; /* no risk of flush, as we are in |pdf_os_mode| */
 
1096
    q = pdf->ptr;
 
1097
    pdf_begin_dict(pdf, pdf->os_cur_objnum, 0); /* switch to PDF stream writing */
 
1098
    pdf_puts(pdf, "/Type /ObjStm\n");
 
1099
    pdf_printf(pdf, "/N %d\n", (int) (pdf->os_idx + 1));
 
1100
    pdf_printf(pdf, "/First %d\n", (int) (q - p));
 
1101
    pdf_begin_stream(pdf);
 
1102
    pdf_room(pdf, q - p);       /* should always fit into the PDF output buffer */
 
1103
    i = p;
 
1104
    while (i < q) {             /* write object number and byte offset pairs */
 
1105
        pdf_quick_out(pdf, pdf->os_buf[i]);
 
1106
        i++;
 
1107
    }
 
1108
    i = 0;
 
1109
    while (i < p) {
 
1110
        q = i + pdf->buf_size;
 
1111
        if (q > p)
 
1112
            q = p;
 
1113
        pdf_room(pdf, q - i);
 
1114
        while (i < q) {         /* write the buffered objects */
 
1115
            pdf_quick_out(pdf, pdf->os_buf[i]);
 
1116
            i++;
 
1117
        }
 
1118
    }
 
1119
    pdf_end_stream(pdf);
 
1120
    pdf->os_cur_objnum = 0;     /* to force object stream generation next time */
 
1121
}
 
1122
 
 
1123
/* begin a PDF object */
 
1124
void pdf_begin_obj(PDF pdf, int i, int pdf_os_level)
 
1125
{
 
1126
    ensure_output_state(pdf, ST_HEADER_WRITTEN);
 
1127
    pdf_os_prepare_obj(pdf, i, pdf_os_level);
 
1128
    if (!pdf->os_mode) {
 
1129
        pdf_printf(pdf, "%d 0 obj\n", (int) i);
 
1130
    } else if (pdf->compress_level == 0) {
 
1131
        pdf_printf(pdf, "%% %d 0 obj\n", (int) i);      /* debugging help */
 
1132
    }
 
1133
}
 
1134
 
 
1135
/* begin a new PDF object */
 
1136
void pdf_new_obj(PDF pdf, int t, int i, int pdf_os)
 
1137
{
 
1138
    pdf_create_obj(pdf, t, i);
 
1139
    pdf_begin_obj(pdf, pdf->obj_ptr, pdf_os);
 
1140
}
 
1141
 
 
1142
/* end a PDF object */
 
1143
void pdf_end_obj(PDF pdf)
 
1144
{
 
1145
    if (pdf->os_mode) {
 
1146
        if (pdf->os_idx == pdf_os_max_objs - 1)
 
1147
            pdf_os_write_objstream(pdf);
 
1148
    } else {
 
1149
        pdf_puts(pdf, "endobj\n");      /* end a PDF object */
 
1150
    }
 
1151
}
 
1152
 
 
1153
void write_stream_length(PDF pdf, int length, longinteger offset)
 
1154
{
 
1155
    if (jobname_cstr == NULL)
 
1156
        jobname_cstr = makecstring(job_name);
 
1157
    if (pdf->draftmode == 0) {
 
1158
        xfseeko(pdf->file, (off_t) offset, SEEK_SET, jobname_cstr);
 
1159
        fprintf(pdf->file, "%li", (long int) length);
 
1160
        xfseeko(pdf->file, pdf_offset(pdf), SEEK_SET, jobname_cstr);
 
1161
    }
 
1162
}
 
1163
 
 
1164
/* Converts any string given in in in an allowed PDF string which can be
 
1165
 * handled by printf et.al.: \ is escaped to \\, parenthesis are escaped and
 
1166
 * control characters are octal encoded.
 
1167
 * This assumes that the string does not contain any already escaped
 
1168
 * characters!
 
1169
 */
 
1170
char *convertStringToPDFString(const char *in, int len)
 
1171
{
 
1172
    static char pstrbuf[MAX_PSTRING_LEN];
 
1173
    char *out = pstrbuf;
 
1174
    int i, j, k;
 
1175
    char buf[5];
 
1176
    j = 0;
 
1177
    for (i = 0; i < len; i++) {
 
1178
        check_buf(j + sizeof(buf), MAX_PSTRING_LEN);
 
1179
        if (((unsigned char) in[i] < '!') || ((unsigned char) in[i] > '~')) {
 
1180
            /* convert control characters into oct */
 
1181
            k = snprintf(buf, sizeof(buf),
 
1182
                         "\\%03o", (unsigned int) (unsigned char) in[i]);
 
1183
            check_nprintf(k, sizeof(buf));
 
1184
            out[j++] = buf[0];
 
1185
            out[j++] = buf[1];
 
1186
            out[j++] = buf[2];
 
1187
            out[j++] = buf[3];
 
1188
        } else if ((in[i] == '(') || (in[i] == ')')) {
 
1189
            /* escape paranthesis */
 
1190
            out[j++] = '\\';
 
1191
            out[j++] = in[i];
 
1192
        } else if (in[i] == '\\') {
 
1193
            /* escape backslash */
 
1194
            out[j++] = '\\';
 
1195
            out[j++] = '\\';
 
1196
        } else {
 
1197
            /* copy char :-) */
 
1198
            out[j++] = in[i];
 
1199
        }
 
1200
    }
 
1201
    out[j] = '\0';
 
1202
    return pstrbuf;
 
1203
}
 
1204
 
 
1205
/* Converts any string given in in in an allowed PDF string which is
 
1206
 * hexadecimal encoded;
 
1207
 * sizeof(out) should be at least lin*2+1.
 
1208
 */
 
1209
 
 
1210
static void convertStringToHexString(const char *in, char *out, int lin)
 
1211
{
 
1212
    int i, j, k;
 
1213
    char buf[3];
 
1214
    j = 0;
 
1215
    for (i = 0; i < lin; i++) {
 
1216
        k = snprintf(buf, sizeof(buf),
 
1217
                     "%02X", (unsigned int) (unsigned char) in[i]);
 
1218
        check_nprintf(k, sizeof(buf));
 
1219
        out[j++] = buf[0];
 
1220
        out[j++] = buf[1];
 
1221
    }
 
1222
    out[j] = '\0';
 
1223
}
 
1224
 
 
1225
/* Compute the ID string as per PDF1.4 9.3:
 
1226
  <blockquote>
 
1227
    File identifers are defined by the optional ID entry in a PDF file's
 
1228
    trailer dictionary (see Section 3.4.4, "File Trailer"; see also
 
1229
    implementation note 105 in Appendix H). The value of this entry is an
 
1230
    array of two strings. The first string is a permanent identifier based
 
1231
    on the contents of the file at the time it was originally created, and
 
1232
    does not change when the file is incrementally updated. The second
 
1233
    string is a changing identifier based on the file's contents at the
 
1234
    time it was last updated. When a file is first written, both
 
1235
    identifiers are set to the same value. If both identifiers match when a
 
1236
    file reference is resolved, it is very likely that the correct file has
 
1237
    been found; if only the first identifier matches, then a different
 
1238
    version of the correct file has been found.
 
1239
        To help ensure the uniqueness of file identifiers, it is recommend
 
1240
    that they be computed using a message digest algorithm such as MD5
 
1241
    (described in Internet RFC 1321, The MD5 Message-Digest Algorithm; see
 
1242
    the Bibliography), using the following information (see implementation
 
1243
    note 106 in Appendix H):
 
1244
    - The current time
 
1245
    - A string representation of the file's location, usually a pathname
 
1246
    - The size of the file in bytes
 
1247
    - The values of all entries in the file's document information
 
1248
      dictionary (see Section 9.2.1,  Document Information Dictionary )
 
1249
  </blockquote>
 
1250
  This stipulates only that the two IDs must be identical when the file is
 
1251
  created and that they should be reasonably unique. Since it's difficult
 
1252
  to get the file size at this point in the execution of pdfTeX and
 
1253
  scanning the info dict is also difficult, we start with a simpler
 
1254
  implementation using just the first two items.
 
1255
 */
 
1256
void print_ID(PDF pdf, char *file_name)
 
1257
{
 
1258
    time_t t;
 
1259
    size_t size;
 
1260
    char time_str[32];
 
1261
    md5_state_t state;
 
1262
    md5_byte_t digest[16];
 
1263
    char id[64];
 
1264
    char pwd[4096];
 
1265
    /* start md5 */
 
1266
    md5_init(&state);
 
1267
    /* get the time */
 
1268
    t = time(NULL);
 
1269
    size = strftime(time_str, sizeof(time_str), "%Y%m%dT%H%M%SZ", gmtime(&t));
 
1270
    md5_append(&state, (const md5_byte_t *) time_str, size);
 
1271
    /* get the file name */
 
1272
    if (getcwd(pwd, sizeof(pwd)) == NULL)
 
1273
        pdftex_fail("getcwd() failed (%s), (path too long?)", strerror(errno));
 
1274
    md5_append(&state, (const md5_byte_t *) pwd, strlen(pwd));
 
1275
    md5_append(&state, (const md5_byte_t *) "/", 1);
 
1276
    md5_append(&state, (const md5_byte_t *) file_name, strlen(file_name));
 
1277
    /* finish md5 */
 
1278
    md5_finish(&state, digest);
 
1279
    /* write the IDs */
 
1280
    convertStringToHexString((char *) digest, id, 16);
 
1281
    pdf_printf(pdf, "/ID [<%s> <%s>]", id, id);
 
1282
}
 
1283
 
 
1284
/* Print the /CreationDate entry.
 
1285
 
 
1286
  PDF Reference, third edition says about the expected date format:
 
1287
  <blockquote>
 
1288
    3.8.2 Dates
 
1289
 
 
1290
      PDF defines a standard date format, which closely follows that of
 
1291
      the international standard ASN.1 (Abstract Syntax Notation One),
 
1292
      defined in ISO/IEC 8824 (see the Bibliography). A date is a string
 
1293
      of the form
 
1294
 
 
1295
        (D:YYYYMMDDHHmmSSOHH'mm')
 
1296
 
 
1297
      where
 
1298
 
 
1299
        YYYY is the year
 
1300
        MM is the month
 
1301
        DD is the day (01-31)
 
1302
        HH is the hour (00-23)
 
1303
        mm is the minute (00-59)
 
1304
        SS is the second (00-59)
 
1305
        O is the relationship of local time to Universal Time (UT),
 
1306
          denoted by one of the characters +, -, or Z (see below)
 
1307
        HH followed by ' is the absolute value of the offset from UT
 
1308
          in hours (00-23)
 
1309
        mm followed by ' is the absolute value of the offset from UT
 
1310
          in minutes (00-59)
 
1311
 
 
1312
      The apostrophe character (') after HH and mm is part of the syntax.
 
1313
      All fields after the year are optional. (The prefix D:, although also
 
1314
      optional, is strongly recommended.) The default values for MM and DD
 
1315
      are both 01; all other numerical fields default to zero values.  A plus
 
1316
      sign (+) as the value of the O field signifies that local time is
 
1317
      later than UT, a minus sign (-) that local time is earlier than UT,
 
1318
      and the letter Z that local time is equal to UT. If no UT information
 
1319
      is specified, the relationship of the specified time to UT is
 
1320
      considered to be unknown. Whether or not the time zone is known, the
 
1321
      rest of the date should be specified in local time.
 
1322
 
 
1323
      For example, December 23, 1998, at 7:52 PM, U.S. Pacific Standard
 
1324
      Time, is represented by the string
 
1325
 
 
1326
        D:199812231952-08'00'
 
1327
  </blockquote>
 
1328
 
 
1329
  The main difficulty is get the time zone offset. strftime() does this in ISO
 
1330
  C99 (e.g. newer glibc) with %z, but we have to work with other systems (e.g.
 
1331
  Solaris 2.5).
 
1332
*/
 
1333
#define TIME_STR_SIZE 30        /* minimum size for time_str is 24: "D:YYYYmmddHHMMSS+HH'MM'" */
 
1334
static void makepdftime(PDF pdf)
 
1335
{
 
1336
    struct tm lt, gmt;
 
1337
    size_t size;
 
1338
    int i, off, off_hours, off_mins;
 
1339
    time_t t = pdf->start_time;
 
1340
    char *time_str = pdf->start_time_str;
 
1341
 
 
1342
    /* get the time */
 
1343
    lt = *localtime(&t);
 
1344
    size = strftime(time_str, TIME_STR_SIZE, "D:%Y%m%d%H%M%S", &lt);
 
1345
    /* expected format: "YYYYmmddHHMMSS" */
 
1346
    if (size == 0) {
 
1347
        /* unexpected, contents of time_str is undefined */
 
1348
        time_str[0] = '\0';
 
1349
        return;
 
1350
    }
 
1351
 
 
1352
    /* correction for seconds: %S can be in range 00..61,
 
1353
       the PDF reference expects 00..59,
 
1354
       therefore we map "60" and "61" to "59" */
 
1355
    if (time_str[14] == '6') {
 
1356
        time_str[14] = '5';
 
1357
        time_str[15] = '9';
 
1358
        time_str[16] = '\0';    /* for safety */
 
1359
    }
 
1360
 
 
1361
    /* get the time zone offset */
 
1362
    gmt = *gmtime(&t);
 
1363
 
 
1364
    /* this calculation method was found in exim's tod.c */
 
1365
    off = 60 * (lt.tm_hour - gmt.tm_hour) + lt.tm_min - gmt.tm_min;
 
1366
    if (lt.tm_year != gmt.tm_year) {
 
1367
        off += (lt.tm_year > gmt.tm_year) ? 1440 : -1440;
 
1368
    } else if (lt.tm_yday != gmt.tm_yday) {
 
1369
        off += (lt.tm_yday > gmt.tm_yday) ? 1440 : -1440;
 
1370
    }
 
1371
 
 
1372
    if (off == 0) {
 
1373
        time_str[size++] = 'Z';
 
1374
        time_str[size] = 0;
 
1375
    } else {
 
1376
        off_hours = off / 60;
 
1377
        off_mins = abs(off - off_hours * 60);
 
1378
        i = snprintf(&time_str[size], 9, "%+03d'%02d'", off_hours, off_mins);
 
1379
        check_nprintf(i, 9);
 
1380
    }
 
1381
    pdf->start_time = t;
 
1382
}
 
1383
 
 
1384
void init_start_time(PDF pdf)
 
1385
{
 
1386
    assert(pdf);
 
1387
    if (pdf->start_time == 0) {
 
1388
        pdf->start_time = time((time_t *) NULL);
 
1389
        pdf->start_time_str = xtalloc(TIME_STR_SIZE, char);
 
1390
        makepdftime(pdf);
 
1391
    }
 
1392
}
 
1393
 
 
1394
void print_creation_date(PDF pdf)
 
1395
{
 
1396
    init_start_time(pdf);
 
1397
    pdf_printf(pdf, "/CreationDate (%s)\n", pdf->start_time_str);
 
1398
}
 
1399
 
 
1400
void print_mod_date(PDF pdf)
 
1401
{
 
1402
    init_start_time(pdf);
 
1403
    pdf_printf(pdf, "/ModDate (%s)\n", pdf->start_time_str);
 
1404
}
 
1405
 
 
1406
char *getcreationdate(PDF pdf)
 
1407
{
 
1408
    assert(pdf);
 
1409
    init_start_time(pdf);
 
1410
    return pdf->start_time_str;
 
1411
}
 
1412
 
 
1413
void remove_pdffile(PDF pdf)
 
1414
{
 
1415
    if (pdf != NULL) {
 
1416
        if (!kpathsea_debug && pdf->file_name && (pdf->draftmode != 0)) {
 
1417
            xfclose(pdf->file, pdf->file_name);
 
1418
            remove(pdf->file_name);
 
1419
        }
 
1420
    }
 
1421
}
 
1422
 
 
1423
static void realloc_fb(PDF pdf)
 
1424
{
 
1425
    if (pdf->fb_array == NULL) {
 
1426
        pdf->fb_limit = SMALL_ARRAY_SIZE;
 
1427
        pdf->fb_array = xtalloc(pdf->fb_limit, char);
 
1428
        pdf->fb_ptr = pdf->fb_array;
 
1429
    } else if ((size_t) (pdf->fb_ptr - pdf->fb_array + 1) > pdf->fb_limit) {
 
1430
        size_t last_ptr_index = pdf->fb_ptr - pdf->fb_array;
 
1431
        pdf->fb_limit *= 2;
 
1432
        if ((size_t) (pdf->fb_ptr - pdf->fb_array + 1) > pdf->fb_limit)
 
1433
            pdf->fb_limit = pdf->fb_ptr - pdf->fb_array + 1;
 
1434
        xretalloc(pdf->fb_array, pdf->fb_limit, char);
 
1435
        pdf->fb_ptr = pdf->fb_array + last_ptr_index;
 
1436
    }
 
1437
}
 
1438
 
 
1439
int fb_offset(PDF pdf)
 
1440
{
 
1441
    return pdf->fb_ptr - pdf->fb_array;
 
1442
}
 
1443
 
 
1444
void fb_seek(PDF pdf, int offset)
 
1445
{
 
1446
    pdf->fb_ptr = pdf->fb_array + offset;
 
1447
}
 
1448
 
 
1449
 
 
1450
void fb_putchar(PDF pdf, eight_bits b)
 
1451
{
 
1452
    if ((size_t) (pdf->fb_ptr - pdf->fb_array + 1) > pdf->fb_limit)
 
1453
        realloc_fb(pdf);
 
1454
    *(pdf->fb_ptr)++ = b;
 
1455
}
 
1456
 
 
1457
void fb_flush(PDF pdf)
 
1458
{
 
1459
    char *p;
 
1460
    int n;
 
1461
    for (p = pdf->fb_array; p < pdf->fb_ptr;) {
 
1462
        n = pdf->buf_size - pdf->ptr;
 
1463
        if (pdf->fb_ptr - p < n)
 
1464
            n = pdf->fb_ptr - p;
 
1465
        memcpy(pdf->buf + pdf->ptr, p, (unsigned) n);
 
1466
        pdf->ptr += n;
 
1467
        if (pdf->ptr == pdf->buf_size)
 
1468
            pdf_flush(pdf);
 
1469
        p += n;
 
1470
    }
 
1471
    pdf->fb_ptr = pdf->fb_array;
 
1472
}
 
1473
 
 
1474
void fb_free(PDF pdf)
 
1475
{
 
1476
    xfree(pdf->fb_array);
 
1477
}
 
1478
 
 
1479
 
 
1480
#define ZIP_BUF_SIZE  32768
 
1481
 
 
1482
#define check_err(f, fn)                        \
 
1483
  if (f != Z_OK)                                \
 
1484
    pdftex_fail("zlib: %s() failed (error code %d)", fn, f)
 
1485
 
 
1486
void write_zip(PDF pdf, boolean finish)
 
1487
{
 
1488
    int err;
 
1489
    int level = pdf->compress_level;
 
1490
    assert(level > 0);
 
1491
    /* This was just to suppress the filename report in |pdftex_fail|
 
1492
       but zlib errors are rare enough (especially now that the
 
1493
       compress level is fixed) that I don't care about the slightly
 
1494
       ugly error message that could result.
 
1495
     */
 
1496
    /* cur_file_name = NULL; */
 
1497
    if (pdf->stream_length == 0) {
 
1498
        if (pdf->zipbuf == NULL) {
 
1499
            pdf->zipbuf = xtalloc(ZIP_BUF_SIZE, char);
 
1500
            pdf->c_stream.zalloc = (alloc_func) 0;
 
1501
            pdf->c_stream.zfree = (free_func) 0;
 
1502
            pdf->c_stream.opaque = (voidpf) 0;
 
1503
            check_err(deflateInit(&pdf->c_stream, level), "deflateInit");
 
1504
        } else {
 
1505
            check_err(deflateReset(&pdf->c_stream), "deflateReset");
 
1506
        }
 
1507
        pdf->c_stream.next_out = (Bytef *) pdf->zipbuf;
 
1508
        pdf->c_stream.avail_out = ZIP_BUF_SIZE;
 
1509
    }
 
1510
    assert(pdf->zipbuf != NULL);
 
1511
    pdf->c_stream.next_in = pdf->buf;
 
1512
    pdf->c_stream.avail_in = pdf->ptr;
 
1513
    for (;;) {
 
1514
        if (pdf->c_stream.avail_out == 0) {
 
1515
            pdf->gone += xfwrite(pdf->zipbuf, 1, ZIP_BUF_SIZE, pdf->file);
 
1516
            pdf->last_byte = pdf->zipbuf[ZIP_BUF_SIZE - 1];     /* not needed */
 
1517
            pdf->c_stream.next_out = (Bytef *) pdf->zipbuf;
 
1518
            pdf->c_stream.avail_out = ZIP_BUF_SIZE;
 
1519
        }
 
1520
        err = deflate(&pdf->c_stream, finish ? Z_FINISH : Z_NO_FLUSH);
 
1521
        if (finish && err == Z_STREAM_END)
 
1522
            break;
 
1523
        check_err(err, "deflate");
 
1524
        if (!finish && pdf->c_stream.avail_in == 0)
 
1525
            break;
 
1526
    }
 
1527
    if (finish) {
 
1528
        if (pdf->c_stream.avail_out < ZIP_BUF_SIZE) {   /* at least one byte has been output */
 
1529
            pdf->gone +=
 
1530
                xfwrite(pdf->zipbuf, 1, ZIP_BUF_SIZE - pdf->c_stream.avail_out,
 
1531
                        pdf->file);
 
1532
            pdf->last_byte =
 
1533
                pdf->zipbuf[ZIP_BUF_SIZE - pdf->c_stream.avail_out - 1];
 
1534
        }
 
1535
        xfflush(pdf->file);
 
1536
    }
 
1537
    pdf->stream_length = pdf->c_stream.total_out;
 
1538
}
 
1539
 
 
1540
void zip_free(PDF pdf)
 
1541
{
 
1542
    if (pdf->zipbuf != NULL) {
 
1543
        check_err(deflateEnd(&pdf->c_stream), "deflateEnd");
 
1544
        free(pdf->zipbuf);
 
1545
    }
 
1546
}
 
1547
 
 
1548
void pdf_error(char *t, char *p)
 
1549
{
 
1550
    normalize_selector();
 
1551
    print_err("LuaTeX error");
 
1552
    if (t != NULL) {
 
1553
        tprint(" (");
 
1554
        tprint(t);
 
1555
        tprint(")");
 
1556
    }
 
1557
    tprint(": ");
 
1558
    if (p != NULL)
 
1559
        tprint(p);
 
1560
    succumb();
 
1561
}
 
1562
 
 
1563
void pdf_warning(char *t, char *p, boolean prepend_nl, boolean append_nl)
 
1564
{
 
1565
    if (prepend_nl)
 
1566
        print_ln();
 
1567
    tprint("LuaTeX warning");
 
1568
    if (t != NULL) {
 
1569
        tprint(" (");
 
1570
        tprint(t);
 
1571
        tprint(")");
 
1572
    }
 
1573
    tprint(": ");
 
1574
    if (p != NULL)
 
1575
        tprint(p);
 
1576
    if (append_nl)
 
1577
        print_ln();
 
1578
    if (history == spotless)
 
1579
        history = warning_issued;
 
1580
}
 
1581
 
 
1582
/**********************************************************************/
 
1583
/* Use check_o_mode() in the backend-specific "Implement..." chunks */
 
1584
 
 
1585
void check_o_mode(PDF pdf, char *s, int o_mode_bitpattern, boolean strict)
 
1586
{
 
1587
 
 
1588
    char warn_string[100];
 
1589
    char *m;
 
1590
    output_mode o_mode;
 
1591
 
 
1592
    /* in warn mode (strict == false):
 
1593
       only check, don't do fix_o_mode() here! pdf->o_mode is left
 
1594
       in possibly wrong state until real output, ok.
 
1595
     */
 
1596
 
 
1597
    if (pdf->o_mode == OMODE_NONE) {
 
1598
        if (pdf_output > 0) {
 
1599
            if (pdf_output == 2009)
 
1600
                o_mode = OMODE_LUA;
 
1601
            else
 
1602
                o_mode = OMODE_PDF;
 
1603
        } else
 
1604
            o_mode = OMODE_DVI;
 
1605
    } else
 
1606
        o_mode = pdf->o_mode;
 
1607
    if (!((1 << o_mode) & o_mode_bitpattern)) { /* warning or error */
 
1608
        switch (o_mode) {
 
1609
        case OMODE_DVI:
 
1610
            m = "DVI";
 
1611
            break;
 
1612
        case OMODE_PDF:
 
1613
            m = "PDF";
 
1614
            break;
 
1615
        case OMODE_LUA:
 
1616
            m = "Lua";
 
1617
            break;
 
1618
        default:
 
1619
            assert(0);
 
1620
        }
 
1621
        snprintf(warn_string, 99, "not allowed in %s mode (\\pdfpoutput = %d)",
 
1622
                 m, (int) pdf_output);
 
1623
        if (strict)
 
1624
            pdf_error(s, warn_string);
 
1625
        else
 
1626
            pdf_warning(s, warn_string, true, true);
 
1627
    } else if (strict)
 
1628
        ensure_output_state(pdf, ST_HEADER_WRITTEN);
 
1629
}
 
1630
 
 
1631
/**********************************************************************/
 
1632
 
 
1633
void set_job_id(PDF pdf, int year, int month, int day, int time)
 
1634
{
 
1635
    char *name_string, *format_string, *s;
 
1636
    size_t slen;
 
1637
    int i;
 
1638
 
 
1639
    if (pdf->job_id_string != NULL)
 
1640
        return;
 
1641
 
 
1642
    name_string = makecstring(job_name);
 
1643
    format_string = makecstring(format_ident);
 
1644
    make_pdftex_banner();
 
1645
    slen = SMALL_BUF_SIZE +
 
1646
        strlen(name_string) + strlen(format_string) + strlen(pdftex_banner);
 
1647
    s = xtalloc(slen, char);
 
1648
    /* The Web2c version string starts with a space.  */
 
1649
    i = snprintf(s, slen,
 
1650
                 "%.4d/%.2d/%.2d %.2d:%.2d %s %s %s",
 
1651
                 year, month, day, time / 60, time % 60,
 
1652
                 name_string, format_string, pdftex_banner);
 
1653
    check_nprintf(i, slen);
 
1654
    pdf->job_id_string = xstrdup(s);
 
1655
    xfree(s);
 
1656
    xfree(name_string);
 
1657
    xfree(format_string);
 
1658
} char *get_resname_prefix(PDF pdf)
 
1659
{
 
1660
 
 
1661
/*     static char name_str[] = */
 
1662
/* "!\"$&'*+,-.0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\\" */
 
1663
/* "^_`abcdefghijklmnopqrstuvwxyz|~"; */
 
1664
    static char name_str[] =
 
1665
        "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
 
1666
    static char prefix[7];      /* make a tag of 6 chars long */
 
1667
    unsigned long crc;
 
1668
    short i;
 
1669
    size_t base = strlen(name_str);
 
1670
    crc = crc32(0L, Z_NULL, 0);
 
1671
    crc = crc32(crc, (Bytef *) pdf->job_id_string, strlen(pdf->job_id_string));
 
1672
    for (i = 0; i < 6; i++) {
 
1673
        prefix[i] = name_str[crc % base];
 
1674
        crc /= base;
 
1675
    }
 
1676
    prefix[6] = '\0';
 
1677
    return prefix;
 
1678
}
 
1679
 
 
1680
#define mag int_par(mag_code)
 
1681
 
 
1682
#define pdf_xform_attr equiv(pdf_xform_attr_loc)
 
1683
#define pdf_xform_resources equiv(pdf_xform_resources_loc)
 
1684
 
 
1685
void pdf_begin_page(PDF pdf, boolean shipping_page)
 
1686
{
 
1687
    scaled form_margin = one_bp;
 
1688
    ensure_output_state(pdf, ST_HEADER_WRITTEN);
 
1689
    init_pdf_pagecalculations(pdf);
 
1690
 
 
1691
    if (pdf->resources == NULL)
 
1692
        pdf->resources = xmalloc(sizeof(pdf_resource_struct));
 
1693
    reset_resource_lists(pdf->resources);
 
1694
    pdf->resources->last_resources = pdf_new_objnum(pdf);
 
1695
 
 
1696
    if (shipping_page) {
 
1697
        pdf->last_page = get_obj(pdf, obj_type_page, total_pages + 1, 0);
 
1698
        set_obj_aux(pdf, pdf->last_page, 1);    /* mark that this page has been created */
 
1699
        pdf_new_dict(pdf, obj_type_pagestream, 0, 0);
 
1700
        pdf->last_stream = pdf->obj_ptr;
 
1701
        pdf->last_thread = null;
 
1702
    } else {
 
1703
        pdf_begin_dict(pdf, pdf_cur_form, 0);
 
1704
        pdf->last_stream = pdf_cur_form;
 
1705
 
 
1706
        /* Write out Form stream header */
 
1707
        pdf_puts(pdf, "/Type /XObject\n");
 
1708
        pdf_puts(pdf, "/Subtype /Form\n");
 
1709
        if (pdf_xform_attr != null)
 
1710
            pdf_print_toks_ln(pdf, pdf_xform_attr);
 
1711
        if (obj_xform_attr(pdf, pdf_cur_form) != null) {
 
1712
            pdf_print_toks_ln(pdf, obj_xform_attr(pdf, pdf_cur_form));
 
1713
            delete_token_ref(obj_xform_attr(pdf, pdf_cur_form));
 
1714
            set_obj_xform_attr(pdf, pdf_cur_form, null);
 
1715
        }
 
1716
        pdf_puts(pdf, "/BBox [");
 
1717
        pdf_print_bp(pdf, -form_margin);
 
1718
        pdf_out(pdf, ' ');
 
1719
        pdf_print_bp(pdf, -form_margin);
 
1720
        pdf_out(pdf, ' ');
 
1721
        pdf_print_bp(pdf, cur_page_size.h + form_margin);
 
1722
        pdf_out(pdf, ' ');
 
1723
        pdf_print_bp(pdf, cur_page_size.v + form_margin);
 
1724
        pdf_puts(pdf, "]\n");
 
1725
        pdf_puts(pdf, "/FormType 1\n");
 
1726
        pdf_puts(pdf, "/Matrix [1 0 0 1 0 0]\n");
 
1727
        pdf_indirect_ln(pdf, "Resources", pdf->resources->last_resources);
 
1728
    }
 
1729
    /* Start stream of page/form contents */
 
1730
    pdf_begin_stream(pdf);
 
1731
    if (shipping_page) {
 
1732
        /* Adjust transformation matrix for the magnification ratio */
 
1733
        if (mag != 1000) {
 
1734
            pdf_print_real(pdf, mag, 3);
 
1735
            pdf_puts(pdf, " 0 0 ");
 
1736
            pdf_print_real(pdf, mag, 3);
 
1737
            pdf_puts(pdf, " 0 0 cm\n");
 
1738
        }
 
1739
    }
 
1740
    pdf_shipout_begin(shipping_page);
 
1741
 
 
1742
    if (shipping_page)
 
1743
        pdf_out_colorstack_startpage(pdf);
 
1744
}
 
1745
 
 
1746
#define pdf_page_attr equiv(pdf_page_attr_loc)
 
1747
#define pdf_page_resources equiv(pdf_page_resources_loc)
 
1748
 
 
1749
void pdf_end_page(PDF pdf, boolean shipping_page)
 
1750
{
 
1751
    int j, ff;
 
1752
    pdf_resource_struct *res_p = pdf->resources;
 
1753
    pdf_resource_struct local_resources;
 
1754
    pdf_object_list *ol;
 
1755
    scaledpos save_cur_page_size;       /* to save |cur_page_size| during flushing pending forms */
 
1756
 
 
1757
 
 
1758
    /* Finish stream of page/form contents */
 
1759
    pdf_goto_pagemode(pdf);
 
1760
    pdf_shipout_end(shipping_page);
 
1761
    pdf_end_stream(pdf);
 
1762
 
 
1763
    if (shipping_page) {
 
1764
        /* Write out page object */
 
1765
 
 
1766
        pdf_begin_dict(pdf, pdf->last_page, 1);
 
1767
        pdf->last_pages = pdf_do_page_divert(pdf, pdf->last_page, 0);
 
1768
        pdf_puts(pdf, "/Type /Page\n");
 
1769
        pdf_indirect_ln(pdf, "Contents", pdf->last_stream);
 
1770
        pdf_indirect_ln(pdf, "Resources", res_p->last_resources);
 
1771
        pdf_puts(pdf, "/MediaBox [0 0 ");
 
1772
        pdf_print_mag_bp(pdf, cur_page_size.h);
 
1773
        pdf_out(pdf, ' ');
 
1774
        pdf_print_mag_bp(pdf, cur_page_size.v);
 
1775
        pdf_puts(pdf, "]\n");
 
1776
        if (pdf_page_attr != null)
 
1777
            pdf_print_toks_ln(pdf, pdf_page_attr);
 
1778
        pdf_indirect_ln(pdf, "Parent", pdf->last_pages);
 
1779
        if (pdf->img_page_group_val > 0) {
 
1780
            pdf_printf(pdf, "/Group %d 0 R\n", pdf->img_page_group_val);
 
1781
            pdf->img_page_group_val = 0;
 
1782
        }
 
1783
        /* Generate array of annotations or beads in page */
 
1784
        if ((res_p->annot_list != NULL)
 
1785
            || (res_p->link_list != NULL)) {
 
1786
            pdf_puts(pdf, "/Annots [ ");
 
1787
            ol = res_p->annot_list;
 
1788
            while (ol != NULL) {
 
1789
                if (ol->info > 0)
 
1790
                    pdf_print_int(pdf, ol->info);
 
1791
                else
 
1792
                    pdf_print_int(pdf, (-ol->info));
 
1793
                pdf_puts(pdf, " 0 R ");
 
1794
                ol = ol->link;
 
1795
            }
 
1796
            ol = res_p->link_list;
 
1797
            while (ol != NULL) {
 
1798
                pdf_print_int(pdf, ol->info);
 
1799
                pdf_puts(pdf, " 0 R ");
 
1800
                ol = ol->link;
 
1801
            }
 
1802
            pdf_puts(pdf, "]\n");
 
1803
        }
 
1804
        print_beads_list(pdf);
 
1805
        pdf_end_dict(pdf);
 
1806
 
 
1807
    }
 
1808
    /* Write out resource lists */
 
1809
    /* Write out pending raw objects */
 
1810
    if ((ol = res_p->obj_list) != NULL) {
 
1811
        while (ol != NULL) {
 
1812
            if (!is_obj_written(pdf, ol->info))
 
1813
                pdf_write_obj(pdf, ol->info);
 
1814
            ol = ol->link;
 
1815
        }
 
1816
    }
 
1817
 
 
1818
    /* Write out pending forms */
 
1819
    /* When flushing pending forms we need to save and restore resource lists
 
1820
       (|font_list|, |pdf_obj_list|, |pdf_xform_list| and |pdf_ximage_list|),
 
1821
       which are also used by page shipping.
 
1822
       Saving and restoring |cur_page_size| is needed for proper
 
1823
       writing out pending PDF marks. */
 
1824
    if ((ol = res_p->xform_list) != NULL) {
 
1825
        while (ol != NULL) {
 
1826
            if (!is_obj_written(pdf, ol->info)) {
 
1827
                pdf_cur_form = ol->info;
 
1828
                save_cur_page_size = cur_page_size;
 
1829
                pdf->resources = &local_resources;
 
1830
                ship_out(pdf, obj_xform_box(pdf, pdf_cur_form), false);
 
1831
                cur_page_size = save_cur_page_size;
 
1832
                /* Restore resource lists */
 
1833
                pdf->resources = res_p;
 
1834
            }
 
1835
            ol = ol->link;
 
1836
        }
 
1837
    }
 
1838
 
 
1839
    /* Write out pending images */
 
1840
    if ((ol = res_p->ximage_list) != NULL) {
 
1841
        while (ol != NULL) {
 
1842
            if (!is_obj_written(pdf, ol->info))
 
1843
                pdf_write_image(pdf, ol->info);
 
1844
            ol = ol->link;
 
1845
        }
 
1846
    }
 
1847
 
 
1848
    if (shipping_page) {
 
1849
        /* Write out pending PDF marks */
 
1850
        /* Write out PDF annotations */
 
1851
        if ((ol = res_p->annot_list) != NULL) {
 
1852
            while (ol != NULL) {
 
1853
                if (ol->info > 0) {
 
1854
                    j = obj_annot_ptr(pdf, ol->info);   /* |j| points to |pdf_annot_node| */
 
1855
                    pdf_begin_dict(pdf, ol->info, 1);
 
1856
                    pdf_puts(pdf, "/Type /Annot\n");
 
1857
                    pdf_print_toks_ln(pdf, pdf_annot_data(j));
 
1858
                    pdf_rectangle(pdf, j);
 
1859
                    pdf_end_dict(pdf);
 
1860
                }
 
1861
                ol = ol->link;
 
1862
            }
 
1863
        }
 
1864
 
 
1865
        /* Write out PDF link annotations */
 
1866
        if ((ol = res_p->link_list) != NULL) {
 
1867
            while (ol != NULL) {
 
1868
                j = obj_annot_ptr(pdf, ol->info);
 
1869
                pdf_begin_dict(pdf, ol->info, 1);
 
1870
                pdf_puts(pdf, "/Type /Annot\n");
 
1871
                if (pdf_action_type(pdf_link_action(j)) != pdf_action_user)
 
1872
                    pdf_puts(pdf, "/Subtype /Link\n");
 
1873
                if (pdf_link_attr(j) != null)
 
1874
                    pdf_print_toks_ln(pdf, pdf_link_attr(j));
 
1875
                pdf_rectangle(pdf, j);
 
1876
                if (pdf_action_type(pdf_link_action(j)) != pdf_action_user)
 
1877
                    pdf_puts(pdf, "/A ");
 
1878
                write_action(pdf, pdf_link_action(j));
 
1879
                pdf_end_dict(pdf);
 
1880
                ol = ol->link;
 
1881
            }
 
1882
            /* Flush |pdf_start_link_node|'s created by |append_link| */
 
1883
            ol = res_p->link_list;
 
1884
            while (ol != NULL) {
 
1885
                j = obj_annot_ptr(pdf, ol->info);
 
1886
                /* nodes with |subtype = pdf_link_data_node| were created by |append_link| and
 
1887
                   must be flushed here, as they are not linked in any list */
 
1888
                if (subtype(j) == pdf_link_data_node)
 
1889
                    flush_node(j);
 
1890
                ol = ol->link;
 
1891
            }
 
1892
        }
 
1893
 
 
1894
        /* Write out PDF mark destinations */
 
1895
        write_out_pdf_mark_destinations(pdf);
 
1896
        /* Write out PDF bead rectangle specifications */
 
1897
        print_bead_rectangles(pdf);
 
1898
 
 
1899
    }
 
1900
    /* Write out resources dictionary */
 
1901
    pdf_begin_dict(pdf, res_p->last_resources, 1);
 
1902
    /* Print additional resources */
 
1903
    if (shipping_page) {
 
1904
        if (pdf_page_resources != null)
 
1905
            pdf_print_toks_ln(pdf, pdf_page_resources);
 
1906
    } else {
 
1907
        if (pdf_xform_resources != null)
 
1908
            pdf_print_toks_ln(pdf, pdf_xform_resources);
 
1909
        if (obj_xform_resources(pdf, pdf_cur_form) != null) {
 
1910
            pdf_print_toks_ln(pdf, obj_xform_resources(pdf, pdf_cur_form));
 
1911
            delete_token_ref(obj_xform_resources(pdf, pdf_cur_form));
 
1912
            set_obj_xform_resources(pdf, pdf_cur_form, null);
 
1913
        }
 
1914
    }
 
1915
 
 
1916
    /* Generate font resources */
 
1917
    if ((ol = res_p->font_list) != NULL) {
 
1918
        pdf_puts(pdf, "/Font << ");
 
1919
        while (ol != NULL) {
 
1920
            pdf_puts(pdf, "/F");
 
1921
            set_ff(ol->info);
 
1922
            pdf_print_int(pdf, ff);
 
1923
            pdf_print_resname_prefix(pdf);
 
1924
            pdf_out(pdf, ' ');
 
1925
            pdf_print_int(pdf, pdf_font_num(ff));
 
1926
            pdf_puts(pdf, " 0 R ");
 
1927
            ol = ol->link;
 
1928
        }
 
1929
        pdf_puts(pdf, ">>\n");
 
1930
        res_p->text_procset = true;
 
1931
    }
 
1932
 
 
1933
    /* Generate XObject resources */
 
1934
    if ((res_p->xform_list != NULL)
 
1935
        || (res_p->ximage_list != NULL)) {
 
1936
        pdf_puts(pdf, "/XObject << ");
 
1937
        if ((ol = res_p->xform_list) != NULL) {
 
1938
            while (ol != NULL) {
 
1939
                pdf_printf(pdf, "/Fm");
 
1940
                pdf_print_int(pdf, obj_info(pdf, ol->info));
 
1941
                pdf_print_resname_prefix(pdf);
 
1942
                pdf_out(pdf, ' ');
 
1943
                pdf_print_int(pdf, ol->info);
 
1944
                pdf_puts(pdf, " 0 R ");
 
1945
                ol = ol->link;
 
1946
            }
 
1947
        }
 
1948
        if ((ol = res_p->ximage_list) != NULL) {
 
1949
            while (ol != null) {
 
1950
                pdf_puts(pdf, "/Im");
 
1951
                pdf_print_int(pdf, obj_data_ptr(pdf, ol->info));
 
1952
                pdf_print_resname_prefix(pdf);
 
1953
                pdf_out(pdf, ' ');
 
1954
                pdf_print_int(pdf, ol->info);
 
1955
                pdf_puts(pdf, " 0 R ");
 
1956
                update_image_procset(obj_data_ptr(pdf, ol->info));
 
1957
                ol = ol->link;
 
1958
            }
 
1959
        }
 
1960
        pdf_puts(pdf, ">>\n");
 
1961
    }
 
1962
 
 
1963
    /* Generate ProcSet */
 
1964
    pdf_puts(pdf, "/ProcSet [ /PDF");
 
1965
    if (res_p->text_procset)
 
1966
        pdf_puts(pdf, " /Text");
 
1967
    if (check_image_b(res_p->image_procset))
 
1968
        pdf_puts(pdf, " /ImageB");
 
1969
    if (check_image_c(res_p->image_procset))
 
1970
        pdf_puts(pdf, " /ImageC");
 
1971
    if (check_image_i(res_p->image_procset))
 
1972
        pdf_puts(pdf, " /ImageI");
 
1973
    pdf_puts(pdf, " ]\n");
 
1974
 
 
1975
    pdf_end_dict(pdf);
 
1976
 
 
1977
    /* In the end of shipping out a page we reset all the lists holding objects
 
1978
       have been created during the page shipping. */
 
1979
 
 
1980
    flush_resource_lists(pdf);
 
1981
}
 
1982
 
 
1983
/**********************************************************************/
 
1984
 
 
1985
/* Finishing the PDF output file. */
 
1986
 
 
1987
#define pdf_gen_tounicode int_par(pdf_gen_tounicode_code)
 
1988
 
 
1989
/*
 
1990
Destinations that have been referenced but don't exists have
 
1991
|obj_dest_ptr=null|. Leaving them undefined might cause troubles for
 
1992
PDF browsers, so we need to fix them; they point to the last page.
 
1993
*/
 
1994
 
 
1995
static void check_nonexisting_destinations(PDF pdf)
 
1996
{
 
1997
    int k;
 
1998
    for (k = pdf->head_tab[obj_type_dest]; k != 0; k = obj_link(pdf, k)) {
 
1999
        if (obj_dest_ptr(pdf, k) == null) {
 
2000
            pdf_warning("dest", NULL, false, false);
 
2001
            if (obj_info(pdf, k) < 0) {
 
2002
                tprint("name{");
 
2003
                print(-obj_info(pdf, k));
 
2004
                tprint("}");
 
2005
            } else {
 
2006
                tprint("num");
 
2007
                print_int(obj_info(pdf, k));
 
2008
            }
 
2009
            tprint
 
2010
                (" has been referenced but does not exist, replaced by a fixed one");
 
2011
            print_ln();
 
2012
            print_ln();
 
2013
            pdf_begin_obj(pdf, k, 1);
 
2014
            pdf_out(pdf, '[');
 
2015
            pdf_print_int(pdf, pdf->last_page);
 
2016
            pdf_puts(pdf, " 0 R /Fit]\n");
 
2017
            pdf_end_obj(pdf);
 
2018
        }
 
2019
    }
 
2020
}
 
2021
 
 
2022
static void check_nonexisting_pages(PDF pdf)
 
2023
{
 
2024
    struct avl_traverser t;
 
2025
    oentry *p;
 
2026
    struct avl_table *page_tree = pdf->obj_tree[obj_type_page];
 
2027
    avl_t_init(&t, page_tree);
 
2028
    /* search from the end backward until the last real page is found */
 
2029
    for (p = avl_t_last(&t, page_tree);
 
2030
         p != NULL && obj_aux(pdf, p->objptr) == 0; p = avl_t_prev(&t)) {
 
2031
        pdf_warning("dest", "Page ", false, false);
 
2032
        print_int(obj_info(pdf, p->objptr));
 
2033
        tprint(" has been referenced but does not exist!");
 
2034
        print_ln();
 
2035
        print_ln();
 
2036
    }
 
2037
}
 
2038
 
 
2039
/*
 
2040
If the same keys in a dictionary are given several times, then it is not
 
2041
defined which value is choosen by an application.  Therefore the keys
 
2042
|/Producer| and |/Creator| are only set if the token list
 
2043
|pdf_info_toks| converted to a string does not contain these key strings.
 
2044
*/
 
2045
 
 
2046
boolean substr_of_str(char *s, char *t)
 
2047
{
 
2048
    if (strstr(t, s) == NULL)
 
2049
        return false;
 
2050
    return true;
 
2051
}
 
2052
 
 
2053
void pdf_print_info(PDF pdf, int luatex_version, str_number luatex_revision)
 
2054
{                               /* print info object */
 
2055
    boolean creator_given, producer_given, creationdate_given, moddate_given,
 
2056
        trapped_given;
 
2057
    char *s = NULL;
 
2058
    int len = 0;
 
2059
    pdf_new_dict(pdf, obj_type_others, 0, 3);   /* keep Info readable unless explicitely forced */
 
2060
    creator_given = false;
 
2061
    producer_given = false;
 
2062
    creationdate_given = false;
 
2063
    moddate_given = false;
 
2064
    trapped_given = false;
 
2065
    if (pdf_info_toks != 0) {
 
2066
        s = tokenlist_to_cstring(pdf_info_toks, true, &len);
 
2067
        creator_given = substr_of_str("/Creator", s);
 
2068
        producer_given = substr_of_str("/Producer", s);
 
2069
        creationdate_given = substr_of_str("/CreationDate", s);
 
2070
        moddate_given = substr_of_str("/ModDate", s);
 
2071
        trapped_given = substr_of_str("/Trapped", s);
 
2072
    }
 
2073
    if (!producer_given) {
 
2074
        /* Print the Producer key */
 
2075
        pdf_puts(pdf, "/Producer (LuaTeX-");
 
2076
        pdf_print_int(pdf, luatex_version / 100);
 
2077
        pdf_out(pdf, '.');
 
2078
        pdf_print_int(pdf, luatex_version % 100);
 
2079
        pdf_out(pdf, '.');
 
2080
        pdf_print(pdf, luatex_revision);
 
2081
        pdf_puts(pdf, ")\n");
 
2082
 
 
2083
    }
 
2084
    if (pdf_info_toks != null) {
 
2085
        if (len > 0) {
 
2086
            pdf_puts(pdf, s);
 
2087
            pdf_print_nl(pdf);
 
2088
            xfree(s);
 
2089
        }
 
2090
        delete_token_ref(pdf_info_toks);
 
2091
        pdf_info_toks = null;
 
2092
    }
 
2093
    if (!creator_given)
 
2094
        pdf_str_entry_ln(pdf, "Creator", "TeX");
 
2095
    if (!creationdate_given) {
 
2096
        print_creation_date(pdf);
 
2097
    }
 
2098
    if (!moddate_given) {
 
2099
        print_mod_date(pdf);
 
2100
    }
 
2101
    if (!trapped_given) {
 
2102
        pdf_puts(pdf, "/Trapped /False\n");
 
2103
    }
 
2104
    pdf_str_entry_ln(pdf, "PTEX.Fullbanner", pdftex_banner);
 
2105
    pdf_end_dict(pdf);
 
2106
}
 
2107
 
 
2108
void build_free_object_list(PDF pdf)
 
2109
{
 
2110
    int k, l;
 
2111
    l = 0;
 
2112
    set_obj_fresh(pdf, l);      /* null object at begin of list of free objects */
 
2113
    for (k = 1; k <= pdf->sys_obj_ptr; k++) {
 
2114
        if (!is_obj_written(pdf, k)) {
 
2115
            set_obj_link(pdf, l, k);
 
2116
            l = k;
 
2117
        }
 
2118
    }
 
2119
    set_obj_link(pdf, l, 0);
 
2120
}
 
2121
 
 
2122
/**********************************************************************/
 
2123
 
 
2124
/*
 
2125
Now the finish of PDF output file. At this moment all Page objects
 
2126
are already written completely to PDF output file.
 
2127
*/
 
2128
 
 
2129
void finish_pdf_file(PDF pdf, int luatex_version, str_number luatex_revision)
 
2130
{
 
2131
    boolean res;
 
2132
    int i, j, k;
 
2133
    int root, outlines, threads, names_tree;
 
2134
    int xref_offset_width;
 
2135
    int callback_id = callback_defined(stop_run_callback);
 
2136
 
 
2137
    if (total_pages == 0) {
 
2138
        if (callback_id == 0) {
 
2139
            tprint_nl("No pages of output.");
 
2140
        } else if (callback_id > 0) {
 
2141
            res = run_callback(callback_id, "->");
 
2142
        }
 
2143
        if (pdf->gone > 0)
 
2144
            garbage_warning();
 
2145
    } else {
 
2146
        if (pdf->draftmode == 0) {
 
2147
            pdf_flush(pdf);     /* to make sure that the output file name has been already created */
 
2148
            flush_jbig2_page0_objects(pdf);     /* flush page 0 objects from JBIG2 images, if any */
 
2149
 
 
2150
            check_nonexisting_pages(pdf);
 
2151
            check_nonexisting_destinations(pdf);
 
2152
 
 
2153
            /* Output fonts definition */
 
2154
            for (k = 1; k <= max_font_id(); k++) {
 
2155
                if (font_used(k) && (pdf_font_num(k) < 0)) {
 
2156
                    i = -pdf_font_num(k);
 
2157
                    assert(pdf_font_num(i) > 0);
 
2158
                    for (j = font_bc(k); j <= font_ec(k); j++)
 
2159
                        if (quick_char_exists(k, j) && pdf_char_marked(k, j))
 
2160
                            pdf_mark_char(i, j);
 
2161
                    if ((pdf_font_attr(i) == 0) && (pdf_font_attr(k) != 0)) {
 
2162
                        set_pdf_font_attr(i, pdf_font_attr(k));
 
2163
                    } else if ((pdf_font_attr(k) == 0)
 
2164
                               && (pdf_font_attr(i) != 0)) {
 
2165
                        set_pdf_font_attr(k, pdf_font_attr(i));
 
2166
                    } else if ((pdf_font_attr(i) != 0)
 
2167
                               && (pdf_font_attr(k) != 0)
 
2168
                               &&
 
2169
                               (!str_eq_str
 
2170
                                (pdf_font_attr(i), pdf_font_attr(k)))) {
 
2171
                        pdf_warning("\\pdffontattr", "fonts ", false, false);
 
2172
                        print_font_identifier(i);
 
2173
                        tprint(" and ");
 
2174
                        print_font_identifier(k);
 
2175
                        tprint
 
2176
                            (" have conflicting attributes; I will ignore the attributes assigned to ");
 
2177
                        print_font_identifier(i);
 
2178
                        print_ln();
 
2179
                        print_ln();
 
2180
                    }
 
2181
                }
 
2182
            }
 
2183
            pdf->gen_tounicode = pdf_gen_tounicode;
 
2184
            k = pdf->head_tab[obj_type_font];
 
2185
            while (k != 0) {
 
2186
                f = obj_info(pdf, k);
 
2187
                assert(pdf_font_num(f) > 0);
 
2188
                do_pdf_font(pdf, k, f);
 
2189
                k = obj_link(pdf, k);
 
2190
            }
 
2191
            write_fontstuff(pdf);
 
2192
 
 
2193
            pdf->last_pages = output_pages_tree(pdf);
 
2194
            /* Output outlines */
 
2195
            outlines = print_outlines(pdf);
 
2196
 
 
2197
            /* Output name tree */
 
2198
            /* The name tree is very similiar to Pages tree so its construction should be
 
2199
               certain from Pages tree construction. For intermediate node |obj_info| will be
 
2200
               the first name and |obj_link| will be the last name in \.{\\Limits} array.
 
2201
               Note that |pdf_dest_names_ptr| will be less than |obj_ptr|, so we test if
 
2202
               |k < pdf_dest_names_ptr| then |k| is index of leaf in |dest_names|; else
 
2203
               |k| will be index in |obj_tab| of some intermediate node.
 
2204
             */
 
2205
            names_tree = output_name_tree(pdf);
 
2206
 
 
2207
            /* Output article threads */
 
2208
            if (pdf->head_tab[obj_type_thread] != 0) {
 
2209
                pdf_new_obj(pdf, obj_type_others, 0, 1);
 
2210
                threads = pdf->obj_ptr;
 
2211
                pdf_out(pdf, '[');
 
2212
                k = pdf->head_tab[obj_type_thread];
 
2213
                while (k != 0) {
 
2214
                    pdf_print_int(pdf, k);
 
2215
                    pdf_puts(pdf, " 0 R ");
 
2216
                    k = obj_link(pdf, k);
 
2217
                }
 
2218
                pdf_remove_last_space(pdf);
 
2219
                pdf_puts(pdf, "]\n");
 
2220
                pdf_end_obj(pdf);
 
2221
                k = pdf->head_tab[obj_type_thread];
 
2222
                while (k != 0) {
 
2223
                    out_thread(pdf, k);
 
2224
                    k = obj_link(pdf, k);
 
2225
                }
 
2226
            } else {
 
2227
                threads = 0;
 
2228
            }
 
2229
 
 
2230
            /* Output the catalog object */
 
2231
            pdf_new_dict(pdf, obj_type_others, 0, 1);
 
2232
            root = pdf->obj_ptr;
 
2233
            pdf_puts(pdf, "/Type /Catalog\n");
 
2234
            pdf_indirect_ln(pdf, "Pages", pdf->last_pages);
 
2235
            if (threads != 0)
 
2236
                pdf_indirect_ln(pdf, "Threads", threads);
 
2237
            if (outlines != 0)
 
2238
                pdf_indirect_ln(pdf, "Outlines", outlines);
 
2239
            if (names_tree != 0)
 
2240
                pdf_indirect_ln(pdf, "Names", names_tree);
 
2241
            if (pdf_catalog_toks != null) {
 
2242
                pdf_print_toks_ln(pdf, pdf_catalog_toks);
 
2243
                delete_token_ref(pdf_catalog_toks);
 
2244
                pdf_catalog_toks = null;
 
2245
            }
 
2246
            if (pdf_catalog_openaction != 0)
 
2247
                pdf_indirect_ln(pdf, "OpenAction", pdf_catalog_openaction);
 
2248
            pdf_end_dict(pdf);
 
2249
 
 
2250
            pdf_print_info(pdf, luatex_version, luatex_revision);       /* last candidate for object stream */
 
2251
 
 
2252
            if (pdf->os_enable) {
 
2253
                pdf_os_switch(pdf, true);
 
2254
                pdf_os_write_objstream(pdf);
 
2255
                pdf_flush(pdf);
 
2256
                pdf_os_switch(pdf, false);
 
2257
                /* Output the cross-reference stream dictionary */
 
2258
                pdf_new_dict(pdf, obj_type_others, 0, 0);
 
2259
                if ((obj_offset(pdf, pdf->sys_obj_ptr) / 256) > 16777215)
 
2260
                    xref_offset_width = 5;
 
2261
                else if (obj_offset(pdf, pdf->sys_obj_ptr) > 16777215)
 
2262
                    xref_offset_width = 4;
 
2263
                else if (obj_offset(pdf, pdf->sys_obj_ptr) > 65535)
 
2264
                    xref_offset_width = 3;
 
2265
                else
 
2266
                    xref_offset_width = 2;
 
2267
                /* Build a linked list of free objects */
 
2268
                build_free_object_list(pdf);
 
2269
                pdf_puts(pdf, "/Type /XRef\n");
 
2270
                pdf_puts(pdf, "/Index [0 ");
 
2271
                pdf_print_int(pdf, pdf->obj_ptr + 1);
 
2272
                pdf_puts(pdf, "]\n");
 
2273
                pdf_int_entry_ln(pdf, "Size", pdf->obj_ptr + 1);
 
2274
                pdf_puts(pdf, "/W [1 ");
 
2275
                pdf_print_int(pdf, xref_offset_width);
 
2276
                pdf_puts(pdf, " 1]\n");
 
2277
                pdf_indirect_ln(pdf, "Root", root);
 
2278
                pdf_indirect_ln(pdf, "Info", pdf->obj_ptr - 1);
 
2279
                if (pdf_trailer_toks != null) {
 
2280
                    pdf_print_toks_ln(pdf, pdf_trailer_toks);
 
2281
                    delete_token_ref(pdf_trailer_toks);
 
2282
                    pdf_trailer_toks = null;
 
2283
                }
 
2284
                print_ID(pdf, pdf->file_name);
 
2285
                pdf_print_nl(pdf);
 
2286
                pdf_begin_stream(pdf);
 
2287
                for (k = 0; k <= pdf->sys_obj_ptr; k++) {
 
2288
                    if (!is_obj_written(pdf, k)) {      /* a free object */
 
2289
                        pdf_out(pdf, 0);
 
2290
                        pdf_out_bytes(pdf, obj_link(pdf, k), xref_offset_width);
 
2291
                        pdf_out(pdf, 255);
 
2292
                    } else if (obj_os_idx(pdf, k) == -1) {      /* object not in object stream */
 
2293
                        pdf_out(pdf, 1);
 
2294
                        pdf_out_bytes(pdf, obj_offset(pdf, k),
 
2295
                                      xref_offset_width);
 
2296
                        pdf_out(pdf, 0);
 
2297
                    } else {    /* object in object stream */
 
2298
                        pdf_out(pdf, 2);
 
2299
                        pdf_out_bytes(pdf, obj_offset(pdf, k),
 
2300
                                      xref_offset_width);
 
2301
                        pdf_out(pdf, obj_os_idx(pdf, k));
 
2302
                    }
 
2303
                }
 
2304
                pdf_end_stream(pdf);
 
2305
                /* TODO: generate a debug version of the crossref */
 
2306
 
 
2307
                pdf_flush(pdf);
 
2308
            } else {
 
2309
                /* Output the |obj_tab| */
 
2310
                /* Build a linked list of free objects */
 
2311
                build_free_object_list(pdf);
 
2312
 
 
2313
                pdf_save_offset(pdf);
 
2314
                pdf_puts(pdf, "xref\n");
 
2315
                pdf_puts(pdf, "0 ");
 
2316
                pdf_print_int_ln(pdf, pdf->obj_ptr + 1);
 
2317
                pdf_print_fw_int(pdf, obj_link(pdf, 0), 10);
 
2318
                pdf_puts(pdf, " 65535 f \n");
 
2319
                for (k = 1; k <= pdf->obj_ptr; k++) {
 
2320
                    if (!is_obj_written(pdf, k)) {
 
2321
                        pdf_print_fw_int(pdf, obj_link(pdf, k), 10);
 
2322
                        pdf_puts(pdf, " 00000 f \n");
 
2323
                    } else {
 
2324
                        pdf_print_fw_int(pdf, obj_offset(pdf, k), 10);
 
2325
                        pdf_puts(pdf, " 00000 n \n");
 
2326
                    }
 
2327
                }
 
2328
 
 
2329
            }
 
2330
 
 
2331
            /* Output the trailer */
 
2332
            if (!pdf->os_enable) {
 
2333
                pdf_puts(pdf, "trailer\n");
 
2334
                pdf_puts(pdf, "<< ");
 
2335
                pdf_int_entry_ln(pdf, "Size", pdf->sys_obj_ptr + 1);
 
2336
                pdf_indirect_ln(pdf, "Root", root);
 
2337
                pdf_indirect_ln(pdf, "Info", pdf->sys_obj_ptr);
 
2338
                if (pdf_trailer_toks != null) {
 
2339
                    pdf_print_toks_ln(pdf, pdf_trailer_toks);
 
2340
                    delete_token_ref(pdf_trailer_toks);
 
2341
                    pdf_trailer_toks = null;
 
2342
                }
 
2343
                print_ID(pdf, pdf->file_name);
 
2344
                pdf_puts(pdf, " >>\n");
 
2345
            }
 
2346
            pdf_puts(pdf, "startxref\n");
 
2347
            if (pdf->os_enable)
 
2348
                pdf_print_int_ln(pdf, obj_offset(pdf, pdf->sys_obj_ptr));
 
2349
            else
 
2350
                pdf_print_int_ln(pdf, pdf_saved_offset(pdf));
 
2351
            pdf_puts(pdf, "%%EOF\n");
 
2352
 
 
2353
            pdf_flush(pdf);
 
2354
            if (callback_id == 0) {
 
2355
                tprint_nl("Output written on ");
 
2356
                tprint(pdf->file_name);
 
2357
                tprint(" (");
 
2358
                print_int(total_pages);
 
2359
                tprint(" page");
 
2360
                if (total_pages != 1)
 
2361
                    print_char('s');
 
2362
                tprint(", ");
 
2363
                print_int(pdf_offset(pdf));
 
2364
                tprint(" bytes).");
 
2365
            } else if (callback_id > 0) {
 
2366
                res = run_callback(callback_id, "->");
 
2367
            }
 
2368
        }
 
2369
        libpdffinish(pdf);
 
2370
        if (pdf->draftmode == 0)
 
2371
            close_file(pdf->file);
 
2372
        else
 
2373
            pdf_warning(NULL,
 
2374
                        "\\pdfdraftmode enabled, not changing output pdf",
 
2375
                        true, true);
 
2376
    }
 
2377
 
 
2378
    if (callback_id == 0) {
 
2379
        if (log_opened) {
 
2380
            fprintf(log_file,
 
2381
                    "\nPDF statistics: %d PDF objects out of %d (max. %d)\n",
 
2382
                    (int) pdf->obj_ptr, (int) pdf->obj_tab_size,
 
2383
                    (int) sup_obj_tab_size);
 
2384
            if (pdf->os_cntr > 0) {
 
2385
                fprintf(log_file,
 
2386
                        " %d compressed objects within %d object stream%s\n",
 
2387
                        (int) ((pdf->os_cntr - 1) * pdf_os_max_objs +
 
2388
                               pdf->os_idx + 1), (int) pdf->os_cntr,
 
2389
                        (pdf->os_cntr > 1 ? "s" : ""));
 
2390
            }
 
2391
            fprintf(log_file, " %d named destinations out of %d (max. %d)\n",
 
2392
                    (int) pdf->dest_names_ptr, (int) pdf->dest_names_size,
 
2393
                    (int) sup_dest_names_size);
 
2394
            fprintf(log_file,
 
2395
                    " %d words of extra memory for PDF output out of %d (max. %d)\n",
 
2396
                    (int) pdf->mem_ptr, (int) pdf->mem_size,
 
2397
                    (int) sup_pdf_mem_size);
 
2398
        }
 
2399
    }
 
2400
}
 
2401
 
 
2402
void scan_pdfcatalog(PDF pdf)
 
2403
{
 
2404
    halfword p;
 
2405
    scan_pdf_ext_toks();
 
2406
    pdf_catalog_toks = concat_tokens(pdf_catalog_toks, def_ref);
 
2407
    if (scan_keyword("openaction")) {
 
2408
        if (pdf_catalog_openaction != 0) {
 
2409
            pdf_error("ext1", "duplicate of openaction");
 
2410
        } else {
 
2411
            check_o_mode(pdf, "\\pdfcatalog", 1 << OMODE_PDF, true);
 
2412
            p = scan_action(pdf);
 
2413
            pdf_new_obj(pdf, obj_type_others, 0, 1);
 
2414
            pdf_catalog_openaction = pdf->obj_ptr;
 
2415
            write_action(pdf, p);
 
2416
            pdf_end_obj(pdf);
 
2417
            delete_action_ref(p);
 
2418
        }
 
2419
    }
 
2420
}