|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T d
Length: 14570 (0x38ea) Types: TextFile Names: »dvi_draw.c«
└─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12 └─⟦af5ba6c8e⟧ »unix3.0/DVIWARE.tar.Z« └─⟦ca79c7339⟧ └─⟦this⟧ »DVIware/crt-viewers/X/xdvi/dvi_draw.c«
/* * DVI previewer for X. * * Eric Cooper, CMU, September 1985. * * Code derived from dvi-imagen.c. * * Modification history: * 1/1986 Modified for X.10 by Bob Scheifler, MIT LCS. * 7/1988 Modified for X.11 by Mark Eichin, MIT * 12/1988 Added 'R' option, toolkit, magnifying glass * --Paul Vojta, UC Berkeley. * 2/1989 Added tpic support --Jeffrey Lee, U of Toronto * 4/1989 Modified for System V by Donald Richardson, Clarkson Univ. * 3/1990 Added VMS support --Scott Allendorf, U of Iowa * * Compilation options: * SYSV compile for System V * VMS compile for VMS * X10 compile for X10 * NOTOOL compile without toolkit (X11 only) * BUTTONS compile with buttons on the side of the window (needs toolkit) * MSBITFIRST store bitmaps internally with most significant bit first * BMSHORT store bitmaps in shorts instead of bytes * BMLONG store bitmaps in longs instead of bytes * ALTFONT default for -altfont option * A4 use European size paper */ #include <stdio.h> #include <ctype.h> #include "xdvi.h" #include "dvi.h" /* * Explanation of the following constant: * pixels_per_inch << 16: one inch margin * shrink_factor << 16: one pixel page border * shrink_factor << 15: rounding for pixel_conv */ #define PAGE_OFFSET (pixels_per_inch << 16) + (shrink_factor * 3 << 15) struct frame *stack; struct frame *stackp; #ifndef BMLONG #ifndef BMSHORT unsigned char bit_masks[9] = { 0x0, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff }; #else /* BMSHORT */ unsigned short bit_masks[17] = { 0x0, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, 0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff, 0x3fff, 0x7fff, 0xffff }; #endif /* BMSHORT */ #else /* BMLONG */ unsigned long bit_masks[33] = { 0x0, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, 0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff, 0x3fff, 0x7fff, 0xffff, 0x1ffff, 0x3ffff, 0x7ffff, 0xfffff, 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff, 0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff }; #endif /* BMLONG */ char *malloc(); Boolean check_dvi_file(); void applicationDoSpecial(); static print_bitmap(bitmap) register struct bitmap *bitmap; { register BMUNIT *ptr = (BMUNIT *) bitmap->bits; register int x, y, i; if (ptr == NULL) oops("print_bitmap called with null pointer."); Printf("w = %d, h = %d, bytes wide = %d\n", bitmap->w, bitmap->h, bitmap->bytes_wide); for (y = 0; y < bitmap->h; ++y) { for (x = bitmap->bytes_wide; x > 0; x -= BYTES_PER_BMUNIT) { #ifndef MSBITFIRST for (i = 0; i < BITS_PER_BMUNIT; ++i) #else for (i = BITS_PER_BMUNIT - 1; i >= 0; --i) #endif putchar((*ptr & (1 << i)) ? '@' : ' '); ++ptr; } putchar('\n'); } } static void print_char(ch, g) ubyte ch; struct glyph *g; { Printf("char %d", ch); if (isprint(ch)) Printf(" (%c)", ch); putchar('\n'); Printf("x = %d, y = %d, dvi = %d\n", g->x, g->y, g->dvi_adv); print_bitmap(&g->bitmap); } static char *dvi_table1[] = { "SET1", NULL, NULL, NULL, "SETRULE", "PUT1", NULL, NULL, NULL, "PUTRULE", "NOP", "BOP", "EOP", "PUSH", "POP", "RIGHT1", "RIGHT2", "RIGHT3", "RIGHT4", "W0", "W1", "W2", "W3", "W4", "X0", "X1", "X2", "X3", "X4", "DOWN1", "DOWN2", "DOWN3", "DOWN4", "Y0", "Y1", "Y2", "Y3", "Y4", "Z0", "Z1", "Z2", "Z3", "Z4"}; static char *dvi_table2[] = { "FNT1", "FNT2", "FNT3", "FNT4", "XXX1", "XXX2", "XXX3", "XXX4", "FNTDEF1", "FNTDEF2", "FNTDEF3", "FNTDEF4", "PRE", "POST", "POSTPOST", NULL, NULL, NULL, NULL, NULL, NULL}; static void print_dvi(ch) ubyte ch; { char *s; Printf("%4d %4d ", PXL_H, PXL_V); if (ch <= SETCHAR0 + 127) { Printf("SETCHAR%-3d", ch - SETCHAR0); if (isprint(ch)) Printf(" (%c)", ch); putchar('\n'); return; } else if (ch < FNTNUM0) s = dvi_table1[ch - 128]; else if (ch <= FNTNUM0 + 63) { Printf("FNTNUM%d\n", ch - FNTNUM0); return; } else s = dvi_table2[ch - (FNTNUM0+64)]; if (s) puts(s); else oops("Unknown op-code %d, offset %d", ch, ftell(dvi_file)-1); } /** ** Allocate bitmap for given font and character **/ void alloc_bitmap(bitmap, fontname, ch) register struct bitmap *bitmap; char *fontname; ubyte ch; { register unsigned int size; /* width must be multiple of 16 bits for raster_op */ bitmap->bytes_wide = ROUNDUP(bitmap->w, BITS_PER_BMUNIT) * BYTES_PER_BMUNIT; size = bitmap->bytes_wide * bitmap->h; bitmap->bits = malloc(size != 0 ? size : 1); if (bitmap->bits == NULL) oops("Can't allocate bitmap for character %d of font %s (%d by %d)", ch, fontname, bitmap->w, bitmap->h); } char sample_count[] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4}; static int sample(bits, bytes_wide, bit_skip, w, h) BMUNIT *bits; int bytes_wide, bit_skip, w, h; { BMUNIT *ptr, *endp; register BMUNIT *cp; int bits_left; register int n, bit_shift, wid; ptr = bits + bit_skip / BITS_PER_BMUNIT; endp = ADD(bits, h * bytes_wide); bits_left = w; #ifndef MSBITFIRST bit_shift = bit_skip % BITS_PER_BMUNIT; #else bit_shift = BITS_PER_BMUNIT - bit_skip % BITS_PER_BMUNIT; #endif n = 0; while (bits_left) { #ifndef MSBITFIRST wid = BITS_PER_BMUNIT - bit_shift; #else wid = bit_shift; #endif if (wid > bits_left) wid = bits_left; if (wid > 4) wid = 4; #ifdef MSBITFIRST bit_shift -= wid; #endif for (cp = ptr; cp < endp; cp = ADD(cp, bytes_wide)) n += sample_count[(*cp >> bit_shift) & bit_masks[wid]]; #ifndef MSBITFIRST bit_shift += wid; if (bit_shift == BITS_PER_BMUNIT) { bit_shift = 0; ++ptr; } #else if (bit_shift == 0) { bit_shift = BITS_PER_BMUNIT; ++ptr; } #endif bits_left -= wid; } return n; } static void shrink_glyph(g) register struct glyph *g; { int shrunk_bytes_wide, shrunk_height; int rows_left, rows, init_cols, cols_left; register int cols; BMUNIT *old_ptr, *new_ptr; register BMUNIT m, *cp; int min_sample = shrink_factor * shrink_factor * density / 100; /* These machinations ensure that the character is shrunk according to its hot point, rather than its upper left-hand corner. */ g->x2 = g->x / shrink_factor; init_cols = g->x - g->x2 * shrink_factor; if (init_cols <= 0) init_cols += shrink_factor; else ++g->x2; g->bitmap2.w = g->x2 + ROUNDUP(g->bitmap.w - g->x, shrink_factor); /* include row zero with the positively numbered rows */ cols = g->y + 1; /* spare register variable */ g->y2 = cols / shrink_factor; rows = cols - g->y2 * shrink_factor; if (rows <= 0) { rows += shrink_factor; --g->y2; } g->bitmap2.h = shrunk_height = g->y2 + ROUNDUP(g->bitmap.h - cols, shrink_factor) + 1; if (g->bitmap2.bits) free(g->bitmap2.bits); alloc_bitmap(&g->bitmap2, "(shrunken)", 0); old_ptr = (BMUNIT *) g->bitmap.bits; new_ptr = (BMUNIT *) g->bitmap2.bits; shrunk_bytes_wide = g->bitmap2.bytes_wide; rows_left = g->bitmap.h; bzero((char *) new_ptr, shrunk_bytes_wide * shrunk_height); while (rows_left) { if (rows > rows_left) rows = rows_left; cols_left = g->bitmap.w; #ifndef MSBITFIRST m = (1 << 0); #else m = (1 << (BITS_PER_BMUNIT-1)); #endif cp = new_ptr; cols = init_cols; while (cols_left) { if (cols > cols_left) cols = cols_left; if (sample(old_ptr, g->bitmap.bytes_wide, g->bitmap.w - cols_left, cols, rows) >= min_sample) *cp |= m; #ifndef MSBITFIRST if (m == (BMUNIT)(1 << (BITS_PER_BMUNIT-1))) { m = (1 << 0); ++cp; } else m <<= 1; #else if (m == (1 << 0)) { m = (1 << (BITS_PER_BMUNIT-1)); ++cp; } else m >>= 1; #endif cols_left -= cols; cols = shrink_factor; } *((char **) &new_ptr) += shrunk_bytes_wide; *((char **) &old_ptr) += rows * g->bitmap.bytes_wide; rows_left -= rows; rows = shrink_factor; } g->y2 = g->y / shrink_factor; if (debug & DBG_BITMAP) print_bitmap(&g->bitmap2); } static void set_char(ch) ubyte ch; { register struct glyph *g; if (ch > maxchar || (g = ¤t_font->glyph[ch])->bitmap.bits == NULL) { if (ch > maxchar || g->addr == 0) oops("Character %d not defined in font %s", ch, current_font->fontname); open_pxl_file(current_font); Fseek(current_font->file, g->addr, 0); (*current_font->read_char)(current_font, ch); g->dvi_adv = g->dvi_adv * current_font->factor; if (debug & DBG_BITMAP) print_char(ch, g); } if (shrink_factor == 1) put_bitmap(&g->bitmap, PXL_H - g->x, PXL_V - g->y); else { if (g->bitmap2.bits == NULL) { shrink_glyph(g); } put_bitmap(&g->bitmap2, PXL_H - g->x2, PXL_V - g->y2); } } static void set_rule(h, w) int h, w; { /* (w,h) specifies lower left corner of rule box */ put_rectangle(PXL_H, PXL_V - h + 1, w, h, False); } /** ** Close the pixel file for the least recently used font. **/ close_a_file() { register struct font *fontp; struct font *f = NULL; for (fontp = current_font; fontp != NULL; fontp = fontp->next) if (fontp->file != NULL) f=fontp; if (f == NULL) oops("Can't find an open pixel file to close"); Fclose(f->file); f->file = NULL; ++n_fonts_left; } /** ** Open a font file. **/ open_pxl_file(fontp) struct font *fontp; { if (fontp->file == NULL) { if (n_fonts_left == 0) close_a_file(); fontp->file = fopen(fontp->filename, OPEN_MODE); if (fontp->file == NULL) oops("Font file disappeared: %s", fontp->filename); --n_fonts_left; } } /* * Find font #n and move it to the head of the list. */ static change_font(n) unsigned long n; { register struct font *fontp, **prev; prev = ¤t_font; for (;;) { fontp = *prev; if (fontp == NULL) oops("Non-existent font #%d", n); if (fontp->TeXnumber == n) break; prev = &(fontp->next); } *prev = fontp->next; fontp->next = current_font; current_font = fontp; maxchar = current_font->maxchar; } static special(nbytes) long nbytes; { static char *cmd = NULL; static long cmdlen = -1; if (cmdlen < nbytes) { if (cmd) free(cmd); cmd = malloc((unsigned) nbytes+1); if (cmd == NULL) oops("Can't allocate memory for special (%d bytes)", nbytes); cmdlen = nbytes; } Fread(cmd, sizeof(char), (int) nbytes, dvi_file); cmd[nbytes] = '\0'; applicationDoSpecial(cmd); } draw_page() { ubyte ch; /* Check for changes in dvi file. */ if (!check_dvi_file()) return; put_border(ROUNDUP(unshrunk_paper_w, shrink_factor) + 1, ROUNDUP(unshrunk_paper_h, shrink_factor) + 1, 1); Fseek(dvi_file, page_offset[current_page], 0); for (;;) { ch = one(dvi_file); if (debug & DBG_DVI) print_dvi(ch); if (ch <= SETCHAR0 + 127) { set_char(ch); DVI_H += current_font->glyph[ch].dvi_adv; } else if (FNTNUM0 <= ch && ch <= FNTNUM0 + 63) { change_font((unsigned long) (ch - FNTNUM0)); } else { long a, b; ubyte ch1; switch (ch) { case SET1: case PUT1: ch1 = one(dvi_file); set_char(ch1); if (ch == SET1) DVI_H += current_font->glyph[ch1].dvi_adv; break; case SETRULE: a = spellfour(dvi_file); b = spellfour(dvi_file); if (a > 0 && b > 0) set_rule(pixel_round(a), pixel_round(b)); DVI_H += b; break; case PUTRULE: a = spellfour(dvi_file); b = spellfour(dvi_file); if (a > 0 && b > 0) set_rule(pixel_round(a), pixel_round(b)); break; case NOP: break; case BOP: Fseek(dvi_file, (long) 11*4, 1); stackp = stack; DVI_H = DVI_V = PAGE_OFFSET; PXL_V = pixel_conv(PAGE_OFFSET); WW = XX = YY = ZZ = 0; break; case EOP: if (stackp > stack) oops("Stack not empty at EOP (%d)", stackp - stack); return; case PUSH: stackp++; if (stackp > stack + maxstack) oops("More PUSHes than were promised"); *stackp = stackp[-1]; break; case POP: if (stackp <= stack) oops("More POPs than PUSHes"); stackp--; break; case RIGHT1: case RIGHT2: case RIGHT3: case RIGHT4: DVI_H += spellnum(dvi_file, ch - RIGHT1 + 1); break; case X1: case X2: case X3: case X4: XX = spellnum(dvi_file, ch - X0); case X0: DVI_H += XX; break; case W1: case W2: case W3: case W4: WW = spellnum(dvi_file, ch - W0); case W0: DVI_H += WW; break; case Y1: case Y2: case Y3: case Y4: YY = spellnum(dvi_file, ch - Y0); case Y0: DVI_V += YY; PXL_V = pixel_conv(DVI_V); break; case Z1: case Z2: case Z3: case Z4: ZZ = spellnum(dvi_file, ch - Z0); case Z0: DVI_V += ZZ; PXL_V = pixel_conv(DVI_V); break; case DOWN1: case DOWN2: case DOWN3: case DOWN4: DVI_V += spellnum(dvi_file, ch - DOWN1 + 1); PXL_V = pixel_conv(DVI_V); break; case FNT1: case FNT2: case FNT3: case FNT4: change_font(num(dvi_file, ch - FNT1 + 1)); break; case XXX1: case XXX2: case XXX3: case XXX4: a = num(dvi_file, ch - XXX1 + 1); if(a > 0) special(a); break; case FNTDEF1: case FNTDEF2: case FNTDEF3: case FNTDEF4: Fseek(dvi_file, (long) (12 + ch - FNTDEF1 + 1), 1); a = one(dvi_file) + one(dvi_file); Fseek(dvi_file, (long) a, 1); break; case PRE: oops("Shouldn't happen: PRE encountered."); break; case POST: oops("Shouldn't happen: POST encountered."); break; case POSTPOST: oops("Unexpected POSTPOST encountered."); break; default: oops("Unknown op-code %d, offset %d", ch, ftell(dvi_file)); } /* end switch*/ } /* end else (ch not a SETCHAR or FNTNUM) */ } /* end for */ } /* ** ** Read size bytes from the FILE fp, constructing them into a ** signed/unsigned integer. ** */ unsigned long num(fp, size) register FILE *fp; register ubyte size; { register int i; register long x; x = 0; for (i = 0; i < size; i += 1) x = (x<<8) + (unsigned) (getc(fp) & 0xff); return (x); } long snum(fp, size) register FILE *fp; register ubyte size; { register int i; register long x; x = getc(fp) & 0xff; if (x & 0x80) x -= 0x100; for (i = 1; i < size; i += 1) x = (x<<8) + (unsigned) (getc(fp) & 0xff); return (x); } /* VARARGS1 */ oops(message, a, b, c, d, e, f) char *message; { Fprintf(stderr, "%s: ", prog); Fprintf(stderr, message, a, b, c, d, e, f); putc('\n', stderr); exit(1); }