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 i

⟦2d35d7d4d⟧ TextFile

    Length: 11232 (0x2be0)
    Types: TextFile
    Names: »imagen1.c«

Derivation

└─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12
    └─⟦af5ba6c8e⟧ »unix3.0/DVIWARE.tar.Z« 
        └─⟦ca79c7339⟧ 
            └─⟦this⟧ »DVIware/laser-setters/mctex/imagen/imagen1.c« 

TextFile

/*
 * Copyright (c) 1987, 1989 University of Maryland
 * Department of Computer Science.  All rights reserved.
 * Permission to copy for any purpose is hereby granted
 * so long as this copyright notice remains intact.
 */

#ifndef lint
static char rcsid[] = "$Header: /usr/src/local/tex/local/mctex/imagen/RCS/imagen1.c,v 3.2 89/09/01 13:56:54 chris Exp $";
#endif

/*
 * DVI to Imagen driver
 *
 * Reads DVI version 2 files and converts to imPRESS commands for spooling to
 * the Imagen (via ipr).
 *
 * TODO:
 *	think about fonts with characters outside [0..127]
 */

#include <stdio.h>
#include "types.h"
#include "conv.h"
#include "dviclass.h"
#include "dvicodes.h"
#include "error.h"
#include "fio.h"
#include "font.h"
#include "gripes.h"
#include "dvistate.h"

#include "imagen.h"
#include "imPcodes.h"

char *ProgName;
extern char *optarg;
extern int optind;

/* Globals */
char serrbuf[BUFSIZ];		/* buffer for stderr */

/*
 * We store Imagen font family numbers in the f_int field the font
 * routines allocate for us.
 */
#define	f_family f_un.f_int

int	LFlag;			/* -l => landscape mode */
int	ReversePages;		/* -p => [no] page reversal */
int	SFlag;			/* -s => silent (no page numbers) */
int	Debug;			/* -D => debug flag */

int	ImHH;			/* Imagen horizontal position */
int	ImVV;			/* Imagen vertical position */
int	ImFamily;		/* Imagen current-font number */

char	*PrintEngine;		/* e.g., canon, ricoh */

char	*DVIFileName;		/* name of input DVI file */

void	DownLoadGlyph();

/* Put byte and two-byte (word) value to the Imagen */
#undef putbyte
#define putbyte(b) ((void) putchar(b))
#define putword(w) (putbyte((int)(w) >> 8), putbyte((int)(w)))

/*
 * Set the Imagen's h & v positions.  It is currently at ImHH, ImVV.
 *
 * This is invoked from within the main put-characters-on-page loop and
 * should go fast.
 */
#define	SetPosition(h, v) { \
	if (ImHH != (h)) { \
		if (ImHH == (h) - 1) \
			putbyte(imP_Forw); \
		else if (ImHH == (h) + 1) \
			putbyte(imP_Backw); \
		else { \
			putbyte(imP_SetHAbs); \
			putword(h); \
		} \
		ImHH = (h); \
	} \
	if (ImVV != (v)) { \
		putbyte(imP_SetVAbs); \
		putword(v); \
		ImVV = (v); \
	} \
}

int
AllocateFamily()
{
	static int nextfamily;	/* next available Imagen glyph-family index */

	if (nextfamily == MaxImFamily)
		error(0, 0, "\
WARNING: out of Imagen font family indicies;\n\
\toutput will probably resemble freshly scrambled eggs.");
	return (nextfamily++);
}

/*
 * Assign a unique Imagen family to each font in the DVI file.
 */
struct font *
DefineFont(name, dvimag, dvidsz)
	char *name;
	i32 dvimag, dvidsz;
{
	register struct font *f;
	char *path;

	f = GetFont(name, dvimag, dvidsz, PrintEngine, &path);
	if (f == NULL) {
		GripeCannotGetFont(name, dvimag, dvidsz, PrintEngine, path);
		return (NULL);
	}
	f->f_family = AllocateFamily();
	if (Debug) {
		(void) fprintf(stderr, "[%s -> %s]\n", Font_TeXName(f), path);
		(void) fflush(stderr);
	}
	return (f);
}

