home *** CD-ROM | disk | FTP | other *** search
- Subject: v11i049: Tektronix4014 to PostScript filter
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rs@uunet.UU.NET
-
- Submitted-by: Michael S. Fischbein <msf@ames-nas.arpa>
- Posting-number: Volume 11, Issue 49
- Archive-name: tek2ps
-
- Here's my first contribution to the wonderful world of public domain source
- codes, with a tip of the hat to the GNU Manifesto.
-
- I've used several of the postings, so I thought I'd deliver this small piece
- up to the net. We have several plot programs that have been developed or
- customized over the years, but they ALL support 4014s. So, we now have a
- fast way to get good quality hardcopy. Hope some other people can use it
-
- Just thought I'd explain one code peculiarity: the use of fprintf(stdout,....
- throughout is because I was originally going to add a -o outputfile option.
- Redirecting stdout seemed a better choice once it was written.
- mike
-
- # This is a shell archive. Remove anything before this line,
- # then unpack it by saving it in a file and typing "sh file".
- #
- # Contents: Makefile README pstek.pro tek.h tek2ps.c tek2ps.doc
-
- echo x - Makefile
- sed 's/^@//' > "Makefile" <<'@//E*O*F Makefile//'
- # %W% Makefile
- CFLAGS=-g
-
- OBJ=tek2ps.o
-
- all: tek2ps
-
- tek2ps: ${OBJ} tek.h
- cc ${CFLAGS} -o $@ ${OBJ}
-
- @//E*O*F Makefile//
-
- echo x - README
- sed 's/^@//' > "README" <<'@//E*O*F README//'
- This program will filter tektronix style plots to postscript output,
- letting you use your laserprinter instead of the thermal printer that
- tektronix has been selling since the dark ages.
-
- I haven't been able to really test the defocussed Z axis stuff (no plot
- programs that we have use it).
-
- I have put as much as possible into the prolog file so a user can fairly
- easily change the defaults I like to those he or she likes. The tough
- part about figuring out how this works is understanding the Tek addressing
- schemes. Other than that, it is pretty simple. There is one `undocumented'
- flag: -d, which enables more verbose messages when an otherwise ignored
- character is encountered. Usually, these are padding characters (4010s
- are very slow by modern standards).
-
- BE SURE TO EDIT THE PROGRAM (tek2ps.c, find def_pro) AND DOCUMENTATION
- (tek2ps.doc, about the tenth line) to put the correct location
- for the default prolog file in!
-
- Any corrections or additions? Let me know at:
-
- Michael Fischbein msf@prandtl.arpa
- msf@prandtl.arc.nasa.gov
- ...!seismo!decuac!csmunix!icase!msf
-
- @//E*O*F README//
-
- echo x - pstek.pro
- sed 's/^@//' > "pstek.pro" <<'@//E*O*F pstek.pro//'
- %!PS-Adobe-1.0
- %%DocumentFonts: Courier
- %%Title: pstek prolog file, version 1.0 @(#)pstek.pro 1.10
- %%Creator: Michael Fischbein
- %% Copyright 1987 Michael Fischbein. Commercial reproduction prohibited;
- %% non-profit reproduction and distribution encouraged.
- %%CreationDate: %?% 5 June 1987
- %%For: tektronics-to-PS converter
- %%BoundingBox: 40 40 540 540
- %%EndComments
-
- % Font definitions (make 3/4 functions to avoid scaling if not needed)
- /FntH /Courier findfont 80 scalefont def
- /DFntL { /FntL /Courier findfont 73.4 scalefont def } def
- /DFntM { /FntM /Courier findfont 50.2 scalefont def } def
- /DFntS { /FntS /Courier findfont 44 scalefont def } def
-
- % tektronix line styles
- /NV { [] 0 setdash } def % normal vectors
- /DV { [8] 0 setdash } def % dotted vectors
- /DDV { [8 8 32 8] 0 setdash } def % dot-dash vectors
- /SDV { [32 8] 0 setdash } def % short-dash vectors
- /LDV { [64 8] 0 setdash } def % long-dash vectors
-
- % Defocussed Z axis and Focussed Z axis
- /DZ { .5 setgray } def
- /FZ { 0 setgray } def
-
- /PR % char x y -> - prints character
- { moveto show } def
-
- /NP % - -> - new page
- % change default scale and orentation to match tek's
- { 572 40 translate % leave a border
- 90 rotate
- % .71707 .692308 scale % 0-1023X, 0-780Y
- .1730769 .17626953 scale %0-4096X, 0-3120Y
- } def
-
- /DP % tsizey -> - erase and home
- { clippath 1 setgray fill
- 0 setgray
- 0 exch moveto
- } def
-
- FntH setfont
-
- NP
-
- @//E*O*F pstek.pro//
-
- echo x - tek.h
- sed 's/^@//' > "tek.h" <<'@//E*O*F tek.h//'
- /* t2ps header file @(#)tek.h 1.10 (Copyright) Michael Fischbein */
- /* Copyright 1987 Michael Fischbein. Commercial reproduction prohibited; */
- /* non-profit reproduction and distribution encouraged. */
- #define XDIM 4096
- #define YDIM 3120
-
- #define FALSE 0
- #define TRUE (~FALSE)
-
- /* 4014 modes */
- #define ALPHA 0
- #define GRAPH 1
- #define INCRE 2
- #define LCEMD 3
- #define PTPLT 4
-
- /* type sizes (char/line, or lines/page) (for 12bit) */
- #define CHUGEX 55
- #define CLARGEX 51
- #define CMEDX 34
- #define CSMALLX 31
- #define CHUGEY 89
- #define CLARGEY 82
- #define CMEDY 54
- #define CSMALLY 49
-
- /* ASCII */
- #define NUL 0
- #define SOH 1
- #define STX 2
- #define ETX 3
- #define EOT 4
- #define ENQ 5
- #define ACK 6
- #define BEL 7
- #define BS 8
- #define HT 9
- #define LF 10
- #define VT 11
- #define FF 12
- #define NL 13
- #define CR 13
- #define SO 14
- #define SI 15
- #define DLE 16
- #define DC1 17
- #define DC2 18
- #define DC3 19
- #define DC4 20
- #define NAK 21
- #define SYN 22
- #define ETB 23
- #define CAN 24
- #define EM 25
- #define SUB 26
- #define ESC 27
- #define FS 28
- #define GS 29
- #define RS 30
- #define US 31
- #define SPACE 32
- #define DEL 127
-
- @//E*O*F tek.h//
-
- echo x - tek2ps.c
- sed 's/^@//' > "tek2ps.c" <<'@//E*O*F tek2ps.c//'
- #include <stdio.h>
- #include <ctype.h>
- #include "tek.h"
-
- extern char *optarg;
- extern int optind;
- extern double atof();
-
- /* output filter for tektronics 4010-graphics files to generate postscript
- * files. This does a simple-minded byte by byte translation to predefined
- * PS routines, contained in a prolog file.
- * Defaults:
- * input: stdin
- * output: stdout
- * prolog: ~msf/tek2ps/pstek.pro
- */
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- #ifndef lint
- static char sccsid[]=" @(#)t2p.c 1.10 tek2ps (Copyright) M. Fischbein Commercial reproduction prohibited; non-profit reproduction and distribution encouraged.";
- #endif
- static char def_pro[]="/mnt/cmb/msf/tek2ps/pstek.pro";
- char *pro_fn = def_pro;
- FILE *pro_fp, *infile = stdin;
- int c, mode=ALPHA, tsizex=CHUGEX, tsizey=CHUGEY, oldmode;
- int cx=0, cy=YDIM-CHUGEY, leftmargin=0;
- int used_large=FALSE, used_med=FALSE, used_small=FALSE;
- int dark_vector, HiX=0, HiY=0, LoY=0, LoX=0, BX=0, BY=0;
- int gotLoY=FALSE, debug=FALSE, beamon, pr_on_er=FALSE;
- double scale_factor=1.0;
-
- /* first, parse command line */
- while ((c = getopt (argc, argv, "s:p:de")) != EOF) {
- switch (c) {
- case 'p' : /* use custom prolog */
- pro_fn = optarg;
- break;
-
- case 'd' : /* toggle debugging */
- if (debug) {
- debug = FALSE;
- } else {
- debug = TRUE;
- }
- break;
-
- case 'e': /* turn on print-before-erase */
- /* and erase-after-print */
- pr_on_er = TRUE;
- break;
-
- case 's': /* set scale option */
- scale_factor = atof(optarg)/100.;
- break;
- default:
- fprintf(stderr, "Usage: %s [-p prologfile] [-de] [input]\n", argv[0]);
-
- }
- }
-
- /* next, copy the prolog file */
- if( (pro_fp = fopen(pro_fn, "r")) == NULL) {
- fprintf(stderr, "Can't open prolog file %s\n", pro_fn);
- exit(1);
- }
- while ((c = getc(pro_fp)) != EOF) {
- putc((char) c, stdout);
- }
- fclose(pro_fp);
-
- /* check for named file (loop if more than one) */
- do { /* should indent here */
- if (optind < argc) {
- if ((infile = fopen( argv[optind], "r")) == NULL) {
- fprintf(stderr, "Can't open input file %s\n", argv[optind]);
- exit(1);
- }
- }
- /* check for scale factor */
- if (scale_factor != 1.0) { /* I know floating pt equality is
- * a bad idea, but if the option is not
- * present I explicity initialize to
- * 1.0, so the bit pattern should be
- * identical portably
- */
- fprintf(stdout,"%f %f scale\n", scale_factor, scale_factor);
- }
-
- /* Now, read a byte and figure out what to do about it */
- while ((c = getc(infile)) != EOF) { /* should indent below */
- switch (mode) {
- case ALPHA:
- if ( isgraph((char) c) ) { /* normal printing char */
- /* put char at current position */
- fprintf(stdout,"(%c) %d %d PR\n", (char) c, cx, cy);
- /* increment current postion, wrt type size */
- if ((cx += tsizex) > XDIM) {
- /* new line or margin */
- if((cy -= tsizey) < 0) {
- cy = YDIM - tsizey;
- leftmargin = leftmargin ? 0 : XDIM/2;
- }
- cx = leftmargin;
- }
- } else { /* isn't normal printing character */
- switch (c) {
- case ( HT ):
- case ( SPACE ):
- if ((cx += tsizex) > XDIM) {
- /* new line or margin */
- if((cy -= tsizey) < 0) {
- cy = YDIM - tsizey;
- leftmargin = leftmargin ? 0 : XDIM/2;
- }
- cx = leftmargin;
- }
- break;
-
- case ( CR ):
- case ( LF ):
- if ((cy -= tsizey) < 0) {
- cy = YDIM - tsizey;
- leftmargin = leftmargin ? 0 : XDIM/2;
- }
- cx = leftmargin;
- break;
-
- case ( BS ):
- if ((cx -= tsizex) < 0) {
- cx = XDIM;
- }
- break;
-
- case ( VT ):
- if ((cy += tsizey) > YDIM) {
- cy = 0;
- }
- break;
-
- case ( GS ):
- mode = GRAPH;
- dark_vector = TRUE;
- break;
-
- case ( RS ):
- mode = INCRE;
- break;
-
- case ( FS ):
- mode = PTPLT;
- break;
-
- case ( US ): /* put in ALPHA mode, already there */
- case ( BEL ):
- case ( SYN ): /* padding character, ignore*/
- case ( NUL ): /* padding character, ignore*/
- break;
-
- case ( ESC ):
- oldmode = ALPHA;
- mode = LCEMD;
- break;
-
- default :
- if (debug) fprintf(stderr, "Unknown ALPHA mode character 0x%02x\n", c);
- break;
- } /* end of switch on non-printing char in ALPHA mode */
- } /* end of printing vs non-printing char in ALPHA mode */
- break; /* end of ALPHA mode */
-
- case PTPLT:
- case GRAPH:
- if ( (char) c > US ) { /* first, handle vector case */
- if( (char) c < '@') { /* High byte */
- if (gotLoY) { /* must be HiX */
- HiX = ((char) c & 0x1f) << 7;
- } else { /* must be HiY */
- HiY = ((char) c & 0x1f) << 7;
- }
- } else if ( (char) c < '`') { /* Lo X: plot */
- gotLoY = FALSE;
- LoX = (c & 0x1f) << 2;
- /* now actually do a plot */
- if (dark_vector) {
- dark_vector = FALSE;
- cx = HiX + LoX + BX;
- cy = HiY + LoY + BY;
- fprintf(stdout,"%d %d moveto\n",cx, cy);
- } else { /* draw the line */
- cx = HiX + LoX + BX;
- cy = HiY + LoY + BY;
- if (mode == GRAPH) {
- fprintf(stdout,"%d %d lineto stroke %d %d moveto\n", cx, cy, cx, cy);
- } else { /* mode == PTPLT */
- fprintf(stdout,"%d %d moveto %d %d 1 0 360 arc\n", cx, cy, cx, cy);
- }
- }
- } else { /* Lo Y or extra byte */
- if (gotLoY) { /* previous LoY => extra byte */
- BX = (LoY & 0x0c) >> 2;
- BY = (LoY & 0x30) >> 4;
- LoY = (c & 0x1f) << 2;
- /* gotLoY stays TRUE */
- } else { /* assume is LoY */
- LoY = (c & 0x1f) << 2;
- gotLoY = TRUE;
- }
- }
- } else /* end of GRAPH mode vector address parsing*/
- /* so, it isn't a vector address */
- switch ( c ) {
- case ( NUL ): /* padding */
- case ( SYN ): /* padding */
- case ( BEL ): /* ignore */
- break;
-
- case ( LF ):
- cy -= tsizey;
- fprintf(stdout, "%d %d moveto\n", cx, cy);
- break;
-
- case ( CR ):
- mode = ALPHA;
- leftmargin = 0;
- break;
-
- case ( RS ):
- mode = INCRE;
- break;
-
- case ( FS ):
- fprintf(stderr,"special point plot not implemented\n");
- break;
-
- case ( GS ):
- dark_vector = TRUE;
- break;
-
- case ( US ):
- mode = ALPHA;
- break;
-
- case ( ESC ):
- oldmode = GRAPH;
- mode = LCEMD;
- break;
-
- default :
- if (debug) fprintf(stderr, "Unknown GRAPH mode character 0x%02x\n", c);
- break;
- } /* end of switch on non-vector char in GRAPH mode */
- break; /* end of GRAPH mode */
-
- case INCRE:
- /* could do with bit masking and check for control, */
- /* but this is is simpler. (Let the compiler work). */
- switch ( c ) {
- case ( 32 ):
- fprintf(stdout,"stroke %d %d moveto\n", cx, cy);
- beamon = FALSE;
- break;
-
- case ( 80 ):
- fprintf(stdout,"%d %d moveto\n", cx, cy);
- beamon = TRUE;
- break;
-
- case ( 68 ): /* N */
- if (++cy > YDIM) cy = YDIM;
- if (beamon) fprintf(stdout,"%d %d lineto\n", cx, cy);
- break;
-
- case ( 69 ): /* NE */
- if (++cy > YDIM) cy = YDIM;
- if (++cx > XDIM) cx = XDIM;
- if (beamon) fprintf(stdout,"%d %d lineto\n", cx, cy);
- break;
-
- case ( 65 ): /* E */
- if (++cx > XDIM) cx = XDIM;
- if (beamon) fprintf(stdout,"%d %d lineto\n", cx, cy);
- break;
-
- case ( 73 ): /* SE */
- if (--cy < 0) cy = 0;
- if (++cx > XDIM) cx = XDIM;
- if (beamon) fprintf(stdout,"%d %d lineto\n", cx, cy);
- break;
-
- case ( 72 ): /* S */
- if (--cy < 0) cy = 0;
- if (beamon) fprintf(stdout,"%d %d lineto\n", cx, cy);
- break;
-
- case ( 74 ): /* SW */
- if (--cy < 0) cy = 0;
- if (--cx < 0) cx = 0;
- if (beamon) fprintf(stdout,"%d %d lineto\n", cx, cy);
- break;
-
- case ( 66 ): /* W */
- if (--cx < 0) cx = 0;
- if (beamon) fprintf(stdout,"%d %d lineto\n", cx, cy);
- break;
-
- case ( 70 ): /* NW */
- if (++cy > YDIM) cy = YDIM;
- if (--cx < 0) cx = 0;
- if (beamon) fprintf(stdout,"%d %d lineto\n", cx, cy);
- break;
-
- case ( ESC ):
- if (beamon) fprintf(stdout,"stroke %d %d moveto\n", cx, cy);
- oldmode = INCRE;
- mode = LCEMD;
- break;
-
- case ( FS ):
- if (beamon) fprintf(stdout,"stroke %d %d moveto\n", cx, cy);
- mode = PTPLT;
- break;
-
- case ( GS ):
- if (beamon) fprintf(stdout,"stroke %d %d moveto\n", cx, cy);
- mode = GRAPH;
- dark_vector = TRUE;
- break;
-
- case ( RS ):
- break;
-
- case ( US ):
- if (beamon) fprintf(stdout,"stroke %d %d moveto\n", cx, cy);
- mode = ALPHA;
- break;
-
- default:
- if (debug) fprintf(stderr,"Unknown incremental mode character 0x%02x\n", c);
- break;
- } /* end of INCR switch on c */
- break; /* end of INCREmental mode */
-
- case LCEMD:
- if ((c > 95) && (c < 117)) {
- /* set Z axis */
- if ((char) c & 0x08) {
- fprintf(stdout,"DZ\n");
- } else {
- fprintf(stdout,"FZ\n");
- }
- /* set vector type */
- switch ((char) c & 0x07) {
- case 0: /* normal vectors */
- fprintf(stdout,"NV\n");
- break;
-
- case 1: /* dotted vectors */
- fprintf(stdout,"DV\n");
- break;
-
- case 2: /* dot-dash vectors */
- fprintf(stdout,"DDV\n");
- break;
-
- case 3: /* short-dash vectors */
- fprintf(stdout,"SDV\n");
- break;
-
- case 4: /* long-dash vectors */
- fprintf(stdout,"LDV\n");
- break;
-
- default: /* error */
- if (debug) fprintf(stderr,"Unknown beam selector 0x%02x\n", (char) c);
- break;
- }
- } else {
- switch ( c ) {
- case ( FF ): /* erase */
- if (pr_on_er) {
- fprintf(stdout,"showpage\nNP\n");
- if (scale_factor != 1.0) {
- fprintf(stdout,"%f %f scale\n", scale_factor, scale_factor);
- }
- }
- fprintf(stdout, "%d DP\n", tsizey);
- cx = 0; cy = YDIM - tsizey;
- break;
-
- case ( '8' ):
- /* default size */
- fprintf(stdout, "FntH setfont\n");
- tsizex = CHUGEX; tsizey = CHUGEY;
- break;
-
- case ( '9' ):
- if (! used_large ) {
- used_large = TRUE;
- fprintf(stdout,"DFntL\n");
- }
- fprintf(stdout, "FntL setfont\n");
- tsizex = CLARGEX; tsizey = CLARGEY;
- break;
-
- case ( ':' ):
- tsizex = CMEDX; tsizey = CMEDY;
- if (! used_med ) {
- used_med = TRUE;
- fprintf(stdout,"DFntM\n");
- }
- fprintf(stdout, "FntM setfont\n");
- break;
-
- case ( ';' ):
- tsizex = CSMALLX; tsizey = CSMALLY;
- if (! used_small ) {
- used_small = TRUE;
- fprintf(stdout,"DFntS\n");
- }
- fprintf(stdout, "FntS setfont\n");
- break;
-
- case ( BS ):
- if ((cx -= tsizex) < 0) {
- cx = XDIM;
- }
- break;
-
- case ( HT ):
- case ( SPACE ):
- if ((cx += tsizex) > XDIM) {
- /* new line or margin */
- if((cy -= tsizey) < 0) {
- cy = YDIM - tsizey;
- leftmargin = leftmargin ? 0 : XDIM/2;
- }
- cx = leftmargin;
- }
- break;
-
- case ( VT ):
- if ((cy += tsizey) > YDIM) {
- cy = 0;
- }
- break;
-
- case ( GS ):
- mode = GRAPH;
- dark_vector = TRUE;
- break;
-
- case ( LF ):
- case ( CR ):
- case ( DEL ):
- case ( NUL ):
- case ( ESC ):
- case ( BEL ):
- case ( SYN ):
- ungetc( (char) ESC, infile);
- break;
-
- case ( ETB ): /* make copy: print & start new page */
- if (pr_on_er) {
- fprintf(stdout, "showpage\nNP\n");
- if (scale_factor != 1.0) {
- fprintf(stdout,"%f %f scale\n", scale_factor, scale_factor);
- }
- cx = 0; cy = YDIM - tsizey;
- } else {
- fprintf(stdout, "copypage\n");
- }
- break;
-
- case ( SO ):
- case ( SI ):
- if (debug) fprintf(stderr, "No alternate character set implemented\n");
- break;
-
- case ( CAN ):
- case ( SUB ):
- case ( ENQ ):
- if (debug) fprintf(stderr, "GIN and BYPASS modes not implemented\n");
- break;
-
- case ( '?' ):
- ungetc( (char) DEL, infile);
- break;
-
- default :
- if (debug) fprintf(stderr, "Unknown LCE mode character 0x%02x ignored\n", c);
- break;
- } /* end of LCE mode switch */
- }
- mode = oldmode;
- break;
-
- default:
- if (debug) fprintf(stderr, "Unknown major mode %d\n", mode);
- break;
- } /* end of mode switch */
- } /* end of main input loop */
- fprintf(stdout,"showpage\n");
- } while ( ++optind < argc );
- }
-
- @//E*O*F tek2ps.c//
-
- echo x - tek2ps.doc
- sed 's/^@//' > "tek2ps.doc" <<'@//E*O*F tek2ps.doc//'
- @.EV
- @.T1 tek2ps 1
- @.SH NAME
- tek2ps \- convert Tektronix\*R 4014 commands to PostScript\*R
- @.SH SYNTAX
- tek2ps [-p \fIprologfile\fR] [-e] [-s \fIscale] files
- @.SH OPTIONS
- @.IP -p
- will use the named prologfile instead of the default (currently
- /mnt/cmb/msf/tek2ps/tekps.pro).
- @.IP -e
- will make `erase' (ESC FF) and `hardcopy' (ESC ETB) synonymous: each will
- print the current page and then erase it. The default will erase without
- printing or print without erasing.
- @.IP -s
- will scale the entire plot by the per centage specified. The default maps
- the Tektronix screen to an 8.5 x 11 inch sheet of paper.
- @.SH DESCRIPTION
- @.PP
- Tek2ps will take any output designed to be displayed on a Tektronix 4014
- terminal and translate it to PostScript suitable for sending to any PostScript
- device. Some manual editing will probably be required if the PostScript
- is to be included in another file. Tek2ps supports 10 and 12-bit addressing
- modes, incremental plots, and defocussed Z axis. It does
- @.I not
- support crosshair (GIN) mode or special point plot (6-bit greyscale).
- @.PP
- Multiple
- @.I files
- may be specified; if none are listed standard input is read. Output is to
- standard output.
- @.SH EXAMPLE
- plot -T4014 myplot | tek2ps | lpr -Plw
- @.SH SPECIAL CONSIDERATIONS
- @.PP
- If you place multiple screens in a single file, you must either use the
- hardcopy command followed by an erase to prevent overwriting, or the
- -e option.
- @.SH FILES
- /mnt/cmb/msf/tek2ps/tekps.pro
- @.SH SEE ALSO
- graph(1), plot(1)
- @.SH BUGS
- Tek2ps will not support crosshair (GIN) mode or special point plot
- (6-bit greyscale).
- @.SH AUTHOR
- Michael Fischbein
-
- @//E*O*F tek2ps.doc//
-
- exit 0
-