home *** CD-ROM | disk | FTP | other *** search
- /*
- ** printed circuit board printer, Copyright (C) Randy Nevin 1989, 1990.
- **
- ** you may give this software to anyone, make as many copies as you like, and
- ** post it on public computer bulletin boards and file servers. you may not
- ** sell it or charge any fee for distribution (except for media and postage),
- ** remove this comment or the copyright notice from the code, or claim that
- ** you wrote this code or anything derived from it. you may modify the code as
- ** much as you want (please document clearly with comments, and maintain the
- ** coding style), but programs which are derived from this one are subject to
- ** the conditions stated here. i am providing this code so that people can
- ** learn from it, so if you distribute it, please include source code, not
- ** just executables. contact me to report bugs or suggest enhancements; i do
- ** not guarantee support, but i will make an effort to help you, and i want to
- ** act as a central clearing house for future versions. you should contact me
- ** before undertaking a significant development effort, to avoid reinventing
- ** the wheel. if you come up with an enhancement you consider particularly
- ** useful, i would appreciate being informed so that it can be incorporated in
- ** future versions. my address is: Randy Nevin, 1731 211th PL NE, Redmond,
- ** WA 98053, USA. this code is available directly from the author; just send a
- ** 360k floppy and a self-addressed floppy mailer with sufficient postage.
- **
- ** HISTORY
- ** (name date description)
- ** ----------------------------------------------------
- ** randy nevin 3/4/89 initial version
- ** randy nevin 3/4/89 released version 1.00
- ** randy nevin 4/22/89 implemented /H and /V switches to
- ** distinguish between hp laser jet
- ** commands and vector-oriented commands;
- ** the new vector-oriented commands
- ** should be easy to translate into
- ** postscript or other graphics printer
- ** languages such as hpgl, and are
- ** human-readable
- ** randy nevin 4/27/89 released version 1.10
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "cell.h"
-
- /*
- ** usage: PCBPRINT [/H] [/V] [/P] [/L] [/Rn] [/Zm] infile
- **
- ** /P indicates portrait orientation (paper is longer from top to bottom), and
- ** /L indicates landscape orientation (paper is longer side-to-side). only one
- ** of /P and /L can be present. n is the laser printer resolution (75, 100,
- ** 150, or 300) and m is the zoom factor (0, 1, 2, or 3). the defaults are:
- ** /P /R150 /Z1. this program creates 6 output files (H, T, B, HT, HB, and
- ** HTB). each of these files can be fed to a hewlett-packard laser printer to
- ** produce a picture of part or all of the routed printed circuit board. H
- ** contains commands to print only the holes and routing holes. T and B
- ** contain commands to print only the top-side or bottom-side traces,
- ** respectively. HT and HB are the same, but also include the holes, and HTB
- ** contains everything (holes, top-side traces, and bottom-side traces).
- **
- ** /H selects hewlett-packard laser printer commands, and is the default.
- ** /V selects vector-oriented commands; if it is selected, none of the other
- ** switches are available. when /V is selected, the output files are as above,
- ** but consist of the following types of lines:
- ** 1) DIMENSION(rowmax, colmax)
- ** 2) LINE(row1, col1, row2, col2)
- ** 3) CIRCLE(row, col, radius)
- ** all parameters are real numbers, and specified in mils (1/1000 of an inch).
- ** DIMENSION tells the maximum row and column values that will be encountered.
- ** LINE specifies the endpoints of a line. CIRCLE gives a circle center and
- ** radius. here is a blow-up of one 50-mil-by-50-mil cell, with certain points
- ** of interest labeled by their position relative to the origin (0.0,0.0):
- **
- ** A---------------B---------------C
- ** | |
- ** | **D** |
- ** | * * |
- ** | E F |
- ** | * * |
- ** G H I J K
- ** | * * |
- ** | L M |
- ** | * * |
- ** | **N** |
- ** | |
- ** O---------------P---------------Q
- **
- ** A = ( 50, 0 )
- ** B = ( 50, 25 )
- ** C = ( 50, 50 )
- ** D = ( 37.5, 25 )
- ** E = ( 33.8388, 16.1612 )
- ** F = ( 33.8388, 33.8388 )
- ** G = ( 25, 0 )
- ** H = ( 25, 12.5 )
- ** I = ( 25, 25 )
- ** J = ( 25, 37.5 )
- ** K = ( 25, 50 )
- ** L = ( 16.1612, 16.1612 )
- ** M = ( 16.1612, 33.8388 )
- ** N = ( 12.5, 25 )
- ** O = ( 0, 0 )
- ** P = ( 0, 25 )
- ** Q = ( 0, 50 )
- */
-
- /* markers that hole-related traces have been processed */
- #define NOT_NORTH 0x00000200L /* upward */
- #define NOT_NORTHEAST 0x00000400L /* upward and right */
- #define NOT_EAST 0x00000800L /* to the right */
- #define NOT_SOUTHEAST 0x00001000L /* downward and right */
- #define NOT_SOUTH 0x00002000L /* downward */
- #define NOT_SOUTHWEST 0x00004000L /* downward and left */
- #define NOT_WEST 0x00008000L /* to the left */
- #define NOT_NORTHWEST 0x00010000L /* upward and left */
- #define NOT_ALL ( NOT_NORTH \
- | NOT_NORTHEAST \
- | NOT_EAST \
- | NOT_SOUTHEAST \
- | NOT_SOUTH \
- | NOT_SOUTHWEST \
- | NOT_WEST \
- | NOT_NORTHWEST )
-
- #define MAXZOOM 3 /* maximum zoom number; minimum is 0 */
-
- #define ZOOM0 3 /* 3x3 dots per cell */
- #define ZOOM1 6 /* 6x6 dots per cell */
- #define ZOOM2 10 /* 10x10 dots per cell */
- #define ZOOM3 18 /* 18x18 dots per cell */
-
- #define HPLASERJET 0 /* hp laser jet commands */
- #define VECTOR 1 /* vector-oriented commands */
-
- static int size[MAXZOOM+1] = { ZOOM0, ZOOM1, ZOOM2, ZOOM3 };
-
- #define H 1 /* holes */
- #define T 2 /* top-side traces */
- #define B 4 /* bottom-side traces */
- #define HT (H+T) /* holes and top-side traces */
- #define HB (H+B) /* holes and bottom-side traces */
- #define HTB (H+T+B) /* holes, top- and bottom-side traces */
-
- static int style; /* 0 = /H, 1 = /V */
- static int currnt; /* current image type (one of the six above) */
- static int orient; /* 0=portrait, 1=landscape */
- static int resol; /* resolution (one of 75,100,150,300) */
- static int zoom; /* 0=3x3, 1=6x6, 2=10x10, 3=18x18 */
- static int nbytes; /* number of bytes per image row */
-
- int JustBoard = 1; /* only need the board data structure */
-
- extern int Nrows, Ncols; /* board dimensions */
-
- extern void InitBoard( void );
- extern long GetCell( int, int, int );
- extern void SetCell( int, int, int, long );
-
- void main( int, char *[] );
- static void dofile( char *, int );
- static void prolog( FILE * );
- static void epilog( FILE * );
- static void doimage( FILE * );
- static void dovector( FILE * );
- static void trace( FILE *, int, int, int, int, int, int, int, int );
- static void map( long, long, int, FILE * );
- static void initbit( void );
- static void flushbit( FILE * );
- static void outbit( int, FILE * );
-
- void main ( argc, argv ) /* input routed board, output laser printer files */
- int argc;
- char *argv[];
- {
- char *self, *p;
- register int r, c;
- int i1, i2, i3, i4, i, j;
- FILE *fp;
- long x;
- char oset, rset, zset;
-
- printf( "Copyright (C) Randy Nevin, 1989, 1990. Version 1.10\n" );
- printf( "See source code for rights granted.\n\n" );
- style = HPLASERJET;
- orient = 0; /* portrait mode */
- resol = 150; /* 150 dots per inch */
- zoom = 1; /* 6x6 cells */
- oset = rset = zset = 0; /* so far, just defaults */
- self = argv[0];
- /* get rid of initial part of path */
- if ((p = strrchr( self, '\\' )) || (p = strrchr( self, ':' )))
- self = ++p;
- /* get rid of extension */
- if ((p = strrchr( self, '.' )) && !stricmp( p, ".EXE" ))
- *p = 0;
- if (argc < 2 || argc > 5) { /* need infile and up to 4 switches */
- fprintf( stderr,
- "usage: %s [/H] [/V] [/P] [/L] [/Rn] [/Zm] infile\n",
- self );
- fprintf( stderr, " H = hp laser jet commands (default)\n" );
- fprintf( stderr, " V = vector-oriented commands\n" );
- fprintf( stderr, " P = portrait orientation\n" );
- fprintf( stderr, " L = landscape orientation\n" );
- fprintf( stderr, " n = resolution (75,100,150,300)\n" );
- fprintf( stderr, " m = zoom (0,1,2,3)\n" );
- exit( -1 );
- }
- for (i = 1; i < argc-1; i++) { /* process switches */
- if (!stricmp( argv[i], "/h" ))
- style = HPLASERJET;
- else if (!stricmp( argv[i], "/v" ))
- style = VECTOR;
- else if (!stricmp( argv[i], "/p" )) {
- if (oset)
- fprintf( stderr, "duplicate orientation %s\n",
- argv[i] );
- else {
- oset = 1;
- orient = 0;
- }
- }
- else if (!stricmp( argv[i], "/l" )) {
- if (oset)
- fprintf( stderr, "duplicate orientation %s\n",
- argv[i] );
- else {
- oset = 1;
- orient = 1;
- }
- }
- else if (*argv[i] == '/' && (*(argv[i]+1) == 'R'
- || *(argv[i]+1) == 'r')) {
- if (rset)
- fprintf( stderr, "duplicate resolution %s\n",
- argv[i] );
- else {
- rset = 1;
- resol = atoi( argv[i]+2 );
- }
- }
- else if (*argv[i] == '/' && (*(argv[i]+1) == 'Z'
- || *(argv[i]+1) == 'z')) {
- if (zset)
- fprintf( stderr, "duplicate zoom %s\n",
- argv[i] );
- else {
- zset = 1;
- zoom = atoi( argv[i]+2 );
- }
- }
- else
- fprintf( stderr, "unknown option %s\n", argv[i] );
- }
- if (!(fp = fopen( argv[argc-1], "rb" ))) {
- fprintf( stderr, "can't open %s\n", argv[argc-1] );
- exit( -1 );
- }
- /* fetch the board dimensions */
- if ((i = getc( fp )) == EOF || (j = getc( fp )) == EOF) {
- fprintf( stderr, "premature eof\n" );
- exit( -1 );
- }
- Nrows = (i & 0xFF) | ((j << 8) & 0xFF00);
- if ((i = getc( fp )) == EOF || (j = getc( fp )) == EOF) {
- fprintf( stderr, "premature eof\n" );
- exit( -1 );
- }
- Ncols = (i & 0xFF) | ((j << 8) & 0xFF00);
- InitBoard(); /* allocate memory for data structures */
- for (r = 0; r < Nrows; r++) { /* read in the board, row by column */
- for (c = 0; c < Ncols; c++) {
- /* first do top-side */
- if ((i1 = getc( fp )) == EOF
- || (i2 = getc( fp )) == EOF
- || (i3 = getc( fp )) == EOF
- || (i4 = getc( fp )) == EOF) {
- fprintf( stderr, "premature eof\n" );
- exit( -1 );
- }
- x = (long)i1;
- x |= (((long)i2) << 8);
- x |= (((long)i3) << 16);
- x |= (((long)i4) << 24);
- SetCell( r, c, TOP, x );
- /* then do bottom-side */
- if ((i1 = getc( fp )) == EOF
- || (i2 = getc( fp )) == EOF
- || (i3 = getc( fp )) == EOF
- || (i4 = getc( fp )) == EOF) {
- fprintf( stderr, "premature eof\n" );
- exit( -1 );
- }
- x = (long)i1;
- x |= (((long)i2) << 8);
- x |= (((long)i3) << 16);
- x |= (((long)i4) << 24);
- SetCell( r, c, BOTTOM, x );
- }
- }
- nbytes = (Ncols * size[zoom] + 7) / 8;
- dofile( "H", H );
- dofile( "T", T );
- dofile( "B", B );
- dofile( "HT", HT );
- dofile( "HB", HB );
- dofile( "HTB", HTB );
- exit( 0 );
- }
-
- static void dofile ( p, i ) /* create a board image file */
- char *p;
- int i;
- {
- FILE *fp;
-
- printf( "producing %s image file\n", p );
- currnt = i;
- if (!(fp = fopen( p, "wb" ))) {
- fprintf( stderr, "can't open %s\n", p );
- exit( -1 );
- }
- if (style == HPLASERJET) {
- prolog( fp ); /* initial laser printer commands */
- doimage( fp ); /* create the board image */
- epilog( fp ); /* final laser printer commands */
- }
- else if (style == VECTOR)
- dovector( fp ); /* create the board image */
- else {
- fprintf( stderr, "internal error\n" );
- exit( -1 );
- }
- if (fclose( fp )) {
- fprintf( stderr, "can't close %s\n", p );
- exit( -1 );
- }
- }
-
- static void prolog ( fp ) /* output initial laser printer commands */
- register FILE *fp;
- {
- putc( 0x1B, fp ); /* <esc> */
- putc( 'E', fp ); /* reset */
- putc( 0x1B, fp ); /* <esc> */
- fprintf( fp, "&l%dO", orient ); /* set image orientation */
- putc( 0x1B, fp ); /* <esc> */
- fprintf( fp, "&a10R" ); /* cursor to row 10 */
- putc( 0x1B, fp ); /* <esc> */
- fprintf( fp, "&a10C" ); /* cursor to column 10 */
- putc( 0x1B, fp ); /* <esc> */
- fprintf( fp, "*t%dR", resol ); /* set resolution in dots per inch */
- putc( 0x1B, fp ); /* <esc> */
- fprintf( fp, "*r1A" ); /* start graphics at cursor */
- if (ferror( fp ))
- fprintf( stderr, "output error; disk might be full\n" );
- }
-
- static void epilog ( fp ) /* output final laser printer commands */
- register FILE *fp;
- {
- putc( 0x1B, fp ); /* <esc> */
- fprintf( fp, "*rB" ); /* end graphics */
- putc( 0x12, fp ); /* formfeed to eject paper */
- putc( 0x1B, fp ); /* <esc> */
- putc( 'E', fp ); /* reset */
- if (ferror( fp ))
- fprintf( stderr, "output error; disk might be full\n" );
- }
-
- static void doimage ( fp ) /* create the board image, row by column */
- FILE *fp;
- {
- register int r, c;
- int ir;
- long x, y;
-
- for (r = Nrows-1; r >= 0; r--) { /* each row */
- for (ir = size[zoom]-1; ir >= 0; ir--) { /* each scan line */
- putc( 0x1B, fp ); /* <esc> */
- fprintf( fp, "*b%dW", nbytes );
- initbit();
- for (c = 0; c < Ncols; c++) {
- x = GetCell( r, c, TOP );
- y = GetCell( r, c, BOTTOM );
- map( x, y, ir, fp );
- }
- flushbit( fp );
- }
- }
- if (ferror( fp ))
- fprintf( stderr, "output error; disk might be full\n" );
- }
-
- /* statement formats */
- static char dimstmt[] = "DIMENSION(%d.%d, %d.%d)\r\n";
- static char cirstmt[] = "CIRCLE(%d.%d, %d.%d, %d.%d)\r\n";
- static char linstmt[] = "LINE(%d.%d, %d.%d, %d.%d, %d.%d)\r\n";
-
- static void dovector ( fp ) /* create the board image, row by column */
- FILE *fp;
- {
- register int r, c;
- int r50, c50;
- long x;
-
- fprintf( fp, dimstmt, Nrows*50, 0, Ncols*50, 0 );
- for (r = 0, r50 = 0; r < Nrows; r++, r50 += 50)
- for (c = 0, c50 = 0; c < Ncols; c++, c50 += 50) {
- x = GetCell( r, c, TOP );
- if (x & HOLE) {
- if (currnt & H)
- fprintf( fp, cirstmt, r50+25, 0,
- c50+25, 0, 12, 5 );
- if (currnt & T) {
- /*
- ** NOTE: when the trace exits to a corner, we should check which of the
- ** 3 adjoining cells it actually goes into. for now, we assume it goes
- ** into the diagonal one. if this is a false assumption, the cases
- ** below for NORTHEAST, SOUTHEAST, SOUTHWEST, and NORTHWEST will require
- ** more checking before the trace() can be started.
- */
- if ((x&(HOLE_NORTH|NOT_NORTH))
- == HOLE_NORTH)
- trace( fp, r+1, c,
- TOP, FROM_SOUTH,
- r50+37, 5,
- c50+25, 0 );
- if ((x&(HOLE_NORTHEAST|NOT_NORTHEAST))
- == HOLE_NORTHEAST)
- trace( fp, r+1, c+1,
- TOP, FROM_SOUTHWEST,
- r50+33, 8388,
- c50+33, 8388 );
- if ((x&(HOLE_EAST|NOT_EAST))
- == HOLE_EAST)
- trace( fp, r, c+1,
- TOP, FROM_WEST,
- r50+25, 0,
- c50+37, 5 );
- if ((x&(HOLE_SOUTHEAST|NOT_SOUTHEAST))
- == HOLE_SOUTHEAST)
- trace( fp, r-1, c+1,
- TOP, FROM_NORTHWEST,
- r50+16, 1612,
- c50+33, 8388 );
- if ((x&(HOLE_SOUTH|NOT_SOUTH))
- == HOLE_SOUTH)
- trace( fp, r-1, c,
- TOP, FROM_NORTH,
- r50+12, 5,
- c50+25, 0 );
- if ((x&(HOLE_SOUTHWEST|NOT_SOUTHWEST))
- == HOLE_SOUTHWEST)
- trace( fp, r-1, c-1,
- TOP, FROM_NORTHEAST,
- r50+16, 1612,
- c50+16, 1612 );
- if ((x&(HOLE_WEST|NOT_WEST))
- == HOLE_WEST)
- trace( fp, r, c-1,
- TOP, FROM_EAST,
- r50+25, 0,
- c50+12, 5 );
- if ((x&(HOLE_NORTHWEST|NOT_NORTHWEST))
- == HOLE_NORTHWEST)
- trace( fp, r+1, c-1,
- TOP, FROM_SOUTHEAST,
- r50+33, 8388,
- c50+16, 1612 );
- }
- if (currnt & B) {
- x = GetCell( r, c, BOTTOM );
- if ((x&(HOLE_NORTH|NOT_NORTH))
- == HOLE_NORTH)
- trace( fp, r+1, c,
- BOTTOM,
- FROM_SOUTH,
- r50+37, 5,
- c50+25, 0 );
- if ((x&(HOLE_NORTHEAST|NOT_NORTHEAST))
- == HOLE_NORTHEAST)
- trace( fp, r+1, c+1,
- BOTTOM,
- FROM_SOUTHWEST,
- r50+33, 8388,
- c50+33, 8388 );
- if ((x&(HOLE_EAST|NOT_EAST))
- == HOLE_EAST)
- trace( fp, r, c+1,
- BOTTOM,
- FROM_WEST,
- r50+25, 0,
- c50+37, 5 );
- if ((x&(HOLE_SOUTHEAST|NOT_SOUTHEAST))
- == HOLE_SOUTHEAST)
- trace( fp, r-1, c+1,
- BOTTOM,
- FROM_NORTHWEST,
- r50+16, 1612,
- c50+33, 8388 );
- if ((x&(HOLE_SOUTH|NOT_SOUTH))
- == HOLE_SOUTH)
- trace( fp, r-1, c,
- BOTTOM,
- FROM_NORTH,
- r50+12, 5,
- c50+25, 0 );
- if ((x&(HOLE_SOUTHWEST|NOT_SOUTHWEST))
- == HOLE_SOUTHWEST)
- trace( fp, r-1, c-1,
- BOTTOM,
- FROM_NORTHEAST,
- r50+16, 1612,
- c50+16, 1612 );
- if ((x&(HOLE_WEST|NOT_WEST))
- == HOLE_WEST)
- trace( fp, r, c-1,
- BOTTOM,
- FROM_EAST,
- r50+25, 0,
- c50+12, 5 );
- if ((x&(HOLE_NORTHWEST|NOT_NORTHWEST))
- == HOLE_NORTHWEST)
- trace( fp, r+1, c-1,
- BOTTOM,
- FROM_SOUTHEAST,
- r50+33, 8388,
- c50+16, 1612 );
- }
- }
- }
- for (r = 0; r < Nrows; r++) /* reset hole-done indicator bits */
- for (c = 0; c < Ncols; c++) {
- x = GetCell( r, c, TOP );
- if (x & HOLE) {
- SetCell( r, c, TOP, x&(~NOT_ALL) );
- x = GetCell( r, c, BOTTOM );
- SetCell( r, c, BOTTOM, x&(~NOT_ALL) );
- }
- }
- }
-
- static void trace ( fp, r, c, s, d, lr, lrf, lc, lcf )
- /* draw a trace with LINE statements */
- FILE *fp;
- register int r, c;
- int s, d, lr, lrf, lc, lcf;
- {
- int r50, c50, a;
- long x;
-
- /*
- ** (r,c,s) gives the current cell; (r50,c50) maintains (r*50,c*50)
- ** so we don't have to keep doing multiplies; d gives the FROM_x
- ** direction we entered this cell from; a gives the FROM_x
- ** direction (angle) of the line currently being built;
- ** (lr.lrf,lc.lcf) gives the mil location (whole and fractional
- ** part, maintained separately so we don't have to do floating
- ** point math) of the last point connected.
- */
-
- r50 = r*50;
- c50 = c*50;
- a = d; /* angle of trace is same as initial direction */
- for (;;) { /* search for the terminating HOLE */
- x = GetCell( r, c, s );
- if (x & HOLE) { /* found it? */
- /*
- ** NOTE: we should really include a check here that the proper HOLE_x
- ** bit is turned on. for now, we assume it is.
- */
- switch (d) { /* output the last LINE */
- case FROM_NORTH:
- if (a != FROM_NORTH) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+50, 0, c50+25, 0 );
- lr = r50+50;
- lc = c50+25;
- lrf = lcf = 0;
- }
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+37, 5, c50+25, 0 );
- SetCell( r, c, s, x|NOT_NORTH );
- break;
- case FROM_NORTHEAST:
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+33, 8388, c50+33, 8388 );
- SetCell( r, c, s, x|NOT_NORTHEAST );
- break;
- case FROM_EAST:
- if (a != FROM_EAST) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50+50, 0 );
- lr = r50+25;
- lc = c50+50;
- lrf = lcf = 0;
- }
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50+37, 5 );
- SetCell( r, c, s, x|NOT_EAST );
- break;
- case FROM_SOUTHEAST:
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+16, 1612, c50+33, 8388 );
- SetCell( r, c, s, x|NOT_SOUTHEAST );
- break;
- case FROM_SOUTH:
- if (a != FROM_SOUTH) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50, 0, c50+25, 0 );
- lr = r50;
- lc = c50+25;
- lrf = lcf = 0;
- }
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+12, 5, c50+25, 0 );
- SetCell( r, c, s, x|NOT_SOUTH );
- break;
- case FROM_SOUTHWEST:
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+16, 1612, c50+16, 1612 );
- SetCell( r, c, s, x|NOT_SOUTHWEST );
- break;
- case FROM_WEST:
- if (a != FROM_WEST) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50, 0 );
- lr = r50+25;
- lc = c50;
- lrf = lcf = 0;
- }
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50+12, 5 );
- SetCell( r, c, s, x|NOT_WEST );
- break;
- case FROM_NORTHWEST:
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+33, 8388, c50+16, 1612 );
- SetCell( r, c, s, x|NOT_NORTHWEST );
- break;
- default:
- fprintf( stderr, "internal error\n" );
- exit( -1 );
- break;
- }
- return;
- }
-
- /*
- ** not a HOLE; keep walking along the trace. if the angle is
- ** still right, just move along. otherwise, output a LINE
- ** statement for any turns that are made, reset the last
- ** point connected, and go to the next cell.
- */
-
- switch (d) {
- case FROM_NORTH:
- if (x & LINE_VERTICAL) {
- if (a != FROM_NORTH) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+50, 0, c50+25, 0 );
- lr = r50+50;
- lc = c50+25;
- lrf = lcf = 0;
- a = FROM_NORTH;
- }
- r--; r50 -= 50;
- }
- else if (x & CORNER_NORTHEAST) {
- if (a != FROM_NORTHWEST) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+50, 0, c50+25, 0 );
- lr = r50+50;
- lc = c50+25;
- lrf = lcf = 0;
- a = FROM_NORTHWEST;
- }
- c++; c50 += 50;
- d = FROM_WEST;
- }
- else if (x & CORNER_NORTHWEST) {
- if (a != FROM_NORTHEAST) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+50, 0, c50+25, 0 );
- lr = r50+50;
- lc = c50+25;
- lrf = lcf = 0;
- a = FROM_NORTHEAST;
- }
- c--; c50 -= 50;
- d = FROM_EAST;
- }
- else if (x & (BENT_NtoSE | BENT_NtoSW)) {
- if (a != FROM_NORTH) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+50, 0, c50+25, 0 );
- lr = r50+50;
- lc = c50+25;
- lrf = lcf = 0;
- }
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50+25, 0 );
- lr = r50+25;
- lc = c50+25;
- lrf = lcf = 0;
- r--; r50 -= 50;
- if (x & BENT_NtoSE) {
- d = a = FROM_NORTHWEST;
- c++; c50 += 50;
- }
- else {
- d = a = FROM_NORTHEAST;
- c--; c50 -= 50;
- }
- }
- else if (x & (SHARP_NtoNE | SHARP_NtoNW)) {
- if (a != FROM_NORTH) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+50, 0, c50+25, 0 );
- lr = r50+50;
- lc = c50+25;
- lrf = lcf = 0;
- }
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50+25, 0 );
- lr = r50+25;
- lc = c50+25;
- lrf = lcf = 0;
- r++; r50 += 50;
- if (x & SHARP_NtoNE) {
- d = a = FROM_SOUTHWEST;
- c++; c50 += 50;
- }
- else {
- d = a = FROM_SOUTHEAST;
- c--; c50 -= 50;
- }
- }
- else {
- fprintf( stderr, "internal error\n" );
- exit( -1 );
- }
- break;
- case FROM_NORTHEAST:
- if (x & DIAG_NEtoSW) {
- r--; r50 -= 50;
- c--; c50 -= 50;
- }
- else if (x & (BENT_StoNE | BENT_WtoNE)) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50+25, 0 );
- lr = r50+25;
- lc = c50+25;
- lrf = lcf = 0;
- if (x & BENT_StoNE) {
- d = a = FROM_NORTH;
- r--; r50 -= 50;
- }
- else {
- d = a = FROM_EAST;
- c--; c50 -= 50;
- }
- }
- else if (x & (ANGLE_NEtoSE | ANGLE_NWtoNE)) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50+25, 0 );
- lr = r50+25;
- lc = c50+25;
- lrf = lcf = 0;
- if (x & ANGLE_NEtoSE) {
- d = a = FROM_NORTHWEST;
- r--; r50 -= 50;
- c++; c50 += 50;
- }
- else {
- d = a = FROM_SOUTHEAST;
- r++; r50 += 50;
- c--; c50 -= 50;
- }
- }
- else if (x & (SHARP_NtoNE | SHARP_EtoNE)) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50+25, 0 );
- lr = r50+25;
- lc = c50+25;
- lrf = lcf = 0;
- if (x & SHARP_NtoNE) {
- d = a = FROM_SOUTH;
- r++; r50 += 50;
- }
- else {
- d = a = FROM_WEST;
- c++; c50 += 50;
- }
- }
- else {
- fprintf( stderr, "internal error\n" );
- exit( -1 );
- }
- break;
- case FROM_EAST:
- if (x & LINE_HORIZONTAL) {
- if (a != FROM_EAST) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50+50, 0 );
- lr = r50+25;
- lc = c50+50;
- lrf = lcf = 0;
- a = FROM_EAST;
- }
- c--; c50 -= 50;
- }
- else if (x & CORNER_NORTHEAST) {
- if (a != FROM_SOUTHEAST) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50+50, 0 );
- lr = r50+25;
- lc = c50+50;
- lrf = lcf = 0;
- a = FROM_SOUTHEAST;
- }
- r++; r50 += 50;
- d = FROM_SOUTH;
- }
- else if (x & CORNER_SOUTHEAST) {
- if (a != FROM_NORTHEAST) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50+50, 0 );
- lr = r50+25;
- lc = c50+50;
- lrf = lcf = 0;
- a = FROM_NORTHEAST;
- }
- r--; r50 -= 50;
- d = FROM_NORTH;
- }
- else if (x & (BENT_EtoSW | BENT_EtoNW)) {
- if (a != FROM_EAST) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50+50, 0 );
- lr = r50+25;
- lc = c50+50;
- lrf = lcf = 0;
- }
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50+25, 0 );
- lr = r50+25;
- lc = c50+25;
- lrf = lcf = 0;
- c--; c50 -= 50;
- if (x & BENT_EtoSW) {
- d = a = FROM_NORTHEAST;
- r--; r50 -= 50;
- }
- else {
- d = a = FROM_SOUTHEAST;
- r++; r50 += 50;
- }
- }
- else if (x & (SHARP_EtoNE | SHARP_EtoSE)) {
- if (a != FROM_EAST) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50+50, 0 );
- lr = r50+25;
- lc = c50+50;
- lrf = lcf = 0;
- }
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50+25, 0 );
- lr = r50+25;
- lc = c50+25;
- lrf = lcf = 0;
- c++; c50 += 50;
- if (x & SHARP_EtoNE) {
- d = a = FROM_SOUTHWEST;
- r++; r50 += 50;
- }
- else {
- d = a = FROM_NORTHWEST;
- r--; r50 -= 50;
- }
- }
- else {
- fprintf( stderr, "internal error\n" );
- exit( -1 );
- }
- break;
- case FROM_SOUTHEAST:
- if (x & DIAG_SEtoNW) {
- r++; r50 += 50;
- c--; c50 -= 50;
- }
- else if (x & (BENT_NtoSE | BENT_WtoSE)) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50+25, 0 );
- lr = r50+25;
- lc = c50+25;
- lrf = lcf = 0;
- if (x & BENT_NtoSE) {
- d = a = FROM_SOUTH;
- r++; r50 += 50;
- }
- else {
- d = a = FROM_EAST;
- c--; c50 -= 50;
- }
- }
- else if (x & (ANGLE_NEtoSE | ANGLE_SEtoSW)) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50+25, 0 );
- lr = r50+25;
- lc = c50+25;
- lrf = lcf = 0;
- if (x & ANGLE_NEtoSE) {
- d = a = FROM_SOUTHWEST;
- r++; r50 += 50;
- c++; c50 += 50;
- }
- else {
- d = a = FROM_NORTHEAST;
- r--; r50 -= 50;
- c--; c50 -= 50;
- }
- }
- else if (x & (SHARP_EtoSE | SHARP_StoSE)) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50+25, 0 );
- lr = r50+25;
- lc = c50+25;
- lrf = lcf = 0;
- if (x & SHARP_EtoSE) {
- d = a = FROM_WEST;
- c++; c50 += 50;
- }
- else {
- d = a = FROM_NORTH;
- r--; r50 -= 50;
- }
- }
- else {
- fprintf( stderr, "internal error\n" );
- exit( -1 );
- }
- break;
- case FROM_SOUTH:
- if (x & LINE_VERTICAL) {
- if (a != FROM_SOUTH) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50, 0, c50+25, 0 );
- lr = r50;
- lc = c50+25;
- lrf = lcf = 0;
- a = FROM_SOUTH;
- }
- r++; r50 += 50;
- }
- else if (x & CORNER_SOUTHEAST) {
- if (a != FROM_SOUTHWEST) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50, 0, c50+25, 0 );
- lr = r50;
- lc = c50+25;
- lrf = lcf = 0;
- a = FROM_SOUTHWEST;
- }
- c++; c50 += 50;
- d = FROM_WEST;
- }
- else if (x & CORNER_SOUTHWEST) {
- if (a != FROM_SOUTHEAST) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50, 0, c50+25, 0 );
- lr = r50;
- lc = c50+25;
- lrf = lcf = 0;
- a = FROM_SOUTHEAST;
- }
- c--; c50 -= 50;
- d = FROM_EAST;
- }
- else if (x & (BENT_StoNE | BENT_StoNW)) {
- if (a != FROM_SOUTH) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50, 0, c50+25, 0 );
- lr = r50;
- lc = c50+25;
- lrf = lcf = 0;
- }
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50+25, 0 );
- lr = r50+25;
- lc = c50+25;
- lrf = lcf = 0;
- r++; r50 += 50;
- if (x & BENT_StoNE) {
- d = a = FROM_SOUTHWEST;
- c++; c50 += 50;
- }
- else {
- d = a = FROM_SOUTHEAST;
- c--; c50 -= 50;
- }
- }
- else if (x & (SHARP_StoSE | SHARP_StoSW)) {
- if (a != FROM_SOUTH) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50, 0, c50+25, 0 );
- lr = r50;
- lc = c50+25;
- lrf = lcf = 0;
- }
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50+25, 0 );
- lr = r50+25;
- lc = c50+25;
- lrf = lcf = 0;
- r--; r50 -= 50;
- if (x & SHARP_StoSE) {
- d = a = FROM_NORTHWEST;
- c++; c50 += 50;
- }
- else {
- d = a = FROM_NORTHEAST;
- c--; c50 -= 50;
- }
- }
- else {
- fprintf( stderr, "internal error\n" );
- exit( -1 );
- }
- break;
- case FROM_SOUTHWEST:
- if (x & DIAG_NEtoSW) {
- r++; r50 += 50;
- c++; c50 += 50;
- }
- else if (x & (BENT_NtoSW | BENT_EtoSW)) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50+25, 0 );
- lr = r50+25;
- lc = c50+25;
- lrf = lcf = 0;
- if (x & BENT_NtoSW) {
- d = a = FROM_SOUTH;
- r++; r50 += 50;
- }
- else {
- d = a = FROM_WEST;
- c++; c50 += 50;
- }
- }
- else if (x & (ANGLE_SEtoSW | ANGLE_SWtoNW)) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50+25, 0 );
- lr = r50+25;
- lc = c50+25;
- lrf = lcf = 0;
- if (x & ANGLE_SEtoSW) {
- d = a = FROM_NORTHWEST;
- r--; r50 -= 50;
- c++; c50 += 50;
- }
- else {
- d = a = FROM_SOUTHEAST;
- r++; r50 += 50;
- c--; c50 -= 50;
- }
- }
- else if (x & (SHARP_StoSW | SHARP_WtoSW)) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50+25, 0 );
- lr = r50+25;
- lc = c50+25;
- lrf = lcf = 0;
- if (x & SHARP_StoSW) {
- d = a = FROM_NORTH;
- r--; r50 -= 50;
- }
- else {
- d = a = FROM_EAST;
- c--; c50 -= 50;
- }
- }
- else {
- fprintf( stderr, "internal error\n" );
- exit( -1 );
- }
- break;
- case FROM_WEST:
- if (x & LINE_HORIZONTAL) {
- if (a != FROM_WEST) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50, 0 );
- lr = r50+25;
- lc = c50;
- lrf = lcf = 0;
- a = FROM_WEST;
- }
- c++; c50 += 50;
- }
- else if (x & CORNER_NORTHWEST) {
- if (a != FROM_SOUTHWEST) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50, 0 );
- lr = r50+25;
- lc = c50;
- lrf = lcf = 0;
- a = FROM_SOUTHWEST;
- }
- r++; r50 += 50;
- d = FROM_SOUTH;
- }
- else if (x & CORNER_SOUTHWEST) {
- if (a != FROM_NORTHWEST) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50, 0 );
- lr = r50+25;
- lc = c50;
- lrf = lcf = 0;
- a = FROM_NORTHWEST;
- }
- r--; r50 -= 50;
- d = FROM_NORTH;
- }
- else if (x & (BENT_WtoNE | BENT_WtoSE)) {
- if (a != FROM_WEST) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50, 0 );
- lr = r50+25;
- lc = c50;
- lrf = lcf = 0;
- }
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50+25, 0 );
- lr = r50+25;
- lc = c50+25;
- lrf = lcf = 0;
- c++; c50 += 50;
- if (x & BENT_WtoNE) {
- d = a = FROM_SOUTHWEST;
- r++; r50 += 50;
- }
- else {
- d = a = FROM_NORTHWEST;
- r--; r50 -= 50;
- }
- }
- else if (x & (SHARP_WtoNW | SHARP_WtoSW)) {
- if (a != FROM_WEST) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50, 0 );
- lr = r50+25;
- lc = c50;
- lrf = lcf = 0;
- }
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50+25, 0 );
- lr = r50+25;
- lc = c50+25;
- lrf = lcf = 0;
- c--; c50 -= 50;
- if (x & SHARP_WtoNW) {
- d = a = FROM_SOUTHEAST;
- r++; r50 += 50;
- }
- else {
- d = a = FROM_NORTHEAST;
- r--; r50 -= 50;
- }
- }
- else {
- fprintf( stderr, "internal error\n" );
- exit( -1 );
- }
- break;
- case FROM_NORTHWEST:
- if (x & DIAG_SEtoNW) {
- r--; r50 -= 50;
- c++; c50 += 50;
- }
- else if (x & (BENT_EtoNW | BENT_StoNW)) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50+25, 0 );
- lr = r50+25;
- lc = c50+25;
- lrf = lcf = 0;
- if (x & BENT_EtoNW) {
- d = a = FROM_WEST;
- c++; c50 += 50;
- }
- else {
- d = a = FROM_NORTH;
- r--; r50 -= 50;
- }
- }
- else if (x & (ANGLE_SWtoNW | ANGLE_NWtoNE)) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50+25, 0 );
- lr = r50+25;
- lc = c50+25;
- lrf = lcf = 0;
- if (x & ANGLE_SWtoNW) {
- d = a = FROM_NORTHEAST;
- r--; r50 -= 50;
- c--; c50 -= 50;
- }
- else {
- d = a = FROM_SOUTHWEST;
- r++; r50 += 50;
- c++; c50 += 50;
- }
- }
- else if (x & (SHARP_WtoNW | SHARP_NtoNW)) {
- fprintf( fp, linstmt,
- lr, lrf, lc, lcf,
- r50+25, 0, c50+25, 0 );
- lr = r50+25;
- lc = c50+25;
- lrf = lcf = 0;
- if (x & SHARP_WtoNW) {
- d = a = FROM_EAST;
- c--; c50 -= 50;
- }
- else {
- d = a = FROM_SOUTH;
- r++; r50 += 50;
- }
- }
- else {
- fprintf( stderr, "internal error\n" );
- exit( -1 );
- }
- break;
- default:
- fprintf( stderr, "internal error\n" );
- exit( -1 );
- break;
- }
- }
- }
-
- struct x { /* group the bit templates for an object */
- long t; /* the object type */
- char t0[ZOOM0][ZOOM0]; /* tiny zoom template */
- char t1[ZOOM1][ZOOM1]; /* small zoom template */
- char t2[ZOOM2][ZOOM2]; /* medium zoom template */
- char t3[ZOOM3][ZOOM3]; /* large zoom template */
- };
-
- extern struct x y1[]; /* hole templates */
- extern struct x y2[]; /* hole-related templates */
- extern struct x y3[]; /* non-hole-related templates */
-
- extern int z1; /* number of hole types */
- extern int z2; /* number of hole-related types */
- extern int z3; /* number of non-hole-related types */
-
- #define domap1(v) { int i; \
- for (i = 0; i < z1; i++) { \
- if (v & (y1[i].t)) { \
- if (zoom == 0) \
- bit |= y1[i].t0[ir][ic]; \
- else if (zoom == 1) \
- bit |= y1[i].t1[ir][ic]; \
- else if (zoom == 2) \
- bit |= y1[i].t2[ir][ic]; \
- else if (zoom == 3) \
- bit |= y1[i].t3[ir][ic]; \
- } \
- if (bit) \
- break; \
- } }
-
- #define domap2(v) { int i; \
- for (i = 0; i < z2; i++) { \
- if (v & (y2[i].t)) { \
- if (zoom == 0) \
- bit |= y2[i].t0[ir][ic]; \
- else if (zoom == 1) \
- bit |= y2[i].t1[ir][ic]; \
- else if (zoom == 2) \
- bit |= y2[i].t2[ir][ic]; \
- else if (zoom == 3) \
- bit |= y2[i].t3[ir][ic]; \
- } \
- if (bit) \
- break; \
- } }
-
- #define domap3(v) { int i; \
- for (i = 0; i < z3; i++) { \
- if (v & (y3[i].t)) { \
- if (zoom == 0) \
- bit |= y3[i].t0[ir][ic]; \
- else if (zoom == 1) \
- bit |= y3[i].t1[ir][ic]; \
- else if (zoom == 2) \
- bit |= y3[i].t2[ir][ic]; \
- else if (zoom == 3) \
- bit |= y3[i].t3[ir][ic]; \
- } \
- if (bit) \
- break; \
- } }
-
- static void map ( v0, v1, ir, fp ) /* map a cell to the image */
- long v0, v1;
- int ir;
- FILE *fp;
- {
- register int ic, bit;
-
- for (ic = 0; ic < size[zoom]; ic++) { /* do each scan column */
- bit = 0;
- if (v0 & HOLE) {
- if (currnt & H) /* plot holes? */
- domap1( v0 );
- if (!bit && (currnt & T)) /* plot top-side? */
- domap2( v0 );
- if (!bit && (currnt & B)) /* plot bottom-side? */
- domap2( v1 );
- }
- else {
- if (v0 && (currnt & T)) /* plot top-side? */
- domap3( v0 );
- if (!bit && v1 && (currnt & B)) /* plot bottom-side? */
- domap3( v1 );
- }
- outbit( bit, fp );
- }
- }
-
- static int shift; /* how far to shift next bit */
- static char byte; /* the byte buffer */
-
- static void initbit () { /* initialize bit output */
- byte = 0;
- shift = 7;
- }
-
- static void flushbit ( fp ) /* flush bit output */
- FILE *fp;
- {
- if (shift != 7) /* buffer empty? */
- putc( byte, fp ); /* no, output partial byte */
- }
-
- static void outbit( bit, fp ) /* output a bit using byte buffering */
- int bit;
- FILE *fp;
- {
- byte |= ((char)bit << shift);
- if (!shift) {
- putc( byte, fp );
- byte = 0;
- shift = 7;
- }
- else
- shift--;
- }
-