/*
 * Start a new page (interpreter found a DVI_BOP).
 */
void
BeginPage(count)
	i32 *count;
{

	if (!SFlag) {
		static int beenhere;

		if (beenhere)
			(void) putc(' ', stderr);
		else
			beenhere = 1;
		(void) fprintf(stderr, "[%ld", (long)count[0]);
		(void) fflush(stderr);
	}
	putbyte(imP_Page);
	ImHH = 0;
	ImVV = 0;
}

/*
 * End the page (interpreter found a DVI_EOP).
 */
void
EndPage()
{

	if (!SFlag) {
		(void) putc(']', stderr);
		(void) fflush(stderr);
	}
	putbyte(imP_EndPage);
}

/*
 * Perform a \special.
 * This version ignores all, with a warning.
 */
void
DoSpecial(len)
	i32 len;
{

	error(0, 0, "warning: ignoring \\special");
	(void) fseek(ds.ds_fp, (long)len, 1);
}

/*
 * Set a rule at dvi_hh, dvi_vv.
 */
void
SetRule(h, w)
	register i32 h, w;
{

	/* put the rule out */
	SetPosition(dvi_hh, dvi_vv);
	(void) putchar(imP_Rule);
	putword(w);
	putword(h);
	putword(-h + 1);
}

/*
 * Check the range of a character, to be sure the device can handle it.
 * Called for DVI_SET and DVI_PUT opcodes only.
 */
int
CheckChar(c)
	i32 c;
{

	if ((ui32)c > 127) {
		error(0, 0, "Warning: character code %ld too big for Imagen",
		    (long)c);
		return (1);
	}
	return (0);
}

/*
 * Main page loop.  This reads one page of the DVI file.
 * Returns 1 for EOP and 0 for end of last page (POST).
 */
