1 /* This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
2
3 Copyright (C) 2002-2014 by Jin-Hwan Cho and Shunsaku Hirata,
4 the dvipdfmx project team.
5
6 Copyright (C) 2012-2015 by Khaled Hosny <khaledhosny@eglug.org>
7
8 Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks@kettering.edu>
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 */
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <sys/types.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <ctype.h>
33
34 #ifdef WIN32
35 #include <fcntl.h>
36 #include <io.h>
37 #endif
38
39 #include "system.h"
40 #include "mem.h"
41 #include "error.h"
42 #include "mfileio.h"
43 #include "numbers.h"
44
45 #include "pdfdev.h"
46 #include "pdfdoc.h"
47 #include "pdfparse.h"
48 #include "pdfencrypt.h"
49
50 #include "fontmap.h"
51
52 #include "dvicodes.h"
53 #include "tfm.h"
54 #include "vf.h"
55 #include "subfont.h"
56
57 #include "spc_util.h"
58 #include "specials.h"
59
60 #include "dvi.h"
61 #include "dvipdfmx.h"
62
63 #ifdef XETEX
64 #include "dpxfile.h"
65 #include "pdfximage.h"
66 #include "tt_aux.h"
67 #include "tt_table.h"
68 #endif
69
70 #define DVI_STACK_DEPTH_MAX 256u
71 #define TEX_FONTS_ALLOC_SIZE 16u
72 #define VF_NESTING_MAX 16u
73
74 /* UTF-32 over U+FFFF -> UTF-16 surrogate pair */
75 #define UTF32toUTF16HS(x) (0xd800 + (((x-0x10000) >> 10) & 0x3ff))
76 #define UTF32toUTF16LS(x) (0xdc00 + ( x & 0x3ff))
77
78 /* Interal Variables */
79 static FILE *dvi_file = NULL;
80 static char linear = 0; /* set to 1 for strict linear processing of the input */
81
82 static int32_t *page_loc = NULL;
83 static unsigned int num_pages = 0;
84
85 static uint32_t dvi_file_size = 0;
86
87 static struct dvi_header
88 {
89 uint32_t unit_num;
90 uint32_t unit_den;
91 uint32_t mag;
92 uint32_t media_width, media_height;
93 unsigned int stackdepth;
94 char comment[257];
95 } dvi_info = {
96 25400000 , /* num */
97 473628672, /* den */
98 1000, /* mag */
99 0, 0, /* media width and height */
100 0, /* stackdepth */
101 {'\0'} /* comment */
102 };
103
104 static double dev_origin_x = 72.0, dev_origin_y = 770.0;
105
get_origin(int x)106 double get_origin (int x)
107 {
108 return x ? dev_origin_x : dev_origin_y;
109 }
110
111 #define LTYPESETTING 0 /* typesetting from left to right */
112 #define RTYPESETTING 1 /* typesetting from right to left */
113 #define SKIMMING 2 /* skimming through reflected segment measuring its width */
114 #define REVERSE(MODE) (LTYPESETTING + RTYPESETTING - MODE)
115
116 struct dvi_lr
117 {
118 int state, font;
119 unsigned int buf_index;
120 };
121
122 static struct dvi_lr lr_state; /* state at start of current skimming */
123 static int lr_mode; /* current direction or skimming depth */
124 static uint32_t lr_width; /* total width of reflected segment */
125 static uint32_t lr_width_stack[DVI_STACK_DEPTH_MAX];
126 static unsigned lr_width_stack_depth = 0;
127
128 #define PHYSICAL 1
129 #define VIRTUAL 2
130 #define SUBFONT 3
131 #define NATIVE 4
132 #define DVI 1
133 #define VF 2
134
135 static struct loaded_font
136 {
137 int type; /* Type is physical or virtual */
138 int font_id; /* id returned by dev (for PHYSICAL fonts)
139 * or by vf module for (VIRTUAL fonts)
140 */
141 int subfont_id; /* id returned by subfont_locate_font() */
142 int tfm_id;
143 spt_t size;
144 int source; /* Source is either DVI or VF */
145 #ifdef XETEX
146 uint32_t rgba_color;
147 struct tt_longMetrics *hvmt;
148 int ascent;
149 int descent;
150 unsigned unitsPerEm;
151 unsigned numGlyphs;
152 int layout_dir;
153 float extend;
154 float slant;
155 float embolden;
156 #endif
157 } *loaded_fonts = NULL;
158 static int num_loaded_fonts = 0, max_loaded_fonts = 0;
159
160 static void
need_more_fonts(unsigned n)161 need_more_fonts (unsigned n)
162 {
163 if (num_loaded_fonts + n > max_loaded_fonts) {
164 max_loaded_fonts += TEX_FONTS_ALLOC_SIZE;
165 loaded_fonts = RENEW (loaded_fonts, max_loaded_fonts, struct loaded_font);
166 }
167 }
168
169 static struct font_def
170 {
171 int32_t tex_id;
172 spt_t point_size;
173 spt_t design_size;
174 char *font_name;
175 int font_id; /* index of _loaded_ font in loaded_fonts array */
176 int used;
177 #ifdef XETEX
178 int native; /* boolean */
179 uint32_t rgba_color; /* only used for native fonts in XeTeX */
180 uint32_t face_index;
181 int layout_dir; /* 1 = vertical, 0 = horizontal */
182 int extend;
183 int slant;
184 int embolden;
185 #endif
186 } *def_fonts = NULL;
187
188 #ifdef XETEX
189 #define XDV_FLAG_VERTICAL 0x0100
190 #define XDV_FLAG_COLORED 0x0200
191 #define XDV_FLAG_FEATURES 0x0400
192 #define XDV_FLAG_EXTEND 0x1000
193 #define XDV_FLAG_SLANT 0x2000
194 #define XDV_FLAG_EMBOLDEN 0x4000
195 #endif
196
197 static int num_def_fonts = 0, max_def_fonts = 0;
198 static int compute_boxes = 0, link_annot = 1;
199 static int verbose = 0;
200
201 #define DVI_PAGE_BUF_CHUNK 0x10000U /* 64K should be plenty for most pages */
202
203 static unsigned char* dvi_page_buffer;
204 static unsigned int dvi_page_buf_size;
205 static unsigned int dvi_page_buf_index;
206
207 /* functions to read numbers from the dvi file and store them in dvi_page_buffer */
get_and_buffer_unsigned_byte(FILE * file)208 static int get_and_buffer_unsigned_byte (FILE *file)
209 {
210 int ch;
211 if ((ch = fgetc (file)) < 0)
212 ERROR ("File ended prematurely\n");
213 if (dvi_page_buf_index >= dvi_page_buf_size) {
214 dvi_page_buf_size += DVI_PAGE_BUF_CHUNK;
215 dvi_page_buffer = RENEW(dvi_page_buffer, dvi_page_buf_size, unsigned char);
216 }
217 dvi_page_buffer[dvi_page_buf_index++] = ch;
218 return ch;
219 }
220
221 #ifdef XETEX
get_and_buffer_unsigned_pair(FILE * file)222 static unsigned int get_and_buffer_unsigned_pair (FILE *file)
223 {
224 unsigned int pair = get_and_buffer_unsigned_byte(file);
225 pair = (pair << 8) | get_and_buffer_unsigned_byte(file);
226 return pair;
227 }
228 #endif
229
get_and_buffer_bytes(FILE * file,unsigned int count)230 static void get_and_buffer_bytes(FILE *file, unsigned int count)
231 {
232 if (dvi_page_buf_index + count >= dvi_page_buf_size) {
233 dvi_page_buf_size = dvi_page_buf_index + count + DVI_PAGE_BUF_CHUNK;
234 dvi_page_buffer = RENEW(dvi_page_buffer, dvi_page_buf_size, unsigned char);
235 }
236 if (fread(dvi_page_buffer + dvi_page_buf_index, 1, count, file) != count)
237 ERROR ("File ended prematurely\n");
238 dvi_page_buf_index += count;
239 }
240
241 /* functions to fetch values from dvi_page_buffer */
242
get_buffered_unsigned_byte(void)243 static int get_buffered_unsigned_byte (void)
244 {
245 return dvi_page_buffer[dvi_page_buf_index++];
246 }
247
248 #ifdef XETEX
get_buffered_unsigned_pair(void)249 static unsigned int get_buffered_unsigned_pair (void)
250 {
251 unsigned int pair = dvi_page_buffer[dvi_page_buf_index++];
252 pair = (pair << 8) | dvi_page_buffer[dvi_page_buf_index++];
253 return pair;
254 }
255 #endif
256
get_buffered_signed_quad(void)257 static int32_t get_buffered_signed_quad(void)
258 {
259 int i;
260 int32_t quad = dvi_page_buffer[dvi_page_buf_index++];
261 /* Check sign on first byte before reading others */
262 if (quad >= 0x80)
263 quad -= 0x100;
264 for (i=0; i<3; i++) {
265 quad = (quad << 8) | dvi_page_buffer[dvi_page_buf_index++];
266 }
267 return quad;
268 }
269
get_buffered_signed_num(unsigned char num)270 static int32_t get_buffered_signed_num(unsigned char num)
271 {
272 int32_t quad = dvi_page_buffer[dvi_page_buf_index++];
273 if (quad > 0x7f)
274 quad -= 0x100;
275 switch (num) {
276 case 3: quad = (quad << 8) | dvi_page_buffer[dvi_page_buf_index++];
277 case 2: quad = (quad << 8) | dvi_page_buffer[dvi_page_buf_index++];
278 case 1: quad = (quad << 8) | dvi_page_buffer[dvi_page_buf_index++];
279 default: break;
280 }
281 return quad;
282 }
283
get_buffered_unsigned_num(unsigned char num)284 static int32_t get_buffered_unsigned_num(unsigned char num)
285 {
286 int32_t quad = dvi_page_buffer[dvi_page_buf_index++];
287 switch (num) {
288 case 3: if (quad > 0x7f)
289 quad -= 0x100;
290 quad = (quad << 8) | dvi_page_buffer[dvi_page_buf_index++];
291 case 2: quad = (quad << 8) | dvi_page_buffer[dvi_page_buf_index++];
292 case 1: quad = (quad << 8) | dvi_page_buffer[dvi_page_buf_index++];
293 default: break;
294 }
295 return quad;
296 }
297
298 #define skip_bufferd_bytes(n) dvi_page_buf_index += n
299
300 void
dvi_set_verbose(void)301 dvi_set_verbose (void)
302 {
303 verbose++;
304 subfont_set_verbose();
305 tfm_set_verbose();
306 vf_set_verbose ();
307 spc_set_verbose();
308 }
309
310 unsigned int
dvi_npages(void)311 dvi_npages (void)
312 {
313 return num_pages;
314 }
315
316 static const char invalid_signature[] =
317 "Something is wrong. Are you sure this is a DVI file?";
318
319 #define range_check_loc(loc) \
320 if ((loc) > dvi_file_size) {\
321 ERROR(invalid_signature); \
322 }
323
324 static int32_t
find_post(void)325 find_post (void)
326 {
327 off_t dvi_size;
328 int32_t current;
329 int ch;
330
331 /* First find end of file */
332 dvi_size = xfile_size (dvi_file, "DVI");
333 if (dvi_size > 0x7fffffff)
334 ERROR("DVI file size exceeds 31-bit");
335 dvi_file_size = dvi_size;
336 current = dvi_size;
337
338 /* Scan backwards through PADDING */
339 do {
340 xseek_absolute (dvi_file, --current, "DVI");
341 } while ((ch = fgetc(dvi_file)) == PADDING &&
342 current > 0);
343
344 /* file_position now points to last non padding character or
345 * beginning of file */
346 if (dvi_file_size - current < 4 || current == 0 ||
347 !(ch == DVI_ID || ch == DVIV_ID || ch == XDV_ID)) {
348 MESG("DVI ID = %d\n", ch);
349 ERROR(invalid_signature);
350 }
351
352 is_xdv = ch == XDV_ID;
353
354 /* Make sure post_post is really there */
355 current = current - 5;
356 xseek_absolute (dvi_file, current, "DVI");
357 if ((ch = fgetc(dvi_file)) != POST_POST) {
358 MESG("Found %d where post_post opcode should be\n", ch);
359 ERROR(invalid_signature);
360 }
361 current = get_signed_quad(dvi_file);
362 xseek_absolute (dvi_file, current, "DVI");
363 if ((ch = fgetc(dvi_file)) != POST) {
364 MESG("Found %d where post_post opcode should be\n", ch);
365 ERROR(invalid_signature);
366 }
367
368 return current;
369 }
370
371 static void
get_page_info(int32_t post_location)372 get_page_info (int32_t post_location)
373 {
374 int i;
375
376 xseek_absolute (dvi_file, post_location + 27, "DVI");
377 num_pages = get_unsigned_pair(dvi_file);
378 if (num_pages == 0) {
379 ERROR("Page count is 0!");
380 }
381 if (verbose > 2) {
382 MESG("Page count:\t %4d\n", num_pages);
383 }
384
385 page_loc = NEW(num_pages, int32_t);
386
387 xseek_absolute (dvi_file, post_location + 1, "DVI");
388 page_loc[num_pages-1] = get_unsigned_quad(dvi_file);
389 range_check_loc(page_loc[num_pages-1] + 41);
390 for (i = num_pages - 2; i >= 0; i--) {
391 xseek_absolute (dvi_file, page_loc[i+1] + 41, "DVI");
392 page_loc[i] = get_unsigned_quad(dvi_file);
393 range_check_loc(page_loc[num_pages-1] + 41);
394 }
395 }
396
397 /* Following are computed "constants" used for unit conversion */
398 static double dvi2pts = 1.52018, total_mag = 1.0;
399
400 double
dvi_tell_mag(void)401 dvi_tell_mag (void)
402 {
403 return total_mag;
404 }
405
406 static void
do_scales(double mag)407 do_scales (double mag)
408 {
409 total_mag = (double) dvi_info.mag / 1000.0 * mag;
410 dvi2pts = (double) dvi_info.unit_num / (double) dvi_info.unit_den;
411 dvi2pts *= (72.0 / 254000.0);
412 }
413
414 static void
get_dvi_info(int32_t post_location)415 get_dvi_info (int32_t post_location)
416 {
417 xseek_absolute (dvi_file, post_location + 5, "DVI");
418
419 dvi_info.unit_num = get_unsigned_quad(dvi_file);
420 dvi_info.unit_den = get_unsigned_quad(dvi_file);
421 dvi_info.mag = get_unsigned_quad(dvi_file);
422
423 dvi_info.media_height = get_unsigned_quad(dvi_file);
424 dvi_info.media_width = get_unsigned_quad(dvi_file);
425
426 dvi_info.stackdepth = get_unsigned_pair(dvi_file);
427
428 if (dvi_info.stackdepth > DVI_STACK_DEPTH_MAX) {
429 WARN("DVI need stack depth of %d,", dvi_info.stackdepth);
430 WARN("but DVI_STACK_DEPTH_MAX is %d.", DVI_STACK_DEPTH_MAX);
431 ERROR("Capacity exceeded.");
432 }
433
434 if (verbose > 2) {
435 MESG("DVI File Info\n");
436 MESG("Unit: %ld / %ld\n", dvi_info.unit_num, dvi_info.unit_den);
437 MESG("Magnification: %ld\n", dvi_info.mag);
438 MESG("Media Height: %ld\n", dvi_info.media_height);
439 MESG("Media Width: %ld\n", dvi_info.media_width);
440 MESG("Stack Depth: %d\n", dvi_info.stackdepth);
441 }
442 }
443
444 static void
get_preamble_dvi_info(void)445 get_preamble_dvi_info (void)
446 {
447 int ch;
448
449 ch = get_unsigned_byte(dvi_file);
450 if (ch != PRE) {
451 MESG("Found %d where PRE was expected\n", ch);
452 ERROR(invalid_signature);
453 }
454
455 ch = get_unsigned_byte(dvi_file);
456 if (!(ch == DVI_ID || ch == DVIV_ID || ch == XDV_ID)) {
457 MESG("DVI ID = %d\n", ch);
458 ERROR(invalid_signature);
459 }
460
461 is_xdv = ch == XDV_ID;
462
463 dvi_info.unit_num = get_positive_quad(dvi_file, "DVI", "unit_num");
464 dvi_info.unit_den = get_positive_quad(dvi_file, "DVI", "unit_den");
465 dvi_info.mag = get_positive_quad(dvi_file, "DVI", "mag");
466
467 ch = get_unsigned_byte(dvi_file);
468 if (fread(dvi_info.comment,
469 1, ch, dvi_file) != ch) {
470 ERROR(invalid_signature);
471 }
472 dvi_info.comment[ch] = '\0';
473
474 if (verbose > 2) {
475 MESG("DVI File Info\n");
476 MESG("Unit: %ld / %ld\n", dvi_info.unit_num, dvi_info.unit_den);
477 MESG("Magnification: %ld\n", dvi_info.mag);
478 }
479
480 if (verbose) {
481 MESG("DVI Comment: %s\n", dvi_info.comment);
482 }
483
484 num_pages = 0x7FFFFFFU; /* for linear processing: we just keep going! */
485 }
486
487 const char *
dvi_comment(void)488 dvi_comment (void)
489 {
490 return dvi_info.comment;
491 }
492
493 static void
read_font_record(int32_t tex_id)494 read_font_record (int32_t tex_id)
495 {
496 int dir_length, name_length;
497 uint32_t point_size, design_size;
498 char *directory, *font_name;
499
500 if (num_def_fonts >= max_def_fonts) {
501 max_def_fonts += TEX_FONTS_ALLOC_SIZE;
502 def_fonts = RENEW (def_fonts, max_def_fonts, struct font_def);
503 }
504 get_unsigned_quad(dvi_file);
505 point_size = get_positive_quad(dvi_file, "DVI", "point_size");
506 design_size = get_positive_quad(dvi_file, "DVI", "design_size");
507 dir_length = get_unsigned_byte(dvi_file);
508 name_length = get_unsigned_byte(dvi_file);
509
510 directory = NEW(dir_length + 1, char);
511 if (fread(directory, 1, dir_length, dvi_file) != dir_length) {
512 ERROR(invalid_signature);
513 }
514 directory[dir_length] = '\0';
515 RELEASE(directory); /* unused */
516
517 font_name = NEW(name_length + 1, char);
518 if (fread(font_name, 1, name_length, dvi_file) != name_length) {
519 ERROR(invalid_signature);
520 }
521 font_name[name_length] = '\0';
522 def_fonts[num_def_fonts].tex_id = tex_id;
523 def_fonts[num_def_fonts].font_name = font_name;
524 def_fonts[num_def_fonts].point_size = point_size;
525 def_fonts[num_def_fonts].design_size = design_size;
526 def_fonts[num_def_fonts].used = 0;
527 #ifdef XETEX
528 def_fonts[num_def_fonts].native = 0;
529 def_fonts[num_def_fonts].rgba_color = 0xffffffff;
530 def_fonts[num_def_fonts].face_index = 0;
531 def_fonts[num_def_fonts].layout_dir = 0;
532 def_fonts[num_def_fonts].extend = 0x00010000; /* 1.0 */
533 def_fonts[num_def_fonts].slant = 0;
534 def_fonts[num_def_fonts].embolden = 0;
535 #endif
536 num_def_fonts++;
537
538 return;
539 }
540
541 #ifdef XETEX
542 static void
read_native_font_record(int32_t tex_id)543 read_native_font_record (int32_t tex_id)
544 {
545 unsigned int flags;
546 uint32_t point_size;
547 char *font_name;
548 int len;
549 uint32_t index;
550
551 if (num_def_fonts >= max_def_fonts) {
552 max_def_fonts += TEX_FONTS_ALLOC_SIZE;
553 def_fonts = RENEW (def_fonts, max_def_fonts, struct font_def);
554 }
555 point_size = get_positive_quad(dvi_file, "DVI", "point_size");
556 flags = get_unsigned_pair(dvi_file);
557
558 len = (int) get_unsigned_byte(dvi_file); /* font name length */
559 font_name = NEW(len + 1, char);
560 if (fread(font_name, 1, len, dvi_file) != len) {
561 ERROR(invalid_signature);
562 }
563 font_name[len] = '\0';
564
565 index = get_positive_quad(dvi_file, "DVI", "index");
566
567 def_fonts[num_def_fonts].tex_id = tex_id;
568 def_fonts[num_def_fonts].font_name = font_name;
569 def_fonts[num_def_fonts].face_index = index;
570 def_fonts[num_def_fonts].point_size = point_size;
571 def_fonts[num_def_fonts].design_size = 655360; /* hard-code as 10pt for now, not used anyway */
572 def_fonts[num_def_fonts].used = 0;
573 def_fonts[num_def_fonts].native = 1;
574
575 def_fonts[num_def_fonts].layout_dir = 0;
576 def_fonts[num_def_fonts].rgba_color = 0xffffffff;
577 def_fonts[num_def_fonts].extend = 0x00010000;
578 def_fonts[num_def_fonts].slant = 0;
579 def_fonts[num_def_fonts].embolden = 0;
580
581 if (flags & XDV_FLAG_VERTICAL)
582 def_fonts[num_def_fonts].layout_dir = 1;
583
584 if (flags & XDV_FLAG_COLORED)
585 def_fonts[num_def_fonts].rgba_color = get_unsigned_quad(dvi_file);
586
587 if (flags & XDV_FLAG_EXTEND)
588 def_fonts[num_def_fonts].extend = get_signed_quad(dvi_file);
589
590 if (flags & XDV_FLAG_SLANT)
591 def_fonts[num_def_fonts].slant = get_signed_quad(dvi_file);
592
593 if (flags & XDV_FLAG_EMBOLDEN)
594 def_fonts[num_def_fonts].embolden = get_signed_quad(dvi_file);
595
596 num_def_fonts++;
597
598 return;
599 }
600 #endif
601
602 static void
get_dvi_fonts(int32_t post_location)603 get_dvi_fonts (int32_t post_location)
604 {
605 int code;
606
607 xseek_absolute (dvi_file, post_location + 29, "DVI");
608 while ((code = get_unsigned_byte(dvi_file)) != POST_POST) {
609 switch (code) {
610 case FNT_DEF1: case FNT_DEF2: case FNT_DEF3: case FNT_DEF4:
611 read_font_record(get_unsigned_num(dvi_file, code-FNT_DEF1));
612 break;
613 #ifdef XETEX
614 case XDV_NATIVE_FONT_DEF:
615 read_native_font_record(get_signed_quad(dvi_file));
616 break;
617 #endif
618 default:
619 MESG("Unexpected op code: %3d\n", code);
620 ERROR(invalid_signature);
621 }
622 }
623 if (verbose > 2) {
624 unsigned i;
625
626 MESG("\n");
627 MESG("DVI file font info\n");
628 for (i = 0; i < num_def_fonts; i++) {
629 MESG("TeX Font: %10s loaded at ID=%5d, ",
630 def_fonts[i].font_name, def_fonts[i].tex_id);
631 MESG("size=%5.2fpt (scaled %4.1f%%)",
632 def_fonts[i].point_size * dvi2pts,
633 100.0 * ((double) def_fonts[i].point_size / def_fonts[i].design_size));
634 MESG("\n");
635 }
636 }
637 }
638
get_comment(void)639 static void get_comment (void)
640 {
641 int length;
642
643 xseek_absolute (dvi_file, 14, "DVI");
644 length = get_unsigned_byte(dvi_file);
645 if (fread(dvi_info.comment,
646 1, length, dvi_file) != length) {
647 ERROR(invalid_signature);
648 }
649 dvi_info.comment[length] = '\0';
650 if (verbose) {
651 MESG("DVI Comment: %s\n", dvi_info.comment);
652 }
653 }
654
655 /*
656 * The section below this line deals with the actual processing of the
657 * dvi file.
658 *
659 * The dvi file processor state is contained in the following variables:
660 */
661
662 struct dvi_registers
663 {
664 int32_t h, v, w, x, y, z;
665 unsigned int d;
666 };
667
668 static struct dvi_registers dvi_state;
669 static struct dvi_registers dvi_stack[DVI_STACK_DEPTH_MAX];
670 static unsigned dvi_stack_depth = 0 ;
671 static int current_font = -1;
672 static int processing_page = 0 ;
673
674 static void
clear_state(void)675 clear_state (void)
676 {
677 dvi_state.h = 0; dvi_state.v = 0; dvi_state.w = 0;
678 dvi_state.x = 0; dvi_state.y = 0; dvi_state.z = 0;
679 dvi_state.d = 0; /* direction */
680 dvi_stack_depth = 0;
681 current_font = -1;
682 }
683
684 /* Migrated from pdfdev.c:
685 * The following codes are originally put into pdfdev.c.
686 * But they are moved to here to make PDF output independent
687 * from DVI input.
688 * pdfdoc, pdfspecial and htex are also modified. pdfspecial
689 * and htex does tag/untag depth. pdfdev and pdfdoc now does
690 * not care about line-breaking at all.
691 */
692 static unsigned marked_depth = 0;
693 static int tagged_depth = -1;
694
695 static void
dvi_mark_depth(void)696 dvi_mark_depth (void)
697 {
698 /* If decreasing below tagged_depth */
699 if (link_annot &&
700 marked_depth == tagged_depth &&
701 dvi_stack_depth == tagged_depth - 1) {
702 /*
703 * See if this appears to be the end of a "logical unit"
704 * that's been broken. If so, flush the logical unit.
705 */
706 pdf_doc_break_annot();
707 }
708 marked_depth = dvi_stack_depth;
709 }
710
711 /*
712 * The following routines setup and tear down a callback at a
713 * certain stack depth. This is used to handle broken (linewise)
714 * links.
715 */
716 void
dvi_tag_depth(void)717 dvi_tag_depth (void)
718 {
719 tagged_depth = marked_depth;
720 dvi_compute_boxes(1);
721 }
722
723 void
dvi_untag_depth(void)724 dvi_untag_depth (void)
725 {
726 tagged_depth = -1;
727 dvi_compute_boxes(0);
728 }
729
730 void
dvi_compute_boxes(int flag)731 dvi_compute_boxes (int flag)
732 {
733 compute_boxes = flag;
734 }
735
736 void
dvi_link_annot(int flag)737 dvi_link_annot (int flag)
738 {
739 link_annot = flag;
740 }
741
742 int
dvi_is_tracking_boxes(void)743 dvi_is_tracking_boxes(void)
744 {
745 return (compute_boxes && link_annot && marked_depth >= tagged_depth);
746 }
747
748 void
dvi_do_special(const void * buffer,int32_t size)749 dvi_do_special (const void *buffer, int32_t size)
750 {
751 double x_user, y_user, mag;
752 const char *p;
753
754 graphics_mode();
755
756 p = (const char *) buffer;
757
758 x_user = dvi_state.h * dvi2pts;
759 y_user = -dvi_state.v * dvi2pts;
760 mag = dvi_tell_mag();
761
762 if (spc_exec_special(p, size, x_user, y_user, mag) < 0) {
763 if (verbose) {
764 dump(p, p + size);
765 }
766 }
767
768 return;
769 }
770
771 double
dvi_unit_size(void)772 dvi_unit_size (void)
773 {
774 return dvi2pts;
775 }
776
777
778 int
dvi_locate_font(const char * tfm_name,spt_t ptsize)779 dvi_locate_font (const char *tfm_name, spt_t ptsize)
780 {
781 int cur_id = -1;
782 const char *name = tfm_name;
783 int subfont_id = -1, font_id; /* VF or device font ID */
784 fontmap_rec *mrec;
785
786 if (verbose)
787 MESG("<%s@%.2fpt", tfm_name, ptsize * dvi2pts);
788
789 need_more_fonts(1);
790
791 /* This routine needs to be recursive/reentrant. Load current high water
792 * mark into an automatic variable.
793 */
794 cur_id = num_loaded_fonts++;
795
796 mrec = pdf_lookup_fontmap_record(tfm_name);
797 /* Load subfont mapping table */
798 if (mrec && mrec->charmap.sfd_name && mrec->charmap.subfont_id) {
799 subfont_id = sfd_load_record(mrec->charmap.sfd_name, mrec->charmap.subfont_id);
800 }
801
802 memset(&loaded_fonts[cur_id], 0, sizeof (struct loaded_font));
803
804 /* TFM must exist here. */
805 loaded_fonts[cur_id].tfm_id = tfm_open(tfm_name, 1);
806 loaded_fonts[cur_id].subfont_id = subfont_id;
807 loaded_fonts[cur_id].size = ptsize;
808 /* This will be reset later if it was really generated by the dvi file. */
809 loaded_fonts[cur_id].source = VF;
810
811 /* The order of searching fonts is as follows:
812 *
813 * 1. If mrec is null, that is, there is no map entry matching
814 * with tfm_name, then search a virtual font matching with
815 * tfm_name at first. If no virtual font is found, search a
816 * PK font matching with tfm_name.
817 *
818 * 2. If mrec is non-null, search a physical scalable font.
819 *
820 * 3. Notice that every subfont gets non-null mrec. In this case,
821 * enc_name corresponding to mrec will be used instead of mrec.
822 * That is enc_name is NULL, search a virtual font for Omega (.ovf)
823 * matching with the base name of the subfont. If no virtual font
824 * for Omega is found, it is a fatal error because there is no PK font
825 * for Omega.
826 */
827 if (!mrec) {
828 font_id = vf_locate_font(tfm_name, ptsize);
829 if (font_id >= 0) {
830 loaded_fonts[cur_id].type = VIRTUAL;
831 loaded_fonts[cur_id].font_id = font_id;
832 if (verbose)
833 MESG("(VF)>");
834 return cur_id;
835 }
836 }
837 #if 1
838 /* Sorry, I don't understand this well... Please fix.
839 * The purpose of this seems to be:
840 *
841 * Map 8-bit char codes in subfont to 16-bit code with SFD mapping
842 * and map subfonts to single OVF font.
843 *
844 * But it apparently only does TFM -> OVF mapping but no character
845 * code mapping. Please see dvi_set(), you can't have both font->type
846 * VIRTUAL and font->subfont_id >= 0. Am I missing something?
847 */
848 else if (subfont_id >= 0 && mrec->map_name)
849 {
850 fontmap_rec *mrec1 = pdf_lookup_fontmap_record(mrec->map_name);
851 /* enc_name=NULL should be used only for 'built-in' encoding.
852 * Please fix this!
853 */
854 if (mrec1 && !mrec1->enc_name) {
855 font_id = vf_locate_font(mrec1->font_name, ptsize);
856 if (font_id < 0)
857 WARN("Could not locate Omega Virtual Font \"%s\" for \"%s\".",
858 mrec1->font_name, tfm_name);
859 else {
860 loaded_fonts[cur_id].type = VIRTUAL;
861 loaded_fonts[cur_id].font_id = font_id;
862 if (verbose)
863 MESG("(OVF)>");
864 return cur_id;
865 }
866 }
867 }
868 #endif /* 1 */
869
870 /* Failed to load a virtual font so we try to load a physical font. */
871
872 /* If mrec->map_name is not NULL, font name identified in PDF output
873 * is different than tfm_name, this can happen for subfonts grouped
874 * into a single "intermediate" font foo@SFD@.
875 * This is necessary for optimal output; to avoid unnecessary creation
876 * of multiple instances of a same font, to avoid frequent font selection
877 * and break of string_mode.
878 */
879 if (mrec && mrec->map_name) {
880 name = mrec->map_name;
881 } else {
882 name = tfm_name;
883 }
884
885 /* We need ptsize for PK font creation. */
886 font_id = pdf_dev_locate_font(name, ptsize);
887 if (font_id < 0) {
888 WARN("Could not locate a virtual/physical font for TFM \"%s\".", tfm_name);
889 if (mrec && mrec->map_name) { /* has map_name */
890 fontmap_rec *mrec1 = pdf_lookup_fontmap_record(mrec->map_name);
891 WARN(">> This font is mapped to an intermediate 16-bit font \"%s\" with SFD charmap=<%s,%s>,",
892 mrec->map_name, mrec->charmap.sfd_name, mrec->charmap.subfont_id);
893 if (!mrec1)
894 WARN(">> but I couldn't find font mapping for \"%s\".", mrec->map_name);
895 else {
896 WARN(">> and then mapped to a physical font \"%s\" by fontmap.", mrec1->font_name);
897 WARN(">> Please check if kpathsea library can find this font: %s", mrec1->font_name);
898 }
899 } else if (mrec && !mrec->map_name) {
900 WARN(">> This font is mapped to a physical font \"%s\".", mrec->font_name);
901 WARN(">> Please check if kpathsea library can find this font: %s", mrec->font_name);
902 } else {
903 WARN(">> There are no valid font mapping entry for this font.");
904 WARN(">> Font file name \"%s\" was assumed but failed to locate that font.", tfm_name);
905 }
906 ERROR("Cannot proceed without .vf or \"physical\" font for PDF output...");
907 }
908 loaded_fonts[cur_id].type = PHYSICAL;
909 loaded_fonts[cur_id].font_id = font_id;
910
911 if (verbose)
912 MESG(">");
913
914 return cur_id;
915 }
916
917 #ifdef XETEX
918 static int
dvi_locate_native_font(const char * filename,uint32_t index,spt_t ptsize,int layout_dir,int extend,int slant,int embolden)919 dvi_locate_native_font (const char *filename, uint32_t index,
920 spt_t ptsize, int layout_dir, int extend, int slant, int embolden)
921 {
922 int cur_id = -1;
923 fontmap_rec *mrec;
924 char *fontmap_key;
925 FILE *fp;
926 char *path;
927 sfnt *sfont;
928 unsigned offset = 0;
929 struct tt_head_table *head;
930 struct tt_maxp_table *maxp;
931 struct tt_hhea_table *hhea;
932 int is_dfont = 0, is_type1 = 0;
933
934 if (verbose)
935 MESG("<%s@%.2fpt", filename, ptsize * dvi2pts);
936
937 if ((path = dpx_find_dfont_file(filename)) != NULL &&
938 (fp = fopen(path, "rb")) != NULL)
939 is_dfont = 1;
940 else if ((path = dpx_find_type1_file(filename)) != NULL)
941 is_type1 = 1;
942 else if (((path = dpx_find_opentype_file(filename)) == NULL
943 && (path = dpx_find_truetype_file(filename)) == NULL)
944 || (fp = fopen(path, "rb")) == NULL) {
945 ERROR("Cannot proceed without the font: %s", filename);
946 }
947 need_more_fonts(1);
948
949 cur_id = num_loaded_fonts++;
950
951 fontmap_key = malloc(strlen(path) + 40); // CHECK this is enough
952 sprintf(fontmap_key, "%s/%u/%c/%d/%d/%d", path, index, layout_dir == 0 ? 'H' : 'V', extend, slant, embolden);
953 mrec = pdf_lookup_fontmap_record(fontmap_key);
954 if (mrec == NULL) {
955 if ((mrec = pdf_insert_native_fontmap_record(path, index, layout_dir, extend, slant, embolden)) == NULL) {
956 ERROR("Failed to insert font record for font: %s", filename);
957 }
958 }
959
960 memset(&loaded_fonts[cur_id], 0, sizeof (struct loaded_font));
961
962 loaded_fonts[cur_id].font_id = pdf_dev_locate_font(fontmap_key, ptsize);
963 loaded_fonts[cur_id].size = ptsize;
964 loaded_fonts[cur_id].type = NATIVE;
965 free(fontmap_key);
966
967 if (is_type1 == 0) {
968 if (is_dfont)
969 sfont = dfont_open(fp, index);
970 else
971 sfont = sfnt_open(fp);
972 if (sfont->type == SFNT_TYPE_TTC)
973 offset = ttc_read_offset(sfont, index);
974 else if (sfont->type == SFNT_TYPE_DFONT)
975 offset = sfont->offset;
976 sfnt_read_table_directory(sfont, offset);
977 head = tt_read_head_table(sfont);
978 maxp = tt_read_maxp_table(sfont);
979 hhea = tt_read_hhea_table(sfont);
980 loaded_fonts[cur_id].ascent = hhea->ascent;
981 loaded_fonts[cur_id].descent = hhea->descent;
982 loaded_fonts[cur_id].unitsPerEm = head->unitsPerEm;
983 loaded_fonts[cur_id].numGlyphs = maxp->numGlyphs;
984 if (layout_dir == 1 && sfnt_find_table_pos(sfont, "vmtx") > 0) {
985 struct tt_vhea_table *vhea = tt_read_vhea_table(sfont);
986 sfnt_locate_table(sfont, "vmtx");
987 loaded_fonts[cur_id].hvmt = tt_read_longMetrics(sfont, maxp->numGlyphs, vhea->numOfLongVerMetrics, vhea->numOfExSideBearings);
988 RELEASE(vhea);
989 } else {
990 sfnt_locate_table(sfont, "hmtx");
991 loaded_fonts[cur_id].hvmt = tt_read_longMetrics(sfont, maxp->numGlyphs, hhea->numOfLongHorMetrics, hhea->numOfExSideBearings);
992 }
993 RELEASE(hhea);
994 RELEASE(maxp);
995 RELEASE(head);
996 sfnt_close(sfont);
997 fclose(fp);
998 }
999
1000 free(path);
1001
1002 loaded_fonts[cur_id].layout_dir = layout_dir;
1003 loaded_fonts[cur_id].extend = mrec->opt.extend;
1004 loaded_fonts[cur_id].slant = mrec->opt.slant;
1005 loaded_fonts[cur_id].embolden = mrec->opt.bold;
1006
1007 if (verbose)
1008 MESG(">");
1009
1010 return cur_id;
1011 }
1012 #endif
1013
1014 double
dvi_dev_xpos(void)1015 dvi_dev_xpos (void)
1016 {
1017 return dvi_state.h * dvi2pts;
1018 }
1019
1020 double
dvi_dev_ypos(void)1021 dvi_dev_ypos (void)
1022 {
1023 return -(dvi_state.v * dvi2pts);
1024 }
1025
do_moveto(int32_t x,int32_t y)1026 static void do_moveto (int32_t x, int32_t y)
1027 {
1028 dvi_state.h = x;
1029 dvi_state.v = y;
1030 }
1031
1032 /* FIXME: dvi_forward() might be a better name */
dvi_right(int32_t x)1033 void dvi_right (int32_t x)
1034 {
1035 if (lr_mode >= SKIMMING) {
1036 lr_width += x;
1037 return;
1038 }
1039
1040 if (lr_mode == RTYPESETTING)
1041 x = -x;
1042
1043 switch (dvi_state.d) {
1044 case 0:
1045 dvi_state.h += x; break;
1046 case 1:
1047 dvi_state.v += x; break;
1048 case 3:
1049 dvi_state.v -= x; break;
1050 }
1051 }
1052
dvi_down(int32_t y)1053 void dvi_down (int32_t y)
1054 {
1055 if (lr_mode < SKIMMING) {
1056 switch (dvi_state.d) {
1057 case 0:
1058 dvi_state.v += y; break;
1059 case 1:
1060 dvi_state.h -= y; break;
1061 case 3:
1062 dvi_state.h += y; break;
1063 }
1064 }
1065 }
1066
1067 /* _FIXME_
1068 * CMap decoder wants multibyte strings as input but
1069 * how DVI char codes are converted to multibyte sting
1070 * is not clear.
1071 */
1072 void
dvi_set(int32_t ch)1073 dvi_set (int32_t ch)
1074 {
1075 struct loaded_font *font;
1076 spt_t width, height, depth;
1077 unsigned char wbuf[4];
1078
1079 if (current_font < 0) {
1080 ERROR("No font selected!");
1081 }
1082 /* The division by dvi2pts seems strange since we actually know the
1083 * "dvi" size of the fonts contained in the DVI file. In other
1084 * words, we converted from DVI units to pts and back again!
1085 * The problem comes from fonts defined in VF files where we don't know
1086 * the DVI size. It's keeping me sane to keep *point sizes* of *all*
1087 * fonts in the dev.c file and convert them back if necessary.
1088 */
1089 font = &loaded_fonts[current_font];
1090
1091 width = tfm_get_fw_width(font->tfm_id, ch);
1092 width = sqxfw(font->size, width);
1093
1094 if (lr_mode >= SKIMMING) {
1095 lr_width += width;
1096 return;
1097 }
1098
1099 if (lr_mode == RTYPESETTING)
1100 dvi_right(width); /* Will actually move left */
1101
1102 switch (font->type) {
1103 case PHYSICAL:
1104 if (ch > 65535) { /* _FIXME_ */
1105 wbuf[0] = (UTF32toUTF16HS(ch) >> 8) & 0xff;
1106 wbuf[1] = UTF32toUTF16HS(ch) & 0xff;
1107 wbuf[2] = (UTF32toUTF16LS(ch) >> 8) & 0xff;
1108 wbuf[3] = UTF32toUTF16LS(ch) & 0xff;
1109 pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 4,
1110 width, font->font_id, 2);
1111 } else if (ch > 255) { /* _FIXME_ */
1112 wbuf[0] = (ch >> 8) & 0xff;
1113 wbuf[1] = ch & 0xff;
1114 pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 2,
1115 width, font->font_id, 2);
1116 } else if (font->subfont_id >= 0) {
1117 unsigned short uch = lookup_sfd_record(font->subfont_id, (unsigned char) ch);
1118 wbuf[0] = (uch >> 8) & 0xff;
1119 wbuf[1] = uch & 0xff;
1120 pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 2,
1121 width, font->font_id, 2);
1122 } else {
1123 wbuf[0] = (unsigned char) ch;
1124 pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 1,
1125 width, font->font_id, 1);
1126 }
1127 if (dvi_is_tracking_boxes()) {
1128 pdf_rect rect;
1129
1130 height = tfm_get_fw_height(font->tfm_id, ch);
1131 depth = tfm_get_fw_depth (font->tfm_id, ch);
1132 height = sqxfw(font->size, height);
1133 depth = sqxfw(font->size, depth);
1134
1135 pdf_dev_set_rect (&rect, dvi_state.h, -dvi_state.v,
1136 width, height, depth);
1137 pdf_doc_expand_box(&rect);
1138 }
1139 break;
1140 case VIRTUAL:
1141 #if 0
1142 /* See comment in locate_font() */
1143 if (font->subfont_id >= 0)
1144 ch = lookup_sfd_record(font->subfont_id, (unsigned char) ch);
1145 #endif /* 0 */
1146 vf_set_char(ch, font->font_id); /* push/pop invoked */
1147 break;
1148 }
1149
1150 if (lr_mode == LTYPESETTING)
1151 dvi_right(width);
1152
1153 }
1154
1155 void
dvi_put(int32_t ch)1156 dvi_put (int32_t ch)
1157 {
1158 struct loaded_font *font;
1159 spt_t width, height, depth;
1160 unsigned char wbuf[4];
1161
1162 if (current_font < 0) {
1163 ERROR("No font selected!");
1164 }
1165
1166 font = &loaded_fonts[current_font];
1167
1168 switch (font->type) {
1169 case PHYSICAL:
1170 width = tfm_get_fw_width(font->tfm_id, ch);
1171 width = sqxfw(font->size, width);
1172
1173 /* Treat a single character as a one byte string and use the
1174 * string routine.
1175 */
1176 if (ch > 65535) { /* _FIXME_ */
1177 wbuf[0] = (UTF32toUTF16HS(ch) >> 8) & 0xff;
1178 wbuf[1] = UTF32toUTF16HS(ch) & 0xff;
1179 wbuf[2] = (UTF32toUTF16LS(ch) >> 8) & 0xff;
1180 wbuf[3] = UTF32toUTF16LS(ch) & 0xff;
1181 pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 4,
1182 width, font->font_id, 2);
1183 } else if (ch > 255) { /* _FIXME_ */
1184 wbuf[0] = (ch >> 8) & 0xff;
1185 wbuf[1] = ch & 0xff;
1186 pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 2,
1187 width, font->font_id, 2);
1188 } else if (font->subfont_id >= 0) {
1189 unsigned int uch;
1190
1191 uch = lookup_sfd_record(font->subfont_id, (unsigned char) ch);
1192 wbuf[0] = (uch >> 8) & 0xff;
1193 wbuf[1] = uch & 0xff;
1194 pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 2,
1195 width, font->font_id, 2);
1196 } else {
1197 wbuf[0] = (unsigned char) ch;
1198 pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 1,
1199 width, font->font_id, 1);
1200 }
1201 if (dvi_is_tracking_boxes()) {
1202 pdf_rect rect;
1203
1204 height = tfm_get_fw_height(font->tfm_id, ch);
1205 depth = tfm_get_fw_depth (font->tfm_id, ch);
1206 height = sqxfw(font->size, height);
1207 depth = sqxfw(font->size, depth);
1208
1209 pdf_dev_set_rect (&rect, dvi_state.h, -dvi_state.v,
1210 width, height, depth);
1211 pdf_doc_expand_box(&rect);
1212 }
1213 break;
1214 case VIRTUAL:
1215 #if 0
1216 /* See comment in locate_font() */
1217 if (font->subfont_id >= 0)
1218 ch = lookup_sfd_record(font->subfont_id, (unsigned char) ch);
1219 #endif /* 0 */
1220 vf_set_char(ch, font->font_id);
1221 break;
1222 }
1223
1224 return;
1225 }
1226
1227
1228 void
dvi_rule(int32_t width,int32_t height)1229 dvi_rule (int32_t width, int32_t height)
1230 {
1231 if (width > 0 && height > 0) {
1232 do_moveto(dvi_state.h, dvi_state.v);
1233
1234 switch (dvi_state.d) {
1235 case 0:
1236 pdf_dev_set_rule(dvi_state.h, -dvi_state.v, width, height);
1237 break;
1238 case 1:
1239 pdf_dev_set_rule(dvi_state.h, -dvi_state.v - width, height, width);
1240 break;
1241 case 3:
1242 pdf_dev_set_rule(dvi_state.h - height, -dvi_state.v , height, width);
1243 break;
1244 }
1245 }
1246 }
1247
1248 void
dvi_dir(unsigned char dir)1249 dvi_dir (unsigned char dir)
1250 {
1251 if (verbose)
1252 fprintf(stderr, " > dvi_dir %d\n", dir);
1253 dvi_state.d = dir;
1254 pdf_dev_set_dirmode(dvi_state.d); /* 0: horizontal, 1,3: vertical */
1255 }
1256
1257 static void
do_setrule(void)1258 do_setrule (void)
1259 {
1260 int32_t width, height;
1261
1262 height = get_buffered_signed_quad();
1263 width = get_buffered_signed_quad();
1264 switch (lr_mode) {
1265 case LTYPESETTING:
1266 dvi_rule(width, height);
1267 dvi_right(width);
1268 break;
1269 case RTYPESETTING:
1270 dvi_right(width);
1271 dvi_rule(width, height);
1272 break;
1273 default:
1274 lr_width += width;
1275 break;
1276 }
1277 }
1278
1279 static void
do_putrule(void)1280 do_putrule (void)
1281 {
1282 int32_t width, height;
1283
1284 height = get_buffered_signed_quad ();
1285 width = get_buffered_signed_quad ();
1286 switch (lr_mode) {
1287 case LTYPESETTING:
1288 dvi_rule(width, height);
1289 break;
1290 case RTYPESETTING:
1291 dvi_right(width);
1292 dvi_rule(width, height);
1293 dvi_right(-width);
1294 break;
1295 default:
1296 break;
1297 }
1298 }
1299
1300 void
dvi_push(void)1301 dvi_push (void)
1302 {
1303 if (dvi_stack_depth >= DVI_STACK_DEPTH_MAX)
1304 ERROR("DVI stack exceeded limit.");
1305
1306 dvi_stack[dvi_stack_depth++] = dvi_state;
1307 }
1308
1309 void
dvi_pop(void)1310 dvi_pop (void)
1311 {
1312 if (dvi_stack_depth <= 0)
1313 ERROR ("Tried to pop an empty stack.");
1314
1315 dvi_state = dvi_stack[--dvi_stack_depth];
1316 do_moveto(dvi_state.h, dvi_state.v);
1317 pdf_dev_set_dirmode(dvi_state.d); /* 0: horizontal, 1,3: vertical */
1318 }
1319
1320
1321 void
dvi_w(int32_t ch)1322 dvi_w (int32_t ch)
1323 {
1324 dvi_state.w = ch;
1325 dvi_right(ch);
1326 }
1327
1328 void
dvi_w0(void)1329 dvi_w0 (void)
1330 {
1331 dvi_right(dvi_state.w);
1332 }
1333
1334 void
dvi_x(int32_t ch)1335 dvi_x (int32_t ch)
1336 {
1337 dvi_state.x = ch;
1338 dvi_right(ch);
1339 }
1340
1341 void
dvi_x0(void)1342 dvi_x0 (void)
1343 {
1344 dvi_right(dvi_state.x);
1345 }
1346
1347 void
dvi_y(int32_t ch)1348 dvi_y (int32_t ch)
1349 {
1350 dvi_state.y = ch;
1351 dvi_down(ch);
1352 }
1353
1354 void
dvi_y0(void)1355 dvi_y0 (void)
1356 {
1357 dvi_down(dvi_state.y);
1358 }
1359
1360 void
dvi_z(int32_t ch)1361 dvi_z (int32_t ch)
1362 {
1363 dvi_state.z = ch;
1364 dvi_down(ch);
1365 }
1366
1367 void
dvi_z0(void)1368 dvi_z0 (void)
1369 {
1370 dvi_down(dvi_state.z);
1371 }
1372
1373 static void
skip_fntdef(void)1374 skip_fntdef (void)
1375 {
1376 int area_len, name_len;
1377
1378 skip_bytes(12, dvi_file);
1379 area_len = get_unsigned_byte(dvi_file);
1380 name_len = get_unsigned_byte(dvi_file);
1381 skip_bytes(area_len + name_len, dvi_file);
1382 }
1383
1384 /* when pre-scanning the page, we process fntdef
1385 and remove the fntdef opcode from the buffer */
1386 static void
do_fntdef(int32_t tex_id)1387 do_fntdef (int32_t tex_id)
1388 {
1389 if (linear)
1390 read_font_record(tex_id);
1391 else
1392 skip_fntdef();
1393 --dvi_page_buf_index;
1394 }
1395
1396 void
dvi_set_font(int font_id)1397 dvi_set_font (int font_id)
1398 {
1399 current_font = font_id;
1400 }
1401
1402 static void
do_fnt(int32_t tex_id)1403 do_fnt (int32_t tex_id)
1404 {
1405 int i;
1406
1407 for (i = 0; i < num_def_fonts; i++) {
1408 if (def_fonts[i].tex_id == tex_id)
1409 break;
1410 }
1411
1412 if (i == num_def_fonts) {
1413 ERROR("Tried to select a font that hasn't been defined: id=%d", tex_id);
1414 }
1415
1416 if (!def_fonts[i].used) {
1417 int font_id;
1418
1419 #ifdef XETEX
1420 if (def_fonts[i].native) {
1421 font_id = dvi_locate_native_font(def_fonts[i].font_name,
1422 def_fonts[i].face_index,
1423 def_fonts[i].point_size,
1424 def_fonts[i].layout_dir,
1425 def_fonts[i].extend,
1426 def_fonts[i].slant,
1427 def_fonts[i].embolden);
1428 } else {
1429 font_id = dvi_locate_font(def_fonts[i].font_name,
1430 def_fonts[i].point_size);
1431 }
1432 loaded_fonts[font_id].rgba_color = def_fonts[i].rgba_color;
1433 #else
1434 font_id = dvi_locate_font(def_fonts[i].font_name, def_fonts[i].point_size);
1435 #endif
1436 loaded_fonts[font_id].source = DVI;
1437 def_fonts[i].used = 1;
1438 def_fonts[i].font_id = font_id;
1439 }
1440 current_font = def_fonts[i].font_id;
1441 }
1442
1443 static void
do_xxx(int32_t size)1444 do_xxx (int32_t size)
1445 {
1446 if (lr_mode < SKIMMING)
1447 dvi_do_special(dvi_page_buffer + dvi_page_buf_index, size);
1448 dvi_page_buf_index += size;
1449 }
1450
1451 static void
do_bop(void)1452 do_bop (void)
1453 {
1454 int i;
1455
1456 if (processing_page)
1457 ERROR("Got a bop in the middle of a page!");
1458
1459 /* For now, ignore TeX's count registers */
1460 for (i = 0; i < 10; i++) {
1461 skip_bufferd_bytes(4);
1462 }
1463 /* Ignore previous page pointer since we have already
1464 * saved this information
1465 */
1466 skip_bufferd_bytes(4);
1467 clear_state();
1468 processing_page = 1;
1469
1470 pdf_doc_begin_page(dvi_tell_mag(), dev_origin_x, dev_origin_y);
1471 spc_exec_at_begin_page();
1472
1473 return;
1474 }
1475
1476 static void
do_eop(void)1477 do_eop (void)
1478 {
1479 processing_page = 0;
1480
1481 if (dvi_stack_depth != 0) {
1482 ERROR("DVI stack depth is not zero at end of page");
1483 }
1484 spc_exec_at_end_page();
1485
1486 pdf_doc_end_page();
1487
1488 return;
1489 }
1490
1491 static void
do_dir(void)1492 do_dir (void)
1493 {
1494 dvi_state.d = get_buffered_unsigned_byte();
1495 pdf_dev_set_dirmode(dvi_state.d); /* 0: horizontal, 1,3: vertical */
1496 }
1497
1498 static void
lr_width_push(void)1499 lr_width_push (void)
1500 {
1501 if (lr_width_stack_depth >= DVI_STACK_DEPTH_MAX)
1502 ERROR("Segment width stack exceeded limit.");
1503
1504 lr_width_stack[lr_width_stack_depth++] = lr_width;
1505 }
1506
1507 static void
lr_width_pop(void)1508 lr_width_pop (void)
1509 {
1510 if (lr_width_stack_depth <= 0)
1511 ERROR("Tried to pop an empty segment width stack.");
1512
1513 lr_width = lr_width_stack[--lr_width_stack_depth];
1514 }
1515
1516 static void
dvi_begin_reflect(void)1517 dvi_begin_reflect (void)
1518 {
1519 if (lr_mode >= SKIMMING) {
1520 ++lr_mode;
1521 } else {
1522 lr_state.buf_index = dvi_page_buf_index;
1523 lr_state.font = current_font;
1524 lr_state.state = lr_mode;
1525 lr_mode = SKIMMING;
1526 lr_width = 0;
1527 }
1528 }
1529
1530 static void
dvi_end_reflect(void)1531 dvi_end_reflect (void)
1532 {
1533 switch (lr_mode) {
1534 case SKIMMING:
1535 current_font = lr_state.font;
1536 dvi_page_buf_index = lr_state.buf_index;
1537 lr_mode = REVERSE(lr_state.state); /* must precede dvi_right */
1538 dvi_right(-(int32_t)lr_width);
1539 lr_width_push();
1540 break;
1541 case LTYPESETTING:
1542 case RTYPESETTING:
1543 lr_width_pop();
1544 dvi_right(-(int32_t)lr_width);
1545 lr_mode = REVERSE(lr_mode);
1546 break;
1547 default: /* lr_mode > SKIMMING */
1548 lr_mode--;
1549 }
1550 }
1551
1552 #ifdef XETEX
1553 static void
do_native_font_def(int32_t tex_id)1554 do_native_font_def (int32_t tex_id)
1555 {
1556 if (linear) {
1557 read_native_font_record(tex_id);
1558 } else {
1559 unsigned int flags;
1560 int name_length, i;
1561
1562 get_unsigned_quad(dvi_file); /* skip point size */
1563 flags = get_unsigned_pair(dvi_file);
1564 name_length = (int) get_unsigned_byte(dvi_file);
1565 for (i = 0; i < name_length; ++i)
1566 get_unsigned_byte(dvi_file);
1567 get_unsigned_quad(dvi_file);
1568 if (flags & XDV_FLAG_COLORED) {
1569 get_unsigned_quad(dvi_file);
1570 }
1571 }
1572 --dvi_page_buf_index; /* don't buffer the opcode */
1573 }
1574
1575 static void
skip_glyphs(void)1576 skip_glyphs (void)
1577 {
1578 unsigned int i, slen = 0;
1579 slen = (unsigned int) get_buffered_unsigned_pair();
1580 for (i = 0; i < slen; i++) {
1581 skip_bufferd_bytes(4);
1582 skip_bufferd_bytes(4);
1583 skip_bufferd_bytes(2);
1584 }
1585 }
1586
1587 static void
do_glyphs(void)1588 do_glyphs (void)
1589 {
1590 struct loaded_font *font;
1591 spt_t width, height, depth, *xloc, *yloc, glyph_width = 0;
1592 unsigned char wbuf[2];
1593 unsigned int i, glyph_id, slen = 0;
1594
1595 if (current_font < 0)
1596 ERROR("No font selected!");
1597
1598 font = &loaded_fonts[current_font];
1599
1600 width = get_buffered_signed_quad();
1601
1602 if (lr_mode >= SKIMMING) {
1603 lr_width += width;
1604 skip_glyphs();
1605 return;
1606 }
1607
1608 if (lr_mode == RTYPESETTING)
1609 dvi_right(width); /* Will actually move left */
1610
1611 slen = (unsigned int) get_buffered_unsigned_pair();
1612 xloc = NEW(slen, spt_t);
1613 yloc = NEW(slen, spt_t);
1614 for (i = 0; i < slen; i++) {
1615 xloc[i] = get_buffered_signed_quad();
1616 yloc[i] = get_buffered_signed_quad();
1617 }
1618
1619 if (font->rgba_color != 0xffffffff) {
1620 pdf_color color;
1621 pdf_color_rgbcolor(&color,
1622 (double)((unsigned char)(font->rgba_color >> 24) & 0xff) / 255,
1623 (double)((unsigned char)(font->rgba_color >> 16) & 0xff) / 255,
1624 (double)((unsigned char)(font->rgba_color >> 8) & 0xff) / 255);
1625 pdf_color_push(&color, &color);
1626 }
1627
1628 for (i = 0; i < slen; i++) {
1629 glyph_id = get_buffered_unsigned_pair(); /* freetype glyph index */
1630 if (glyph_id < font->numGlyphs) {
1631 unsigned advance = (font->hvmt)[glyph_id].advance;
1632 glyph_width = (double)font->size * (double)advance / (double)font->unitsPerEm;
1633 glyph_width = glyph_width * font->extend;
1634
1635 if (dvi_is_tracking_boxes()) {
1636 pdf_rect rect;
1637 height = (double)font->size * (double)font->ascent / (double)font->unitsPerEm;
1638 depth = (double)font->size * -(double)font->descent / (double)font->unitsPerEm;
1639 pdf_dev_set_rect(&rect, dvi_state.h + xloc[i], -dvi_state.v - yloc[i], glyph_width, height, depth);
1640 pdf_doc_expand_box(&rect);
1641 }
1642 }
1643
1644 wbuf[0] = glyph_id >> 8;
1645 wbuf[1] = glyph_id & 0xff;
1646 pdf_dev_set_string(dvi_state.h + xloc[i], -dvi_state.v - yloc[i], wbuf, 2,
1647 glyph_width, font->font_id, -1);
1648 }
1649
1650 if (font->rgba_color != 0xffffffff) {
1651 pdf_color_pop();
1652 }
1653 RELEASE(xloc);
1654 RELEASE(yloc);
1655
1656 if (lr_mode == LTYPESETTING)
1657 dvi_right(width);
1658
1659 return;
1660 }
1661 #endif
1662
1663 /* Note to be absolutely certain that the string escape buffer doesn't
1664 * hit its limit, FORMAT_BUF_SIZE should set to 4 times S_BUFFER_SIZE
1665 * in pdfobj.c. Is there any application that genenerate words with
1666 * 1k characters?
1667 */
1668
1669 #define SBUF_SIZE 1024
1670
1671 /* Most of the work of actually interpreting
1672 * the dvi file is here.
1673 */
1674 void
dvi_do_page(double page_paper_height,double hmargin,double vmargin)1675 dvi_do_page (double page_paper_height, double hmargin, double vmargin)
1676 {
1677 unsigned char opcode;
1678
1679 /* before this is called, we have scanned the page for papersize specials
1680 and the complete DVI data is now in dvi_page_buffer */
1681 dvi_page_buf_index = 0;
1682
1683 /* DVI coordinate */
1684 dev_origin_x = hmargin;
1685 dev_origin_y = page_paper_height - vmargin;
1686
1687 dvi_stack_depth = 0;
1688 for (;;) {
1689 opcode = get_buffered_unsigned_byte();
1690
1691 if (opcode <= SET_CHAR_127) {
1692 dvi_set(opcode);
1693 continue;
1694 }
1695
1696 /* If we are here, we have an opcode that is something
1697 * other than SET_CHAR.
1698 */
1699 if (opcode >= FNT_NUM_0 && opcode <= FNT_NUM_63) {
1700 do_fnt(opcode-FNT_NUM_0);
1701 continue;
1702 }
1703
1704 switch (opcode) {
1705 case SET1: case SET2: case SET3:
1706 dvi_set(get_buffered_unsigned_num(opcode-SET1)); break;
1707 case SET4:
1708 ERROR("Multibyte (>24 bits) character not supported!");
1709 break;
1710
1711 case SET_RULE:
1712 do_setrule();
1713 break;
1714
1715 case PUT1: case PUT2: case PUT3:
1716 dvi_put(get_buffered_unsigned_num(opcode-PUT1)); break;
1717 case PUT4:
1718 ERROR("Multibyte (>24 bits) character not supported!");
1719 break;
1720
1721 case PUT_RULE:
1722 do_putrule();
1723 break;
1724
1725 case NOP:
1726 break;
1727
1728 case BOP:
1729 do_bop();
1730 break;
1731 case EOP:
1732 do_eop();
1733 return;
1734
1735 case PUSH:
1736 dvi_push();
1737 if (lr_mode >= SKIMMING)
1738 lr_width_push();
1739 /* The following line needs to go here instead of in
1740 * dvi_push() since logical structure of document is
1741 * oblivous to virtual fonts. For example the last line on a
1742 * page could be at stack level 3 and the page footer should
1743 * be at stack level 3. However, if the page footer contains
1744 * virtual fonts (or other nested constructions), it could
1745 * fool the link breaker into thinking it was a continuation
1746 * of the link */
1747 dvi_mark_depth();
1748 break;
1749 case POP:
1750 dvi_pop();
1751 if (lr_mode >= SKIMMING)
1752 lr_width_pop();
1753 /* Above explanation holds for following line too */
1754 dvi_mark_depth();
1755 break;
1756
1757 case RIGHT1: case RIGHT2: case RIGHT3: case RIGHT4:
1758 dvi_right(get_buffered_signed_num(opcode-RIGHT1)); break;
1759
1760 case W0: dvi_w0(); break;
1761 case W1: case W2: case W3: case W4:
1762 dvi_w(get_buffered_signed_num(opcode-W1)); break;
1763
1764 case X0: dvi_x0(); break;
1765 case X1: case X2: case X3: case X4:
1766 dvi_x(get_buffered_signed_num(opcode-X1)); break;
1767
1768 case DOWN1: case DOWN2: case DOWN3: case DOWN4:
1769 dvi_down(get_buffered_signed_num(opcode-DOWN1)); break;
1770
1771 case Y0: dvi_y0(); break;
1772 case Y1: case Y2: case Y3: case Y4:
1773 dvi_y(get_buffered_signed_num(opcode-Y1)); break;
1774
1775 case Z0: dvi_z0(); break;
1776 case Z1: case Z2: case Z3: case Z4:
1777 dvi_z(get_buffered_signed_num(opcode-Z1)); break;
1778
1779 case FNT1: case FNT2: case FNT3: case FNT4:
1780 do_fnt(get_buffered_unsigned_num(opcode-FNT1)); break;
1781
1782 /* Specials */
1783 case XXX1: case XXX2: case XXX3: case XXX4:
1784 {
1785 int32_t size = get_buffered_unsigned_num(opcode-XXX1);
1786 if (size < 0)
1787 WARN("DVI: Special with %d bytes???", size);
1788 else
1789 do_xxx(size);
1790 break;
1791 }
1792
1793 /* These should not occur - processed during pre-scanning */
1794 case FNT_DEF1: case FNT_DEF2: case FNT_DEF3: case FNT_DEF4:
1795 break;
1796
1797 /* pTeX extension */
1798 case PTEXDIR:
1799 do_dir();
1800 break;
1801
1802 #ifdef XETEX
1803 /* XeTeX extension */
1804 case XDV_GLYPHS:
1805 do_glyphs();
1806 break;
1807 /* should not occur - processed during pre-scanning */
1808 case XDV_NATIVE_FONT_DEF:
1809 break;
1810 #endif
1811 case BEGIN_REFLECT:
1812 dvi_begin_reflect();
1813 break;
1814 case END_REFLECT:
1815 dvi_end_reflect();
1816 break;
1817
1818 case POST:
1819 if (linear && !processing_page) {
1820 /* for linear processing, this means there are no more pages */
1821 num_pages = 0; /* force loop to terminate */
1822 return;
1823 }
1824 /* else fall through to error case */
1825 case PRE: case POST_POST:
1826 ERROR("Unexpected preamble or postamble in dvi file");
1827 break;
1828 default:
1829 ERROR("Unexpected opcode or DVI file ended prematurely");
1830 }
1831 }
1832 }
1833
1834 double
dvi_init(char * dvi_filename,double mag)1835 dvi_init (char *dvi_filename, double mag)
1836 {
1837 int32_t post_location;
1838
1839 if (!dvi_filename) { /* no filename: reading from stdin, probably a pipe */
1840 #ifdef WIN32
1841 setmode(fileno(stdin), _O_BINARY);
1842 #endif
1843 dvi_file = stdin;
1844 linear = 1;
1845
1846 get_preamble_dvi_info();
1847 do_scales(mag);
1848 } else {
1849 dvi_file = MFOPEN(dvi_filename, FOPEN_RBIN_MODE);
1850 if (!dvi_file) {
1851 char *p;
1852 p = strrchr(dvi_filename, '.');
1853 if (p == NULL || (!FILESTRCASEEQ(p, ".dvi") &&
1854 !FILESTRCASEEQ(p, ".xdv"))) {
1855 strcat(dvi_filename, ".xdv");
1856 dvi_file = MFOPEN(dvi_filename, FOPEN_RBIN_MODE);
1857 if (!dvi_file) {
1858 dvi_filename[strlen(dvi_filename) - 4] = '\0';
1859 strcat(dvi_filename, ".dvi");
1860 dvi_file = MFOPEN(dvi_filename, FOPEN_RBIN_MODE);
1861 }
1862 }
1863 }
1864 if (!dvi_file) {
1865 ERROR("Could not open specified DVI (or XDV) file: %s",
1866 dvi_filename);
1867 return 0.0;
1868 }
1869
1870 /* DVI files are most easily read backwards by
1871 * searching for post_post and then post opcode.
1872 */
1873 post_location = find_post();
1874 get_dvi_info(post_location);
1875 do_scales(mag);
1876 get_page_info(post_location);
1877 get_comment();
1878 get_dvi_fonts(post_location);
1879 }
1880 clear_state();
1881
1882 dvi_page_buf_size = DVI_PAGE_BUF_CHUNK;
1883 dvi_page_buffer = NEW(dvi_page_buf_size, unsigned char);
1884
1885 return dvi2pts;
1886 }
1887
1888 void
dvi_close(void)1889 dvi_close (void)
1890 {
1891 int i;
1892
1893 if (linear) {
1894 /* probably reading a pipe from xetex; consume any remaining data */
1895 while (fgetc(dvi_file) != EOF)
1896 ;
1897 }
1898
1899 /* We add comment in dvi_close instead of dvi_init so user
1900 * has a change to overwrite it. The docinfo dictionary is
1901 * treated as a write-once record.
1902 */
1903
1904 /* Do some house cleaning */
1905 MFCLOSE(dvi_file);
1906 dvi_file = NULL;
1907
1908 if (def_fonts) {
1909 for (i = 0; i < num_def_fonts; i++) {
1910 if (def_fonts[i].font_name)
1911 RELEASE(def_fonts[i].font_name);
1912 def_fonts[i].font_name = NULL;
1913 }
1914 RELEASE(def_fonts);
1915 }
1916 def_fonts = NULL;
1917
1918 if (page_loc)
1919 RELEASE(page_loc);
1920 page_loc = NULL;
1921 num_pages = 0;
1922
1923 #ifdef XETEX
1924 for (i = 0; i < num_loaded_fonts; i++)
1925 {
1926 if (loaded_fonts[i].hvmt != NULL)
1927 RELEASE(loaded_fonts[i].hvmt);
1928
1929 loaded_fonts[i].hvmt = NULL;
1930 }
1931 #endif
1932
1933 if (loaded_fonts)
1934 RELEASE(loaded_fonts);
1935 loaded_fonts = NULL;
1936 num_loaded_fonts = 0;
1937
1938 vf_close_all_fonts();
1939 tfm_close_all ();
1940
1941 if (dvi_page_buffer) {
1942 RELEASE(dvi_page_buffer);
1943 dvi_page_buffer = NULL;
1944 dvi_page_buf_size = 0;
1945 }
1946 }
1947
1948 /* The following are need to implement virtual fonts
1949 According to documentation, the vf "subroutine"
1950 must have state pushed and must have
1951 w,v,y, and z set to zero. The current font
1952 is determined by the virtual font header, which
1953 may be undefined */
1954
1955 static int saved_dvi_font[VF_NESTING_MAX];
1956 static int num_saved_fonts = 0;
1957
1958 void
dvi_vf_init(int dev_font_id)1959 dvi_vf_init (int dev_font_id)
1960 {
1961 dvi_push();
1962
1963 dvi_state.w = 0; dvi_state.x = 0;
1964 dvi_state.y = 0; dvi_state.z = 0;
1965
1966 /* do not reset dvi_state.d. */
1967 if (num_saved_fonts < VF_NESTING_MAX) {
1968 saved_dvi_font[num_saved_fonts++] = current_font;
1969 } else
1970 ERROR("Virtual fonts nested too deeply!");
1971 current_font = dev_font_id;
1972 }
1973
1974 /* After VF subroutine is finished, we simply pop the DVI stack */
1975 void
dvi_vf_finish(void)1976 dvi_vf_finish (void)
1977 {
1978 dvi_pop();
1979 if (num_saved_fonts > 0)
1980 current_font = saved_dvi_font[--num_saved_fonts];
1981 else {
1982 ERROR("Tried to pop an empty font stack");
1983 }
1984 }
1985
1986
1987 /* Scan various specials */
1988 #include "dpxutil.h"
1989
1990 /* This need to allow 'true' prefix for unit and
1991 * length value must be divided by current magnification.
1992 */
1993 static int
read_length(double * vp,double mag,const char ** pp,const char * endptr)1994 read_length (double *vp, double mag, const char **pp, const char *endptr)
1995 {
1996 char *q;
1997 const char *p = *pp;
1998 double v, u = 1.0;
1999 const char *_ukeys[] = {
2000 #define K_UNIT__PT 0
2001 #define K_UNIT__IN 1
2002 #define K_UNIT__CM 2
2003 #define K_UNIT__MM 3
2004 #define K_UNIT__BP 4
2005 "pt", "in", "cm", "mm", "bp",
2006 NULL
2007 };
2008 int k, error = 0;
2009
2010 q = parse_float_decimal(&p, endptr);
2011 if (!q) {
2012 *vp = 0.0; *pp = p;
2013 return -1;
2014 }
2015
2016 v = atof(q);
2017 RELEASE(q);
2018
2019 skip_white(&p, endptr);
2020 q = parse_c_ident(&p, endptr);
2021 if (q) {
2022 char *qq = q; /* remember this for RELEASE, because q may be advanced */
2023 if (strlen(q) >= strlen("true") &&
2024 !memcmp(q, "true", strlen("true"))) {
2025 u /= mag != 0.0 ? mag : 1.0; /* inverse magnify */
2026 q += strlen("true");
2027 }
2028 if (strlen(q) == 0) { /* "true" was a separate word from the units */
2029 RELEASE(qq);
2030 skip_white(&p, endptr);
2031 qq = q = parse_c_ident(&p, endptr);
2032 }
2033 if (q) {
2034 for (k = 0; _ukeys[k] && strcmp(_ukeys[k], q); k++);
2035 switch (k) {
2036 case K_UNIT__PT: u *= 72.0 / 72.27; break;
2037 case K_UNIT__IN: u *= 72.0; break;
2038 case K_UNIT__CM: u *= 72.0 / 2.54 ; break;
2039 case K_UNIT__MM: u *= 72.0 / 25.4 ; break;
2040 case K_UNIT__BP: u *= 1.0 ; break;
2041 default:
2042 WARN("Unknown unit of measure: %s", q);
2043 error = -1;
2044 break;
2045 }
2046 RELEASE(qq);
2047 }
2048 else {
2049 WARN("Missing unit of measure after \"true\"");
2050 error = -1;
2051 }
2052 }
2053
2054 *vp = v * u; *pp = p;
2055 return error;
2056 }
2057
2058
2059 static int
scan_special(double * wd,double * ht,double * xo,double * yo,char * lm,unsigned * minorversion,int * do_enc,unsigned * key_bits,unsigned * permission,char * owner_pw,char * user_pw,const char * buf,uint32_t size)2060 scan_special (double *wd, double *ht, double *xo, double *yo, char *lm,
2061 unsigned *minorversion,
2062 int *do_enc, unsigned *key_bits, unsigned *permission, char *owner_pw, char *user_pw,
2063 const char *buf, uint32_t size)
2064 {
2065 char *q;
2066 const char *p = buf, *endptr;
2067 int ns_pdf = 0, error = 0;
2068 double tmp;
2069
2070 endptr = p + size;
2071
2072 skip_white(&p, endptr);
2073
2074 q = parse_c_ident(&p, endptr);
2075 if (q && !strcmp(q, "pdf")) {
2076 skip_white(&p, endptr);
2077 if (p < endptr && *p == ':') {
2078 p++;
2079 skip_white(&p, endptr);
2080 RELEASE(q);
2081 q = parse_c_ident(&p, endptr); ns_pdf = 1;
2082 }
2083 }
2084 else if (q && !strcmp(q, "x")) {
2085 skip_white(&p, endptr);
2086 if (p < endptr && *p == ':') {
2087 p++;
2088 skip_white(&p, endptr);
2089 RELEASE(q);
2090 q = parse_c_ident(&p, endptr);
2091 }
2092 }
2093 skip_white(&p, endptr);
2094
2095 if (q) {
2096 if (!strcmp(q, "landscape")) {
2097 *lm = 1;
2098 } else if (ns_pdf && !strcmp(q, "pagesize")) {
2099 while (!error && p < endptr) {
2100 char *kp = parse_c_ident(&p, endptr);
2101 if (!kp)
2102 break;
2103 else {
2104 skip_white(&p, endptr);
2105 if (!strcmp(kp, "width")) {
2106 error = read_length(&tmp, dvi_tell_mag(), &p, endptr);
2107 if (!error)
2108 *wd = tmp * dvi_tell_mag();
2109 } else if (!strcmp(kp, "height")) {
2110 error = read_length(&tmp, dvi_tell_mag(), &p, endptr);
2111 if (!error)
2112 *ht = tmp * dvi_tell_mag();
2113 } else if (!strcmp(kp, "xoffset")) {
2114 error = read_length(&tmp, dvi_tell_mag(), &p, endptr);
2115 if (!error)
2116 *xo = tmp * dvi_tell_mag();
2117 } else if (!strcmp(kp, "yoffset")) {
2118 error = read_length(&tmp, dvi_tell_mag(), &p, endptr);
2119 if (!error)
2120 *yo = tmp * dvi_tell_mag();
2121 } else if (!strcmp(kp, "default")) {
2122 *wd = paper_width;
2123 *ht = paper_height;
2124 *lm = landscape_mode;
2125 *xo = *yo = 72.0;
2126 }
2127 RELEASE(kp);
2128 }
2129 skip_white(&p, endptr);
2130 }
2131 } else if (!strcmp(q, "papersize")) {
2132 char qchr = 0;
2133 if (*p == '=') p++;
2134 skip_white(&p, endptr);
2135 if (p < endptr && (*p == '\'' || *p == '\"')) {
2136 qchr = *p; p++;
2137 skip_white(&p, endptr);
2138 }
2139 error = read_length(&tmp, 1.0, &p, endptr);
2140 if (!error) {
2141 double tmp1;
2142
2143 skip_white(&p, endptr);
2144 if (p < endptr && *p == ',') {
2145 p++; skip_white(&p, endptr);
2146 }
2147 error = read_length(&tmp1, 1.0, &p, endptr);
2148 if (!error)
2149 *wd = tmp;
2150 *ht = tmp1;
2151 skip_white(&p, endptr);
2152 }
2153 if (!error && qchr) { /* Check if properly quoted */
2154 if (p >= endptr || *p != qchr)
2155 error = -1;
2156 }
2157 if (error == 0) {
2158 paper_width = *wd;
2159 paper_height = *ht;
2160 }
2161 } else if (minorversion && ns_pdf && !strcmp(q, "minorversion")) {
2162 char *kv;
2163 if (*p == '=') p++;
2164 skip_white(&p, endptr);
2165 kv = parse_float_decimal(&p, endptr);
2166 if (kv) {
2167 *minorversion = (unsigned)strtol(kv, NULL, 10);
2168 RELEASE(kv);
2169 }
2170 } else if (ns_pdf && !strcmp(q, "encrypt") && do_enc) {
2171 *do_enc = 1;
2172 *owner_pw = *user_pw = 0;
2173 while (!error && p < endptr) {
2174 char *kp = parse_c_ident(&p, endptr);
2175 if (!kp)
2176 break;
2177 else {
2178 pdf_obj *obj;
2179 skip_white(&p, endptr);
2180 if (!strcmp(kp, "ownerpw")) {
2181 if ((obj = parse_pdf_string(&p, endptr))) {
2182 strncpy(owner_pw, pdf_string_value(obj), MAX_PWD_LEN);
2183 pdf_release_obj(obj);
2184 } else
2185 error = -1;
2186 } else if (!strcmp(kp, "userpw")) {
2187 if ((obj = parse_pdf_string(&p, endptr))) {
2188 strncpy(user_pw, pdf_string_value(obj), MAX_PWD_LEN);
2189 pdf_release_obj(obj);
2190 } else
2191 error = -1;
2192 } else if (!strcmp(kp, "length")) {
2193 if ((obj = parse_pdf_number(&p, endptr)) && PDF_OBJ_NUMBERTYPE(obj)) {
2194 *key_bits = (unsigned) pdf_number_value(obj);
2195 } else
2196 error = -1;
2197 if (obj)
2198 pdf_release_obj(obj);
2199 } else if (!strcmp(kp, "perm")) {
2200 if ((obj = parse_pdf_number(&p, endptr)) && PDF_OBJ_NUMBERTYPE(obj)) {
2201 *permission = (unsigned) pdf_number_value(obj);
2202 } else
2203 error = -1;
2204 if (obj)
2205 pdf_release_obj(obj);
2206 } else
2207 error = -1;
2208 RELEASE(kp);
2209 }
2210 skip_white(&p, endptr);
2211 }
2212 }
2213 RELEASE(q);
2214 }
2215
2216 return error;
2217 }
2218
2219
2220 void
dvi_scan_specials(int page_no,double * page_width,double * page_height,double * x_offset,double * y_offset,char * landscape,unsigned * minorversion,int * do_enc,unsigned * key_bits,unsigned * permission,char * owner_pw,char * user_pw)2221 dvi_scan_specials (int page_no,
2222 double *page_width, double *page_height,
2223 double *x_offset, double *y_offset, char *landscape,
2224 unsigned *minorversion,
2225 int *do_enc, unsigned *key_bits, unsigned *permission, char *owner_pw, char *user_pw)
2226 {
2227 FILE *fp = dvi_file;
2228 int32_t offset;
2229 unsigned char opcode;
2230 static int buffered_page = -1;
2231 #if XETEX
2232 unsigned int len;
2233 #endif
2234
2235 if (page_no == buffered_page)
2236 return; /* because dvipdfmx wants to scan first page twice! */
2237 buffered_page = page_no;
2238
2239 dvi_page_buf_index = 0;
2240
2241 if (!linear) {
2242 if (page_no >= num_pages)
2243 ERROR("Invalid page number: %u", page_no);
2244 offset = page_loc[page_no];
2245
2246 xseek_absolute (fp, offset, "DVI");
2247 }
2248
2249 while ((opcode = get_and_buffer_unsigned_byte(fp)) != EOP) {
2250 if (opcode <= SET_CHAR_127 ||
2251 (opcode >= FNT_NUM_0 && opcode <= FNT_NUM_63))
2252 continue;
2253 else if (opcode == XXX1 || opcode == XXX2 ||
2254 opcode == XXX3 || opcode == XXX4) {
2255 uint32_t size = get_and_buffer_unsigned_byte(fp);
2256 switch (opcode) {
2257 case XXX4: size = size * 0x100u + get_and_buffer_unsigned_byte(fp);
2258 if (size > 0x7fff)
2259 WARN("Unsigned number starting with %x exceeds 0x7fffffff", size);
2260 case XXX3: size = size * 0x100u + get_and_buffer_unsigned_byte(fp);
2261 case XXX2: size = size * 0x100u + get_and_buffer_unsigned_byte(fp);
2262 default: break;
2263 }
2264 if (dvi_page_buf_index + size >= dvi_page_buf_size) {
2265 dvi_page_buf_size = (dvi_page_buf_index + size + DVI_PAGE_BUF_CHUNK);
2266 dvi_page_buffer = RENEW(dvi_page_buffer, dvi_page_buf_size, unsigned char);
2267 }
2268 #define buf (char*)dvi_page_buffer + dvi_page_buf_index
2269 if (fread(buf, sizeof(char), size, fp) != size)
2270 ERROR("Reading DVI file failed!");
2271 if (scan_special(page_width, page_height, x_offset, y_offset, landscape,
2272 minorversion, do_enc, key_bits, permission, owner_pw, user_pw,
2273 buf, size))
2274 WARN("Reading special command failed: \"%.*s\"", size, buf);
2275 #undef buf
2276 dvi_page_buf_index += size;
2277 continue;
2278 }
2279
2280 /* Skipping... */
2281 switch (opcode) {
2282 case BOP:
2283 get_and_buffer_bytes(fp, 44);
2284 break;
2285 case NOP: case PUSH: case POP:
2286 case W0: case X0: case Y0: case Z0:
2287 break;
2288 case SET1: case PUT1: case RIGHT1: case DOWN1:
2289 case W1: case X1: case Y1: case Z1: case FNT1:
2290 get_and_buffer_bytes(fp, 1);
2291 break;
2292
2293 case SET2: case PUT2: case RIGHT2: case DOWN2:
2294 case W2: case X2: case Y2: case Z2: case FNT2:
2295 get_and_buffer_bytes(fp, 2);
2296 break;
2297
2298 case SET3: case PUT3: case RIGHT3: case DOWN3:
2299 case W3: case X3: case Y3: case Z3: case FNT3:
2300 get_and_buffer_bytes(fp, 3);
2301 break;
2302
2303 case SET4: case PUT4: case RIGHT4: case DOWN4:
2304 case W4: case X4: case Y4: case Z4: case FNT4:
2305 get_and_buffer_bytes(fp, 4);
2306 break;
2307
2308 case SET_RULE: case PUT_RULE:
2309 get_and_buffer_bytes(fp, 8);
2310 break;
2311
2312 case FNT_DEF1: case FNT_DEF2: case FNT_DEF3: case FNT_DEF4:
2313 do_fntdef(get_unsigned_num(fp, opcode-FNT_DEF1));
2314 break;
2315 #ifdef XETEX
2316 case XDV_GLYPHS:
2317 get_and_buffer_bytes(fp, 4); /* width */
2318 len = get_and_buffer_unsigned_pair(fp); /* glyph count */
2319 get_and_buffer_bytes(fp, len * 10); /* 2 bytes ID + 8 bytes x,y-location per glyph */
2320 break;
2321 case XDV_NATIVE_FONT_DEF:
2322 do_native_font_def(get_signed_quad(dvi_file));
2323 break;
2324 #endif
2325 case BEGIN_REFLECT:
2326 case END_REFLECT:
2327 break;
2328
2329 case PTEXDIR:
2330 get_and_buffer_bytes(fp, 1);
2331 break;
2332
2333 case POST:
2334 if (linear && dvi_page_buf_index == 1) {
2335 /* this is actually an indication that we've reached the end of the input */
2336 return;
2337 }
2338 /* else fall through to error case */
2339 default: /* case PRE: case POST_POST: and others */
2340 ERROR("Unexpected opcode %d at pos=0x%x", opcode, tell_position(fp));
2341 break;
2342 }
2343 }
2344
2345 return;
2346 }
2347
2348