% vfpacket.w % Copyright 1996-2006 Han The Thanh % Copyright 2006-2011 Taco Hoekwater % 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 . @ @c #include "ptexlib.h" static const char _svn_version[] = "$Id: vfpacket.w 4098 2011-04-07 21:01:11Z hhenkel $ " "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.70.1/source/texk/web2c/luatexdir/font/vfpacket.w $"; @ The |do_vf_packet| procedure is called in order to interpret the character packet for a virtual character. Such a packet may contain the instruction to typeset a character from the same or an other virtual font; in such cases |do_vf_packet| calls itself recursively. The recursion level, i.e., the number of times this has happened, is kept in the global variable |packet_cur_s| and should not exceed |packet_max_recursion|. @c #define packet_max_recursion 100 typedef unsigned char packet_stack_index; /* an index into the stack */ typedef struct packet_stack_record { scaled stack_h; scaled stack_v; } packet_stack_record; static packet_stack_index packet_cur_s = 0; /* current recursion level */ static packet_stack_record packet_stack[packet_max_recursion]; static packet_stack_index packet_stack_ptr = 0; /* pointer into |packet_stack| */ @ Some macros for processing character packets. @c #define do_packet_byte() vf_packets[cur_packet_byte++] #define packet_number(fw) { \ fw = do_packet_byte(); \ fw = fw*256 + do_packet_byte(); \ fw = fw*256 + do_packet_byte(); \ fw = fw*256 + do_packet_byte(); } #define packet_scaled(a,fs) { int fw; \ fw = do_packet_byte(); \ if (fw>127) fw = fw - 256; \ fw = fw*256 + do_packet_byte(); \ fw = fw*256 + do_packet_byte(); \ fw = fw*256 + do_packet_byte(); \ a = store_scaled_f(fw, fs); } @ count the number of bytes in a command packet @c int vf_packet_bytes(charinfo * co) { eight_bits *vf_packets; int cur_packet_byte; unsigned k; int cmd; vf_packets = get_charinfo_packets(co); if (vf_packets == NULL) { return 0; } cur_packet_byte = 0; while ((cmd = vf_packets[cur_packet_byte]) != packet_end_code) { cur_packet_byte++; switch (cmd) { case packet_char_code: case packet_font_code: case packet_right_code: case packet_down_code: case packet_node_code: cur_packet_byte += 4; break; case packet_push_code: case packet_pop_code: break; case packet_rule_code: cur_packet_byte += 8; break; case packet_special_code: packet_number(k); /* +4 */ cur_packet_byte = (cur_packet_byte + (int) k); break; case packet_image_code: cur_packet_byte += 4; break; case packet_nop_code: break; default: pdf_error("vf", "invalid DVI command (1)"); } }; return (cur_packet_byte + 1); } @ typeset the \.{DVI} commands in the character packet for character |c| in current font |f| @c const char *packet_command_names[] = { "char", "font", "pop", "push", "special", "image", "right", "down", "rule", "node", "nop", "end", NULL }; void do_vf_packet(PDF pdf, internal_font_number vf_f, int c) { internal_font_number lf; charinfo *co; scaledpos cur = { 0, 0 }, size; eight_bits *vf_packets; int cur_packet_byte; int cmd, fs_f; scaled i; unsigned k; str_number s; posstructure localpos; /* the position structure local within this function */ posstructure *refpos; /* the list origin pos. on the page, provided by the caller */ lf = 0; /* for -Wall */ packet_cur_s++; if (packet_cur_s >= packet_max_recursion) overflow("max level recursion of virtual fonts", packet_max_recursion); co = get_charinfo(vf_f, c); vf_packets = get_charinfo_packets(co); if (vf_packets == NULL) { packet_cur_s--; return; } refpos = pdf->posstruct; pdf->posstruct = &localpos; /* use local structure for recursion */ localpos.pos = refpos->pos; localpos.dir = dir_TLT; /* invariably for vf */ cur_packet_byte = 0; fs_f = font_size(vf_f); while ((cmd = vf_packets[cur_packet_byte]) != packet_end_code) { cur_packet_byte++; #ifdef DEBUG if (cmd>packet_end_code) { fprintf(stdout, "do_vf_packet(%i,%i) command code = illegal \n", vf_f,c); } else { fprintf(stdout, "do_vf_packet(%i,%i) command code = %s\n",vf_f, c, packet_command_names[cmd]); } #endif switch (cmd) { case packet_font_code: packet_number(lf); break; case packet_push_code: packet_stack[packet_stack_ptr].stack_h = cur.h; packet_stack[packet_stack_ptr].stack_v = cur.v; packet_stack_ptr++; break; case packet_pop_code: packet_stack_ptr--; cur.h = packet_stack[packet_stack_ptr].stack_h; cur.v = packet_stack[packet_stack_ptr].stack_v; break; case packet_char_code: packet_number(k); if (!char_exists(lf, (int) k)) { char_warning(lf, (int) k); } else { if (has_packet(lf, (int) k)) do_vf_packet(pdf, lf, (int) k); else backend_out[glyph_node] (pdf, lf, (int) k); } cur.h = cur.h + char_width(lf, (int) k); break; case packet_rule_code: packet_scaled(size.v, fs_f); /* height (where is depth?) */ packet_scaled(size.h, fs_f); if (size.h > 0 && size.v > 0) pdf_place_rule(pdf, 0, size); /* the 0 is unused */ cur.h = cur.h + size.h; break; case packet_right_code: packet_scaled(i, fs_f); cur.h = cur.h + i; break; case packet_down_code: packet_scaled(i, fs_f); cur.v = cur.v + i; break; case packet_special_code: packet_number(k); str_room((unsigned) k); while (k > 0) { k--; append_char(do_packet_byte()); } s = make_string(); pdf_literal(pdf, s, scan_special, false); flush_str(s); break; case packet_image_code: packet_number(k); vf_out_image(pdf, k); break; case packet_node_code: packet_number(k); hlist_out(pdf, (halfword) k); break; case packet_nop_code: break; default: pdf_error("vf", "invalid DVI command (2)"); } synch_pos_with_cur(&localpos, refpos, cur); /* trivial case, always TLT */ } packet_cur_s--; pdf->posstruct = refpos; } @ @c int *packet_local_fonts(internal_font_number f, int *num) { int c, cmd, cur_packet_byte, lf, k, l, i; int localfonts[256] = { 0 }; int *lfs; charinfo *co; eight_bits *vf_packets; k = 0; for (c = font_bc(f); c <= font_ec(f); c++) { if (quick_char_exists(f, c)) { co = get_charinfo(f, c); vf_packets = get_charinfo_packets(co); if (vf_packets == NULL) continue; cur_packet_byte = 0; while ((cmd = vf_packets[cur_packet_byte]) != packet_end_code) { cur_packet_byte++; switch (cmd) { case packet_font_code: packet_number(lf); for (l = 0; l < k; l++) { if (localfonts[l] == lf) { break; } } if (l == k) { localfonts[k++] = lf; } break; case packet_push_code: case packet_pop_code: case packet_nop_code: break; case packet_char_code: case packet_right_code: case packet_down_code: case packet_node_code: cur_packet_byte += 4; break; case packet_rule_code: cur_packet_byte += 8; break; case packet_special_code: packet_number(i); while (i-- > 0) (void) do_packet_byte(); break; case packet_image_code: cur_packet_byte += 4; break; default: pdf_error("vf", "invalid DVI command (3)"); } } } } *num = k; if (k > 0) { lfs = xmalloc((unsigned) ((unsigned) k * sizeof(int))); memcpy(lfs, localfonts, (size_t) ((unsigned) k * sizeof(int))); return lfs; } return NULL; } @ @c void replace_packet_fonts(internal_font_number f, int *old_fontid, int *new_fontid, int count) { int c, cmd, cur_packet_byte, lf, k, l; charinfo *co; eight_bits *vf_packets; k = 0; for (c = font_bc(f); c <= font_ec(f); c++) { if (quick_char_exists(f, c)) { co = get_charinfo(f, c); vf_packets = get_charinfo_packets(co); if (vf_packets == NULL) continue; cur_packet_byte = 0; while ((cmd = vf_packets[cur_packet_byte]) != packet_end_code) { cur_packet_byte++; switch (cmd) { case packet_font_code: packet_number(lf); for (l = 0; l < count; l++) { if (old_fontid[l] == lf) { break; } } if (l < count) { k = new_fontid[l]; vf_packets[(cur_packet_byte - 4)] = (eight_bits) ((k & 0xFF000000) >> 24); vf_packets[(cur_packet_byte - 3)] = (eight_bits) ((k & 0x00FF0000) >> 16); vf_packets[(cur_packet_byte - 2)] = (eight_bits) ((k & 0x0000FF00) >> 8); vf_packets[(cur_packet_byte - 1)] = (eight_bits) (k & 0x000000FF); } break; case packet_push_code: case packet_pop_code: case packet_nop_code: break; case packet_char_code: case packet_right_code: case packet_down_code: case packet_node_code: cur_packet_byte += 4; break; case packet_rule_code: cur_packet_byte += 8; break; case packet_special_code: packet_number(k); while (k-- > 0) (void) do_packet_byte(); break; case packet_image_code: cur_packet_byte += 4; break; default: pdf_error("vf", "invalid DVI command (4)"); } } } } }