int
PageLoop()
{
	static struct font NoFont;	/* font with zero pspace, etc */
	register int c;
	register i32 p;
	register struct font *f = &NoFont;
	register FILE *fp = ds.ds_fp;
	int doingpage = 0, advance;

	if (ReversePages)
		if (ds.ds_prevpage == -1)
			return (0);	/* Mark 10:31 (kilroy was here) */
		else
			(void) fseek(fp, ds.ds_prevpage, 0);

	/*
	 * This would be a `for (;;)', but that makes the function
	 * crawl off the right of the screen.
	 *
	 * We handle ordinary characters early, as they are the
	 * most common opcodes in DVI files, and doing so makes the
	 * loop run faster.
	 */
loop:
	c = fgetbyte(fp);
	if (DVI_IsChar(c)) {
		register struct glyph *g;

		p = c;
		advance = 1;
do_char:
		g = GLYPH(f, p);
		if (!GVALID(g)) {
			GripeBadGlyph(p, f);
			goto loop;
		}
		if ((g->g_flags & GF_SEEN) == 0)
			DownLoadGlyph((int)p, f, g);
		if (HASRASTER(g)) {	/* workaround for Imagen bug */
			SetPosition(dvi_hh, dvi_vv);
			if (ImFamily != f->f_family) {
				putbyte(imP_SetFamily);
				putbyte(f->f_family);
				ImFamily = f->f_family;
			}
			putbyte((int)p);
			ImHH += g->g_pixwidth;
		}
		if (advance) {
			dvi_h += g->g_tfmwidth;
			dvi_hh += g->g_pixwidth;
			p = fromSP(dvi_h);
			FIXDRIFT(dvi_hh, p);
		}
		goto loop;
	}

	if (c == EOF)		/* unexpected end of DVI file */
		GripeUnexpectedDVIEOF();

	/*
	 * Gather up a parameter, if known.
	 */
	switch (DVI_OpLen(c)) {

	case DPL_NONE:
		break;

	case DPL_SGN1:
		p = fgetbyte(fp);
		p = Sign8(p);
		break;

	case DPL_SGN2:
		fGetWord(fp, p);
		p = Sign16(p);
		break;

	case DPL_SGN3:
		fGet3Byte(fp, p);
		p = Sign24(p);
		break;

	case DPL_SGN4:
		fGetLong(fp, p);
		break;

	case DPL_UNS1:
		p = fgetbyte(fp);
		p = UnSign8(p);
		break;

	case DPL_UNS2:
		fGetWord(fp, p);
		p = UnSign16(p);
		break;

	case DPL_UNS3:
		fGet3Byte(fp, p);
		p = UnSign24(p);
		break;

	default:
		panic("DVI_OpLen(%d) = %d", c, DVI_OpLen(c));
		/* NOTREACHED */
	}

	/*
	 * Now switch on the type.
	 */
	switch (DVI_DT(c)) {

	case DT_SET:
		advance = 1;
		if (CheckChar(p))
			goto loop;
		goto do_char;

	case DT_PUT:
		advance = 0;
		if (CheckChar(p))
			goto loop;
		goto do_char;

	case DT_SETRULE:
		DVIRule(SetRule, 1);
		goto loop;

	case DT_PUTRULE:
		DVIRule(SetRule, 0);
		goto loop;

	case DT_NOP:
		goto loop;

	case DT_BOP:
		if (doingpage)
			GripeUnexpectedOp("BOP (already in page)");
		DVIBeginPage(BeginPage);
		doingpage = 1;
		goto loop;

	case DT_EOP:
		if (!doingpage)
			GripeUnexpectedOp("EOP (no BOP)");
		EndPage();
		return (1);

	case DT_PUSH:
		*ds.ds_sp++ = ds.ds_cur;
		goto loop;

	case DT_POP:
		ds.ds_cur = *--ds.ds_sp;
		goto loop;

	case DT_W0:
		p = dvi_w;
		goto right;

	case DT_W:
		dvi_w = p;
		goto right;

	case DT_X0:
		p = dvi_x;
		goto right;

	case DT_X:
		dvi_x = p;
		goto right;

	case DT_RIGHT:
right:
		dvi_h += p;
		if (F_SMALLH(f, p)) {
			dvi_hh += fromSP(p);
			p = fromSP(dvi_h);
			FIXDRIFT(dvi_hh, p);
		} else
			dvi_hh = fromSP(dvi_h);
		goto loop;

	case DT_Y0:
		p = dvi_y;
		goto down;

	case DT_Y:
		dvi_y = p;
		goto down;

	case DT_Z0:
		p = dvi_z;
		goto down;

	case DT_Z:
		dvi_z = p;
		goto down;

	case DT_DOWN:
down:
		dvi_v += p;
		if (F_SMALLV(f, p)) {
			dvi_vv += fromSP(p);
			p = fromSP(dvi_v);
			FIXDRIFT(dvi_vv, p);
		} else
			dvi_vv = fromSP(dvi_v);
		goto loop;

	case DT_FNTNUM:
		f = DVIFindFont((i32)(c - DVI_FNTNUM0));
		goto loop;

	case DT_FNT:
		f = DVIFindFont(p);
		goto loop;

	case DT_XXX:
		DoSpecial(p);
		goto loop;

	case DT_FNTDEF:
		SkipFontDef(fp);
		goto loop;

	case DT_PRE:
		GripeUnexpectedOp("PRE");
		/* NOTREACHED */

	case DT_POST:
		if (doingpage) {
			GripeUnexpectedOp("POST (no EOP)");
			/* NOTREACHED */
		}
		return (0);

	case DT_POSTPOST:
		GripeUnexpectedOp("POSTPOST");
		/* NOTREACHED */

	case DT_UNDEF:
		GripeUndefinedOp(c);
		/* NOTREACHED */

	default:
		panic("DVI_DT(%d) = %d", c, DVI_DT(c));
		/* NOTREACHED */
	}
	/* NOTREACHED */
}

