diff options
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/font/vfovf.w')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/font/vfovf.w | 1624 |
1 files changed, 1624 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/font/vfovf.w b/Build/source/texk/web2c/luatexdir/font/vfovf.w new file mode 100644 index 00000000000..cc3c93ad8b5 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/font/vfovf.w @@ -0,0 +1,1624 @@ +% vfovf.w + +% Copyright 1996-2006 Han The Thanh <thanh@@pdftex.org> +% Copyright 2006-2009 Taco Hoekwater <taco@@luatex.org> + +% This file is part of LuaTeX. + +% LuaTeX is free software; you can redistribute it and/or modify it under +% the terms of the GNU General Public License as published by the Free +% Software Foundation; either version 2 of the License, or (at your +% option) any later version. + +% LuaTeX is distributed in the hope that it will be useful, but WITHOUT +% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +% License for more details. + +% You should have received a copy of the GNU General Public License along +% with LuaTeX; if not, see <http://www.gnu.org/licenses/>. + +@ @c +#include "ptexlib.h" + +static const char _svn_version[] = + "$Id: vfovf.w 3584 2010-04-02 17:45:55Z hhenkel $ " + "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.60.0/source/texk/web2c/luatexdir/font/vfovf.w $"; + +@ @c +/* this is a hack! */ +#define font_max 5000 + +#define set_char_0 0 /* typeset character 0 and move right */ +#define set1 128 /* typeset a character and move right */ +#define set2 129 /* typeset a character and move right */ +#define set3 130 /* typeset a character and move right */ +#define set4 131 /* typeset a character and move right */ +#define set_rule 132 /* typeset a rule and move right */ +#define put1 133 /* typeset a character without moving */ +#define put2 134 /* typeset a character without moving */ +#define put3 135 /* typeset a character without moving */ +#define put4 136 /* typeset a character without moving */ +#define put_rule 137 /* typeset a rule */ +#define nop 138 /* no operation */ +#define bop 139 /* beginning of page */ +#define eop 140 /* ending of page */ +#define push 141 /* save the current positions */ +#define pop 142 /* restore previous positions */ +#define right1 143 /* move right */ +#define right2 144 /* move right */ +#define right3 145 /* move right */ +#define right4 146 /* move right, 4 bytes */ +#define w0 147 /* move right by |w| */ +#define w1 148 /* move right and set |w| */ +#define w2 149 /* move right and set |w| */ +#define w3 150 /* move right and set |w| */ +#define w4 151 /* move right and set |w| */ +#define x0 152 /* move right by |x| */ +#define x1 153 /* move right and set |x| */ +#define x2 154 /* move right and set |x| */ +#define x3 155 /* move right and set |x| */ +#define x4 156 /* move right and set |x| */ +#define down1 157 /* move down */ +#define down2 158 /* move down */ +#define down3 159 /* move down */ +#define down4 160 /* move down, 4 bytes */ +#define y0 161 /* move down by |y| */ +#define y1 162 /* move down and set |y| */ +#define y2 163 /* move down and set |y| */ +#define y3 164 /* move down and set |y| */ +#define y4 165 /* move down and set |y| */ +#define z0 166 /* move down by |z| */ +#define z1 167 /* move down and set |z| */ +#define z2 168 /* move down and set |z| */ +#define z3 169 /* move down and set |z| */ +#define z4 170 /* move down and set |z| */ +#define fnt_num_0 171 /* set current font to 0 */ +#define fnt1 235 /* set current font */ +#define fnt2 236 /* set current font */ +#define fnt3 237 /* set current font */ +#define fnt4 238 /* set current font */ +#define xxx1 239 /* extension to DVI primitives */ +#define xxx2 240 /* extension to DVI primitives */ +#define xxx3 241 /* extension to DVI primitives */ +#define xxx4 242 /* potentially long extension to DVI primitives */ +#define fnt_def1 243 /* define the meaning of a font number */ +#define pre 247 /* preamble */ +#define post 248 /* postamble beginning */ +#define post_post 249 /* postamble ending */ +#define yyy1 250 /* PDF literal text */ +#define yyy2 251 /* PDF literal text */ +#define yyy3 252 /* PDF literal text */ +#define yyy4 253 /* PDF literal text */ + +#define null_font 0 + +#define long_char 242 /* \.{VF} command for general character packet */ +#define vf_id 202 /* identifies \.{VF} files */ + +@ go out \.{VF} processing with an error message +@c +#define bad_vf(a) { xfree(vf_buffer); print_nlp(); \ + tprint("Error in processing VF font ("); \ + tprint(font_name(f)); \ + tprint(".vf): "); \ + tprint(a); \ + tprint(", virtual font will be ignored"); \ + print_ln(); return; } + +#define lua_bad_vf(a) { xfree(vf_buffer); \ + lua_settop(L,s_top); \ + lua_pushnil(L); \ + lua_pushstring(L,a); \ + return 2; } + +#define tmp_b0 tmp_w.qqqq.b0 +#define tmp_b1 tmp_w.qqqq.b1 +#define tmp_b2 tmp_w.qqqq.b2 +#define tmp_b3 tmp_w.qqqq.b3 +#define tmp_int tmp_w.cint + +#define vf_stack_size 100 /* \.{DVI} files shouldn't |push| beyond this depth */ + +@ @c +typedef unsigned char vf_stack_index; /* an index into the stack */ + +typedef struct vf_stack_record { + scaled stack_w, stack_x, stack_y, stack_z; +} vf_stack_record; + +boolean auto_expand_vf(internal_font_number f); /* forward */ + +@ get a byte from\.{VF} file +@c +#define vf_byte(a) \ +{ \ + eight_bits vf_tmp_b; \ + if (vf_cur >= vf_size) { \ + pdftex_fail("unexpected eof on virtual font"); \ + } \ + vf_tmp_b = vf_buffer[vf_cur++]; \ + a = vf_tmp_b; \ +} + +@ @c +#define vf_replace_z() \ +{ \ + vf_alpha = 16; \ + while (vf_z >= 040000000) { \ + vf_z = vf_z / 2; \ + vf_alpha += vf_alpha; \ + } \ + vf_beta = (char)(256 / vf_alpha); \ + vf_alpha = (vf_alpha * vf_z); \ +} + + +@ read |k| bytes as an integer from \.{VF} file +beware: the |vf_read()| macro differs from |vf_read()| in vftovp.web for 1...3 byte words. +@c +#define vf_read(k, l) \ +{ \ + int itmp = 0, dtmp = (int)(k), jtmp = 0; \ + while (dtmp > 0) { \ + vf_byte(jtmp); \ + if ((dtmp == (int) k) && jtmp > 127) \ + jtmp = jtmp - 256; \ + itmp = itmp * 256 + jtmp; \ + decr(dtmp); \ + } \ + l = itmp; \ +} + +#define vf_read_u(k, l) \ +{ \ + int dtmp = (int)(k); \ + unsigned int itmp = 0, jtmp = 0; \ + while (dtmp-- > 0) { \ + vf_byte(jtmp); \ + itmp = itmp * 256 + jtmp; \ + } \ + l = itmp; \ +} + +@ @c +void pdf_check_vf(internal_font_number f) +{ + if (font_type(f) == virtual_font_type) + pdf_error("font", "command cannot be used with virtual font"); +} + +static void +vf_local_font_warning(internal_font_number f, internal_font_number k, + const char *s, int a, int b) +{ + print_nlp(); + tprint(s); + tprint(" in local font "); + tprint(font_name(k)); + tprint(" ("); + print_int(b); + tprint(" != "); + print_int(a); + tprint(") in virtual font "); + tprint(font_name(f)); + tprint(".vf ignored."); +} + + +@ process a local font in \.{VF} file +@c +internal_font_number +vf_def_font(internal_font_number f, unsigned char *vf_buffer, int *vf_cr) +{ + internal_font_number k; + str_number s; + char *st; + scaled ds, fs; + four_quarters cs; + memory_word tmp_w; /* accumulator */ + int junk; + unsigned long checksum; + cs.b0 = vf_buffer[(*vf_cr)]; + cs.b1 = vf_buffer[(*vf_cr) + 1]; + cs.b2 = vf_buffer[(*vf_cr) + 2]; + cs.b3 = vf_buffer[(*vf_cr) + 3]; + (*vf_cr) += 4; + checksum = (unsigned) + (cs.b0 * 256 * 256 * 256 + cs.b1 * 256 * 256 + cs.b2 * 256 + cs.b3); + k = vf_buffer[(*vf_cr)]; + (*vf_cr)++; + if (k > 127) + k -= 256; + k = k * 256 + vf_buffer[(*vf_cr)]; + (*vf_cr)++; + k = k * 256 + vf_buffer[(*vf_cr)]; + (*vf_cr)++; + k = k * 256 + vf_buffer[(*vf_cr)]; + (*vf_cr)++; + + fs = store_scaled_f(k, font_size(f)); + + k = vf_buffer[(*vf_cr)]; + (*vf_cr)++; + if (k > 127) + k -= 256; + k = k * 256 + vf_buffer[(*vf_cr)]; + (*vf_cr)++; + k = k * 256 + vf_buffer[(*vf_cr)]; + (*vf_cr)++; + k = k * 256 + vf_buffer[(*vf_cr)]; + (*vf_cr)++; + + ds = k / 16; + + + tmp_b0 = vf_buffer[(*vf_cr)]; + (*vf_cr)++; + tmp_b1 = vf_buffer[(*vf_cr)]; + (*vf_cr)++; + while (tmp_b0 > 0) { + tmp_b0--; + (*vf_cr)++; /* skip the font path */ + } + str_room((unsigned) tmp_b1); + while (tmp_b1 > 0) { + tmp_b1--; + junk = vf_buffer[(*vf_cr)]; + (*vf_cr)++; + append_char(junk); + } + s = make_string(); + st = makecstring(s); + k = tfm_lookup(st, fs, font_expand_ratio(f)); + if (k == null_font) + k = read_font_info(null_cs, st, fs, -1); + free(st); + if (k != null_font) { + if (checksum != 0 && font_checksum(k) != 0 + && checksum != font_checksum(k)) + vf_local_font_warning(f, k, "checksum mismatch", (int) checksum, + (int) font_checksum(k)); + if (ds != font_dsize(k)) + vf_local_font_warning(f, k, "design size mismatch", ds, + font_dsize(k)); + } + if (font_expand_ratio(f) != 0) + set_expand_params(k, font_auto_expand(f), + font_expand_ratio(font_stretch(f)), + -font_expand_ratio(font_shrink(f)), + font_step(f), font_expand_ratio(f)); + return k; +} + +@ @c +static int open_vf_file(const char *fn, unsigned char **vbuffer, int *vsize) +{ + boolean res; /* was the callback successful? */ + int callback_id; + boolean file_read = false; /* was |vf_file| successfully read? */ + FILE *vf_file; + const char *fname = luatex_find_file(fn, find_vf_file_callback); + if (!fname) + fname = fn; + + callback_id = callback_defined(read_vf_file_callback); + if (callback_id > 0) { + res = run_callback(callback_id, "S->bSd", fname, + &file_read, vbuffer, vsize); + if (res && file_read && (*vsize > 0)) { + return 1; + } + if (!file_read) + return 0; /* -1 */ + } else { + if (luatex_open_input + (&(vf_file), fname, kpse_ovf_format, FOPEN_RBIN_MODE, false) + || luatex_open_input(&(vf_file), fname, kpse_vf_format, + FOPEN_RBIN_MODE, false)) { + res = read_vf_file(vf_file, vbuffer, vsize); + close_file(vf_file); + if (res) { + return 1; + } + } else { + return 0; /* -1 */ + } + } + return 0; +} + + + +@ The |do_vf| procedure attempts to read the \.{VF} file for a font, and sets + |font_type()| to |real_font_type| if the \.{VF} file could not be found + or loaded, otherwise sets |font_type()| to |virtual_font_type|. At this + time, |tmp_f| is the internal font number of the current \.{TFM} font. To + process font definitions in virtual font we call |vf_def_font|. + +@c +#define append_packet(k) vpackets[vf_np++] = (eight_bits)(k) + +@ life is easier if all internal font commands are fnt4 and + all character commands are set4 or put4 + +@c +#define append_fnt_set(k) \ +{ \ + assert(k > 0); \ + append_packet(packet_font_code); \ + append_four(k); \ +} + +#define append_four(k) \ +{ \ + append_packet((k & 0xFF000000) >> 24); \ + append_packet((k & 0x00FF0000) >> 16); \ + append_packet((k & 0x0000FF00) >> 8); \ + append_packet((k & 0x000000FF)); \ +} + +@ some of these things happen twice, adding a define is simplest + +@c +#define test_checksum() { vf_byte(tmp_b0); vf_byte(tmp_b1); \ + vf_byte(tmp_b2); vf_byte(tmp_b3); \ + if (((tmp_b0 != 0) || (tmp_b1 != 0) || (tmp_b2 != 0) || (tmp_b3 != 0)) && \ + ((font_check_0(f) != 0) || (font_check_1(f) != 0) || \ + (font_check_2(f) != 0) || (font_check_3(f) != 0)) && \ + ((tmp_b0 != font_check_0(f)) || (tmp_b1 != font_check_1(f)) || \ + (tmp_b2 != font_check_2(f)) || (tmp_b3 != font_check_3(f)))) { \ + print_nlp(); \ + tprint("checksum mismatch in font "); \ + tprint(font_name(f)); \ + tprint(".vf ignored "); } } + +#define test_dsize() \ +{ \ + int read_tmp; \ + vf_read(4, read_tmp); \ + if ((read_tmp / 16) != font_dsize(f)) { \ + print_nlp(); \ + tprint("design size mismatch in font "); \ + tprint(font_name(f)); \ + tprint(".vf ignored"); \ + } \ +} + +@ @c +int count_packet_bytes(eight_bits * vf_buf, int cur_bute, int count) +{ + unsigned k = 0; + int ff = 0; + int acc = 0; + unsigned int cmd = 0; + unsigned int d = 0; + while (k < (unsigned) count) { + cmd = vf_buf[cur_bute + (int) k]; + k++; + if (cmd < set1) { + if (ff == 0) { + ff = 1; + acc += 5; + } + acc += 5; + } else if ((fnt_num_0 <= cmd) && (cmd <= fnt_num_0 + 63)) { + ff = 1; + acc += 5; + } else { + switch (cmd) { + case fnt1: + acc += 5; + k += 1; + ff = 1; + break; + case fnt2: + acc += 5; + k += 2; + ff = 1; + break; + case fnt3: + acc += 5; + k += 3; + ff = 1; + break; + case fnt4: + acc += 5; + k += 4; + ff = 1; + break; + case set_rule: + acc += 9; + k += 8; + break; + case put_rule: + acc += 11; + k += 8; + break; + case set1: + acc += 5; + k += 1; + if (ff == 0) { + ff = 1; + acc += 5; + } + break; + case set2: + acc += 5; + k += 2; + if (ff == 0) { + ff = 1; + acc += 5; + } + break; + case set3: + acc += 5; + k += 3; + if (ff == 0) { + ff = 1; + acc += 5; + } + break; + case set4: + acc += 5; + k += 4; + if (ff == 0) { + ff = 1; + acc += 5; + } + break; + case put1: + acc += 7; + k += 1; + if (ff == 0) { + ff = 1; + acc += 5; + } + break; + case put2: + acc += 7; + k += 2; + if (ff == 0) { + ff = 1; + acc += 5; + } + break; + case put3: + acc += 7; + k += 3; + if (ff == 0) { + ff = 1; + acc += 5; + } + break; + case put4: + acc += 7; + k += 4; + if (ff == 0) { + ff = 1; + acc += 5; + } + break; + case right1: + acc += 5; + k += 1; + break; + case right2: + acc += 5; + k += 2; + break; + case right3: + acc += 5; + k += 3; + break; + case right4: + acc += 5; + k += 4; + break; + case w1: + acc += 5; + k += 1; + break; + case w2: + acc += 5; + k += 2; + break; + case w3: + acc += 5; + k += 3; + break; + case w4: + acc += 5; + k += 4; + break; + case x1: + acc += 5; + k += 1; + break; + case x2: + acc += 5; + k += 2; + break; + case x3: + acc += 5; + k += 3; + break; + case x4: + acc += 5; + k += 4; + break; + case down1: + acc += 5; + k += 1; + break; + case down2: + acc += 5; + k += 2; + break; + case down3: + acc += 5; + k += 3; + break; + case down4: + acc += 5; + k += 4; + break; + case y1: + acc += 5; + k += 1; + break; + case y2: + acc += 5; + k += 2; + break; + case y3: + acc += 5; + k += 3; + break; + case y4: + acc += 5; + k += 4; + break; + case z1: + acc += 5; + k += 1; + break; + case z2: + acc += 5; + k += 2; + break; + case z3: + acc += 5; + k += 3; + break; + case z4: + acc += 5; + k += 4; + break; + case xxx1: + d = vf_buf[cur_bute + (int) k]; + k++; + k += d; + acc += 5 + (int) d; + break; + case xxx2: + d = vf_buf[cur_bute + (int) k]; + k++; + d = d * 256 + vf_buf[cur_bute + (int) k]; + k++; + k += d; + acc += 5 + (int) d; + break; + case xxx3: + d = vf_buf[cur_bute + (int) k]; + k++; + d = d * 256 + vf_buf[cur_bute + (int) k]; + k++; + d = d * 256 + vf_buf[cur_bute + (int) k]; + k++; + k += d; + acc += 5 + (int) d; + break; + case xxx4: + d = vf_buf[cur_bute + (int) k]; + k++; + d = d * 256 + vf_buf[cur_bute + (int) k]; + k++; + d = d * 256 + vf_buf[cur_bute + (int) k]; + k++; + d = d * 256 + vf_buf[cur_bute + (int) k]; + k++; + k += d; + acc += 5 + (int) d; + break; + case w0: + acc += 5; + break; + case x0: + acc += 5; + break; + case y0: + acc += 5; + break; + case z0: + acc += 5; + break; + case nop: + break; + case push: + acc += 1; + break; + case pop: + acc += 1; + break; + } + } + } + return (acc + 1); +} + +@ @c +void do_vf(internal_font_number f) +{ + int k, i; + unsigned cmd, n; + scaled x, y, w, z, h, v; + int cc, cmd_length; + unsigned packet_length; + charinfo *co; + scaled tfm_width; + int save_cur_byte; + vf_stack_index stack_level; + int vf_z; /* multiplier */ + int vf_alpha; /* correction for negative values */ + char vf_beta; /* divisor */ + int vf_np; + eight_bits *vpackets; + memory_word tmp_w; /* accumulator */ + vf_stack_record vf_stack[256]; + int junk; + unsigned utmp; + unsigned char *vf_buffer; + int vf_size; + int vf_cur; + unsigned *vf_local_fnts = NULL; /* external font ids */ + unsigned *vf_real_fnts = NULL; /* internal font ids */ + unsigned vf_nf = 0; /* local font counter */ + + if (font_type(f) != unknown_font_type) + return; + set_font_type(f, real_font_type); + if (auto_expand_vf(f)) + return; /* auto-expanded virtual font */ + stack_level = 0; + /* Open |vf_file|, return if not found */ + vf_cur = 0; + vf_buffer = NULL; + vf_size = 0; + if (!open_vf_file(font_name(f), &vf_buffer, &vf_size)) + return; + /* Process the preamble */ + set_font_type(f, virtual_font_type); + vf_byte(k); + if (k != pre) + bad_vf("PRE command expected"); + vf_byte(k); + if (k != vf_id) + bad_vf("wrong id byte"); + vf_byte(cmd_length); + for (k = 1; k <= cmd_length; k++) + vf_byte(junk); + test_checksum(); + test_dsize(); + vf_z = font_size(f); + vf_replace_z(); + /* Process the font definitions */ + /* scan forward to find the number of internal fonts */ + vf_nf = 0; + save_cur_byte = vf_cur; + vf_byte(cmd); + while ((cmd >= fnt_def1) && (cmd <= (fnt_def1 + 3))) { + vf_read_u((cmd - fnt_def1 + 1), utmp); + vf_read(4, junk); + vf_read(4, junk); + vf_read(4, junk); + vf_byte(k); + vf_byte(junk); + k += junk; + while (k-- > 0) { + vf_byte(junk); + } + incr(vf_nf); + vf_byte(cmd); + } + vf_cur = save_cur_byte; + vf_byte(cmd); + /* malloc and fill the local font arrays */ + if (vf_nf > 0) { + unsigned ii = (unsigned) ((unsigned) vf_nf * sizeof(int)); + vf_local_fnts = xmalloc(ii); + memset(vf_local_fnts, 0, ii); + vf_real_fnts = xmalloc(ii); + memset(vf_real_fnts, 0, ii); + vf_nf = 0; + while ((cmd >= fnt_def1) && (cmd <= (fnt_def1 + 3))) { + vf_read_u((cmd - fnt_def1 + 1), vf_local_fnts[vf_nf]); + vf_real_fnts[vf_nf] = (unsigned) vf_def_font(f, vf_buffer, &vf_cur); + incr(vf_nf); + vf_byte(cmd); + } + } + + + while (cmd <= long_char) { + /* Build a character packet */ + vf_np = 0; + if (cmd == long_char) { + vf_read_u(4, packet_length); + vf_read_u(4, utmp); + cc = (int) utmp; + if (!char_exists(f, cc)) { + bad_vf("invalid character code"); + } + vf_read(4, k); + tfm_width = store_scaled_f(k, font_size(f)); + } else { + packet_length = cmd; + vf_byte(cc); + if (!char_exists(f, cc)) { + bad_vf("invalid character code"); + } + vf_read_u(3, utmp); + k = (int) utmp; /* cf. vftovp.web, line 1028 */ + tfm_width = store_scaled_f(k, font_size(f)); + } + + + if (tfm_width != char_width(f, cc)) { + if (tfm_width != char_width(f, cc)) { + print_nlp(); + tprint("character width mismatch in font "); + tprint(font_name(f)); + tprint(".vf ignored"); + } + } + k = count_packet_bytes(vf_buffer, vf_cur, (int) packet_length); + vpackets = xmalloc((unsigned) (k + 1)); /* need one extra extra for |packet_end| */ + co = get_charinfo(f, cc); + k = 0; + w = 0; + x = 0; + y = 0; + z = 0; + while (packet_length > 0) { + vf_byte(cmd); + decr(packet_length); + + if (cmd < set1) { + if (k == 0) { + k = (int) vf_real_fnts[0]; + append_fnt_set(k); + } + append_packet(packet_char_code); + append_four(cmd); + cmd_length = 0; + cmd = nop; + + } else if (((fnt_num_0 <= cmd) && (cmd <= fnt_num_0 + 63)) || + ((fnt1 <= cmd) && (cmd <= fnt1 + 3))) { + if (cmd >= fnt1) { + vf_read_u((cmd - fnt1 + 1), utmp); + k = (int) utmp; + packet_length -= (cmd - fnt1 + 1); + } else { + k = (int) cmd - fnt_num_0; + } + + /* change from local to external font id */ + n = 0; + while ((n < vf_nf) && (vf_local_fnts[n] != (unsigned) k)) + n++; + if (n == vf_nf) + bad_vf("undefined local font"); + + k = (int) vf_real_fnts[n]; + append_fnt_set(k); + cmd_length = 0; + cmd = nop; + } else { + switch (cmd) { + case set_rule: + vf_read(4, h); + vf_read(4, v); + append_packet(packet_rule_code); + append_four(h); + append_four(v); + packet_length -= 8; + break; + case put_rule: + vf_read(4, h); + vf_read(4, v); + append_packet(packet_push_code); + append_packet(packet_rule_code); + append_four(h); + append_four(v); + append_packet(packet_pop_code); + packet_length -= 8; + break; + case set1: + case set2: + case set3: + case set4: + if (k == 0) { + k = (int) vf_real_fnts[0]; + append_fnt_set(k); + } + vf_read_u((cmd - set1 + 1), utmp); + i = (int) utmp; + append_packet(packet_char_code); + append_four(i); + packet_length -= (cmd - set1 + 1); + break; + case put1: + case put2: + case put3: + case put4: + if (k == 0) { + k = (int) vf_real_fnts[0]; + append_fnt_set(k); + } + vf_read_u((cmd - put1 + 1), utmp); + i = (int) utmp; + append_packet(packet_push_code); + append_packet(packet_char_code); + append_four(i); + append_packet(packet_pop_code); + packet_length -= (cmd - put1 + 1); + break; + case right1: + case right2: + case right3: + case right4: + vf_read((cmd - right1 + 1), i); + append_packet(packet_right_code); + append_four(i); + packet_length -= (cmd - right1 + 1); + break; + case w1: + case w2: + case w3: + case w4: + vf_read((cmd - w1 + 1), w); + append_packet(packet_right_code); + append_four(w); + packet_length -= (cmd - w1 + 1); + break; + case x1: + case x2: + case x3: + case x4: + vf_read((cmd - x1 + 1), x); + append_packet(packet_right_code); + append_four(x); + packet_length -= (cmd - x1 + 1); + break; + case down1: + case down2: + case down3: + case down4: + vf_read((cmd - down1 + 1), i); + append_packet(packet_down_code); + append_four(i); + packet_length -= (cmd - down1 + 1); + break; + case y1: + case y2: + case y3: + case y4: + vf_read((cmd - y1 + 1), y); + append_packet(packet_down_code); + append_four(y); + packet_length -= (cmd - y1 + 1); + break; + case z1: + case z2: + case z3: + case z4: + vf_read((cmd - z1 + 1), z); + append_packet(packet_down_code); + append_four(z); + packet_length -= (cmd - z1 + 1); + break; + case xxx1: + case xxx2: + case xxx3: + case xxx4: + vf_read_u((cmd - xxx1 + 1), utmp); + cmd_length = (int) utmp; + packet_length -= (cmd - xxx1 + 1); + if (cmd_length <= 0) + bad_vf("special of negative length"); + packet_length -= (unsigned) cmd_length; + + append_packet(packet_special_code); + append_four(cmd_length); + while (cmd_length > 0) { + cmd_length--; + vf_byte(i); + append_packet(i); + } + break; + case w0: + append_packet(packet_right_code); + append_four(w); + break; + case x0: + append_packet(packet_right_code); + append_four(x); + break; + case y0: + append_packet(packet_down_code); + append_four(y); + break; + case z0: + append_packet(packet_down_code); + append_four(z); + break; + case nop: + break; + case push: + if (stack_level == vf_stack_size) { + overflow("virtual font stack size", vf_stack_size); + } else { + vf_stack[stack_level].stack_w = w; + vf_stack[stack_level].stack_x = x; + vf_stack[stack_level].stack_y = y; + vf_stack[stack_level].stack_z = z; + incr(stack_level); + append_packet(packet_push_code); + } + break; + case pop: + if (stack_level == 0) { + bad_vf("more POPs than PUSHs in character"); + } else { + decr(stack_level); + w = vf_stack[stack_level].stack_w; + x = vf_stack[stack_level].stack_x; + y = vf_stack[stack_level].stack_y; + z = vf_stack[stack_level].stack_z; + append_packet(packet_pop_code); + } + break; + default: + bad_vf("improver DVI command"); + } + } + } + /* signal end of packet */ + append_packet(packet_end_code); + + if (stack_level != 0) + bad_vf("more PUSHs than POPs in character packet"); + if (packet_length != 0) + bad_vf("invalid packet length or DVI command in packet"); + /* \.{Store the packet being built} */ + set_charinfo_packets(co, vpackets); + vf_byte(cmd); + } + if (cmd != post) + bad_vf("POST command expected"); + + xfree(vf_buffer); +} + +@ @c +#define make_command0(N,K) { \ + lua_newtable(L); \ + lua_pushstring(L, N); \ + lua_rawseti(L,-2, 1); \ + lua_rawseti(L,-2, K); \ + K++; } + +#define make_command1(N,V,K) { \ + lua_newtable(L); \ + lua_pushstring(L, N); \ + lua_rawseti(L,-2, 1); \ + lua_pushnumber(L, V); \ + lua_rawseti(L,-2, 2); \ + lua_rawseti(L,-2, K); \ + K++; } + +#define make_command2(N,V,W,K) { \ + lua_newtable(L); \ + lua_pushstring(L, N); \ + lua_rawseti(L,-2, 1); \ + lua_pushnumber(L, V); \ + lua_rawseti(L,-2, 2); \ + lua_pushnumber(L, W); \ + lua_rawseti(L,-2, 3); \ + lua_rawseti(L,-2, K); \ + K++; } + +#define make_commands(N,S,V,K) { \ + lua_newtable(L); \ + lua_pushstring(L, N); \ + lua_rawseti(L,-2, 1); \ + lua_pushlstring(L, S, V); \ + lua_rawseti(L,-2, 2); \ + lua_rawseti(L,-2, K); \ + K++; } + + +int make_vf_table(lua_State * L, const char *cnom, scaled atsize) +{ + int cmd, k, i; + int cc; + unsigned cmd_length, packet_length; + scaled tfm_width; + vf_stack_index stack_level; + int vf_z; /* multiplier */ + int vf_alpha; /* correction for negative values */ + char vf_beta; /* divisor */ + eight_bits *s; + scaled h, v; + scaled w, x, y, z; + int s_top; /* lua stack */ + int vf_nf; /* local font counter */ + scaled ds, fs; + four_quarters cs; + memory_word tmp_w; /* accumulator */ + vf_stack_record vf_stack[256]; + unsigned char *vf_buffer; + int vf_size; + int vf_cur; + unsigned utmp; + + + stack_level = 0; + /* Open |vf_file|, return if not found */ + vf_cur = 0; + vf_buffer = NULL; + vf_size = 0; + if (!open_vf_file(cnom, &vf_buffer, &vf_size)) { + lua_pushnil(L); + return 1; + } + + /* start by creating a table */ + s_top = lua_gettop(L); + lua_newtable(L); + + /* Process the preamble */ + vf_byte(k); + if (k != pre) + lua_bad_vf("PRE command expected"); + vf_byte(k); + if (k != vf_id) + lua_bad_vf("wrong id byte"); + vf_byte(cmd_length); + + s = xmalloc(cmd_length); + for (k = 1; k <= (int) cmd_length; k++) + vf_byte(s[(k - 1)]); + + lua_pushlstring(L, (char *) s, (size_t) cmd_length); + free(s); + lua_setfield(L, -2, "header"); + + vf_byte(cs.b0); + vf_byte(cs.b1); + vf_byte(cs.b2); + vf_byte(cs.b3); + lua_pushnumber(L, + (lua_Number) ((cs.b0 << 24) + (cs.b1 << 16) + + (cs.b2 << 8) + cs.b3)); + lua_setfield(L, -2, "checksum"); + + vf_read(4, k); + ds = k / 16; + lua_pushinteger(L, ds); + lua_setfield(L, -2, "designsize"); + + + lua_pushstring(L, cnom); + lua_setfield(L, -2, "name"); + + lua_pushinteger(L, atsize); + lua_setfield(L, -2, "size"); + + vf_z = atsize; + vf_replace_z(); + /* Process the font definitions */ + vf_byte(cmd); + lua_newtable(L); + + i = 1; + while ((cmd >= fnt_def1) && (cmd <= fnt_def1 + 3)) { + + lua_newtable(L); + vf_read_u((cmd - fnt_def1 + 1), utmp); + vf_nf = (int) utmp; + vf_nf++; + /* checksum */ + vf_byte(cs.b0); + vf_byte(cs.b1); + vf_byte(cs.b2); + vf_byte(cs.b3); + + vf_read(4, k); + fs = store_scaled_f(k, atsize); + lua_pushstring(L, "size"); + lua_pushnumber(L, fs); + lua_rawset(L, -3); + + vf_read(4, k); + ds = k / 16; /* dsize, not used */ + + vf_byte(tmp_b0); + vf_byte(tmp_b1); + while (tmp_b0 > 0) { + tmp_b0--; + vf_byte(k); + } /* skip the font path */ + + s = xmalloc((unsigned) (tmp_b1 + 1)); + k = 0; + while (tmp_b1-- > 0) + vf_byte(s[k++]); + s[k] = 0; + lua_pushstring(L, "name"); + lua_pushstring(L, xstrdup((char *) s)); + free(s); + lua_rawset(L, -3); + + lua_rawseti(L, -2, vf_nf); + i++; + vf_byte(cmd); + } + + if (i > 1) { + lua_setfield(L, -2, "fonts"); + } else { + lua_pop(L, 1); + } + + lua_newtable(L); /* 'characters' */ + while (cmd <= long_char) { + /* Build a character packet */ + if (cmd == long_char) { + vf_read_u(4, packet_length); + vf_read_u(4, utmp); + cc = (int) utmp; + vf_read(4, tfm_width); + } else { + packet_length = (unsigned) cmd; + vf_byte(cc); + vf_read_u(3, utmp); + tfm_width = (int) utmp; + } + + + + lua_newtable(L); /* for this character */ + + lua_pushnumber(L, tfm_width); + lua_setfield(L, -2, "width"); + + lua_newtable(L); /* for 'commands' */ + + k = 1; + vf_nf = 0; + w = 0; + x = 0; + y = 0; + z = 0; + while (packet_length > 0) { + vf_byte(cmd); + decr(packet_length); + + if ((cmd >= set_char_0) && (cmd < set1)) { + if (vf_nf == 0) { + vf_nf = 1; + make_command1("font", vf_nf, k); + } + make_command1("char", cmd, k); + + } else if (((fnt_num_0 <= cmd) && (cmd <= fnt_num_0 + 63)) || + ((fnt1 <= cmd) && (cmd <= fnt1 + 3))) { + if (cmd >= fnt1) { + vf_read_u((cmd - fnt1 + 1), utmp); + vf_nf = (int) utmp; + vf_nf++; + packet_length -= (unsigned) (cmd - fnt1 + 1); + } else { + vf_nf = cmd - fnt_num_0 + 1; + } + make_command1("font", vf_nf, k); + } else { + switch (cmd) { + case set_rule: + vf_read(4, h); + vf_read(4, v); + make_command2("rule", store_scaled_f(h, atsize), + store_scaled_f(v, atsize), k); + packet_length -= 8; + break; + case put_rule: + vf_read(4, h); + vf_read(4, v); + make_command0("push", k); + make_command2("rule", store_scaled_f(h, atsize), + store_scaled_f(v, atsize), k); + make_command0("pop", k); + packet_length -= 8; + break; + case set1: + case set2: + case set3: + case set4: + if (vf_nf == 0) { + vf_nf = 1; + make_command1("font", vf_nf, k); + } + vf_read_u((cmd - set1 + 1), utmp); + i = (int) utmp; + make_command1("char", i, k); + packet_length -= (unsigned) (cmd - set1 + 1); + break; + case put1: + case put2: + case put3: + case put4: + if (vf_nf == 0) { + vf_nf = 1; + make_command1("font", vf_nf, k); + } + vf_read_u((cmd - put1 + 1), utmp); + i = (int) utmp; + make_command0("push", k); + make_command1("char", i, k); + make_command0("pop", k); + packet_length -= (unsigned) (cmd - put1 + 1); + break; + case right1: + case right2: + case right3: + case right4: + vf_read((cmd - right1 + 1), i); + make_command1("right", store_scaled_f(i, atsize), k); + packet_length -= (unsigned) (cmd - right1 + 1); + break; + case w1: + case w2: + case w3: + case w4: + vf_read((cmd - w1 + 1), w); + make_command1("right", store_scaled_f(w, atsize), k); + packet_length -= (unsigned) (cmd - w1 + 1); + break; + case x1: + case x2: + case x3: + case x4: + vf_read((cmd - x1 + 1), x); + make_command1("right", store_scaled_f(x, atsize), k); + packet_length -= (unsigned) (cmd - x1 + 1); + break; + case down1: + case down2: + case down3: + case down4: + vf_read((cmd - down1 + 1), i); + make_command1("down", store_scaled_f(i, atsize), k); + packet_length -= (unsigned) (cmd - down1 + 1); + break; + case y1: + case y2: + case y3: + case y4: + vf_read((cmd - y1 + 1), y); + make_command1("down", store_scaled_f(y, atsize), k); + packet_length -= (unsigned) (cmd - y1 + 1); + break; + case z1: + case z2: + case z3: + case z4: + vf_read((cmd - z1 + 1), z); + make_command1("down", store_scaled_f(z, atsize), k); + packet_length -= (unsigned) (cmd - z1 + 1); + break; + case xxx1: + case xxx2: + case xxx3: + case xxx4: + vf_read_u((cmd - xxx1 + 1), cmd_length); + packet_length -= (unsigned) (cmd - xxx1 + 1); + if (cmd_length <= 0) + lua_bad_vf("special of negative length"); + packet_length -= cmd_length; + + s = xmalloc((cmd_length + 1)); + i = 0; + while (cmd_length > 0) { + cmd_length--; + vf_byte(s[i]); + i++; + } + s[i] = 0; + make_commands("special", xstrdup((char *) s), (size_t) i, + k); + free(s); + break; + case w0: + make_command1("right", store_scaled_f(w, atsize), k); + break; + case x0: + make_command1("right", store_scaled_f(x, atsize), k); + break; + case y0: + make_command1("down", store_scaled_f(y, atsize), k); + break; + case z0: + make_command1("down", store_scaled_f(z, atsize), k); + break; + case nop: + break; + case push: + if (stack_level == vf_stack_size) { + overflow("virtual font stack size", vf_stack_size); + } else { + vf_stack[stack_level].stack_w = w; + vf_stack[stack_level].stack_x = x; + vf_stack[stack_level].stack_y = y; + vf_stack[stack_level].stack_z = z; + incr(stack_level); + make_command0("push", k); + } + break; + case pop: + if (stack_level == 0) { + lua_bad_vf("more POPs than PUSHs in character"); + } else { + decr(stack_level); + w = vf_stack[stack_level].stack_w; + x = vf_stack[stack_level].stack_x; + y = vf_stack[stack_level].stack_y; + z = vf_stack[stack_level].stack_z; + make_command0("pop", k); + } + break; + default: + lua_bad_vf("improver DVI command"); + } + } + } + /* signal end of packet */ + lua_setfield(L, -2, "commands"); + + if (stack_level != 0) + lua_bad_vf("more PUSHs than POPs in character packet"); + if (packet_length != 0) + lua_bad_vf("invalid packet length or DVI command in packet"); + + lua_rawseti(L, -2, cc); + + vf_byte(cmd); + } + lua_setfield(L, -2, "characters"); + + if (cmd != post) + lua_bad_vf("POST command expected"); + xfree(vf_buffer); + return 1; +} + + +@ This function is called from |do_vf|, and fixes up the virtual data +inside an auto-expanded virtual font + +@c +boolean auto_expand_vf(internal_font_number f) +{ + + internal_font_number bf; + int e, k; + int *vf_old_fonts, *vf_new_fonts; + int num = 0; + + if ((!font_auto_expand(f)) || (pdf_font_blink(f) == null_font)) + return false; /* not an auto-expanded font */ + bf = pdf_font_blink(f); + + if (font_type(bf) != virtual_font_type) + return false; /* not a virtual font */ + + e = font_expand_ratio(f); + + vf_old_fonts = packet_local_fonts(bf, &num); + if (num > 0) { + vf_new_fonts = xmalloc((unsigned) ((unsigned) num * sizeof(int))); + for (k = 0; k < num; k++) { + vf_new_fonts[k] = auto_expand_font(vf_old_fonts[k], e); + copy_expand_params(vf_new_fonts[k], vf_old_fonts[k], e); + } + replace_packet_fonts(f, vf_old_fonts, vf_new_fonts, num); + xfree(vf_new_fonts); + xfree(vf_old_fonts); + } + set_font_type(f, virtual_font_type); + return true; +} + +@ @c +internal_font_number auto_expand_font(internal_font_number f, int e) +{ + internal_font_number k; + kerninfo *krn; + charinfo *co; + int i; + scaled w; + k = copy_font(f); + set_font_name(k, font_name(f)); + set_font_expand_ratio(k, e); + for (i = font_bc(k); i <= font_ec(k); i++) { + if (quick_char_exists(k, i)) { + co = get_charinfo(k, i); + w = round_xn_over_d(char_width(f, i), 1000 + e, 1000); + set_charinfo_width(co, w); + w = round_xn_over_d(char_italic(f, i), 1000 + e, 1000); + set_charinfo_italic(co, w); + krn = get_charinfo_kerns(co); + if (krn != NULL) { + while (!kern_end((*krn))) { + kern_kern(*krn) = + round_xn_over_d(kern_kern(*krn), 1000 + e, 1000); + krn++; + } + } + } + } + return k; +} + +@ @c +void vf_expand_local_fonts(internal_font_number f) +{ + internal_font_number lf; + int k, num; + int *vf_old_fonts; + pdfassert(font_type(f) == virtual_font_type); + num = 0; + vf_old_fonts = packet_local_fonts(f, &num); + if (num > 0) { + for (k = 0; k < num; k++) { + lf = vf_old_fonts[k]; + set_expand_params(lf, font_auto_expand(f), + font_expand_ratio(font_stretch(f)), + -font_expand_ratio(font_shrink(f)), + font_step(f), font_expand_ratio(f)); + if (font_type(lf) == virtual_font_type) + vf_expand_local_fonts(lf); + } + xfree(vf_old_fonts); + } +} + +@ @c +internal_font_number +letter_space_font(halfword u, internal_font_number f, int e) +{ + internal_font_number k; + scaled w, r; + + char *new_font_name; + int vf_z; + int vf_alpha; + int vf_beta; + memory_word tmp_w; /* accumulator */ + + + /* read a new font and expand the character widths */ + k = read_font_info(u, font_name(f), font_size(f), font_natural_dir(f)); + set_no_ligatures(k); /* disable ligatures for letter-spaced fonts */ +#if 0 + for (i = 0;i <= font_widths(k);i++) { + set_font_width(k,i,font_width(f,i)+round_xn_over_d(quad(k), e, 1000)); + } +#endif + /* append eg '+100ls' to font name */ + new_font_name = xmalloc((unsigned) (strlen(font_name(k)) + 8)); /* |abs(e) <= 1000| */ + if (e > 0) { + sprintf(new_font_name, "%s+%ils", font_name(k), (int) e); + } else { + /* minus from \%i */ + sprintf(new_font_name, "%s%ils", font_name(k), (int) e); + } + set_font_name(k, new_font_name); + + /* create the corresponding virtual font */ + set_font_type(k, virtual_font_type); + + vf_z = font_size(f); + vf_replace_z(); + w = round_xn_over_d(quad(f), e, 2000); + if (w > 0) { + tmp_b0 = 0; + } else { + tmp_b0 = 255; + w = vf_alpha + w; + } + r = w * vf_beta; + tmp_b1 = (quarterword) (r / vf_z); + r = r % vf_z; + if (r == 0) { + tmp_b2 = 0; + } else { + r = r * 256; + tmp_b2 = (quarterword) (r / vf_z); + r = r % vf_z; + } + if (r == 0) { + tmp_b3 = 0; + } else { + r = r * 256; + tmp_b3 = (quarterword) (r / vf_z); + } +#if 0 + vf_packet_base[k] = new_vf_packet(k); + + for (c=font_bc(k);c<=font_ec(k);c++) { + string_room(17); + append_fnt_set(f); + append_packet(right1 + 3); + append_packet(tmp_b0); + append_packet(tmp_b1); + append_packet(tmp_b2); + append_packet(tmp_b3); + + append_packet(set1); + append_packet(c); + + append_packet(right1 + 3); + append_packet(tmp_b0); + append_packet(tmp_b1); + append_packet(tmp_b2); + append_packet(tmp_b3); + s = make_string(); + store_packet(k, c, s); + flush_str(s); + } +#endif + return k; +} + +@ the fontname has [+-]\d+ls at the end +@c +boolean is_letterspaced_font(internal_font_number f) +{ + char *i, *j; + if (font_type(f) != virtual_font_type) + return false; + j = font_name(f); + i = j + strlen(j); + if ((*(i - 1) != 'l') || (*i != 's')) + return false; + i = i - 2; + while (i >= j) { + if ((*i < '0') || (*i > '9')) + break; + i--; + } + if (i < j) + return false; + if ((*i != '+') && (*i != '-')) + return false; + return true; +} + +@ @c +internal_font_number copy_font_info(internal_font_number f) +{ + return copy_font(f); +} |