/* Copyright (c) 1993 Neal Becker * All rights reserved. * Permission to copy for any purpose is hereby granted * so long as this copyright notice remains intact. */ /* * 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 const char rcsid[] = "$Header: c:/mctex/imagen/rcs/eps.c 1.1 91/08/05 23:40:48 ROOT_DOS Exp Locker: ROOT_DOS $"; #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] */ /* $Log: eps.c $ * Revision 1.1 91/08/05 23:40:48 ROOT_DOS * Initial revision * */ #include "PROTO.h" #include #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 "version.h" #include "epson.h" #include "Bset.h" #include /* for atoi, exit */ 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. */ int LFlag; /* -l => landscape mode */ int ReversePages; /* -p => [no] page reversal */ int SFlag; /* -s => silent (no page numbers) */ int Debug; /* -D => debug flag */ char *PrintEngine; /* e.g., canon, ricoh */ char *DVIFileName; /* name of input DVI file */ epson* Printer; BitMap* theBitMap; #ifdef TWOPASS static int Pass = 0; #endif static void LoadGlyph(struct glyph* g); static void SetGlyph( int c, struct font* f, struct glyph* g); /* * Assign a unique Imagen family to each font in the DVI file. */ struct font * DefineFont(char* name, i32 dvimag, i32 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); } 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(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); } theBitMap->Clear(); Printer->Reset(); } /* * End the page (interpreter found a DVI_EOP). */ void EndPage( ) { if (!SFlag) { (void) putc(']', stderr); (void) fflush(stderr); } #ifdef TWOPASS Printer->PrintBitMap( *theBitMap ); if( Pass % 2 == 1 ) /* finished 2nd pass */ Printer->EoP(); else /* finished first pass */ Printer->SyncVpos(); #else Printer->PrintBitMap( *theBitMap ); Printer->EoP(); #endif /* TWOPASS */ } /* * Perform a \special. * This version ignores all, with a warning. */ void DoSpecial(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(i32 h, i32 w) { if( LFlag == 0 ) { for( int i = 0; i < h; i++ ) { int Row = dvi_vv - i; #ifdef TWOPASS if( Pass % 2 == 1 ) Row -= BitMapRows; #endif int Pos = dvi_hh - LeftMarginPixels; if( Pos >= 0 ) { if( Row >= 0 && Row < BitMapRows ) theBitMap->SetBits( w, Row, Pos ); } } } else { for( int i = 0; i < w; i++ ) { int Row = dvi_hh + i; #ifdef TWOPASS if( Pass % 2 == 1 ) Row -= BitMapRows; #endif if( Row >= 0 && Row < BitMapRows ) { int Pos = HPixels - dvi_vv - LeftMarginPixels; if( Pos >= 0 ) theBitMap->SetBits( h, Row, Pos ); } } } } /* * 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; #ifdef TWOPASS int Pass = 0; long PageStartPos; #endif if (ReversePages) if (ds.ds_prevpage == -1) return (0); /* Mark 10:31 (kilroy was here) */ else (void) fseek(fp, ds.ds_prevpage, 0); #ifdef TWOPASS PageStartPos = ftell( fp ); #endif /* * 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) LoadGlyph(g); SetGlyph( (int)p, f, g); if (advance) { dvi_h += g->g_tfmwidth; dvi_hh += g->g_pixwidth; p = fromSPh(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; goto do_char; case DT_PUT: advance = 0; 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(); #ifdef TWOPASS Pass++; if( Pass % 2 == 1 ) { fseek( fp, PageStartPos, 0 ); doingpage = 0; goto loop; } else #endif 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 += fromSPh(p); p = fromSPh(dvi_h); FIXDRIFT(dvi_hh, p); } else dvi_hh = fromSPh(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 += fromSPv(p); p = fromSPv(dvi_v); FIXDRIFT(dvi_vv, p); } else dvi_vv = fromSPv(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 */ } #if defined( __MSDOS__ ) # if !defined( __GNUC__ ) # include # include # endif /* __GNUC__ */ # include extern int _fmode; #endif void ShowUse( const char* ProgName ) { fprintf( stderr, "Usage: %s [delmpHVsDXYfv]\n", ProgName ); fprintf( stderr, "\ \t-d maxdrift\n\ \t-e engine\n\ \t-l landscape\n\ \t-m mag\n\ \t-p toggle page reversal\n\ \t-H horiz. res. (dpi)\n\ \t-V vert. res. (dpi)\n\ \t-s silent\n\ \t-D debug\n\ \t-X x offset in 0.001 in\n\ \t-Y y offset in 0.001 in\n\ \t-f fast horiz space\n\ \t-v show version number\n\ "); exit( 2 ); } main(int argc, char **argv) { register int c; int xoff = 0, yoff = 0; /* margins from -X and -Y */ int hdpi = DefaultDPIh; /* resolution from -r */ int vdpi = DefaultDPIv; /* resolution from -r */ FILE *fp = stdin; int FastSpace = 0; setbuf(stderr, serrbuf); #ifdef __MSDOS__ _fmode = O_BINARY; setmode( fileno( stdout ), O_BINARY ); setmode( fileno( stdin ), O_BINARY ); #endif ProgName = *argv; ds.ds_usermag = 1000; ds.ds_maxdrift = DefaultMaxDrift; ReversePages = 0; /* default is to reverse pages */ PrintEngine = "epson"; DVIFileName = "`stdin'"; while ((c = getopt(argc, argv, "d:e:lm:pH:V:sDX:Y:fv")) != 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 'H': /* resolution */ hdpi = atoi(optarg); break; case 'V': /* resolution */ vdpi = 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 'f': /* fast spaces */ FastSpace = 1; break; case 'v': fprintf( stderr, "eps version %s\n", EpsVersion ); case '?': ShowUse( ProgName ); } } if (optind < argc) if ((fp = fopen(DVIFileName = argv[optind], "r")) == NULL) error(1, errno, "can't open %s", DVIFileName); #if defined( __MSDOS__ ) && !defined( __GNUC__ ) if( Debug ) fprintf( stderr, "Start: brk(0)=%p,coreleft=%lx\n", sbrk(0), coreleft() ); #endif DVISetState(fp, DefineFont, hdpi, vdpi, xoff, yoff); #if defined( __MSDOS__ ) && !defined( __GNUC__ ) if( Debug ) fprintf( stderr, "After DVISetState: brk(0)=%p,coreleft=%lx\n", sbrk(0), coreleft() ); #endif theBitMap = new BitMap; #if defined( __MSDOS__ ) && !defined( __GNUC__ ) if( Debug ) fprintf( stderr, "After BitMap: brk(0)=%p,coreleft=%lx\n", sbrk(0), coreleft() ); #endif Printer = new epson( stdout, FastSpace ); /* All set! */ while (PageLoop()) /* void */; if (!SFlag) { (void) fprintf(stderr, "\n"); (void) fflush(stderr); } (void) fflush(stdout); if (ferror(stdout)) error(1, -1, "error writing imPRESS output"); exit(0); /* NOTREACHED */ } static void ShowBits( char x ) { for( int i = 7; i >= 0; --i ) { if( x & BitMask[ i ] ) putc( '*', stdout ); else putc( ' ', stdout ); } } /* * Download the character c of font f (glyph=g). * The value of c is guaranteed to be in [0..127]. */ static void LoadGlyph(struct glyph* g) { g->g_pixwidth = fromSPh(g->g_tfmwidth); g->g_flags |= GF_SEEN; } static void SetGlyph(int c, struct font* f, struct glyph* g) { register char *p; register int i, j, w; if (!HASRASTER(g)) /* never load dull glyphs */ return; /* (imagen cannot handle them) */ if (!LFlag) { p = RASTER(g, f, ROT_NORM); } else { p = RASTER(g, f, ROT_RIGHT); } /* Define the character */ /* * Now put out the bitmap. */ /* fprintf( stderr, "adv:%ld width:%ld xor:%ld height:%ld yor:%ld\n", (long)(g->g_pixwidth), (long)(g->g_width), (long)(g->g_xorigin), (long)(g->g_height), (long)(g->g_yorigin) ); */ w = (g->g_width + 7) >> 3; for (i = 0; i < g->g_height; i++ ) { int Row = ( LFlag ) ? ( dvi_hh - g->g_yorigin + i ) : ( dvi_vv - g->g_yorigin + i ) ; #ifdef TWOPASS if( Pass % 2 == 1 ) Row -= BitMapRows; #endif if( Row >= 0 && Row < BitMapRows ) { int Pos = ( LFlag ) ? HPixels - dvi_vv - g->g_xorigin : dvi_hh - g->g_xorigin; Pos -= LeftMarginPixels; if( Pos >= 0 ) theBitMap->Set( p, w, Row, Pos ); } p += w; } /* for (i = 0; i < g->g_height; i++ ) { for (j = 0; j < w; j++ ) { ShowBits( BitMap[ dvi_vv - g->g_yorigin + i ][(dvi_hh - g->g_xorigin)/8 + j] ); } putc( '\n', stdout ); } putc( '\n', stdout ); */ }