main(argc, argv)
	int argc;
	register char **argv;
{
	register int c;
	int xoff = 0, yoff = 0;	/* margins from -X and -Y */
	int dpi = DefaultDPI;	/* resolution from -r */
	FILE *fp = stdin;

	setbuf(stderr, serrbuf);

	ProgName = *argv;
	ds.ds_usermag = 1000;
	ds.ds_maxdrift = DefaultMaxDrift;
	ReversePages = 1;	/* default is to reverse pages */
	PrintEngine = "canon";
	DVIFileName = "`stdin'";

	while ((c = getopt(argc, argv, "d:e:lm:pr:sDX:Y:")) != EOF) {
		switch (c) {

		case 'd':	/* max drift value */
			ds.ds_maxdrift = atoi(optarg);
			break;

		case 'e':	/* engine */
			PrintEngine = optarg;
			break;

		case 'l':	/* landscape mode */
			LFlag++;
			break;

		case 'm':	/* magnification */
			ds.ds_usermag = atoi(optarg);
			break;

		case 'p':	/* toggle page reversal */
			ReversePages = !ReversePages;
			break;

		case 'r':	/* resolution */
			dpi = atoi(optarg);
			break;

		case 's':	/* silent */
			SFlag++;
			break;

		case 'D':
			Debug++;
			break;

		case 'X':	/* x offset, in 1/1000 inch increments */
			xoff = atoi(optarg);
			break;

		case 'Y':	/* y offset */
			yoff = atoi(optarg);
			break;

		case '?':
			(void) fprintf(stderr,
	"Usage: %s [-ls] [more options, see manual] [file]\n", ProgName);
			(void) fflush(stderr);
			exit(1);
		}
	}

	if (optind < argc)
		if ((fp = fopen(DVIFileName = argv[optind], "r")) == NULL)
			error(1, -1, "can't open %s", DVIFileName);

	DVISetState(fp, DefineFont, dpi, xoff, yoff);

	ImFamily = -1;		/* probably 0, but this is safer */

	/* All set! */
	(void) printf("@document(language imPRESS, name \"%s\")", DVIFileName);
	if (LFlag) {
		putbyte(imP_SetHVSystem);
		putbyte(0x55);	/* origin=ulc, h:v=90, h:x=90 */
		putbyte(imP_SetAdvDirs);
		putbyte(0);	/* main=0 (degrees), secondary=90 */
	}
	while (PageLoop())
		/* void */;
	if (!SFlag) {
		(void) fprintf(stderr, "\n");
		(void) fflush(stderr);
	}
	putbyte(imP_EOF);
	(void) fflush(stdout);
	if (ferror(stdout))
		error(1, -1, "error writing imPRESS output");

	exit(0);
	/* NOTREACHED */
}

/*
 * Download the character c of font f (glyph=g).
 * The value of c is guaranteed to be in [0..127].
 */
void
DownLoadGlyph(c, f, g)
	int c;
	struct font *f;
	register struct glyph *g;
{
	register char *p;
	register int i, j, w;

	g->g_pixwidth = fromSP(g->g_tfmwidth);
	g->g_flags |= GF_SEEN;
	if (!HASRASTER(g))	/* never load dull glyphs */
		return;		/* (imagen cannot handle them) */

	if (!LFlag) {
		w = 0;
		p = RASTER(g, f, ROT_NORM);
	} else {
		w = 1 << 14;
		p = RASTER(g, f, ROT_RIGHT);
	}

	w |= (f->f_family << 7) | c;

	/* Define the character */
	putbyte(imP_DefGlyph);	/* a.k.a. BGLY */
	putword(w);		/* rotation, family, member */
	putword(g->g_pixwidth);	/* advance */
	putword(g->g_width);	/* width */
	putword(g->g_xorigin);	/* left offset */
	putword(g->g_height);	/* height */
	putword(g->g_yorigin);	/* top-offset */

	/*
	 * Now put out the bitmap.
	 */
	w = (g->g_width + 7) >> 3;
	for (i = g->g_height; --i >= 0;)
		for (j = w; --j >= 0;)
			putbyte(*p++);

	FreeRaster(g);
}