📄 dvi.cc
字号:
// -*- C++ -*-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. Written by James Clark (jjc@jclark.com)This file is part of groff.groff is free software; you can redistribute it and/or modify it underthe terms of the GNU General Public License as published by the FreeSoftware Foundation; either version 2, or (at your option) any laterversion.groff is distributed in the hope that it will be useful, but WITHOUT ANYWARRANTY; without even the implied warranty of MERCHANTABILITY orFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Licensefor more details.You should have received a copy of the GNU General Public License alongwith groff; see the file COPYING. If not, write to the Free SoftwareFoundation, 675 Mass Ave, Cambridge, MA 02139, USA. */#include "driver.h"#define DEFAULT_LINEWIDTH 40static int linewidth = DEFAULT_LINEWIDTH;static int draw_flag = 1;/* These values were chosen because:(MULTIPLIER*SIZESCALE)/(RES*UNITWIDTH) == 1/(2^20 * 72.27)and 57816 is an exact multiple of both 72.27*SIZESCALE and 72.The width in the groff font file is the product of MULTIPLIER and thewidth in the tfm file. */#define RES 57816#define RES_7227 (RES/7227)#define UNITWIDTH 131072#define SIZESCALE 100#define MULTIPLIER 1#define FILL_MAX 1000class dvi_font : public font { dvi_font(const char *);public: int checksum; int design_size; ~dvi_font(); void handle_unknown_font_command(const char *command, const char *arg, const char *filename, int lineno); static dvi_font *load_dvi_font(const char *);};dvi_font *dvi_font::load_dvi_font(const char *s){ dvi_font *f = new dvi_font(s); if (!f->load()) { delete f; return 0; } return f;}dvi_font::dvi_font(const char *nm): font(nm), checksum(0), design_size(0){}dvi_font::~dvi_font(){}void dvi_font::handle_unknown_font_command(const char *command, const char *arg, const char *filename, int lineno){ char *ptr; if (strcmp(command, "checksum") == 0) { if (arg == 0) fatal_with_file_and_line(filename, lineno, "`checksum' command requires an argument"); checksum = int(strtol(arg, &ptr, 10)); if (checksum == 0 && ptr == arg) { fatal_with_file_and_line(filename, lineno, "bad checksum"); } } else if (strcmp(command, "designsize") == 0) { if (arg == 0) fatal_with_file_and_line(filename, lineno, "`designsize' command requires an argument"); design_size = int(strtol(arg, &ptr, 10)); if (design_size == 0 && ptr == arg) { fatal_with_file_and_line(filename, lineno, "bad design size"); } }}#define FONTS_MAX 256struct output_font { dvi_font *f; int point_size; output_font() : f(0) { }};class dvi_printer : public printer { FILE *fp; int max_drift; int byte_count; int last_bop; int page_count; int cur_h; int cur_v; int end_h; int max_h; int max_v; output_font output_font_table[FONTS_MAX]; font *cur_font; int cur_point_size; int pushed; int pushed_h; int pushed_v; int have_pushed; void preamble(); void postamble(); void define_font(int); void set_font(int); void possibly_begin_line();protected: enum { id_byte = 2, set1 = 128, put1 = 133, put_rule = 137, bop = 139, eop = 140, push = 141, pop = 142, right1 = 143, down1 = 157, fnt_num_0 = 171, fnt1 = 235, xxx1 = 239, fnt_def1 = 243, pre = 247, post = 248, post_post = 249, filler = 223 }; int line_thickness; void out1(int); void out2(int); void out3(int); void out4(int); void moveto(int, int); void out_string(const char *); void out_signed(unsigned char, int); void out_unsigned(unsigned char, int); void do_special(const char *);public: dvi_printer(); ~dvi_printer(); font *make_font(const char *); void begin_page(int); void end_page(int); void set_char(int, font *, const environment *, int w); void special(char *arg, const environment *env); void end_of_line(); void draw(int code, int *p, int np, const environment *env);};class draw_dvi_printer : public dvi_printer { int output_pen_size; int fill; void set_line_thickness(const environment *); void fill_next();public: draw_dvi_printer(); ~draw_dvi_printer(); void draw(int code, int *p, int np, const environment *env); void end_page(int);};dvi_printer::dvi_printer(): byte_count(0), last_bop(-1), page_count(0), cur_font(0), fp(stdout), max_h(0), max_v(0), pushed(0), line_thickness(-1), cur_point_size(-1){ if (font::res != RES) fatal("resolution must be %1", RES); if (font::unitwidth != UNITWIDTH) fatal("unitwidth must be %1", UNITWIDTH); if (font::hor != 1) fatal("hor must be equal to 1"); if (font::vert != 1) fatal("vert must be equal to 1"); if (font::sizescale != SIZESCALE) fatal("sizescale must be equal to %1", SIZESCALE); max_drift = font::res/1000; // this is fairly arbitrary preamble();}dvi_printer::~dvi_printer(){ postamble();}draw_dvi_printer::draw_dvi_printer(): output_pen_size(-1), fill(FILL_MAX){}draw_dvi_printer::~draw_dvi_printer(){}void dvi_printer::out1(int n){ byte_count += 1; putc(n & 0xff, fp);}void dvi_printer::out2(int n){ byte_count += 2; putc((n >> 8) & 0xff, fp); putc(n & 0xff, fp);}void dvi_printer::out3(int n){ byte_count += 3; putc((n >> 16) & 0xff, fp); putc((n >> 8) & 0xff, fp); putc(n & 0xff, fp);}void dvi_printer::out4(int n){ byte_count += 4; putc((n >> 24) & 0xff, fp); putc((n >> 16) & 0xff, fp); putc((n >> 8) & 0xff, fp); putc(n & 0xff, fp);}void dvi_printer::out_string(const char *s){ out1(strlen(s)); while (*s != 0) out1(*s++);}void dvi_printer::end_of_line(){ if (pushed) { out1(pop); pushed = 0; cur_h = pushed_h; cur_v = pushed_v; }}void dvi_printer::possibly_begin_line(){ if (!pushed) { have_pushed = pushed = 1; pushed_h = cur_h; pushed_v = cur_v; out1(push); }}int scale(int x, int z){ int sw; int a, b, c, d; int alpha, beta; alpha = 16*z; beta = 16; while (z >= 040000000L) { z /= 2; beta /= 2; } d = x & 255; c = (x >> 8) & 255; b = (x >> 16) & 255; a = (x >> 24) & 255; sw = (((((d * z) / 0400) + (c * z)) / 0400) + (b * z)) / beta; if (a == 255) sw -= alpha; else assert(a == 0); return sw;}void dvi_printer::set_char(int index, font *f, const environment *env, int w){ int code = f->get_code(index); if (env->size != cur_point_size || f != cur_font) { cur_font = f; cur_point_size = env->size; for (int i = 0;; i++) { if (i >= FONTS_MAX) { fatal("too many output fonts required"); } if (output_font_table[i].f == 0) { output_font_table[i].f = (dvi_font *)cur_font; output_font_table[i].point_size = cur_point_size; define_font(i); } if (output_font_table[i].f == cur_font && output_font_table[i].point_size == cur_point_size) break; } set_font(i); } int distance = env->hpos - cur_h; if (env->hpos != end_h && distance != 0) { out_signed(right1, distance); cur_h = env->hpos; } else if (distance > max_drift) { out_signed(right1, distance - max_drift); cur_h = env->hpos - max_drift; } else if (distance < -max_drift) { out_signed(right1, distance + max_drift); cur_h = env->hpos + max_drift; } if (env->vpos != cur_v) { out_signed(down1, env->vpos - cur_v); cur_v = env->vpos; } possibly_begin_line(); end_h = env->hpos + w; cur_h += scale(f->get_width(index, UNITWIDTH)/MULTIPLIER, cur_point_size*RES_7227); if (cur_h > max_h) max_h = cur_h; if (cur_v > max_v) max_v = cur_v; if (code >= 0 && code <= 127) out1(code); else out_unsigned(set1, code);}void dvi_printer::define_font(int i){ out_unsigned(fnt_def1, i); dvi_font *f = output_font_table[i].f; out4(f->checksum); out4(output_font_table[i].point_size*RES_7227); out4(int((double(f->design_size)/(1<<20))*RES_7227*100 + .5)); const char *nm = f->get_internal_name(); out1(0); out_string(nm);}void dvi_printer::set_font(int i){ if (i >= 0 && i <= 63) out1(fnt_num_0 + i); else out_unsigned(fnt1, i);}void dvi_printer::out_signed(unsigned char base, int param){ if (-128 <= param && param < 128) { out1(base); out1(param); } else if (-32768 <= param && param < 32768) { out1(base+1); out2(param); } else if (-(1 << 23) <= param && param < (1 << 23)) { out1(base+2); out3(param); } else { out1(base+3); out4(param); }}void dvi_printer::out_unsigned(unsigned char base, int param){ if (param >= 0) { if (param < 256) { out1(base); out1(param); } else if (param < 65536) { out1(base+1); out2(param); } else if (param < (1 << 24)) { out1(base+2); out3(param); } else { out1(base+3); out4(param); } } else { out1(base+3); out4(param); }}void dvi_printer::preamble(){ out1(pre); out1(id_byte); out4(254000); out4(font::res); out4(1000); out1(0);}void dvi_printer::postamble(){ int tem = byte_count; out1(post); out4(last_bop); out4(254000); out4(font::res); out4(1000); out4(max_v); out4(max_h); out2(have_pushed); // stack depth out2(page_count); int i; for (i = 0; i < FONTS_MAX && output_font_table[i].f != 0; i++) define_font(i); out1(post_post); out4(tem); out1(id_byte); for (i = 0; i < 4 || byte_count % 4 != 0; i++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -