DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T d

⟦68232d3c7⟧ TextFile

    Length: 14570 (0x38ea)
    Types: TextFile
    Names: »dvi_draw.c«

Derivation

└─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12
    └─⟦af5ba6c8e⟧ »unix3.0/DVIWARE.tar.Z« 
        └─⟦ca79c7339⟧ 
            └─⟦this⟧ »DVIware/crt-viewers/X/xdvi/dvi_draw.c« 

TextFile

/*
 * 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 = &current_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 = &current_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);
}