OSDN Git Service

updated with TeX Live 2014.
[putex/putex.git] / src / dvipdfmx-pu / src / vf.c
1 /*  
2     
3     This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
4
5     Copyright (C) 2007-2012 by Jin-Hwan Cho and Shunsaku Hirata,
6     the dvipdfmx project team.
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 #if HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include "system.h"
30 #include "numbers.h"
31 #include "error.h"
32 #include "mem.h"
33
34 #include "dpxfile.h"
35 /* pdfdev... */
36 #include "pdfdev.h"
37
38 #include "tfm.h"
39 #include "dvi.h"
40 #include "vf.h"
41
42 #include "dvicodes.h"
43
44 #define VF_ALLOC_SIZE  16u
45
46 #define VF_ID 202
47 #define FIX_WORD_BASE 1048576.0
48 #define TEXPT2PT (72.0/72.27)
49 #define FW2PT (TEXPT2PT/((double)(FIX_WORD_BASE)))
50
51 static unsigned char verbose = 0;
52
53 void vf_set_verbose(void)
54 {
55   if (verbose < 255) verbose++;
56 }
57
58 struct font_def {
59   signed long font_id /* id used internally in vf file */;
60   unsigned long checksum, size, design_size;
61   char *directory, *name;
62   int tfm_id;  /* id returned by TFM module */
63   int dev_id;  /* id returned by DEV module */
64 };
65
66 struct vf 
67 {
68   char *tex_name;
69   spt_t ptsize;
70   unsigned long design_size; /* A fixword-pts quantity */
71   int num_dev_fonts, max_dev_fonts;
72   struct font_def *dev_fonts;
73   unsigned char **ch_pkt;
74   unsigned long *pkt_len;
75   unsigned num_chars;
76 };
77
78 struct vf *vf_fonts = NULL;
79 int num_vf_fonts = 0, max_vf_fonts = 0;
80
81 static int read_header(FILE *vf_file, int thisfont) 
82 {
83   int i, result = 1, ch;
84
85   /* Check for usual signature */
86   if ((ch = get_unsigned_byte (vf_file)) == PRE &&
87       (ch = get_unsigned_byte (vf_file)) == VF_ID) {
88
89     /* If here, assume it's a legitimate vf file */
90     ch = get_unsigned_byte (vf_file);
91
92     /* skip comment */
93     for (i=0; i<ch; i++)
94       get_unsigned_byte (vf_file);
95
96     /* Skip checksum */
97     get_unsigned_quad(vf_file);
98     
99     vf_fonts[thisfont].design_size =
100       get_unsigned_quad(vf_file);
101   } else { /* Try to fail gracefully and return an error to caller */
102     fprintf (stderr, "VF file may be corrupt\n");
103     result = 0;
104   }
105   return result;
106 }
107
108
109 static void resize_vf_fonts(int size)
110 {
111   int i;
112   if (size > max_vf_fonts) {
113     vf_fonts = RENEW (vf_fonts, size, struct vf);
114     for (i=max_vf_fonts; i<size; i++) {
115       vf_fonts[i].num_dev_fonts = 0;
116       vf_fonts[i].max_dev_fonts = 0;
117       vf_fonts[i].dev_fonts = NULL;
118     }
119     max_vf_fonts = size;
120   }
121   return;
122 }
123
124 static void resize_one_vf_font (struct vf *a_vf, unsigned size) 
125 {
126   unsigned i;
127   if (size > (a_vf->num_chars)) {
128     size = MAX (size, a_vf->num_chars+256);
129     a_vf->ch_pkt = RENEW (a_vf->ch_pkt, size, unsigned char *);
130     a_vf->pkt_len = RENEW (a_vf->pkt_len, size, unsigned long);
131     for (i=a_vf->num_chars; i<size; i++) {
132       (a_vf->ch_pkt)[i] = NULL;
133       (a_vf->pkt_len)[i] = 0;
134     }
135     a_vf->num_chars = size;
136   }
137 }
138
139 static void read_a_char_def(FILE *vf_file, int thisfont, unsigned long pkt_len,
140                             unsigned ch)
141 {
142   unsigned char *pkt;
143 #ifdef DEBUG
144   fprintf (stderr, "read_a_char_def: len=%ld, ch=%d\n", pkt_len, ch);
145 #endif
146   /* Resize and initialize character arrays if necessary */
147   if (ch >= vf_fonts[thisfont].num_chars) {
148     resize_one_vf_font (vf_fonts+thisfont, ch+1);
149   }
150   if (pkt_len > 0) {
151     pkt = NEW (pkt_len, unsigned char);
152     if (fread (pkt, 1, pkt_len, vf_file) != pkt_len)
153       ERROR ("VF file ended prematurely.");
154     (vf_fonts[thisfont].ch_pkt)[ch] = pkt;
155   }
156   (vf_fonts[thisfont].pkt_len)[ch] = pkt_len;
157   return;
158 }
159
160 static void read_a_font_def(FILE *vf_file, signed long font_id, int thisfont)
161 {
162   struct font_def *dev_font;
163   int dir_length, name_length;
164 #ifdef DEBUG
165   fprintf (stderr, "read_a_font_def: font_id = %ld\n", font_id);
166 #endif
167   if (vf_fonts[thisfont].num_dev_fonts >=
168       vf_fonts[thisfont].max_dev_fonts) {
169     vf_fonts[thisfont].max_dev_fonts += VF_ALLOC_SIZE;
170     vf_fonts[thisfont].dev_fonts = RENEW
171       (vf_fonts[thisfont].dev_fonts,
172        vf_fonts[thisfont].max_dev_fonts,
173        struct font_def);
174   }
175   dev_font = vf_fonts[thisfont].dev_fonts+
176     vf_fonts[thisfont].num_dev_fonts;
177   dev_font -> font_id = font_id;
178   dev_font -> checksum = get_unsigned_quad (vf_file);
179   dev_font -> size = get_unsigned_quad (vf_file);
180   dev_font -> design_size = get_unsigned_quad (vf_file);
181   dir_length = get_unsigned_byte (vf_file);
182   name_length = get_unsigned_byte (vf_file);
183   dev_font -> directory = NEW (dir_length+1, char);
184   dev_font -> name = NEW (name_length+1, char);
185   fread (dev_font -> directory, 1, dir_length, vf_file);
186   fread (dev_font -> name, 1, name_length, vf_file);
187   (dev_font -> directory)[dir_length] = 0;
188   (dev_font -> name)[name_length] = 0;
189   vf_fonts[thisfont].num_dev_fonts += 1;
190   dev_font->tfm_id = tfm_open (dev_font -> name, 1); /* must exist */
191   dev_font->dev_id =
192     dvi_locate_font (dev_font->name, 
193                      sqxfw (vf_fonts[thisfont].ptsize,
194                             dev_font->size));
195 #ifdef DEBUG
196   fprintf (stderr, "[%s/%s]\n", dev_font -> directory, dev_font -> name);
197 #endif
198   return;
199 }
200
201
202 static void process_vf_file (FILE *vf_file, int thisfont)
203 {
204   int eof = 0, code;
205   unsigned long font_id;
206   while (!eof) {
207     code = get_unsigned_byte (vf_file);
208     switch (code) {
209     case FNT_DEF1:
210       font_id = get_unsigned_byte (vf_file);
211       read_a_font_def (vf_file, font_id, thisfont);
212       break;
213     case FNT_DEF2:
214       font_id = get_unsigned_pair (vf_file);
215       read_a_font_def (vf_file, font_id, thisfont);
216       break;
217     case FNT_DEF3:
218       font_id = get_unsigned_triple(vf_file);
219       read_a_font_def (vf_file, font_id, thisfont);
220       break;
221     case FNT_DEF4:
222       font_id = get_signed_quad(vf_file);
223       read_a_font_def (vf_file, font_id, thisfont);
224       break;
225     default:
226       if (code < 242) {
227         long ch;
228         /* For a short packet, code is the pkt_len */
229         ch = get_unsigned_byte (vf_file);
230         /* Skip over TFM width since we already know it */
231         get_unsigned_triple (vf_file);
232         read_a_char_def (vf_file, thisfont, code, ch);
233         break;
234       }
235       if (code == 242) {
236         unsigned long pkt_len, ch;
237         pkt_len = get_unsigned_quad(vf_file);
238         ch = get_unsigned_quad (vf_file);
239         /* Skip over TFM width since we already know it */
240         get_unsigned_quad (vf_file);
241         if (ch < 0x1000000L) 
242           read_a_char_def (vf_file, thisfont, pkt_len, ch);
243         else {
244           fprintf (stderr, "char=%ld\n", ch);
245           ERROR ("Long character (>24 bits) in VF file.\nI can't handle long characters!\n");
246         }
247         break;
248       }
249       if (code == POST) {
250         eof = 1;
251         break;
252       }
253       fprintf (stderr, "Quitting on code=%d\n", code);
254       eof = 1;
255       break;
256     }
257   }
258   return;
259 }
260
261 /* Unfortunately, the following code isn't smart enough
262    to load the vf only once for multiple point sizes. 
263    You will get a separate copy of each VF in memory (and a separate
264    opening and reading of the file) for
265    each point size.  Since VFs are pretty small, I guess
266    this is tolerable for now.  In any case, 
267    the PDF file will never repeat a physical font name */
268 /* Note: This code needs to be able to recurse */
269 /* Global variables such as num_vf_fonts require careful attention */
270 int vf_locate_font (const char *tex_name, spt_t ptsize)
271 {
272   int thisfont = -1, i;
273   char *full_vf_file_name;
274   FILE *vf_file;
275   /* Has this name and ptsize already been loaded as a VF? */
276   for (i=0; i<num_vf_fonts; i++) {
277     if (!strcmp (vf_fonts[i].tex_name, tex_name) &&
278         vf_fonts[i].ptsize == ptsize) 
279       break;
280   }
281   if (i != num_vf_fonts) {
282     thisfont = i;
283   } else {
284     /* It's hasn't already been loaded as a VF, so try to load it */
285     full_vf_file_name = kpse_find_file (tex_name, 
286                                         kpse_vf_format,
287                                         1);
288     if (!full_vf_file_name) {
289       full_vf_file_name = kpse_find_file (tex_name, 
290                                           kpse_ovf_format,
291                                           1);
292     }
293     if (full_vf_file_name &&
294         (vf_file = MFOPEN (full_vf_file_name, FOPEN_RBIN_MODE)) != NULL) {
295       if (verbose == 1)
296         fprintf (stderr, "(VF:%s", tex_name);
297       if (verbose > 1)
298         fprintf (stderr, "(VF:%s", full_vf_file_name);
299       if (num_vf_fonts >= max_vf_fonts) {
300         resize_vf_fonts (max_vf_fonts + VF_ALLOC_SIZE);
301       }
302       thisfont = num_vf_fonts++;
303       { /* Initialize some pointers and such */
304         vf_fonts[thisfont].tex_name = NEW (strlen(tex_name)+1, char);
305         strcpy (vf_fonts[thisfont].tex_name, tex_name);
306         vf_fonts[thisfont].ptsize = ptsize;
307         vf_fonts[thisfont].num_chars = 0;
308         vf_fonts[thisfont].ch_pkt = NULL;
309         vf_fonts[thisfont].pkt_len = NULL;
310       }
311       read_header(vf_file, thisfont);
312       process_vf_file (vf_file, thisfont);
313       if (verbose)
314         fprintf (stderr, ")");
315       MFCLOSE (vf_file);
316     }
317     if (full_vf_file_name)
318       RELEASE(full_vf_file_name);
319   }
320   return thisfont;
321 }
322
323 #define next_byte() (*((*start)++))
324 static UNSIGNED_BYTE unsigned_byte (unsigned char **start, unsigned char *end)
325 {
326   UNSIGNED_BYTE byte = 0;
327   if (*start < end)
328     byte = next_byte();
329   else
330     ERROR ("Premature end of DVI byte stream in VF font\n");
331   return byte;
332 }
333
334 static SIGNED_BYTE signed_byte (unsigned char **start, unsigned char *end)
335 {
336   int byte = 0;
337   if (*start < end) {
338     byte = next_byte();
339     if (byte >= 0x80) 
340       byte -= 0x100;
341   }
342   else
343     ERROR ("Premature end of DVI byte stream in VF font\n");
344   return (SIGNED_BYTE) byte;
345 }
346
347 static UNSIGNED_PAIR unsigned_pair (unsigned char **start, unsigned char *end)
348 {
349   int i;
350   UNSIGNED_BYTE byte;
351   UNSIGNED_PAIR pair = 0;
352   if (end-*start > 1) {
353     for (i=0; i<2; i++) {
354       byte = next_byte();
355       pair = pair*0x100u + byte;
356     }
357   }
358   else
359     ERROR ("Premature end of DVI byte stream in VF font\n");
360   return pair;
361 }
362
363 static SIGNED_PAIR signed_pair (unsigned char **start, unsigned char *end)
364 {
365   int i;
366   long pair = 0;
367   if (end - *start > 1) {
368     for (i=0; i<2; i++) {
369       pair = pair*0x100 + next_byte();
370     }
371     if (pair >= 0x8000) {
372       pair -= 0x10000l;
373     }
374   } else
375     ERROR ("Premature end of DVI byte stream in VF font\n");
376   return (SIGNED_PAIR) pair;
377 }
378
379 static UNSIGNED_TRIPLE unsigned_triple(unsigned char **start, unsigned
380                                     char *end)
381 {
382   int i;
383   long triple = 0;
384   if (end-*start > 2) {
385     for (i=0; i<3; i++) {
386       triple = triple*0x100u + next_byte();
387     }
388   } else
389     ERROR ("Premature end of DVI byte stream in VF font\n");
390   return (UNSIGNED_TRIPLE) triple;
391 }
392
393 static SIGNED_TRIPLE signed_triple(unsigned char **start, unsigned char *end)
394 {
395   int i;
396   long triple = 0;
397   if (end-*start > 2) {
398     for (i=0; i<3; i++) {
399       triple = triple*0x100 + next_byte();
400     }
401     if (triple >= 0x800000l) 
402        triple -= 0x1000000l;
403   } else
404     ERROR ("Premature end of DVI byte stream in VF font\n");
405   return (SIGNED_TRIPLE) triple;
406 }
407
408 static SIGNED_QUAD signed_quad(unsigned char **start, unsigned char *end)
409 {
410   int byte, i;
411   long quad = 0;
412   /* Check sign on first byte before reading others */
413   if (end-*start > 3) {
414     byte = next_byte();
415     quad = byte;
416     if (quad >= 0x80) 
417       quad = byte - 0x100;
418     for (i=0; i<3; i++) {
419       quad = quad*0x100 + next_byte();
420     }
421   } else
422     ERROR ("Premature end of DVI byte stream in VF font\n");
423   return (SIGNED_QUAD) quad;
424 }
425
426 static UNSIGNED_QUAD unsigned_quad(unsigned char **start, unsigned char *end)
427 {
428   int i;
429   unsigned long quad = 0;
430   if (end-*start > 3) {
431     for (i=0; i<4; i++) {
432       quad = quad*0x100u + next_byte();
433     }
434   } else
435     ERROR ("Premature end of DVI byte stream in VF font\n");
436   return (UNSIGNED_QUAD) quad;
437 }
438
439 static void vf_set (SIGNED_QUAD ch)
440 {
441   /* Defer to the dvi_set() defined in dvi.c */
442   dvi_set (ch);
443   return;
444 }
445
446 static void vf_set1(unsigned char **start, unsigned char *end) 
447 {
448   vf_set (unsigned_byte(start, end));
449   return;
450 }
451
452 static void vf_set2(unsigned char **start, unsigned char *end) 
453 {
454   vf_set (unsigned_pair(start, end));
455   return;
456 }
457
458 static void vf_set3(unsigned char **start, unsigned char *end) 
459 {
460   vf_set (unsigned_triple(start, end));
461   return;
462 }
463
464 static void vf_putrule(unsigned char **start, unsigned char *end, spt_t ptsize)
465 {
466   SIGNED_QUAD width, height;
467   height = signed_quad (start, end);
468   width = signed_quad (start, end);
469   if (width > 0 && height > 0) {
470     dvi_rule (sqxfw(ptsize,width), sqxfw(ptsize, height));
471   }
472   return;
473 }
474
475 static void vf_setrule(unsigned char **start, unsigned char *end, spt_t ptsize)
476 {
477   SIGNED_QUAD width, height, s_width;
478   height = signed_quad (start, end);
479   width = signed_quad (start, end);
480   s_width = sqxfw(ptsize, width);
481   if (width > 0 && height > 0) {
482     dvi_rule (s_width, sqxfw(ptsize, height));
483   }
484   dvi_right (s_width);
485   return;
486 }
487
488 static void vf_put1(unsigned char **start, unsigned char *end)
489 {
490   dvi_put (unsigned_byte(start, end));
491   return;
492 }
493
494 static void vf_put2(unsigned char **start, unsigned char *end)
495 {
496   dvi_put (unsigned_pair(start, end));
497   return;
498 }
499
500 static void vf_put3(unsigned char **start, unsigned char *end)
501 {
502   dvi_put (unsigned_triple(start, end));
503   return;
504 }
505
506 static void vf_push(void)
507 {
508   dvi_push();
509   return;
510 }
511
512 static void vf_pop(void)
513 {
514   dvi_pop();
515   return;
516 }
517
518 static void vf_right (SIGNED_QUAD x, spt_t ptsize)
519 {
520   dvi_right ((SIGNED_QUAD) (sqxfw(ptsize, x)));
521   return;
522 }
523
524
525 static void vf_right1(unsigned char **start, unsigned char *end, spt_t ptsize)
526 {
527   vf_right (signed_byte (start, end), ptsize);
528   return;
529 }
530
531 static void vf_right2(unsigned char **start, unsigned char *end, spt_t ptsize)
532 {
533   vf_right (signed_pair (start, end), ptsize);
534   return;
535 }
536
537 static void vf_right3(unsigned char **start, unsigned char *end, spt_t ptsize)
538 {
539   vf_right (signed_triple (start, end), ptsize);
540   return;
541 }
542
543 static void vf_right4(unsigned char **start, unsigned char *end, spt_t ptsize)
544 {
545   vf_right (signed_quad (start, end), ptsize);
546   return;
547 }
548
549 static void vf_w0(void)
550 {
551   dvi_w0();
552   return;
553 }
554
555 static void vf_w (SIGNED_QUAD w, spt_t ptsize)
556 {
557   dvi_w ((SIGNED_QUAD) (sqxfw(ptsize, w)));
558   return;
559 }
560
561 static void vf_w1(unsigned char **start, unsigned char *end, spt_t ptsize)
562 {
563   vf_w (signed_byte(start, end), ptsize);
564   return;
565 }
566
567 static void vf_w2(unsigned char **start, unsigned char *end, spt_t ptsize)
568 {
569   vf_w (signed_pair(start, end), ptsize);
570   return;
571 }
572
573 static void vf_w3(unsigned char **start, unsigned char *end, spt_t ptsize)
574 {
575   vf_w (signed_triple(start, end), ptsize);
576   return;
577 }
578
579 static void vf_w4(unsigned char **start, unsigned char *end, spt_t ptsize)
580 {
581   vf_w (signed_quad(start, end), ptsize);
582   return;
583 }
584
585 static void vf_x0(void)
586 {
587   dvi_x0();
588   return;
589 }
590
591 static void vf_x (SIGNED_QUAD x, spt_t ptsize)
592 {
593   dvi_x ((SIGNED_QUAD) (sqxfw(ptsize, x)));
594   return;
595 }
596
597 static void vf_x1(unsigned char **start, unsigned char *end, spt_t ptsize)
598 {
599   vf_x (signed_byte(start, end), ptsize);
600   return;
601 }
602
603 static void vf_x2(unsigned char **start, unsigned char *end, spt_t ptsize)
604 {
605   vf_x (signed_pair(start, end), ptsize);
606   return;
607 }
608
609 static void vf_x3(unsigned char **start, unsigned char *end, spt_t ptsize)
610 {
611   vf_x (signed_triple(start, end), ptsize);
612   return;
613 }
614
615 static void vf_x4(unsigned char **start, unsigned char *end, spt_t ptsize)
616 {
617   vf_x (signed_quad(start, end), ptsize);
618   return;
619 }
620
621 static void vf_down (SIGNED_QUAD y, spt_t ptsize)
622 {
623   dvi_down ((SIGNED_QUAD) (sqxfw(ptsize, y)));
624   return;
625 }
626
627 static void vf_down1(unsigned char **start, unsigned char *end, spt_t ptsize)
628 {
629   vf_down (signed_byte(start, end), ptsize);
630   return;
631 }
632
633 static void vf_down2(unsigned char **start, unsigned char *end, spt_t ptsize)
634 {
635   vf_down (signed_pair(start, end), ptsize);
636   return;
637 }
638
639 static void vf_down3(unsigned char **start, unsigned char *end, spt_t ptsize)
640 {
641   vf_down (signed_triple(start, end), ptsize);
642   return;
643 }
644
645 static void vf_down4(unsigned char **start, unsigned char *end, spt_t ptsize)
646 {
647   vf_down (signed_quad(start, end), ptsize);
648   return;
649 }
650
651 static void vf_y0(void)
652 {
653   dvi_y0();
654   return;
655 }
656
657 static void vf_y (SIGNED_QUAD y, spt_t ptsize)
658 {
659   dvi_y ((SIGNED_QUAD) (sqxfw(ptsize, y)));
660   return;
661 }
662
663
664 static void vf_y1(unsigned char **start, unsigned char *end, spt_t ptsize)
665 {
666   vf_y (signed_byte(start, end), ptsize);
667   return;
668 }
669
670 static void vf_y2(unsigned char **start, unsigned char *end, spt_t ptsize)
671 {
672   vf_y (signed_pair(start, end), ptsize);
673   return;
674 }
675
676 static void vf_y3(unsigned char **start, unsigned char *end, spt_t ptsize)
677 {
678   vf_y (signed_triple(start, end), ptsize);
679   return;
680 }
681
682 static void vf_y4(unsigned char **start, unsigned char *end, spt_t ptsize)
683 {
684   vf_y (signed_quad(start, end), ptsize);
685   return;
686 }
687
688 static void vf_z0(void)
689 {
690   dvi_z0();
691   return;
692 }
693
694 static void vf_z (SIGNED_QUAD z, spt_t ptsize)
695 {
696   dvi_z ((SIGNED_QUAD) (sqxfw(ptsize, z)));
697   return;
698 }
699
700 static void vf_z1(unsigned char **start, unsigned char *end, spt_t ptsize)
701 {
702   vf_z (signed_byte(start, end), ptsize);
703   return;
704 }
705
706 static void vf_z2(unsigned char **start, unsigned char *end, spt_t ptsize)
707 {
708   vf_z (signed_pair(start, end), ptsize);
709   return;
710 }
711
712 static void vf_z3(unsigned char **start, unsigned char *end, spt_t ptsize)
713 {
714   vf_z (signed_triple(start, end), ptsize);
715   return;
716 }
717
718 static void vf_z4(unsigned char **start, unsigned char *end, spt_t ptsize)
719 {
720   vf_z (signed_quad(start, end), ptsize);
721   return;
722 }
723
724 static void vf_fnt (SIGNED_QUAD font_id, unsigned long vf_font)
725 {
726   int i;
727   for (i=0; i<vf_fonts[vf_font].num_dev_fonts; i++) {
728     if (font_id == ((vf_fonts[vf_font].dev_fonts)[i]).font_id) {
729       break;
730     }
731   }
732   if (i < vf_fonts[vf_font].num_dev_fonts) { /* Font was found */
733     dvi_set_font ((vf_fonts[vf_font].dev_fonts[i]).dev_id);
734   } else {
735     fprintf (stderr, "Font_id: %ld not found in VF\n", font_id);
736   }
737   return;
738 }
739
740 static void vf_fnt1(unsigned char **start, unsigned char *end,
741                     unsigned long vf_font)
742 {
743   vf_fnt (unsigned_byte(start, end), vf_font);
744   return;
745 }
746
747 static void vf_fnt2(unsigned char **start, unsigned char *end,
748                     unsigned long vf_font)
749 {
750   vf_fnt (unsigned_pair(start, end), vf_font);
751   return;
752 }
753
754 static void vf_fnt3(unsigned char **start, unsigned char *end,
755                     unsigned long vf_font)
756 {
757   vf_fnt (unsigned_triple(start, end), vf_font);
758   return;
759 }
760
761 static void vf_fnt4(unsigned char **start, unsigned char *end,
762                     unsigned long vf_font)
763 {
764   vf_fnt (signed_quad(start, end), vf_font);
765   return;
766 }
767
768 /* identical to do_xxx in dvi.c */
769 static void vf_xxx (SIGNED_QUAD len, unsigned char **start, unsigned char *end)
770 {
771   Ubyte *buffer;
772
773   if (*start <= end - len) {
774     buffer = NEW(len+1, Ubyte);
775     memcpy(buffer, *start, len);
776     buffer[len] = '\0';
777     {
778       Ubyte *p = buffer;
779
780       while (p < buffer+len && *p == ' ') p++;
781       /*
782        * Warning message from virtual font.
783        */
784       if (!memcmp((char *)p, "Warning:", 8)) {
785         if (verbose)
786           WARN("VF:%s", p+8);
787       } else {
788         dvi_do_special(buffer, len);
789       }
790     }
791     RELEASE(buffer);
792   } else {
793     ERROR ("Premature end of DVI byte stream in VF font.");
794   }
795
796   *start += len;
797   return;
798 }
799
800 static void vf_xxx1(unsigned char **start, unsigned char *end)
801 {
802   vf_xxx (unsigned_byte(start, end), start, end);
803   return;
804 }
805
806 static void vf_xxx2(unsigned char **start, unsigned char *end)
807 {
808   vf_xxx (unsigned_pair(start, end), start, end);
809   return;
810 }
811
812 static void vf_xxx3(unsigned char **start, unsigned char *end)
813 {
814   vf_xxx (unsigned_triple(start, end), start, end);
815   return;
816 }
817
818 static void vf_xxx4(unsigned char **start, unsigned char *end)
819 {
820   vf_xxx (unsigned_quad(start, end), start, end);
821   return;
822 }
823
824 static void vf_dir(unsigned char **start, unsigned char *end)
825 {
826   dvi_dir (unsigned_byte(start, end));
827   return;
828 }
829
830 void vf_set_char(SIGNED_QUAD ch, int vf_font)
831 {
832   unsigned char opcode;
833   unsigned char *start, *end;
834   spt_t ptsize;
835   int default_font = -1;
836   if (vf_font < num_vf_fonts) {
837     /* Initialize to the first font or -1 if undefined */
838     ptsize = vf_fonts[vf_font].ptsize;
839     if (vf_fonts[vf_font].num_dev_fonts > 0)
840       default_font = ((vf_fonts[vf_font].dev_fonts)[0]).dev_id;
841     dvi_vf_init (default_font);
842     if (ch >= vf_fonts[vf_font].num_chars ||
843         !(start = (vf_fonts[vf_font].ch_pkt)[ch])) {
844       fprintf (stderr, "\nchar=0x%lx(%ld)\n", ch, ch);
845       fprintf (stderr, "Tried to set a nonexistent character in a virtual font");
846       start = end = NULL;
847     } else {
848       end = start + (vf_fonts[vf_font].pkt_len)[ch];
849     }
850     while (start && start < end) {
851       opcode = *(start++);
852 #ifdef DEBUG
853     fprintf (stderr, "VF opcode: %d", opcode);
854     if (isprint (opcode)) fprintf (stderr, " (\'%c\')\n", opcode);
855     else fprintf (stderr, "\n");
856 #endif
857       switch (opcode)
858         {
859         case SET1:
860           vf_set1(&start, end);
861           break;
862         case SET2:
863           vf_set2(&start, end);
864           break;
865         case SET3:
866           vf_set3(&start, end);
867           break;
868         case SET4:
869           ERROR ("Multibyte (>24 bits) character in VF packet.\nI can't handle this!");
870           break;
871         case SET_RULE:
872           vf_setrule(&start, end, ptsize);
873           break;
874         case PUT1:
875           vf_put1(&start, end);
876           break;
877         case PUT2:
878           vf_put2(&start, end);
879           break;
880         case PUT3:
881           vf_put3(&start, end);
882           break;
883         case PUT4:
884           ERROR ("Multibyte (>24 bits) character in VF packet.\nI can't handle this!");
885           break;
886         case PUT_RULE:
887           vf_putrule(&start, end, ptsize);
888           break;
889         case NOP:
890           break;
891         case PUSH:
892           vf_push();
893           break;
894         case POP:
895           vf_pop();
896           break;
897         case RIGHT1:
898           vf_right1(&start, end, ptsize);
899           break;
900         case RIGHT2:
901           vf_right2(&start, end, ptsize);
902           break;
903         case RIGHT3:
904           vf_right3(&start, end, ptsize);
905           break;
906         case RIGHT4:
907           vf_right4(&start, end, ptsize);
908           break;
909         case W0:
910           vf_w0();
911           break;
912         case W1:
913           vf_w1(&start, end, ptsize);
914           break;
915         case W2:
916           vf_w2(&start, end, ptsize);
917           break;
918         case W3:
919           vf_w3(&start, end, ptsize);
920           break;
921         case W4:
922           vf_w4(&start, end, ptsize);
923           break;
924         case X0:
925           vf_x0();
926           break;
927         case X1:
928           vf_x1(&start, end, ptsize);
929           break;
930         case X2:
931           vf_x2(&start, end, ptsize);
932           break;
933         case X3:
934           vf_x3(&start, end, ptsize);
935           break;
936         case X4:
937           vf_x4(&start, end, ptsize);
938           break;
939         case DOWN1:
940           vf_down1(&start, end, ptsize);
941           break;
942         case DOWN2:
943           vf_down2(&start, end, ptsize);
944           break;
945         case DOWN3:
946           vf_down3(&start, end, ptsize);
947           break;
948         case DOWN4:
949           vf_down4(&start, end, ptsize);
950           break;
951         case Y0:
952           vf_y0();
953           break;
954         case Y1:
955           vf_y1(&start, end, ptsize);
956           break;
957         case Y2:
958           vf_y2(&start, end, ptsize);
959           break;
960         case Y3:
961           vf_y3(&start, end, ptsize);
962           break;
963         case Y4:
964           vf_y4(&start, end, ptsize);
965           break;
966         case Z0:
967           vf_z0();
968           break;
969         case Z1:
970           vf_z1(&start, end, ptsize);
971           break;
972         case Z2:
973           vf_z2(&start, end, ptsize);
974           break;
975         case Z3:
976           vf_z3(&start, end, ptsize);
977           break;
978         case Z4:
979           vf_z4(&start, end, ptsize);
980           break;
981         case FNT1:
982           vf_fnt1(&start, end, vf_font);
983           break;
984         case FNT2:
985           vf_fnt2(&start, end, vf_font);
986           break;
987         case FNT3:
988           vf_fnt3(&start, end, vf_font);
989           break;
990         case FNT4:
991           vf_fnt4(&start, end, vf_font);
992           break;
993         case XXX1:
994           vf_xxx1(&start, end);
995           break;
996         case XXX2:
997           vf_xxx2(&start, end);
998           break;
999         case XXX3:
1000           vf_xxx3(&start, end);
1001           break;
1002         case XXX4:
1003           vf_xxx4(&start, end);
1004           break;
1005         case PTEXDIR:
1006           vf_dir(&start, end);
1007           break;
1008         default:
1009           if (opcode <= SET_CHAR_127) {
1010             vf_set (opcode);
1011           } else if (opcode >= FNT_NUM_0 && opcode <= FNT_NUM_63) {
1012             vf_fnt (opcode - FNT_NUM_0, vf_font);
1013           } else {
1014             fprintf (stderr, "Unexpected opcode: %d\n", opcode);
1015             ERROR ("Unexpected opcode in vf file\n");
1016           }
1017         }
1018     }
1019     dvi_vf_finish();
1020   } else {
1021     fprintf (stderr, "vf_set_char: font: %d", vf_font);
1022     ERROR ("Font not loaded\n");
1023   }
1024   return;
1025 }
1026
1027
1028 void vf_close_all_fonts(void)
1029 {
1030   unsigned long i;
1031   int j;
1032   struct font_def *one_font;
1033   for (i=0; i<num_vf_fonts; i++) {
1034     /* Release the packet for each character */
1035     if (vf_fonts[i].ch_pkt) {
1036       for (j=0; j<vf_fonts[i].num_chars; j++) {
1037         if ((vf_fonts[i].ch_pkt)[j] != NULL)
1038           RELEASE ((vf_fonts[i].ch_pkt)[j]);
1039       }
1040       RELEASE (vf_fonts[i].ch_pkt);
1041     }
1042     if (vf_fonts[i].pkt_len)
1043       RELEASE (vf_fonts[i].pkt_len);
1044     if (vf_fonts[i].tex_name)
1045       RELEASE (vf_fonts[i].tex_name);
1046     /* Release each font record */
1047     for (j=0; j<vf_fonts[i].num_dev_fonts; j++) {
1048       one_font = &(vf_fonts[i].dev_fonts)[j];
1049       RELEASE (one_font -> directory);
1050       RELEASE (one_font -> name);
1051     }
1052     if (vf_fonts[i].dev_fonts != NULL)
1053       RELEASE (vf_fonts[i].dev_fonts);
1054   }
1055   if (vf_fonts != NULL)
1056     RELEASE (vf_fonts);
1057   return;
1058 }