diff options
Diffstat (limited to 'dviware/catdvi/readdvi.c')
-rw-r--r-- | dviware/catdvi/readdvi.c | 444 |
1 files changed, 444 insertions, 0 deletions
diff --git a/dviware/catdvi/readdvi.c b/dviware/catdvi/readdvi.c new file mode 100644 index 0000000000..0e47f22565 --- /dev/null +++ b/dviware/catdvi/readdvi.c @@ -0,0 +1,444 @@ +/* catdvi - get text from DVI files + Copyright (C) 1999 J.H.M. Dassen (Ray) <jdassen@wi.LeidenUniv.nl> + Copyright (C) 1999 Antti-Juhani Kaijanaho <gaia@iki.fi> + + This program 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. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + * For a thorough description of the DVI file format, see the dvitype literate + * program as distributed e.g. with teTeX and + * "The DVI Driver Standard, Level 0" available from your neighbourhood CTAN + * site. + */ + +#include <assert.h> +#include <ctype.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> + +#include "fntenc.h" +#include "fontinfo.h" +#include "outenc.h" +#include "page.h" +#include "readdvi.h" +#include "regsta.h" +#include "util.h" + +uint32 magnification = 1000; + +#define COMMENT_MAXLEN 16384 + + +#define DVI_set_char_0 0 +#define DVI_set_char_127 127 +#define DVI_set1 128 +#define DVI_set2 129 +#define DVI_set3 130 +#define DVI_set4 131 +#define DVI_set_rule 132 +#define DVI_put1 133 +#define DVI_put2 134 +#define DVI_put3 135 +#define DVI_put4 136 +#define DVI_put_rule 137 +#define DVI_nop 138 +#define DVI_bop 139 +#define DVI_eop 140 +#define DVI_push 141 +#define DVI_pop 142 +#define DVI_right1 143 +#define DVI_right2 144 +#define DVI_right3 145 +#define DVI_right4 146 +#define DVI_w0 147 +#define DVI_w1 148 +#define DVI_w2 149 +#define DVI_w3 150 +#define DVI_w4 151 +#define DVI_x0 152 +#define DVI_x1 153 +#define DVI_x2 154 +#define DVI_x3 155 +#define DVI_x4 156 +#define DVI_down1 157 +#define DVI_down2 158 +#define DVI_down3 159 +#define DVI_down4 160 +#define DVI_y0 161 +#define DVI_y1 162 +#define DVI_y2 163 +#define DVI_y3 164 +#define DVI_y4 165 +#define DVI_z0 166 +#define DVI_z1 167 +#define DVI_z2 168 +#define DVI_z3 169 +#define DVI_z4 170 +#define DVI_fnt_num_0 171 +#define DVI_fnt_num_1 172 +#define DVI_fnt_num_63 234 +#define DVI_fnt1 235 +#define DVI_fnt2 236 +#define DVI_fnt3 237 +#define DVI_fnt4 238 +#define DVI_xxx1 239 +#define DVI_xxx2 240 +#define DVI_xxx3 241 +#define DVI_xxx4 242 +#define DVI_fnt_def1 243 +#define DVI_fnt_def2 244 +#define DVI_fnt_def3 245 +#define DVI_fnt_def4 246 +#define DVI_pre 247 +#define DVI_post 248 +#define DVI_post_post 249 + + +static double conversion = 1; /* conversion factor DVI units --> 10^-7 m */ + +static void output_glyph(sint32 font, sint32 glyph) +{ + static sint32 currfont = -1; + static int currfenc = -1; + static fix_word_t last_axis_height = double2fw(0.25); + static sint32 curr_math_axis; + + if (font != currfont) { + fix_word_t new_axis_height; + + currfont = font; + currfenc = find_fntenc(font_enc(font), font_family(font)); + new_axis_height = font_axis_height(font); + + if(new_axis_height > 0) { + /* This font really has axis_height defined */ + last_axis_height = new_axis_height; + curr_math_axis = font_scale_fw(font, new_axis_height); + } + else { + /* Since the axis height is usually about constant in a + * whole family of fonts, we have a good chance that + * scaling up the last known one to the current font + * size works. But we make the value negative to mark + * it as bogus. + */ + curr_math_axis = - font_scale_fw(font, last_axis_height); + } + } + + dump_regs(86); + pmesg(85, "OUTPUT_GLYPH: font %li, glyph %li, H %li, V %li\n", + font, glyph, get_reg(REGISTER_H), get_reg(REGISTER_V)); + + page_set_glyph(font, fnt_convert(currfenc, glyph), + font_char_width(currfont, glyph), + font_char_height(currfont, glyph), + font_char_depth(currfont, glyph), + curr_math_axis, + get_reg(REGISTER_H), get_reg(REGISTER_V)); +} + +void process_file(FILE *f) { + byte b; + sint32 sc; + uint32 num, den, c; + sint32 currfont = 0; + char comment[COMMENT_MAXLEN+1]; + + /* Process the preamble */ + efread(&b, 1, 1, f, "Could not read initial byte\n"); + if (b != DVI_pre) + panic("Does not start with preamble\n"); + pmesg(100, "Read preamble byte\n"); + + efread(&b, 1, 1, f, "Could not read second byte\n"); + if (b != 2) + panic("Identification byte wrong\n"); + pmesg(100, "Read identification byte\n"); + + num = u_readbigendiannumber(4, f); + pmesg(80, "Read numerator: %li\n", num); + + den = u_readbigendiannumber(4, f); + pmesg(80, "Read denominator: %li\n", den); + + conversion = ((double) num) / ((double) den); + + magnification = s_readbigendiannumber(4, f); + pmesg(80, "Read magnification: %li\n", magnification); + + efread(&b, 1, 1, f, "Could not read comment length\n"); + pmesg(100, "Read comment length: %i\n", b); + efread(comment, 1, b, f, "Could not read comment\n"); + comment[b+1] = '\0'; + pmesg(80, "Read comment: `%s'\n", comment); + + /* Core processing loop: read an opcode byte, and process its + * arguments (if any) */ + while(1) { + efread(&b, 1, 1, f, "Failed to read opcode byte\n"); + + if (b == DVI_post) + break; + + if ((b >= DVI_set_char_0) && (b <= DVI_set_char_127)) { + c = b; + pmesg(80, "[set char %i: %c]\n", b-DVI_set_char_0, (unsigned char) (b-DVI_set_char_0)); + output_glyph(currfont, b-DVI_set_char_0); + add_reg(REGISTER_H, font_char_width(currfont, b-DVI_set_char_0)); + continue; + } + + if ((b >= DVI_set1) && (b <= DVI_set3)) { + sc = u_readbigendiannumber(b-DVI_set1+1, f); + output_glyph(currfont, sc); + add_reg(REGISTER_H, font_char_width(currfont, sc)); + pmesg(80, "[set char%i: %lX]\n", b-DVI_set1+1, c); + continue; + } + + if (b == DVI_set4) { + sc = u_readbigendiannumber(b-DVI_set1+1, f); + output_glyph(currfont, sc); + add_reg(REGISTER_H, font_char_width(currfont, sc)); + pmesg(80, "[set char%i: %lX]\n", b-DVI_set1+1, sc); + continue; + } + + if (b == DVI_set_rule) { + sint32 rule_width, rule_height; + rule_height = s_readbigendiannumber(4, f); + rule_width = s_readbigendiannumber(4, f); + add_reg(REGISTER_H, rule_width); + pmesg( + 80, + "[setrule: height=%li, width=%li]\n", + rule_height, + rule_width + ); + continue; + } + + if ((b >= DVI_put1) && (b <= DVI_put4)) { + c = u_readbigendiannumber(b-DVI_put1+1, f); + pmesg(80, "[put char%i: %lX]\n", b-DVI_put1+1, c); + continue; + } + + if (b == DVI_put_rule) { + sint32 rule_width, rule_height; + rule_height = s_readbigendiannumber(4, f); + rule_width = s_readbigendiannumber(4, f); + pmesg( + 80, + "[putrule: height=%li, width=%li]\n", + rule_height, + rule_width + ); + continue; + } + + if (b == DVI_nop) { + pmesg(80, "[nop]\n"); + continue; + } + + if (b == DVI_bop) { + sint32 count0; + + count0 = s_readbigendiannumber(4, f); + skipbytes(9*4+4, f); + pmesg(80, "[bop]\n"); + init_regs_stack(100); + page_begin(count0); + continue; + } + + if (b == DVI_eop) { + pmesg(80, "[eop]\n"); + page_end(); + continue; + } + + if (b == DVI_push) { + pmesg(80, "[push]\n"); + push_regs(); + continue; + } + + if (b == DVI_pop) { + pmesg(80, "[pop]\n"); + pop_regs(); + continue; + } + + if ((b >= DVI_right1) && (b <= DVI_right4)) { + sint32 qwerty; + qwerty = s_readbigendiannumber(b-DVI_right1+1, f); + pmesg(80, "[right%i: %li]\n", b-DVI_right1+1, qwerty); + add_reg(REGISTER_H, qwerty); + continue; + } + + if (b == DVI_w0) { + add_reg(REGISTER_H, get_reg(REGISTER_W)); + pmesg(80, "[w0]\n"); + continue; + } + + if ((b >= DVI_w1) && (b <= DVI_w4)) { + set_reg(REGISTER_W, + s_readbigendiannumber(b-DVI_w1+1, f)); + pmesg(80, "[w%i: w=%li]\n", + b-DVI_w1+1, get_reg(REGISTER_W)); + add_reg(REGISTER_H, get_reg(REGISTER_W)); + continue; + } + + if (b == DVI_x0) { + pmesg(80, "[x0]\n"); + add_reg(REGISTER_H, get_reg(REGISTER_X)); + continue; + } + + if ((b >= DVI_x1) && (b <= DVI_x4)) { + set_reg(REGISTER_X, + s_readbigendiannumber(b-DVI_x1+1, f)); + pmesg(80, "[x%i: x=%li]\n", + b-DVI_x1+1, get_reg(REGISTER_X)); + add_reg(REGISTER_H, get_reg(REGISTER_X)); + continue; + } + + if ((b >= DVI_down1) && (b <= DVI_down4)) { + sint32 qwerty; + qwerty = s_readbigendiannumber(b-DVI_down1+1, f); + pmesg(80, "[down%i, %li]\n", b-DVI_down1+1, qwerty); + add_reg(REGISTER_V, qwerty); + continue; + } + + if (b == DVI_y0) { + pmesg(80, "[y0]\n"); + add_reg(REGISTER_V, get_reg(REGISTER_Y)); + continue; + } + + if ((b >= DVI_y1) && (b <= DVI_y4)) { + set_reg(REGISTER_Y, + s_readbigendiannumber(b-DVI_y1+1, f)); + pmesg(80, "[y%i: y=%li]\n", + b-DVI_y1+1, get_reg(REGISTER_Y)); + add_reg(REGISTER_V, get_reg(REGISTER_Y)); + continue; + } + + if (b == DVI_z0) { + add_reg(REGISTER_V, get_reg(REGISTER_Z)); + pmesg(80, "[z0]\n"); + continue; + } + + if ((b >= DVI_z1) && (b <= DVI_z4)) { + set_reg(REGISTER_Z, + s_readbigendiannumber(b-DVI_z1+1, f)); + pmesg(80, "[z%i: z=%li]\n", + b-DVI_z1+1, get_reg(REGISTER_Z)); + add_reg(REGISTER_V, get_reg(REGISTER_Z)); + continue; + } + + if ((b >= DVI_fnt_num_0) && (b <= DVI_fnt_num_63)) { + pmesg(80, "[fnt_num_%i]\n", b-DVI_fnt_num_0); + currfont = b-DVI_fnt_num_0; + continue; + } + + if ((b >= DVI_fnt1) && (b <= DVI_fnt3)) { + pmesg(80, "[fnt%i]\n", b-DVI_fnt1+1); + currfont = u_readbigendiannumber(b-DVI_fnt1+1, f); + continue; + } + + if (b == DVI_fnt4) { + pmesg(80, "[fnt4]\n"); + currfont = s_readbigendiannumber(4, f); + continue; + } + + if ((b >= DVI_xxx1) && (b <= DVI_xxx4)) { + pmesg(80, "[xxx%i]\n", b-DVI_xxx1+1); + c = u_readbigendiannumber(b-DVI_xxx1+1, f); + if (c > COMMENT_MAXLEN) { + panic("too long comment\n"); + } + efread(comment, 1, c, f, "Could not read comment\n"); + comment[c+1] = '\0'; + pmesg(50, "[Comment: `%s']\n", comment); +#if 0 + skipbytes(c, f); +#endif + continue; + } + + if ((b >= DVI_fnt_def1) && (b <= DVI_fnt_def4)) { + sint32 k; + uint32 cs, s, d; + byte a, l; + char * n; + + if (b == DVI_fnt_def4) { + k = s_readbigendiannumber(4, f); + } else { + k = u_readbigendiannumber(b-DVI_fnt_def1+1, f); + } + cs = u_readbigendiannumber(4, f); + s = u_readbigendiannumber(4, f); + d = u_readbigendiannumber(4, f); + a = u_readbigendiannumber(1, f); + l = u_readbigendiannumber(1, f); + + n = malloc(a + l + 1); + if (n == 0) enomem(); + + efread(n, a + l, 1, f, "Failed to read font name"); + n[a+l] = 0; + + pmesg(80, "[fnt_def%i: %s]\n", b-DVI_fnt_def1+1, n); + font_def(k, cs, s, d, a, l, n); + free(n); + continue; + } + + if (b == DVI_pre) + panic("Unexpected preamble start marker\n"); + + if (b == DVI_post) + break; + + if (b == DVI_post_post) + panic("Unexpected postamble end marker\n"); + + if (b > DVI_post_post) + panic("Unimplemented opcode %i\n", b); + } + + /* FIXME: process postamble */ +} + |