/* Copyright (c) 1996-2002 Han The Thanh, This file is part of pdfTeX. pdfTeX 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. pdfTeX 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 General Public License for more details. You should have received a copy of the GNU General Public License along with pdfTeX; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA $Id: vfpacket.c 1169 2008-04-15 14:57:56Z oneiros $ */ #include "ptexlib.h" /* 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|. */ #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. */ #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) { integer 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 = sqxfw(fw, fs); } /* count the number of bytes in a command packet */ int vf_packet_bytes (charinfo *co) { real_eight_bits *vf_packets; integer 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 += k; break; case packet_nop_code: break; default: pdf_error(maketexstring("vf"), maketexstring("invalid DVI command")); } }; return (cur_packet_byte +1); } /* typeset the \.{DVI} commands in the character packet for character |c| in current font |f| */ char *packet_command_names[] = { "char", "font","pop", "push", "special", "right","down","rule","node", "nop","end", NULL}; void do_vf_packet (internal_font_number vf_f, integer c) { internal_font_number lf; charinfo *co; scaled save_cur_h, save_cur_v; real_eight_bits *vf_packets; integer cur_packet_byte; integer cmd, fs_f; scaled i; unsigned k; str_number s; packet_cur_s++; if (packet_cur_s >= packet_max_recursion) overflow_string("max level recursion of virtual fonts", packet_max_recursion); save_cur_v = cur_v; save_cur_h = cur_h; lf = 0; /* for -Wall */ co = get_charinfo(vf_f,c); vf_packets = get_charinfo_packets(co); if (vf_packets == NULL) { packet_cur_s--; return ; } cur_packet_byte = 0; fs_f = font_size(vf_f); while ((cmd = vf_packets[cur_packet_byte]) != packet_end_code) { cur_packet_byte++; /* 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]); } */ 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,k)) { char_warning(lf, k); } else { output_one_char(lf, k); } cur_h = cur_h + char_width(lf,k); break; case packet_rule_code: packet_scaled(rule_ht,fs_f); packet_scaled(rule_wd,fs_f); if ((rule_wd > 0) && (rule_ht > 0)) { pdf_set_rule(cur_h, cur_v, rule_wd, rule_ht); cur_h = cur_h + rule_wd; } 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); string_room(k); while (k > 0) { k--; append_pool_char(do_packet_byte()); } s = make_string(); literal(s, scan_special, false); flush_str(s); break; case packet_node_code: packet_number(k); temp_ptr = k; pdf_hlist_out(); break; case packet_nop_code: break; default: pdf_error(maketexstring("vf"), maketexstring("invalid DVI command")); } }; cur_h = save_cur_h; cur_v = save_cur_v; packet_cur_s--; } integer *packet_local_fonts(internal_font_number f, integer *num) { int c, cmd, cur_packet_byte, lf, k,l, i; integer localfonts[256] = {0}; integer *lfs; charinfo *co; real_eight_bits *vf_packets; k = 0; for (c = font_bc(f);c <= font_ec(f);c++) { if (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 0) (void)do_packet_byte(); break; default: pdf_error(maketexstring("vf"), maketexstring("invalid DVI command")); } } } } *num = k; if (k>0) { lfs = xmalloc (k*sizeof(integer)); memcpy(lfs,localfonts,k*sizeof(integer)); return lfs; } return NULL; } void replace_packet_fonts(internal_font_number f, integer *old_fontid, integer *new_fontid, int count) { int c, cmd, cur_packet_byte, lf, k,l; charinfo *co; real_eight_bits *vf_packets; k = 0; for (c = font_bc(f);c <= font_ec(f);c++) { if (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>24; vf_packets[(cur_packet_byte-3)] = (k&0x00FF0000)>>16; vf_packets[(cur_packet_byte-2)] = (k&0x0000FF00)>>8; vf_packets[(cur_packet_byte-1)] = (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; default: pdf_error(maketexstring("vf"), maketexstring("invalid DVI command")); } } } } } /* this function was copied/borrowed/stolen from dvipdfm code */ scaled sqxfw (scaled sq, integer fw) { int sign = 1; unsigned long a, b, c, d, ad, bd, bc, ac; unsigned long e, f, g, h, i, j, k; unsigned long result; /* Make positive. */ if (sq < 0) { sign = -sign; sq = -sq; } if (fw < 0) { sign = -sign; fw = -fw; } a = ((unsigned long) sq) >> 16u; b = ((unsigned long) sq) & 0xffffu; c = ((unsigned long) fw) >> 16u; d = ((unsigned long) fw) & 0xffffu; ad = a*d; bd = b*d; bc = b*c; ac = a*c; e = bd >> 16u; f = ad >> 16u; g = ad & 0xffffu; h = bc >> 16u; i = bc & 0xffffu; j = ac >> 16u; k = ac & 0xffffu; result = (e+g+i + (1<<3)) >> 4u; /* 1<<3 is for rounding */ result += (f+h+k) << 12u; result += j << 28u; return (sign>0)?result:-result; }