beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / font / vfovf.w
blob80b35f9ea22d60f0da4c32e4764266b593c2991b
1 % vfovf.w
3 % Copyright 1996-2006 Han The Thanh <thanh@@pdftex.org>
4 % Copyright 2006-2013 Taco Hoekwater <taco@@luatex.org>
6 % This file is part of LuaTeX.
8 % LuaTeX is free software; you can redistribute it and/or modify it under
9 % the terms of the GNU General Public License as published by the Free
10 % Software Foundation; either version 2 of the License, or (at your
11 % option) any later version.
13 % LuaTeX is distributed in the hope that it will be useful, but WITHOUT
14 % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 % FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16 % License for more details.
18 % You should have received a copy of the GNU General Public License along
19 % with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
21 @ @c
24 #include "ptexlib.h"
26 @ @c
27 /* this is a hack! */
28 #define font_max 5000
30 #define set_char_0 0 /* typeset character 0 and move right */
31 #define set1 128 /* typeset a character and move right */
32 #define set2 129 /* typeset a character and move right */
33 #define set3 130 /* typeset a character and move right */
34 #define set4 131 /* typeset a character and move right */
35 #define set_rule 132 /* typeset a rule and move right */
36 #define put1 133 /* typeset a character without moving */
37 #define put2 134 /* typeset a character without moving */
38 #define put3 135 /* typeset a character without moving */
39 #define put4 136 /* typeset a character without moving */
40 #define put_rule 137 /* typeset a rule */
41 #define nop 138 /* no operation */
42 #define bop 139 /* beginning of page */
43 #define eop 140 /* ending of page */
44 #define push 141 /* save the current positions */
45 #define pop 142 /* restore previous positions */
46 #define right1 143 /* move right */
47 #define right2 144 /* move right */
48 #define right3 145 /* move right */
49 #define right4 146 /* move right, 4 bytes */
50 #define w0 147 /* move right by |w| */
51 #define w1 148 /* move right and set |w| */
52 #define w2 149 /* move right and set |w| */
53 #define w3 150 /* move right and set |w| */
54 #define w4 151 /* move right and set |w| */
55 #define x0 152 /* move right by |x| */
56 #define x1 153 /* move right and set |x| */
57 #define x2 154 /* move right and set |x| */
58 #define x3 155 /* move right and set |x| */
59 #define x4 156 /* move right and set |x| */
60 #define down1 157 /* move down */
61 #define down2 158 /* move down */
62 #define down3 159 /* move down */
63 #define down4 160 /* move down, 4 bytes */
64 #define y0 161 /* move down by |y| */
65 #define y1 162 /* move down and set |y| */
66 #define y2 163 /* move down and set |y| */
67 #define y3 164 /* move down and set |y| */
68 #define y4 165 /* move down and set |y| */
69 #define z0 166 /* move down by |z| */
70 #define z1 167 /* move down and set |z| */
71 #define z2 168 /* move down and set |z| */
72 #define z3 169 /* move down and set |z| */
73 #define z4 170 /* move down and set |z| */
74 #define fnt_num_0 171 /* set current font to 0 */
75 #define fnt1 235 /* set current font */
76 #define fnt2 236 /* set current font */
77 #define fnt3 237 /* set current font */
78 #define fnt4 238 /* set current font */
79 #define xxx1 239 /* extension to DVI primitives */
80 #define xxx2 240 /* extension to DVI primitives */
81 #define xxx3 241 /* extension to DVI primitives */
82 #define xxx4 242 /* potentially long extension to DVI primitives */
83 #define fnt_def1 243 /* define the meaning of a font number */
84 #define pre 247 /* preamble */
85 #define post 248 /* postamble beginning */
86 #define post_post 249 /* postamble ending */
87 #define yyy1 250 /* PDF literal text */
88 #define yyy2 251 /* PDF literal text */
89 #define yyy3 252 /* PDF literal text */
90 #define yyy4 253 /* PDF literal text */
92 #define null_font 0
94 #define long_char 242 /* \.{VF} command for general character packet */
95 #define vf_id 202 /* identifies \.{VF} files */
97 @ go out \.{VF} processing with an error message
99 #define bad_vf(a) { \
100 xfree(vf_buffer); \
101 print_nlp(); \
102 formatted_warning("virtual font","file '%s', %s, font will be ignored",font_name(f),a); \
103 print_ln(); \
104 return; \
107 #define lua_bad_vf(a) { \
108 xfree(vf_buffer); \
109 lua_settop(L,s_top); \
110 lua_pushnil(L); \
111 lua_pushstring(L,a); \
112 return 2; \
115 #define tmp_b0 tmp_w.qqqq.b0
116 #define tmp_b1 tmp_w.qqqq.b1
117 #define tmp_b2 tmp_w.qqqq.b2
118 #define tmp_b3 tmp_w.qqqq.b3
119 #define tmp_int tmp_w.cint
121 #define vf_stack_size 100 /* \.{DVI} files shouldn't |push| beyond this depth */
123 @ @c
124 typedef unsigned char vf_stack_index; /* an index into the stack */
126 typedef struct vf_stack_record {
127 scaled stack_w, stack_x, stack_y, stack_z;
128 } vf_stack_record;
130 @ get a byte from\.{VF} file
132 #define vf_byte(a) \
134 eight_bits vf_tmp_b; \
135 if (vf_cur >= vf_size) { \
136 normal_error("virtual font","unexpected eof"); \
138 vf_tmp_b = vf_buffer[vf_cur++]; \
139 a = vf_tmp_b; \
142 @ @c
143 #define vf_replace_z() \
145 vf_alpha = 16; \
146 while (vf_z >= 040000000) { \
147 vf_z = vf_z / 2; \
148 vf_alpha += vf_alpha; \
150 /*vf_beta = (char)(256 / vf_alpha);*/ \
151 vf_alpha = (vf_alpha * vf_z); \
155 @ read |k| bytes as an integer from \.{VF} file
156 beware: the |vf_read()| macro differs from |vf_read()| in vftovp.web for 1...3 byte words.
158 #define vf_read(k, l) \
160 int itmp = 0, dtmp = (int)(k), jtmp = 0; \
161 while (dtmp > 0) { \
162 vf_byte(jtmp); \
163 if ((dtmp == (int) k) && jtmp > 127) \
164 jtmp = jtmp - 256; \
165 itmp = itmp * 256 + jtmp; \
166 decr(dtmp); \
168 l = itmp; \
171 #define vf_read_u(k, l) \
173 int dtmp = (int)(k); \
174 unsigned int itmp = 0, jtmp = 0; \
175 while (dtmp-- > 0) { \
176 vf_byte(jtmp); \
177 itmp = itmp * 256 + jtmp; \
179 l = itmp; \
182 @ @c
183 void pdf_check_vf(internal_font_number f)
185 if (font_type(f) == virtual_font_type)
186 normal_error("font", "command cannot be used with virtual font");
189 static void
190 vf_local_font_warning(internal_font_number f, internal_font_number k, const char *s, int a, int b)
192 print_nlp();
193 tprint(s);
194 tprint(" in local font ");
195 tprint(font_name(k));
196 tprint(" (");
197 print_int(b);
198 tprint(" != ");
199 print_int(a);
200 tprint(") in virtual font ");
201 tprint(font_name(f));
202 tprint(".vf ignored.");
206 @ process a local font in \.{VF} file
208 int level = 0;
210 static internal_font_number
211 vf_def_font(internal_font_number f, unsigned char *vf_buffer, int *vf_cr)
213 internal_font_number k;
214 str_number s;
215 char *st;
216 scaled ds, fs;
217 four_quarters cs;
218 memory_word tmp_w; /* accumulator */
219 int junk;
220 unsigned long checksum;
221 cs.b0 = vf_buffer[(*vf_cr)];
222 cs.b1 = vf_buffer[(*vf_cr) + 1];
223 cs.b2 = vf_buffer[(*vf_cr) + 2];
224 cs.b3 = vf_buffer[(*vf_cr) + 3];
225 (*vf_cr) += 4;
226 checksum = (unsigned)
227 (cs.b0 * 256 * 256 * 256 + cs.b1 * 256 * 256 + cs.b2 * 256 + cs.b3);
228 k = vf_buffer[(*vf_cr)];
229 (*vf_cr)++;
230 if (k > 127)
231 k -= 256;
232 k = k * 256 + vf_buffer[(*vf_cr)];
233 (*vf_cr)++;
234 k = k * 256 + vf_buffer[(*vf_cr)];
235 (*vf_cr)++;
236 k = k * 256 + vf_buffer[(*vf_cr)];
237 (*vf_cr)++;
239 fs = store_scaled_f(k, font_size(f));
241 k = vf_buffer[(*vf_cr)];
242 (*vf_cr)++;
243 if (k > 127)
244 k -= 256;
245 k = k * 256 + vf_buffer[(*vf_cr)];
246 (*vf_cr)++;
247 k = k * 256 + vf_buffer[(*vf_cr)];
248 (*vf_cr)++;
249 k = k * 256 + vf_buffer[(*vf_cr)];
250 (*vf_cr)++;
252 ds = k / 16;
255 tmp_b0 = vf_buffer[(*vf_cr)];
256 (*vf_cr)++;
257 tmp_b1 = vf_buffer[(*vf_cr)];
258 (*vf_cr)++;
259 while (tmp_b0 > 0) {
260 tmp_b0--;
261 (*vf_cr)++; /* skip the font path */
263 str_room((unsigned) tmp_b1);
264 while (tmp_b1 > 0) {
265 tmp_b1--;
266 junk = vf_buffer[(*vf_cr)];
267 (*vf_cr)++;
268 append_char(junk);
270 if (level > 5) {
271 normal_warning("vf","quitting at recurse depth > 5");
272 k = f ;
273 } else if ((level > 1) && (fs > 65536*1024)) {
274 normal_warning("vf","quitting when recursing at size > 65536*1024");
275 k = f ;
276 } else {
277 level += 1 ;
278 s = make_string();
279 st = makecstring(s);
280 k = tfm_lookup(st, fs);
281 if (k == null_font)
282 k = read_font_info(null_cs, st, fs, -1);
283 free(st);
284 level -= 1 ;
285 if (k != null_font) {
286 if (checksum != 0 && font_checksum(k) != 0
287 && checksum != font_checksum(k))
288 vf_local_font_warning(f, k, "checksum mismatch", (int) checksum, (int) font_checksum(k));
289 if (ds != font_dsize(k))
290 vf_local_font_warning(f, k, "design size mismatch", ds, font_dsize(k));
293 return k;
296 @ @c
297 static int open_vf_file(const char *fn, unsigned char **vbuffer, int *vsize)
299 boolean res; /* was the callback successful? */
300 int callback_id;
301 boolean file_read = false; /* was |vf_file| successfully read? */
302 FILE *vf_file;
303 const char *fname = luatex_find_file(fn, find_vf_file_callback);
304 if (fname == NULL || strlen(fname) == 0) {
305 /* fname = fn; */
306 return 0;
309 callback_id = callback_defined(read_vf_file_callback);
310 if (callback_id > 0) {
311 res = run_callback(callback_id, "S->bSd", fname,
312 &file_read, vbuffer, vsize);
313 if (res && file_read && (*vsize > 0)) {
314 return 1;
316 if (!file_read)
317 return 0; /* -1 */
318 } else {
319 if (luatex_open_input
320 (&(vf_file), fname, kpse_ovf_format, FOPEN_RBIN_MODE, false)
321 || luatex_open_input(&(vf_file), fname, kpse_vf_format,
322 FOPEN_RBIN_MODE, false)) {
323 res = read_vf_file(vf_file, vbuffer, vsize);
324 close_file(vf_file);
325 if (res) {
326 return 1;
328 } else {
329 return 0; /* -1 */
332 return 0;
337 @ The |do_vf| procedure attempts to read the \.{VF} file for a font, and sets
338 |font_type()| to |real_font_type| if the \.{VF} file could not be found
339 or loaded, otherwise sets |font_type()| to |virtual_font_type|. At this
340 time, |tmp_f| is the internal font number of the current \.{TFM} font. To
341 process font definitions in virtual font we call |vf_def_font|.
344 #define append_packet(k) vpackets[vf_np++] = (eight_bits)(k)
346 @ life is easier if all internal font commands are fnt4 and
347 all character commands are set4 or put4
350 #define append_fnt_set(k) \
352 assert(k > 0); \
353 append_packet(packet_font_code); \
354 append_four(k); \
357 #define append_four(k) \
359 append_packet((k & 0xFF000000) >> 24); \
360 append_packet((k & 0x00FF0000) >> 16); \
361 append_packet((k & 0x0000FF00) >> 8); \
362 append_packet((k & 0x000000FF)); \
365 @ some of these things happen twice, adding a define is simplest
368 #define test_checksum() { vf_byte(tmp_b0); vf_byte(tmp_b1); \
369 vf_byte(tmp_b2); vf_byte(tmp_b3); \
370 if (((tmp_b0 != 0) || (tmp_b1 != 0) || (tmp_b2 != 0) || (tmp_b3 != 0)) && \
371 ((font_check_0(f) != 0) || (font_check_1(f) != 0) || \
372 (font_check_2(f) != 0) || (font_check_3(f) != 0)) && \
373 ((tmp_b0 != font_check_0(f)) || (tmp_b1 != font_check_1(f)) || \
374 (tmp_b2 != font_check_2(f)) || (tmp_b3 != font_check_3(f)))) { \
375 print_nlp(); \
376 tprint("checksum mismatch in font "); \
377 tprint(font_name(f)); \
378 tprint(".vf ignored "); } }
380 #define test_dsize() \
382 int read_tmp; \
383 vf_read(4, read_tmp); \
384 if ((read_tmp / 16) != font_dsize(f)) { \
385 print_nlp(); \
386 tprint("design size mismatch in font "); \
387 tprint(font_name(f)); \
388 tprint(".vf ignored"); \
392 @ @c
393 static int count_packet_bytes(eight_bits * vf_buf, int cur_bute, int count)
395 unsigned k = 0;
396 int ff = 0;
397 int acc = 0;
398 unsigned int cmd = 0;
399 unsigned int d = 0;
400 while (k < (unsigned) count) {
401 cmd = vf_buf[cur_bute + (int) k];
402 k++;
403 if (cmd < set1) {
404 if (ff == 0) {
405 ff = 1;
406 acc += 5;
408 acc += 5;
409 } else if ((fnt_num_0 <= cmd) && (cmd <= fnt_num_0 + 63)) {
410 ff = 1;
411 acc += 5;
412 } else {
413 switch (cmd) {
414 case fnt1:
415 acc += 5;
416 k += 1;
417 ff = 1;
418 break;
419 case fnt2:
420 acc += 5;
421 k += 2;
422 ff = 1;
423 break;
424 case fnt3:
425 acc += 5;
426 k += 3;
427 ff = 1;
428 break;
429 case fnt4:
430 acc += 5;
431 k += 4;
432 ff = 1;
433 break;
434 case set_rule:
435 acc += 9;
436 k += 8;
437 break;
438 case put_rule:
439 acc += 11;
440 k += 8;
441 break;
442 case set1:
443 acc += 5;
444 k += 1;
445 if (ff == 0) {
446 ff = 1;
447 acc += 5;
449 break;
450 case set2:
451 acc += 5;
452 k += 2;
453 if (ff == 0) {
454 ff = 1;
455 acc += 5;
457 break;
458 case set3:
459 acc += 5;
460 k += 3;
461 if (ff == 0) {
462 ff = 1;
463 acc += 5;
465 break;
466 case set4:
467 acc += 5;
468 k += 4;
469 if (ff == 0) {
470 ff = 1;
471 acc += 5;
473 break;
474 case put1:
475 acc += 7;
476 k += 1;
477 if (ff == 0) {
478 ff = 1;
479 acc += 5;
481 break;
482 case put2:
483 acc += 7;
484 k += 2;
485 if (ff == 0) {
486 ff = 1;
487 acc += 5;
489 break;
490 case put3:
491 acc += 7;
492 k += 3;
493 if (ff == 0) {
494 ff = 1;
495 acc += 5;
497 break;
498 case put4:
499 acc += 7;
500 k += 4;
501 if (ff == 0) {
502 ff = 1;
503 acc += 5;
505 break;
506 case right1:
507 acc += 5;
508 k += 1;
509 break;
510 case right2:
511 acc += 5;
512 k += 2;
513 break;
514 case right3:
515 acc += 5;
516 k += 3;
517 break;
518 case right4:
519 acc += 5;
520 k += 4;
521 break;
522 case w1:
523 acc += 5;
524 k += 1;
525 break;
526 case w2:
527 acc += 5;
528 k += 2;
529 break;
530 case w3:
531 acc += 5;
532 k += 3;
533 break;
534 case w4:
535 acc += 5;
536 k += 4;
537 break;
538 case x1:
539 acc += 5;
540 k += 1;
541 break;
542 case x2:
543 acc += 5;
544 k += 2;
545 break;
546 case x3:
547 acc += 5;
548 k += 3;
549 break;
550 case x4:
551 acc += 5;
552 k += 4;
553 break;
554 case down1:
555 acc += 5;
556 k += 1;
557 break;
558 case down2:
559 acc += 5;
560 k += 2;
561 break;
562 case down3:
563 acc += 5;
564 k += 3;
565 break;
566 case down4:
567 acc += 5;
568 k += 4;
569 break;
570 case y1:
571 acc += 5;
572 k += 1;
573 break;
574 case y2:
575 acc += 5;
576 k += 2;
577 break;
578 case y3:
579 acc += 5;
580 k += 3;
581 break;
582 case y4:
583 acc += 5;
584 k += 4;
585 break;
586 case z1:
587 acc += 5;
588 k += 1;
589 break;
590 case z2:
591 acc += 5;
592 k += 2;
593 break;
594 case z3:
595 acc += 5;
596 k += 3;
597 break;
598 case z4:
599 acc += 5;
600 k += 4;
601 break;
602 case xxx1:
603 d = vf_buf[cur_bute + (int) k];
604 k++;
605 k += d;
606 acc += 5 + (int) d;
607 break;
608 case xxx2:
609 d = vf_buf[cur_bute + (int) k];
610 k++;
611 d = d * 256 + vf_buf[cur_bute + (int) k];
612 k++;
613 k += d;
614 acc += 5 + (int) d;
615 break;
616 case xxx3:
617 d = vf_buf[cur_bute + (int) k];
618 k++;
619 d = d * 256 + vf_buf[cur_bute + (int) k];
620 k++;
621 d = d * 256 + vf_buf[cur_bute + (int) k];
622 k++;
623 k += d;
624 acc += 5 + (int) d;
625 break;
626 case xxx4:
627 d = vf_buf[cur_bute + (int) k];
628 k++;
629 d = d * 256 + vf_buf[cur_bute + (int) k];
630 k++;
631 d = d * 256 + vf_buf[cur_bute + (int) k];
632 k++;
633 d = d * 256 + vf_buf[cur_bute + (int) k];
634 k++;
635 k += d;
636 acc += 5 + (int) d;
637 break;
638 case w0:
639 acc += 5;
640 break;
641 case x0:
642 acc += 5;
643 break;
644 case y0:
645 acc += 5;
646 break;
647 case z0:
648 acc += 5;
649 break;
650 case nop:
651 break;
652 case push:
653 acc += 1;
654 break;
655 case pop:
656 acc += 1;
657 break;
661 return (acc + 1);
664 @ @c
665 void do_vf(internal_font_number f)
667 int k, i;
668 unsigned cmd, n;
669 scaled x, y, w, z, h, v;
670 int cc, cmd_length;
671 unsigned packet_length;
672 charinfo *co;
673 scaled tfm_width;
674 int save_cur_byte;
675 vf_stack_index stack_level;
676 int vf_z; /* multiplier */
677 int vf_alpha; /* correction for negative values */
678 /*char vf_beta;*/ /* divisor */
679 int vf_np;
680 eight_bits *vpackets;
681 memory_word tmp_w; /* accumulator */
682 vf_stack_record vf_stack[256];
683 int junk;
684 unsigned utmp;
685 unsigned char *vf_buffer;
686 int vf_size;
687 int vf_cur;
688 unsigned *vf_local_fnts = NULL; /* external font ids */
689 unsigned *vf_real_fnts = NULL; /* internal font ids */
690 unsigned vf_nf = 0; /* local font counter */
692 if (font_type(f) != unknown_font_type)
693 return;
694 set_font_type(f, real_font_type);
695 stack_level = 0;
696 /* Open |vf_file|, return if not found */
697 vf_cur = 0;
698 vf_buffer = NULL;
699 vf_size = 0;
700 if (!open_vf_file(font_name(f), &vf_buffer, &vf_size))
701 return;
702 /* Process the preamble */
703 set_font_type(f, virtual_font_type);
704 vf_byte(k);
705 if (k != pre)
706 bad_vf("PRE command expected");
707 vf_byte(k);
708 if (k != vf_id)
709 bad_vf("wrong id byte");
710 vf_byte(cmd_length);
711 for (k = 1; k <= cmd_length; k++)
712 vf_byte(junk);
713 test_checksum();
714 test_dsize();
715 vf_z = font_size(f);
716 vf_replace_z();
717 /* Process the font definitions */
718 /* scan forward to find the number of internal fonts */
719 vf_nf = 0;
720 save_cur_byte = vf_cur;
721 vf_byte(cmd);
722 while ((cmd >= fnt_def1) && (cmd <= (fnt_def1 + 3))) {
723 vf_read_u((cmd - fnt_def1 + 1), utmp);
724 vf_read(4, junk);
725 vf_read(4, junk);
726 vf_read(4, junk);
727 vf_byte(k);
728 vf_byte(junk);
729 k += junk;
730 while (k-- > 0) {
731 vf_byte(junk);
733 incr(vf_nf);
734 vf_byte(cmd);
736 vf_cur = save_cur_byte;
737 vf_byte(cmd);
738 /* malloc and fill the local font arrays */
739 if (vf_nf > 0) {
740 unsigned ii = (unsigned) ((unsigned) vf_nf * sizeof(int));
741 vf_local_fnts = xmalloc(ii);
742 memset(vf_local_fnts, 0, ii);
743 vf_real_fnts = xmalloc(ii);
744 memset(vf_real_fnts, 0, ii);
745 vf_nf = 0;
746 while ((cmd >= fnt_def1) && (cmd <= (fnt_def1 + 3))) {
747 vf_read_u((cmd - fnt_def1 + 1), vf_local_fnts[vf_nf]);
748 vf_real_fnts[vf_nf] = (unsigned) vf_def_font(f, vf_buffer, &vf_cur);
749 incr(vf_nf);
750 vf_byte(cmd);
755 while (cmd <= long_char) {
756 /* Build a character packet */
757 vf_np = 0;
758 if (cmd == long_char) {
759 vf_read_u(4, packet_length);
760 vf_read_u(4, utmp);
761 cc = (int) utmp;
762 if (!char_exists(f, cc)) {
763 bad_vf("invalid character code");
765 vf_read(4, k);
766 tfm_width = store_scaled_f(k, font_size(f));
767 } else {
768 packet_length = cmd;
769 vf_byte(cc);
770 if (!char_exists(f, cc)) {
771 bad_vf("invalid character code");
773 vf_read_u(3, utmp);
774 k = (int) utmp; /* cf. vftovp.web, line 1028 */
775 tfm_width = store_scaled_f(k, font_size(f));
779 if (tfm_width != char_width(f, cc)) {
780 if (tfm_width != char_width(f, cc)) {
781 print_nlp();
782 tprint("character width mismatch in font ");
783 tprint(font_name(f));
784 tprint(".vf ignored");
787 k = count_packet_bytes(vf_buffer, vf_cur, (int) packet_length);
788 vpackets = xmalloc((unsigned) (k + 1)); /* need one extra extra for |packet_end| */
789 co = get_charinfo(f, cc);
790 k = 0;
791 w = 0;
792 x = 0;
793 y = 0;
794 z = 0;
795 while (packet_length > 0) {
796 vf_byte(cmd);
797 decr(packet_length);
799 if (cmd < set1) {
800 if (k == 0) {
801 k = (int) vf_real_fnts[0];
802 append_fnt_set(k);
804 append_packet(packet_char_code);
805 append_four(cmd);
806 cmd_length = 0;
807 cmd = nop;
809 } else if (((fnt_num_0 <= cmd) && (cmd <= fnt_num_0 + 63)) ||
810 ((fnt1 <= cmd) && (cmd <= fnt1 + 3))) {
811 if (cmd >= fnt1) {
812 vf_read_u((cmd - fnt1 + 1), utmp);
813 k = (int) utmp;
814 packet_length -= (cmd - fnt1 + 1);
815 } else {
816 k = (int) cmd - fnt_num_0;
819 /* change from local to external font id */
820 n = 0;
821 while ((n < vf_nf) && (vf_local_fnts[n] != (unsigned) k))
822 n++;
823 if (n == vf_nf)
824 bad_vf("undefined local font");
826 k = (int) vf_real_fnts[n];
827 append_fnt_set(k);
828 cmd_length = 0;
829 cmd = nop;
830 } else {
831 switch (cmd) {
832 case set_rule:
833 vf_read(4, h);
834 vf_read(4, v);
835 append_packet(packet_rule_code);
836 append_four(h);
837 append_four(v);
838 packet_length -= 8;
839 break;
840 case put_rule:
841 vf_read(4, h);
842 vf_read(4, v);
843 append_packet(packet_push_code);
844 append_packet(packet_rule_code);
845 append_four(h);
846 append_four(v);
847 append_packet(packet_pop_code);
848 packet_length -= 8;
849 break;
850 case set1:
851 case set2:
852 case set3:
853 case set4:
854 if (k == 0) {
855 k = (int) vf_real_fnts[0];
856 append_fnt_set(k);
858 vf_read_u((cmd - set1 + 1), utmp);
859 i = (int) utmp;
860 append_packet(packet_char_code);
861 append_four(i);
862 packet_length -= (cmd - set1 + 1);
863 break;
864 case put1:
865 case put2:
866 case put3:
867 case put4:
868 if (k == 0) {
869 k = (int) vf_real_fnts[0];
870 append_fnt_set(k);
872 vf_read_u((cmd - put1 + 1), utmp);
873 i = (int) utmp;
874 append_packet(packet_push_code);
875 append_packet(packet_char_code);
876 append_four(i);
877 append_packet(packet_pop_code);
878 packet_length -= (cmd - put1 + 1);
879 break;
880 case right1:
881 case right2:
882 case right3:
883 case right4:
884 vf_read((cmd - right1 + 1), i);
885 append_packet(packet_right_code);
886 append_four(i);
887 packet_length -= (cmd - right1 + 1);
888 break;
889 case w1:
890 case w2:
891 case w3:
892 case w4:
893 vf_read((cmd - w1 + 1), w);
894 append_packet(packet_right_code);
895 append_four(w);
896 packet_length -= (cmd - w1 + 1);
897 break;
898 case x1:
899 case x2:
900 case x3:
901 case x4:
902 vf_read((cmd - x1 + 1), x);
903 append_packet(packet_right_code);
904 append_four(x);
905 packet_length -= (cmd - x1 + 1);
906 break;
907 case down1:
908 case down2:
909 case down3:
910 case down4:
911 vf_read((cmd - down1 + 1), i);
912 append_packet(packet_down_code);
913 append_four(i);
914 packet_length -= (cmd - down1 + 1);
915 break;
916 case y1:
917 case y2:
918 case y3:
919 case y4:
920 vf_read((cmd - y1 + 1), y);
921 append_packet(packet_down_code);
922 append_four(y);
923 packet_length -= (cmd - y1 + 1);
924 break;
925 case z1:
926 case z2:
927 case z3:
928 case z4:
929 vf_read((cmd - z1 + 1), z);
930 append_packet(packet_down_code);
931 append_four(z);
932 packet_length -= (cmd - z1 + 1);
933 break;
934 case xxx1:
935 case xxx2:
936 case xxx3:
937 case xxx4:
938 vf_read_u((cmd - xxx1 + 1), utmp);
939 cmd_length = (int) utmp;
940 packet_length -= (cmd - xxx1 + 1);
941 if (cmd_length <= 0)
942 bad_vf("special of negative length");
943 packet_length -= (unsigned) cmd_length;
945 append_packet(packet_special_code);
946 append_four(cmd_length);
947 while (cmd_length > 0) {
948 cmd_length--;
949 vf_byte(i);
950 append_packet(i);
952 break;
953 case w0:
954 append_packet(packet_right_code);
955 append_four(w);
956 break;
957 case x0:
958 append_packet(packet_right_code);
959 append_four(x);
960 break;
961 case y0:
962 append_packet(packet_down_code);
963 append_four(y);
964 break;
965 case z0:
966 append_packet(packet_down_code);
967 append_four(z);
968 break;
969 case nop:
970 break;
971 case push:
972 if (stack_level == vf_stack_size) {
973 overflow("virtual font stack size", vf_stack_size);
974 } else {
975 vf_stack[stack_level].stack_w = w;
976 vf_stack[stack_level].stack_x = x;
977 vf_stack[stack_level].stack_y = y;
978 vf_stack[stack_level].stack_z = z;
979 incr(stack_level);
980 append_packet(packet_push_code);
982 break;
983 case pop:
984 if (stack_level == 0) {
985 bad_vf("more POPs than PUSHs in character");
986 } else {
987 decr(stack_level);
988 w = vf_stack[stack_level].stack_w;
989 x = vf_stack[stack_level].stack_x;
990 y = vf_stack[stack_level].stack_y;
991 z = vf_stack[stack_level].stack_z;
992 append_packet(packet_pop_code);
994 break;
995 default:
996 bad_vf("improver DVI command");
1000 /* signal end of packet */
1001 append_packet(packet_end_code);
1003 if (stack_level != 0)
1004 bad_vf("more PUSHs than POPs in character packet");
1005 if (packet_length != 0)
1006 bad_vf("invalid packet length or DVI command in packet");
1007 /* \.{Store the packet being built} */
1008 set_charinfo_packets(co, vpackets);
1009 vf_byte(cmd);
1011 if (cmd != post)
1012 bad_vf("POST command expected");
1014 xfree(vf_buffer);
1017 @ @c
1018 #define make_command0(N,K) { \
1019 lua_newtable(L); \
1020 lua_pushstring(L, N); \
1021 lua_rawseti(L,-2, 1); \
1022 lua_rawseti(L,-2, K); \
1023 K++; }
1025 #define make_command1(N,V,K) { \
1026 lua_newtable(L); \
1027 lua_pushstring(L, N); \
1028 lua_rawseti(L,-2, 1); \
1029 lua_pushinteger(L, V); \
1030 lua_rawseti(L,-2, 2); \
1031 lua_rawseti(L,-2, K); \
1032 K++; }
1034 #define make_command2(N,V,W,K) { \
1035 lua_newtable(L); \
1036 lua_pushstring(L, N); \
1037 lua_rawseti(L,-2, 1); \
1038 lua_pushinteger(L, V); \
1039 lua_rawseti(L,-2, 2); \
1040 lua_pushinteger(L, W); \
1041 lua_rawseti(L,-2, 3); \
1042 lua_rawseti(L,-2, K); \
1043 K++; }
1045 #define make_commands(N,S,V,K) { \
1046 lua_newtable(L); \
1047 lua_pushstring(L, N); \
1048 lua_rawseti(L,-2, 1); \
1049 lua_pushlstring(L, S, V); \
1050 lua_rawseti(L,-2, 2); \
1051 lua_rawseti(L,-2, K); \
1052 K++; }
1055 int make_vf_table(lua_State * L, const char *cnom, scaled atsize)
1057 int cmd, k, i;
1058 int cc;
1059 unsigned cmd_length, packet_length;
1060 scaled tfm_width;
1061 vf_stack_index stack_level;
1062 int vf_z; /* multiplier */
1063 int vf_alpha; /* correction for negative values */
1064 /*char vf_beta;*/ /* divisor */
1065 eight_bits *s;
1066 scaled h, v;
1067 scaled w, x, y, z;
1068 int s_top; /* lua stack */
1069 int vf_nf; /* local font counter */
1070 scaled ds, fs;
1071 four_quarters cs;
1072 memory_word tmp_w; /* accumulator */
1073 vf_stack_record vf_stack[256];
1074 unsigned char *vf_buffer;
1075 int vf_size;
1076 int vf_cur;
1077 unsigned utmp;
1080 stack_level = 0;
1081 /* Open |vf_file|, return if not found */
1082 vf_cur = 0;
1083 vf_buffer = NULL;
1084 vf_size = 0;
1085 if (!open_vf_file(cnom, &vf_buffer, &vf_size)) {
1086 lua_pushnil(L);
1087 return 1;
1090 /* start by creating a table */
1091 s_top = lua_gettop(L);
1092 lua_newtable(L);
1094 /* Process the preamble */
1095 vf_byte(k);
1096 if (k != pre)
1097 lua_bad_vf("PRE command expected");
1098 vf_byte(k);
1099 if (k != vf_id)
1100 lua_bad_vf("wrong id byte");
1101 vf_byte(cmd_length);
1103 s = xmalloc(cmd_length);
1104 for (k = 1; k <= (int) cmd_length; k++)
1105 vf_byte(s[(k - 1)]);
1107 lua_pushlstring(L, (char *) s, (size_t) cmd_length);
1108 free(s);
1109 lua_setfield(L, -2, "header");
1111 vf_byte(cs.b0);
1112 vf_byte(cs.b1);
1113 vf_byte(cs.b2);
1114 vf_byte(cs.b3);
1115 lua_pushinteger(L, (lua_Number) ((cs.b0 << 24) + (cs.b1 << 16) + (cs.b2 << 8) + cs.b3));
1116 lua_setfield(L, -2, "checksum");
1118 vf_read(4, k);
1119 ds = k / 16;
1120 lua_pushinteger(L, ds);
1121 lua_setfield(L, -2, "designsize");
1124 lua_pushstring(L, cnom);
1125 lua_setfield(L, -2, "name");
1127 lua_pushinteger(L, atsize);
1128 lua_setfield(L, -2, "size");
1130 vf_z = atsize;
1131 vf_replace_z();
1132 /* Process the font definitions */
1133 vf_byte(cmd);
1134 lua_newtable(L);
1136 i = 1;
1137 while ((cmd >= fnt_def1) && (cmd <= fnt_def1 + 3)) {
1139 lua_newtable(L);
1140 vf_read_u((cmd - fnt_def1 + 1), utmp);
1141 vf_nf = (int) utmp;
1142 vf_nf++;
1143 /* checksum */
1144 vf_byte(cs.b0);
1145 vf_byte(cs.b1);
1146 vf_byte(cs.b2);
1147 vf_byte(cs.b3);
1149 vf_read(4, k);
1150 fs = store_scaled_f(k, atsize);
1151 lua_pushstring(L, "size");
1152 lua_pushinteger(L, fs);
1153 lua_rawset(L, -3);
1155 vf_read(4, k);
1156 ds = k / 16; /* dsize, not used */
1158 vf_byte(tmp_b0);
1159 vf_byte(tmp_b1);
1160 while (tmp_b0 > 0) {
1161 tmp_b0--;
1162 vf_byte(k);
1163 } /* skip the font path */
1165 s = xmalloc((unsigned) (tmp_b1 + 1));
1166 k = 0;
1167 while (tmp_b1-- > 0)
1168 vf_byte(s[k++]);
1169 s[k] = 0;
1170 lua_pushstring(L, "name");
1171 lua_pushstring(L, xstrdup((char *) s));
1172 free(s);
1173 lua_rawset(L, -3);
1175 lua_rawseti(L, -2, vf_nf);
1176 i++;
1177 vf_byte(cmd);
1180 if (i > 1) {
1181 lua_setfield(L, -2, "fonts");
1182 } else {
1183 lua_pop(L, 1);
1186 lua_newtable(L); /* 'characters' */
1187 while (cmd <= long_char) {
1188 /* Build a character packet */
1189 if (cmd == long_char) {
1190 vf_read_u(4, packet_length);
1191 vf_read_u(4, utmp);
1192 cc = (int) utmp;
1193 vf_read(4, tfm_width);
1194 } else {
1195 packet_length = (unsigned) cmd;
1196 vf_byte(cc);
1197 vf_read_u(3, utmp);
1198 tfm_width = (int) utmp;
1200 lua_newtable(L); /* for this character */
1201 lua_pushinteger(L, tfm_width);
1202 lua_setfield(L, -2, "width");
1203 lua_newtable(L); /* for 'commands' */
1204 k = 1;
1205 vf_nf = 0;
1206 w = 0;
1207 x = 0;
1208 y = 0;
1209 z = 0;
1210 while (packet_length > 0) {
1211 vf_byte(cmd);
1212 decr(packet_length);
1213 if ((cmd >= set_char_0) && (cmd < set1)) {
1214 if (vf_nf == 0) {
1215 vf_nf = 1;
1216 make_command1("font", vf_nf, k);
1218 make_command1("char", cmd, k);
1219 } else if (((fnt_num_0 <= cmd) && (cmd <= fnt_num_0 + 63)) ||
1220 ((fnt1 <= cmd) && (cmd <= fnt1 + 3))) {
1221 if (cmd >= fnt1) {
1222 vf_read_u((cmd - fnt1 + 1), utmp);
1223 vf_nf = (int) utmp;
1224 vf_nf++;
1225 packet_length -= (unsigned) (cmd - fnt1 + 1);
1226 } else {
1227 vf_nf = cmd - fnt_num_0 + 1;
1229 make_command1("font", vf_nf, k);
1230 } else {
1231 switch (cmd) {
1232 case set_rule:
1233 vf_read(4, h);
1234 vf_read(4, v);
1235 make_command2("rule", store_scaled_f(h, atsize),
1236 store_scaled_f(v, atsize), k);
1237 packet_length -= 8;
1238 break;
1239 case put_rule:
1240 vf_read(4, h);
1241 vf_read(4, v);
1242 make_command0("push", k);
1243 make_command2("rule", store_scaled_f(h, atsize),
1244 store_scaled_f(v, atsize), k);
1245 make_command0("pop", k);
1246 packet_length -= 8;
1247 break;
1248 case set1:
1249 case set2:
1250 case set3:
1251 case set4:
1252 if (vf_nf == 0) {
1253 vf_nf = 1;
1254 make_command1("font", vf_nf, k);
1256 vf_read_u((cmd - set1 + 1), utmp);
1257 i = (int) utmp;
1258 make_command1("char", i, k);
1259 packet_length -= (unsigned) (cmd - set1 + 1);
1260 break;
1261 case put1:
1262 case put2:
1263 case put3:
1264 case put4:
1265 if (vf_nf == 0) {
1266 vf_nf = 1;
1267 make_command1("font", vf_nf, k);
1269 vf_read_u((cmd - put1 + 1), utmp);
1270 i = (int) utmp;
1271 make_command0("push", k);
1272 make_command1("char", i, k);
1273 make_command0("pop", k);
1274 packet_length -= (unsigned) (cmd - put1 + 1);
1275 break;
1276 case right1:
1277 case right2:
1278 case right3:
1279 case right4:
1280 vf_read((cmd - right1 + 1), i);
1281 make_command1("right", store_scaled_f(i, atsize), k);
1282 packet_length -= (unsigned) (cmd - right1 + 1);
1283 break;
1284 case w1:
1285 case w2:
1286 case w3:
1287 case w4:
1288 vf_read((cmd - w1 + 1), w);
1289 make_command1("right", store_scaled_f(w, atsize), k);
1290 packet_length -= (unsigned) (cmd - w1 + 1);
1291 break;
1292 case x1:
1293 case x2:
1294 case x3:
1295 case x4:
1296 vf_read((cmd - x1 + 1), x);
1297 make_command1("right", store_scaled_f(x, atsize), k);
1298 packet_length -= (unsigned) (cmd - x1 + 1);
1299 break;
1300 case down1:
1301 case down2:
1302 case down3:
1303 case down4:
1304 vf_read((cmd - down1 + 1), i);
1305 make_command1("down", store_scaled_f(i, atsize), k);
1306 packet_length -= (unsigned) (cmd - down1 + 1);
1307 break;
1308 case y1:
1309 case y2:
1310 case y3:
1311 case y4:
1312 vf_read((cmd - y1 + 1), y);
1313 make_command1("down", store_scaled_f(y, atsize), k);
1314 packet_length -= (unsigned) (cmd - y1 + 1);
1315 break;
1316 case z1:
1317 case z2:
1318 case z3:
1319 case z4:
1320 vf_read((cmd - z1 + 1), z);
1321 make_command1("down", store_scaled_f(z, atsize), k);
1322 packet_length -= (unsigned) (cmd - z1 + 1);
1323 break;
1324 case xxx1:
1325 case xxx2:
1326 case xxx3:
1327 case xxx4:
1328 vf_read_u((cmd - xxx1 + 1), cmd_length);
1329 packet_length -= (unsigned) (cmd - xxx1 + 1);
1330 if (cmd_length <= 0)
1331 lua_bad_vf("special of negative length");
1332 packet_length -= cmd_length;
1334 s = xmalloc((cmd_length + 1));
1335 i = 0;
1336 while (cmd_length > 0) {
1337 cmd_length--;
1338 vf_byte(s[i]);
1339 i++;
1341 s[i] = 0;
1342 make_commands("special", xstrdup((char *) s), (size_t) i,
1344 free(s);
1345 break;
1346 case w0:
1347 make_command1("right", store_scaled_f(w, atsize), k);
1348 break;
1349 case x0:
1350 make_command1("right", store_scaled_f(x, atsize), k);
1351 break;
1352 case y0:
1353 make_command1("down", store_scaled_f(y, atsize), k);
1354 break;
1355 case z0:
1356 make_command1("down", store_scaled_f(z, atsize), k);
1357 break;
1358 case nop:
1359 break;
1360 case push:
1361 if (stack_level == vf_stack_size) {
1362 overflow("virtual font stack size", vf_stack_size);
1363 } else {
1364 vf_stack[stack_level].stack_w = w;
1365 vf_stack[stack_level].stack_x = x;
1366 vf_stack[stack_level].stack_y = y;
1367 vf_stack[stack_level].stack_z = z;
1368 incr(stack_level);
1369 make_command0("push", k);
1371 break;
1372 case pop:
1373 if (stack_level == 0) {
1374 lua_bad_vf("more POPs than PUSHs in character");
1375 } else {
1376 decr(stack_level);
1377 w = vf_stack[stack_level].stack_w;
1378 x = vf_stack[stack_level].stack_x;
1379 y = vf_stack[stack_level].stack_y;
1380 z = vf_stack[stack_level].stack_z;
1381 make_command0("pop", k);
1383 break;
1384 default:
1385 lua_bad_vf("improver DVI command");
1389 /* signal end of packet */
1390 lua_setfield(L, -2, "commands");
1392 if (stack_level != 0)
1393 lua_bad_vf("more PUSHs than POPs in character packet");
1394 if (packet_length != 0)
1395 lua_bad_vf("invalid packet length or DVI command in packet");
1397 lua_rawseti(L, -2, cc);
1399 vf_byte(cmd);
1401 lua_setfield(L, -2, "characters");
1403 if (cmd != post)
1404 lua_bad_vf("POST command expected");
1405 xfree(vf_buffer);
1406 return 1;
1409 @ @c
1410 internal_font_number
1411 letter_space_font(internal_font_number f, int e, boolean nolig)
1413 internal_font_number k;
1414 scaled w;
1415 int c;
1416 charinfo *co;
1417 char *new_font_name;
1419 /* read a new font and expand the character widths */
1420 k = copy_font(f);
1422 if (nolig)
1423 set_no_ligatures(k); /* disable ligatures for letter-spaced fonts */
1425 /* append eg '+100ls' to font name */
1426 new_font_name = xmalloc((unsigned) (strlen(font_name(k)) + 8)); /* |abs(e) <= 1000| */
1427 if (e > 0) {
1428 sprintf(new_font_name, "%s+%ils", font_name(k), (int) e);
1429 } else {
1430 /* minus from \%i */
1431 sprintf(new_font_name, "%s%ils", font_name(k), (int) e);
1433 set_font_name(k, new_font_name);
1435 /* create the corresponding virtual font */
1436 set_font_type(k, virtual_font_type);
1438 for (c=font_bc(k);c<=font_ec(k);c++) {
1439 if (quick_char_exists(k, c)) {
1440 int half_w;
1441 int vf_np = 0;
1442 eight_bits *vpackets = xmalloc((unsigned) (10+10+1));
1443 if (e<0) {
1444 half_w = -round_xn_over_d(quad(k), -e, 2000);
1445 } else {
1446 half_w = round_xn_over_d(quad(k), e, 2000);
1448 co = get_charinfo(k, c);
1449 w = char_width(k, c)+2*half_w;
1450 set_charinfo_width(co, w);
1452 append_packet(packet_right_code);
1453 append_four(half_w);
1454 append_fnt_set(f);
1455 append_packet(packet_char_code);
1456 append_four(c);
1457 append_packet(packet_right_code);
1458 append_four(half_w);
1459 append_packet(packet_end_code);
1461 set_charinfo_packets(co, vpackets);
1464 /* now patch the quad size */
1465 /* Patch 20100922: do not do this, to remain compatible with pdftex */
1466 #if 0
1467 if (e<0) {
1468 set_font_param(k, quad_code, -round_xn_over_d(quad(k), 1000-e, 1000));
1469 } else {
1470 set_font_param(k, quad_code, round_xn_over_d(quad(k), 1000+e, 1000));
1472 #endif
1473 return k;
1476 @ @c
1477 internal_font_number copy_font_info(internal_font_number f)
1479 return copy_font(f);