[net.math.stat] PostScript

bates@uwstat.UUCP (08/22/85)

The `csh' archive which follows contains a first cut at a PostScript(tm)
device driver for S. There are many things that we hope to modify and
improve in this but, as it stands, it can still produce some very nice
plots. We have had it in use for a couple of months with good results.

PostScript(tm) is a page description language developed by Adobe
Systems. It is incorporated in the Apple LaserWriter(tm) as well as
other laser printers and some phototypesetters. Although it is not
required for the use of this driver, the TranScript(tm) software from
Adobe Systems is usually used to provide the print filters for a
PostScript(tm) printer from a 4.2BSD system.

The biggest difficulty with this driver as it stands is that the "*"
character, which is the default plot character, is rendered in the
Helvetica(tm) font and that asterix is in the superscript position. That
means that, if you make a scatter plot with the `plot' function, the
asterixes are all a little bit too high. The best solution is to use
`plot' with `type="n"' and use `points' with `mark= ' to put the points
on the plot.

A typical sequence to install this driver is to log in as the S
maintainer and

cd $SHOME/slocal
mkdir ps
S FUNCTION -d pscript pscript.i
<unbundle the csh archive>
S MAKE pscript
S MAKE dev.pscript
S NEWDOC pscript

     PostScript and TranScript are trademarks of Adobe Systems
     LaserWriter is a trademark of Apple Computer
     Helvetica is a registered trademark of Allied Corp.

# to unbundle, csh this file
echo pscript.d
sed 's/^X//' >pscript.d <<'End of pscript.d'
X.BG
X.FN pscript
X.TL
Xpscript: Device driver for PostScript\(tm printers
X.CS
Xpscript(width, height, horizo)
X.PP
X.AG width
XWidth of plotting region in inches - defaults to 8
X.AG height
XHeight of plotting region in inches - defaults to 10
X.AG horizo
XChange to horizontal orientation - currently inoperative
X.PP
XThis function identifies the device driver which produces a file of
Xcommands in the PostScript\(tm language to produce the plots.
XThis file is named "PostScript.out" and would usually be sent directly
Xto the PostScript\(tm printer via a command such as
X.PP
Xlpr -Pps PostScript.out
X.PP
XNote that `pscript' appends to the file "PostScript.out" so it is a good
Xidea to remove it after you have printed it.
XA device must be specified before any graphics functions can be used.
X.EX
Xpscript
Xplot(hstart)
Xq	# exit from S
X
Xlpr -Pps -h Po*
Xrm Po*
X.KW graphics
X.WR
'End of pscript.d'
echo pscript.i
sed 's/^X//' >pscript.i <<'End of pscript.i'
X# PostScript device driver function
XFUNCTION pscript(
X	width	/REAL,1,7.5/
X	height	/REAL,1,10.0/
X	horizo	/LGL,1,FALSE/
X	)
XSTATIC(logical streq)
XSTRUCTURE(parms/REAL,3/)	# w,h,vertical
X
Xif(streq(TEXT(FNAME),TSTRING(pscripth))|| horizo){
X    horizo = TRUE
X    if(MISSING(width)) width=10
X    else if (width > 11) FATAL(Width cannot exceed 11 inches)
X    if(MISSING(height)) height=7.5
X    else if (height > 8.5) FATAL(Height cannot exceed 8.5 inches)
X}
Xelse {
X    if (width > 8.5) FATAL(Width cannot exceed 8.5 inches)
X    if (height > 11) FATAL(Height cannot exceed 11 inches)
X}
Xparms[1] = width
Xparms[2] = height
Xif(horizo) parms[3]=1; else parms[3]=0
X
XDEVICE_DRIVER
XRETURN(parms)
XEND
'End of pscript.i'
echo ps/ps.pro
sed 's/^X//' >ps/ps.pro <<'End of ps/ps.pro'
X/M {moveto} def
X/L {lineto} def
X/oldcex 1 def
X/coffset 140 0.375 mul def
X
X/Stext
X  { /pos exch def
X    /srot exch def
X    /cex exch def
X    /ypos exch def
X    /xpos exch def
X    /str exch def
X    
X    xpos ypos moveto
X    oldcex cex ne
X      { currentfont cex oldcex div scalefont setfont
X        /coffset  coffset cex oldcex div mul store
X        /oldcex cex store
X      } if
X    gsave
X	srot rotate
X	str stringwidth pop neg
X	pos 0.5 eq
X	    { 2 div }
X	    { pos 0.5 lt
X	        { pop 0 }
X	      if }
X	ifelse
X	coffset neg rmoveto
X	str show
X    grestore
X  } store
X
X/Schar
X  { /cex exch def
X    /str exch def
X
X    oldcex cex ne
X      { currentfont cex oldcex div scalefont setfont
X        /coffset  coffset cex oldcex div mul store
X        /oldcex cex store
X      } if
X    str stringwidth pop neg 2 div coffset neg rmoveto
X    str show
X  }  store
X
X0.1 0.1 scale	% this version uses integer coordinates at 1/10's of a point
X1 setlinecap 1 setlinejoin
X/Helvetica findfont 140 scalefont setfont % default font is 14 pt. Helvetica
X/oldcex 1 def
X/coffset 140 0.375 mul def
'End of ps/ps.pro'
echo pscriptsource/pscplot.C
sed 's/^X//' >pscriptsource/pscplot.C <<'End of pscriptsource/pscplot.C'
X/*   S device driver for PostScript printers	*/
X#include <stdio.h>
X#include <strings.h>
X
Xchar *strcat();
X
Xdefine(`PSPRO',`"/usr3/s/slocal/ps/ps.pro"')
X
Xextern float    F77_COM(bgrp)[];/* graphical parameters */
Xdefine(`am',`F77_COM(bgrp)[$1-1]')
Xint moved=0;
Xchar *dash_patterns[] = {
X         "[120 40]",
X         "[]",
X         "[10 70]",
X         "[40 40]",
X         "[80 40]",
X         "[130 30]",
X         "[160 20 20 20]",
X         "[80 20 20 20]",
X         "[10 130]",
X         "[60 50]"
X};
X    
Xint widths[] = { 1, 5, 10, 15, 20, 25 };
X
XF77_SUB(zparmz) (par, n)
Xfloat   par[];
Xlong   *n;
X{
X    int     i;
X    FILE *fp, *fopen();
X    char c;
X
X    for (i = 1; i <= 39; i++)
X	am(i) = 0.0;
X
X    am(20) = 80.0;		/* char size in rasters (tenths of a
X				   point)	 */
X    am(21) = 140.0;
X
X    am(22) = (8.5 - *par) * 360.0;	/* x limits in rasters	 */
X    am(23) = (8.5 + *par) * 360.0;
X
X    am(24) = (11.0 - par[1]) * 360.0;	/* y limits in rasters	 */
X    am(25) = (11.0 + par[1]) * 360.0;
X
X    am(26) = 0.5;		/* character offset	 */
X    am(27) = 0.5;
X
X    am(28) = 1.0 / 720;	/* raster size in inches - raster is 1/10
X				   point	 */
X    am(29) = am(28);
X
X    am(30) = -423;		/* device code number - a magic number
X				   (same as `pic' device) to allow
X				   batch use				*/
X    am(31) = 1;
X    am(1) = 1;
X
X    freopen("PostScript.out","a",stdout);
X    printf ("%%!   PostScript from S\n");/* initialize device	 */
X    if ((fp = fopen(strcat("SHOME","/slocal/ps/ps.pro"),"r")) == NULL)
X        FATAL(Unable to open PostScript procedures file)
X    while (EOF != (c = getc(fp)))	/* copy PostScript procedures */
X	putchar(c);
X    F77_SUB(zejecz) ();
X}
X
XF77_SUB(zseekz) (ix, iy)
Xlong int   *ix,
X           *iy;
X{
X    static float    line_type = -1,
X                    line_width = -1;
X
X    moved++;
X    if (line_type != am(8)) {	/* set line type if changed	 */
X	line_type = am(8);
X	printf ("%s 0 setdash\n",dash_patterns[((int) line_type) % 10]);
X    };
X    
X    if (line_width != am(10)) {	/* set line width if changed	*/
X	line_width = am(10);
X	printf ("%d setlinewidth\n",widths[((int) line_width) % 5]);
X    };
X
X    printf ("%d %d M\n", *ix, *iy);
X}
X
XF77_SUB(zlinez) (ix, iy)
Xlong int   *ix,
X           *iy;
X{
X    printf ("%d %d L\n", *ix, *iy);
X}
X
XF77_SUB(zptchz) (ich, crot)
Xchar   *ich;
Xfloat  *crot;
X{
X    printf ("(%c) %g Schar\n", *ich, am(18)/am(89));/* print the character */
X}
X
XF77_SUB(zejecz) () {
X    if (moved)
X        printf ("copypage erasepage\n");
X}
X
XF77_SUB(zflshz) () {
X    printf ("stroke\n");
X    fflush (stdout);
X}
X
XF77_SUB(zwrapz) () {
X    printf ("showpage\n");
X    fflush (stdout);
X}
X
XF77_SUB(ztextz) (xx, yy, buf, n, pos, m)
Xfloat *xx, *yy, *pos;
Xchar buf[];
Xint *n, m;
X{
X    int i;
X    
X    if (*n <= 0) {
X        F77_SUB(zejecz) ();
X        F77_SUB(zerrpz) ("ztextz","Number of characters not positive",6);
X    }
X    putchar('(');
X    for (i = *n; i--; buf++) {
X	switch (*buf) {
X	    case '(':
X	    case ')':
X	    	putchar('\\');
X	}
X	putchar(*buf);
X    }
X    printf ("\) %g %g %g %g %g Stext\n", *xx * am(37) + am(36),
X	*yy * am(39) + am(38), am(18)/am(89), am(48), *pos);
X    moved++;
X}
'End of pscriptsource/pscplot.C'
-- 

Doug Bates @ wisconsin
ARPA:	bates@wisc-stat.arpa
	bates@uwisc   (if you have the old host table)
UUCP:	...!{allegra,heurikon,ihnp4,seismo,sfwin,ucbvax,uwm-evax}!uwvax!bates