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