#include #include #include "defs.h" #include "types.h" #include "exports.h" #include "transforms.h" #include "tmpfile.h" public int xPages; /* number of horizontal pages */ public int yPages; /* number of vertical pages */ private FILE *fout; /* output file */ private char outBuff[ BUFSIZ ]; /* output file buffer */ private char *outfname; /* output filename */ private FILE *vfile, *hfile, *rfile, *labfile; /* tmp. files */ private BBox *rootBox; /* root (plot) bounding box */ #define DEFLT_FSIZE "10.0" /* default font size */ #define DEFLT_FONT "Helvetica" /* default PostScript font */ typedef struct /* Label written out to disk for clipping */ { IPoint pos; char *txt; } LabelFormat; typedef struct /* Rectangle when written out for clipping */ { IRect rect; char *name; } BoxFormat; typedef struct { char type; union { LabelFormat label; BoxFormat box; } d; } LabFileRec; /* Define the output procedures for one page output => * generate the PostScript directly. */ private void OnePageVline( lin ) V_Line *lin; { fprintf( fout, "%d %d %d V\n", lin->top - lin->bot, lin->x, lin->bot); } private void OnePageHline( lin ) H_Line *lin; { fprintf( fout, "%d %d %d H\n", lin->right - lin->left, lin->left, lin->y ); } private void OnePageRect( r ) IRect *r; { fprintf( fout, "%d %d %d %d B\n", r->bot.x, r->bot.y, r->top.x, r->top.y ); } private void OnePageChangeLayer( layNum ) int layNum; { char cc = (color == TRUE) ? 'C' : 'L'; fprintf( fout, "%d S%c\n", layNum, cc ); } private void OnePageLabel( pos, text ) IPoint *pos; char *text; { fprintf( fout, "(%s) %d %d L\n", text, pos->x, pos->y ); } private void OnePageBbox( box, name ) IRect *box; char *name; { if( name == NULL or specialLayers.symbolName == FALSE ) fprintf( fout, "%d %d %d %d BB\n", box->bot.x, box->bot.y, box->top.x, box->top.y ); else fprintf( fout, "(%s) %d %d %d %d BS\n", name, box->bot.x, box->bot.y, box->top.x, box->top.y ); } /* * Define the procedures for a multi-page output => * Buffer the various objects in temporary files which are then used for * clipping to the appropriate page. */ private void MultPageVline( lin ) V_Line *lin; { if( not fwrite( lin, sizeof( V_Line ), 1, vfile ) ) Crash( "write to '%s' failed", 2, tmpFiles[ VLINEFILE ].name ); } private void MultPageHline( lin ) H_Line *lin; { if( not fwrite( lin, sizeof( H_Line ), 1, hfile ) ) Crash( "write to '%s' failed", 2, tmpFiles[ HLINEFILE ].name ); } private void MultPageRect( r ) IRect *r; { if( not fwrite( r, sizeof( IRect ), 1, rfile ) ) Crash( "write to '%s' failed", 2, tmpFiles[ RECTFILE ].name ); } private void MultPageChangeLayer( layNum ) int layNum; { IRect r; r.bot.x = r.bot.y = -1; r.top.x = layNum; if( not fwrite( &r, sizeof( IRect ), 1, rfile ) ) Crash( "write to '%s' failed", 2, tmpFiles[ RECTFILE ].name ); } private void MultPageLabel( pos, text ) IPoint *pos; char *text; { LabFileRec rec; rec.type = 'L'; rec.d.label.pos = *pos; rec.d.label.txt = text; if( not fwrite( &rec, sizeof( rec ), 1, labfile ) ) Crash( "write to '%s' failed", 2, tmpFiles[ LABELFILE ].name ); } private void MultPageBbox( box, name ) IRect *box; char *name; { LabFileRec rec; rec.type = 'B'; rec.d.box.rect = *box; rec.d.box.name = name; if( not fwrite( &rec, sizeof( rec ), 1, labfile ) ) Crash( "write to '%s' failed", 2, tmpFiles[ LABELFILE ].name ); } private void InitializeText( box, name ) IRect *box; char *name; { fprintf( fout, "ST gsave\n" ); OutputBBox = OnePageBbox; OnePageBbox( box, name ); } private FILE *OpenClipFile( fname, mode ) char *fname; char *mode; { FILE *fp; if( (fp = fopen( fname, mode )) == NULL ) Crash( "can't open clip file '%s'", 2, fname ); setbuf( fp, Malloc( BUFSIZ ) ); return( fp ); } public void InitPS( psFile, Fsize, Fname, date, banner, outf, scale, nCop ) char *psFile; char *Fsize; char *Fname; char *date; char *banner; char *outf; Real scale; char *nCop; { int fdin, fdout, n, i; IPoint p1, p2; int width, height; int xdel, ydel, x0, y0, xbrdr, ybrdr; char *ppos, *pkeep; if( (fdin = open( psFile, O_RDONLY, 0 )) < 0 ) Crash( "can't open PostScript-prologue file '%s'\n", 2, psFile ); rootBox = &(root->cell->bigBox); TransformIPoint( rootBox->minC, root->tm, p1 ); TransformIPoint( rootBox->maxC, root->tm, p2 ); /* Encapsulated Postscript Inclusion--Tim Edwards, 10/23/91 */ xbrdr = (int) ( 72 * device->xmargin ); ybrdr = (int) ( 72 * device->ymargin ); if (xPages * yPages == 1) { width = max( p1.x, p2.x ); height = max( p1.y, p2.y ); } else { width = device->pagewidth; height = device->pageheight; } xdel = (int) ((float)width * 72 / device->resolution); ydel = (int) ((float)height * 72 / device->resolution); x0 = reloc ? 0 : (int)((float)(device->pagewidth - width) * 36 / device->resolution); y0 = reloc ? 0 : (int)((float)(device->pageheight - height) * 36 / device->resolution); if( Fsize == NULL ) Fsize = DEFLT_FSIZE; if( Fname == NULL ) Fname = DEFLT_FONT; if (!strcmp(outf, "-")) fout = stdout; else if ((fout = fopen(outf, "w")) == NULL ) Crash( "can't open output file '%s'\n", 2, outfname ); fprintf (fout, "%%!PS-Adobe-2.0 EPSF-1.2\n%%%%Title: %s",outf); fprintf (fout, "\n%%%%CreationDate: %s",date); fprintf (fout, "\n%%%%DocumentFonts: %s", Fname); fprintf (fout, "\n%%%%Pages: %d",xPages*yPages); fprintf (fout, "\n%%%%BoundingBox: %d %d %d %d", x0 + xbrdr - 8, y0 + ybrdr - 8, x0 + xdel + xbrdr + 8, y0 + ydel + ybrdr + 8); fprintf (fout, "\n%%%%EndComments\n\n"); fflush(fout); if (fout != stdout) fclose(fout); /* End Encapsulated Postscript format */ outfname = outf; if (!strcmp(outf, "-")) fdout = fileno(stdout); else { if( (fdout = open( outf, O_CREAT | O_RDWR, 0777 )) < 0 ) Crash( "can't open output file '%s'\n", 2, outf ); lseek(fdout, 0L, 2); /* prepare for append */ } for( n = read( fdin, outBuff, BUFSIZ ); n > 0; ) { /* Substitute actual page width for '#PageWidth' in the prolog */ /* (method added 8/16/01 by Tim) */ for (ppos = outBuff, i = 0; i < n; i++, ppos++) if (*ppos == '#') if (!strncmp(ppos + 1, "PageWidth", 9)) { sprintf(ppos, "%.2f ", device->width); pkeep = ppos + 10; while (*ppos != ' ') ppos++; memmove(ppos, pkeep, strlen(pkeep) + 1); n -= (pkeep - ppos); } write( fdout, outBuff, n ); n = read( fdin, outBuff, BUFSIZ ); } close( fdin ); if (fdout == fileno(stdout)) fout = stdout; else if( (fout = fdopen( fdout, "w" )) == NULL ) Crash( "can't fdopen output file '%s'\n", 2, outfname ); /* MAC II --- Commented out */ /* setbuffer( fout, outBuff, BUFSIZ ); */ /* Encapsulated PostScript Entry */ fprintf( fout, "\n%%%%EndProlog\n"); if (xPages * yPages == 1) fprintf( fout, "%%%%Page: 1 %d\n\n", xPages * yPages); OutputPatterns(); fprintf( fout, "%s %d /%s %s %f INIT\n", nCop, specialLayers.bbox, Fname, Fsize, device->resolution ); WriteHeader( banner, device, scale, date, width, height ); if( xPages * yPages == 1 ) /* one page output */ { int tx, ty; tx = (int) ( device->resolution * device->xmargin + 0.5 ); ty = (int) ( device->resolution * device->ymargin + 0.5 ); tx += (int) ( device->pagewidth - width ) / 2; ty += (int) ( device->pageheight - height ) / 2; if(reloc) fprintf( fout, "SP\n" ); else fprintf( fout, "SP %d %d translate\n", tx, ty ); OutputVline = OnePageVline; OutputHline = OnePageHline; OutputRect = OnePageRect; ChangeLayer = OnePageChangeLayer; OutputLabel = OnePageLabel; OutputBBox = InitializeText; /* 1st time a box is output */ } else { fflush( fout ); if (fout != stdout) fclose( fout ); SaveMem(); if( specialLayers.outline ) { hfile = OpenClipFile( tmpFiles[ HLINEFILE ].name, "w" ); vfile = OpenClipFile( tmpFiles[ VLINEFILE ].name, "w" ); } rfile = OpenClipFile( tmpFiles[ RECTFILE ].name, "w" ); labfile = OpenClipFile( tmpFiles[ LABELFILE ].name, "w" ); OutputVline = MultPageVline; OutputHline = MultPageHline; OutputRect = MultPageRect; ChangeLayer = MultPageChangeLayer; OutputLabel = MultPageLabel; OutputBBox = MultPageBbox; } } private WriteHeader( banner, dev, scaleFac, date, width, height ) char *banner; DevDef *dev; Real scaleFac; char *date; int width, height; { int magFac; int x, y; int xs, ys; x = (int) ( dev->xmargin * dev->resolution + 0.5 ); y = (int) ( dev->ymargin * dev->resolution + 0.5 ); if( xPages * yPages == 1 ) { if(reloc) { x = 0; y = height; } else { x += (int) ( ( dev->pagewidth - width ) / 2 ); y += (int) ( ( dev->pageheight + height ) / 2 ); } } else { y += height - (int) ( dev->resolution * dev->height * (yPages - 1) ); } magFac = (int) ( 25400.0 * scaleFac + 0.5 ); xs = (int) (( rootBox->maxC.x - rootBox->minC.x ) / 100.0); ys = (int) (( rootBox->maxC.y - rootBox->minC.y ) / 100.0); if( xs < 0 ) x = -xs; if( ys < 0 ) y = -ys; fprintf( fout, "ST (%s Scale: %f \\(%dX\\) Size: %d x %d microns", banner, scaleFac, magFac, xs, ys ); fprintf( fout, " %s) %d %d HEADER\n", date, x, y ); } /* * Write the stipple pattern for each layer used. 64 x 64 bit patterns * are generated. Reverse the order of the lines so that the default * PostScript scanning order may be used. * * Also write color information (added 5/28/94, Tim Edwards) */ private OutputPatterns() { int i, j; unsigned int *patp, *patend; char buff[ 130 ]; char *buffp; for( i = 0; i < nLayer; i++ ) { if( totRects[ i ] > 0 and IsVisible( i ) ) { patp = &(layer[ i ]->pat[7]); patend = layer[ i ]->pat; for( buffp = buff; patp >= patend; patp--, buffp += 16 ) (void) sprintf( buffp, "%08x%08x", *patp, *patp ); fprintf( fout, "{<%s>} %d DefPatt\n", buff, i ); } } if( color == TRUE ) { fprintf( fout, "/colors [" ); for( i = 0; i < nLayer; i++ ) for( j = 0; j < 4; j++) fprintf( fout, "%3.2f ", layer[ i ]->color[ j ]); fprintf( fout, "] def\n" ); } } private char *ibuff, *obuff; public void EndPS() { if( xPages * yPages == 1 ) { fprintf( fout, "grestore" ); if(! reloc) fprintf(fout," showpage"); fprintf(fout,"\n\n%%%%Trailer\n" ); fflush( fout ); if (fout != stdout) fclose( fout ); } else { int i, j; int tx, ty; int minX, minY, maxX, maxY; if( specialLayers.outline ) { fclose( hfile ); fclose( vfile ); } fclose( rfile ); fclose( labfile ); if (!strcmp(outfname, "-")) fout = stdout; else if( (fout = fopen( outfname, "a" )) == NULL ) Crash( "can't reopen output file '%s'", 2, outfname ); setbuf( fout, outBuff ); RestoreMem(); ibuff = Malloc( BUFSIZ ); obuff = Malloc( BUFSIZ ); for( j = yPages - 1; j >= 0; j-- ) { for( i = 0; i < xPages; i++ ) { /* Encapsulated PostScript inclustion */ fprintf( fout, "%%%%Page: %d %d\n\n", (yPages - 1 - j)*xPages + i + 1, xPages * yPages); tx = (device->resolution * device->xmargin) - i * device->pagewidth; ty = (device->resolution * device->ymargin) - j * device->pageheight; fprintf( fout, "MSAV SP %d %d translate\n", tx, ty ); minX = i * device->pagewidth; maxX = minX + device->pagewidth; minY = j * device->pageheight; maxY = minY + device->pageheight; ClipRectangles( minX, minY, maxX, maxY ); if( specialLayers.outline ) { ClipVlines( minX, minY, maxX, maxY ); ClipHlines( minX, minY, maxX, maxY ); } if( specialLayers.bbox or specialLayers.symbolName or specialLayers.pointName ) ClipLabels( minX, minY, maxX, maxY ); fprintf( fout, "showpage MRES\n" ); } } fprintf( fout, "\n%%%%Trailer\n"); fflush( fout ); if (fout != stdout) fclose( fout ); } } private ClipRectangles( minX, minY, maxX, maxY ) int minX, minY; int maxX, maxY; { FILE *fi, *fo; IRect r; if( (fi = fopen( tmpFiles[ RECTFILE ].name, "r" )) == NULL ) Crash( "can't reopen file '%s'", 2, tmpFiles[ RECTFILE ].name ); setbuf( fi, ibuff ); if( (fo = fopen( tmpFiles->name, "w" )) == NULL ) Crash( "can't open tmp file '%s'", 2, tmpFiles->name ); setbuf( fo, obuff ); while( fread( &r, sizeof( IRect ), 1, fi ) ) { if( r.bot.x == -1 ) { char cc = (color == TRUE) ? 'C' : 'L'; fprintf( fout, "%d S%c\n", r.top.x, cc ); if( not fwrite( &r, sizeof( IRect ), 1, fo ) ) Crash( "write to '%s' failed", 2, tmpFiles->name ); continue; } if( r.top.y >= minY and r.bot.x <= maxX ) { fprintf( fout, "%d %d %d %d B\n", max( r.bot.x, minX ), max( r.bot.y, minY ), min( r.top.x, maxX ), min( r.top.y, maxY )); } if( r.bot.y < minY or r.top.x > maxX ) { if( not fwrite( &r, sizeof( IRect ), 1, fo ) ) Crash( "write to '%s' failed", 2, tmpFiles->name ); } } fclose( fo ); fclose( fi ); rename( tmpFiles->name, tmpFiles[ RECTFILE ].name ); } ClipVlines( minX, minY, maxX, maxY ) int minX, minY; int maxX, maxY; { FILE *fi, *fo; V_Line lin; if( (fi = fopen( tmpFiles[ VLINEFILE ].name, "r" )) == NULL ) Crash( "can't reopen file '%s'", 2, tmpFiles[ VLINEFILE ].name ); setbuf( fi, ibuff ); if( (fo = fopen( tmpFiles->name, "w" )) == NULL ) Crash( "can't open tmp file '%s'", 2, tmpFiles->name ); setbuf( fo, obuff ); while( fread( &lin, sizeof( V_Line ), 1, fi ) ) { if( lin.top >= minY and lin.x <= maxX ) { register int bot, top; bot = max( lin.bot, minY ); top = min( lin.top, maxY ); fprintf( fout, "%d %d %d V\n", top - bot, lin.x, bot ); } if( lin.bot < minY or lin.x > maxX ) { if( not fwrite( &lin, sizeof( V_Line ), 1, fo ) ) Crash( "write to '%s' failed", 2, tmpFiles->name ); } } fclose( fo ); fclose( fi ); rename( tmpFiles->name, tmpFiles[ VLINEFILE ].name ); } ClipHlines( minX, minY, maxX, maxY ) int minX, minY; int maxX, maxY; { FILE *fi, *fo; H_Line lin; if( (fi = fopen( tmpFiles[ HLINEFILE ].name, "r" )) == NULL ) Crash( "can't reopen file '%s'", 2, tmpFiles[ HLINEFILE ].name ); setbuf( fi, ibuff ); if( (fo = fopen( tmpFiles->name, "w" )) == NULL ) Crash( "can't open tmp file '%s'", 2, tmpFiles->name ); setbuf( fo, obuff ); while( fread( &lin, sizeof( H_Line ), 1, fi ) ) { if( lin.y >= minY and lin.left <= maxX ) { register int left, right; left = max( lin.left, minX ); right = min( lin.right, maxX ); fprintf( fout, "%d %d %d H\n", right - left, left, lin.y ); } if( lin.y < minY or lin.right > maxX ) { if( not fwrite( &lin, sizeof( H_Line ), 1, fo ) ) Crash( "write to '%s' failed", 2, tmpFiles->name ); } } fclose( fo ); fclose( fi ); rename( tmpFiles->name, tmpFiles[ HLINEFILE ].name ); } ClipLabels( minX, minY, maxX, maxY ) int minX, minY; int maxX, maxY; { FILE *fi, *fo; LabFileRec rec; int todo; int writing; if( (fi = fopen( tmpFiles[ LABELFILE ].name, "r" )) == NULL ) Crash( "can't reopen file '%s'", 2, tmpFiles[ LABELFILE ].name ); setbuf( fi, ibuff ); if( (fo = fopen( tmpFiles->name, "w" )) == NULL ) Crash( "can't open tmp file '%s'", 2, tmpFiles->name ); setbuf( fo, obuff ); fprintf( fout, "ST gsave\n" ); todo = fread( &rec, sizeof( LabFileRec ), 1, fi ); while( todo ) { if( rec.type != 'B' ) continue; if( rec.d.box.rect.top.y >= minY and rec.d.box.rect.bot.x <= maxX ) { writing = (rec.d.box.rect.bot.y < minY or rec.d.box.rect.top.x > maxX)? 1:0; if(rec.d.box.name == NULL or specialLayers.symbolName == FALSE ) fprintf( fout, "%d %d %d %d BB\n", rec.d.box.rect.bot.x, rec.d.box.rect.bot.y, rec.d.box.rect.top.x, rec.d.box.rect.top.y ); else fprintf( fout, "(%s) %d %d %d %d BS\n", rec.d.box.name, rec.d.box.rect.bot.x, rec.d.box.rect.bot.y, rec.d.box.rect.top.x, rec.d.box.rect.top.y ); if( writing ) if( not fwrite( &rec, sizeof( rec ), 1, fo ) ) Crash( "write to '%s' failed", 2, tmpFiles->name ); while( (todo = fread( &rec, sizeof( rec ), 1, fi )) and rec.type == 'L' ) { if( rec.d.label.pos.y >= minY and rec.d.label.pos.x <= maxX ) fprintf( fout, "(%s) %d %d L\n", rec.d.label.txt, rec.d.label.pos.x, rec.d.label.pos.y ); if( writing ) if( not fwrite( &rec, sizeof( rec ), 1, fo ) ) Crash( "write to '%s' failed", 2, tmpFiles->name ); } } else { writing = (rec.d.box.rect.bot.y < minY or rec.d.box.rect.top.x > maxX)? 1:0; if( writing ) if( not fwrite( &rec, sizeof( rec ), 1, fo ) ) Crash( "write to '%s' failed", 2, tmpFiles->name ); while( (todo = fread( &rec, sizeof( rec ), 1, fi )) and rec.type == 'L' ) { if( writing ) if( not fwrite( &rec, sizeof( rec ), 1, fo ) ) Crash( "write to '%s' failed", 2, tmpFiles->name ); } } } fprintf( fout, "grestore " ); fclose( fo ); fclose( fi ); rename( tmpFiles->name, tmpFiles[ LABELFILE ].name ); }