|
|
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 i
Length: 11232 (0x2be0)
Types: TextFile
Names: »imagen1.c«
└─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12
└─⟦af5ba6c8e⟧ »unix3.0/DVIWARE.tar.Z«
└─⟦ca79c7339⟧
└─⟦this⟧ »DVIware/laser-setters/mctex/imagen/imagen1.c«
/*
* 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);
}