plt - Software for 2D Plots 2.5

File: <base>/plt/classic/lw.c (7,898 bytes)
/* 	lw.c		Paul Albrecht		July 1987
 
	Copyright (C) Paul Albrecht 1988.  All rights reserved.

	Last Update:	13 June 1995 (GBM)
	EMACS_MODES:	tabstop=4

	Plot drivers for a the Apple LaserWriter.  The plotting space
	for the laser writer is always the same number (300*2) of units
	per inch.  This is done so that the line width and font shapes
	are not changed in size compressed in one dimension.  This code
	needs the prolog file pslw.pro.

	The paths are defined with M (move) and N (next) and stroked
	with L (line) or F (filled region).
*/

#include	"plt.h"
#include	"plot.h"

static void sendstring();
static void flushpath();
static void PTERMInit();
static void setfont();
static void linewidth();
static void linemod();
static void setgray();

#define		MAXPATH		1475	/* Laser Writer can't handle 1500 */

static	Ptype	oldx, oldy;
static	long	npath;


openpl()
{
	npath = 0;
}

closepl()
{
	flushpath();
	fflush( stdout );
}

erase() {
}

space( x0, y0, x1, y1 )
Ptype	x0, y0, x1, y1;
{
	printf( "%.5lg %.5lg %.5lg %.5lg %.5lg ", fscl, xorig, yorig, xorig+xdim, yorig+ydim );
	printf("%ld %ld %ld %ld WDEF\n", (long)x0, (long)y0, (long)x1, (long)y1);
	setfont( DEFAULT_FONT, (double)DEFAULT_PS );
}

label( lbl )
char	*lbl;
{
	sendstring( lbl );
	printf( " show\n" );
	npath = 0;
}

line( x0, y0, x1, y1 )
Ptype	x0, y0, x1, y1;
{
	move( x1, y1 );
	printf( "%ld %ld L\n", (long)(x0-oldx), (long)(y0-oldy) );
	npath = 0;
}

move( x, y )
Ptype	x, y;
{
	flushpath();
	printf( "%ld %ld M\n", (long)x, (long)y );
	oldx = x;
	oldy = y;
	npath = 1;
}

cont( x, y )
Ptype	x, y;
{
	if( npath == 0 )
		err( YES, "Called cont() before move()" );

	if( npath == MAXPATH-1 ) {
		printf( "%ld %ld L\n%ld %ld M\n",
			(long)(x-oldx), (long)(y-oldy), (long)x, (long)y );
		npath = 1;
	}
	else {	printf( "%ld %ld N\n", (long)(x-oldx), (long)(y-oldy) );
		npath++;
	}

	oldx = x;
	oldy = y;
}

static void sendstring( s )
char	*s;
{
register char	c;

	flushpath();
	putchar( '(' );
	while( c = *s++ ) {
		 if( (c == ')') || (c == '(') || (c == '\\') )
			putchar('\\');
	 	if( (c > 0176) || (c <040) ) {
			putchar( '\\' );
			putchar( ((c>>6)&07)+'0' );
			putchar( ((c>>3)&07)+'0' );
			putchar( (c&07)+'0' );
		}
		else	putchar( c );
	}
	putchar( ')' );
	npath = 0;
}

static void flushpath()
{
	if( npath > 1 ) {
		printf( "0 0 L\n" );
		npath = 0;
	}
}

/***** The following subroutines replace the routines in iface.c *****/

static	struct	{
	char	*just;
	short	pos;
	}	*j, jtypes[] = {
	"LB", 0, "LC", 1, "LT", 2, "CT", 3, "RT", 4, "RC", 5,
	"RB", 6, "CB", 7, "CC", 8 };

plabel( lbl, x, y, just, angle )
Ptype	x, y;
char	*lbl, *just;
double	angle;
{
static	char	jtmp[3];

	if( lbl[0] == 0 )
		return;

	for( j=jtypes; j < ENDP(jtypes) ;  j++ ) {
		if( strcmp(j->just,just) == 0 )
			break;
	}
	if( j == ENDP(jtypes) ) {
		err( NO, "Unknown mode `%s' in plabel(%s,...)", just, lbl );
	}
	else {	sendstring( lbl );
		printf( " %ld %ld %ld %.5lg T\n", (long)x, (long)y, (long)(j->pos), angle );
	}
}

alabel( what, lbl, x, y )
Ptype	x, y;
char	*what, *lbl;
{
	sendstring( lbl );
	printf( " %ld %ld %s\n", (long)x, (long)y, what );
}

elabel( what, base, exp, x, y )
char	*what, *base, *exp;
Ptype	x, y;
{
	sendstring( exp );
	putchar( ' ' );
	sendstring( base );
	printf( " %ld %ld %s\n", (long)x, (long)y, what );
}

strsize( str, xsize, ysize, angle )	/* no string size function */
char	*str;
Ptype	*xsize, *ysize;
double	angle;
{
short	len;

	if( fabs(angle) < 1  ) {
		*xsize = chwd * strlen(str);
		*ysize = chht;
	}
	else	if( fabs(angle-90) < 1 ) {
		*xsize = chht;
		*ysize = chwd * strlen(str);
	}
	else	err( NO, "Bad angle %.5lg in for strsize(%s,...)", angle, str );
}


scatterplot( plt, x, y, yneg, ypos )
PltPtr	plt;
Ptype	x, y, yneg, ypos;
{
static	char	lbl[2];

	flushpath();
	yneg -= y;
	ypos -= y;
	if( plt->symbol )
		printf( "%d %ld %ld %ld %ld SY\n", (int)(plt->pc-'0'),
		(long)yneg, (long)ypos, (long)x, (long)y );
	else {	lbl[0] = plt->pc;
		sendstring( lbl );
		printf( " %ld %ld %ld %ld SP\n", (long)yneg, (long)ypos, (long)x, (long)y );
	}
}


PolyDef( x, y, what )
Ptype	x, y;
Const	what;
{
int		fill;

	fill = -1;
	switch( what ) {
		case CMOVE:
			move( x, y );
			break;
		case CBBCONT:
		case CCONT:
			cont( x, y );
			break;
		case CFILL:
		case CFILLI:
			cont( x, y );
			fill = 0;
			break;
		case CSTROKE:
			cont( x, y );	/* flow through */
		case COSTROKE:
			flushpath();
			break;
		case CBBFILL:
		case CBBFILLI:
			cont( x, y );
			fill = 1;
			break;
		default:
			err( YES, "Bad PolyDef() code %d", what );
	}
	if( fill >= 0 ) {
		printf( "%d F\n", fill );
		npath = 0;
	}
	if( npath == MAXPATH )
		fprintf( stderr, "Polygon path exceeds %d sections", MAXPATH );
}

/****************** Special subroutines needed by plt *******************/

special( what, arg0, arg1 )
PtrUnion	arg0, arg1;
{
	switch( what ) {
		case SETPTERM:
			PTERMInit( arg0.c );
			break;
		case SETLINEWIDTH:
			linewidth( *arg0.d );
			break;
		case SETLINEMODE:
			linemod( arg0.c );
			break;
		case SETFONT:
			setfont( arg0.c, *arg1.d );
			break;
		case SETGRAY:
			flushpath();	/* flow through */
		case SETGRAYD:
			setgray( *arg0.d );
			break;
	}
}


static void PTERMInit( pterm )
char	*pterm;
{
double	f1, f2, f3, f4, f5;
short	n;
char	ptmp[50];

	if( pterm == 0 ) {
		ptmp[0] = 0;
		n = 1;
	}
	else
		n = sscanf( pterm, "%s%lf%lf%lf%lf%lf", ptmp, &f1, &f2, &f3, &f4, &f5 );

	PTERMLookup( ptmp, "lw" );	/* defines p */

	if( fscl == DEFAULT )
		fscl = (n > 1) ? f1 : 0.85;
	if( xdim == DEFAULT )
		xdim = (n > 2) ? f2 : p->xinches;
	if( ydim == DEFAULT )
		ydim = (n > 3) ? f3 : p->yinches;
	if( xorig == DEFAULT )
		xorig = (n > 4) ? f4 : 0.5*(8.25-xdim) + 0.25;
	if( yorig == DEFAULT )
		yorig = (n > 5) ? f5 : 0.67*(11-ydim);

	default_ps = DEFAULT_PS;
	xinch = yinch = 300*2;

	p->xinches = xdim;
	p->yinches = ydim;
	p->xfull = p->xsquare = xdim * xinch;
	p->yfull = ydim * yinch;

	p->ch = 1.1*chhtscl*fscl*default_ps/72.0*yinch + 0.5;
	p->cw = 0.5*chwdscl*fscl*default_ps/72.0*xinch + 0.5;

	chht = p->ch;
	chwd = p->cw;
}

/************************************************************************/

static	struct	{
	char	*name;
	char	*code;
	}	*f, fonts[] = {
	"Helvetica", "h",		"Helvetica-Bold", "hb",
	"Helvetica-Oblique", "ho",	"Helvetica-BoldOblique", "hbo",
	"Helvetica-BoldOblique", "hob", 	
	"Courier", "c",			"Courier-Bold",	"cb",
	"Courier-Oblique", "co",	"Courier-BoldOblique", "cbo",
	"Courier-BoldOblique", "cob",
	"Times-Roman", "t",		"Times-Roman", "tr",
	"Times-Italic", "ti",
	"Times-Bold", "tb",		"Times-BoldItalic", "tbi",
	"Times-BoldItalic", "tib",	"Symbol", "s",
	NULLS, NULLS };

static	char	*prev_lm="";


static void setfont( name, ps )
char	*name;
double	ps;
{
static	double	prev_ps = -1;
static	char	*prev_name;
short	n;
char	code[4], *font = name;

	n = 0;
	while( *font ) {
		code[n++] = *(font++) | 040;
		while( *font && *(font++) != '-' );
	}
	code[n] = 0;
		
	for( f=fonts;  f->code != NULLS && strcmp(code,f->code) != 0; f++ );

	if( f->code == NULLS ) {
		f = &fonts[0];
		err( NO, "Unknown font: %s -- Using: %s", name, f->name );
	}
	if( ps < 0  ) {
		err( NO, "Bad font size: %.5lg -- Using 16", ps );
		ps = 16;
	}
	if( prev_ps != ps || prev_name != f->name ) {
		printf( "/%s %.5lg SF\n", prev_name=f->name, prev_ps=ps );
		if( *prev_lm != 0 && strcmp(prev_lm,"solid") != 0 )
			printf( "%s setdash\n", prev_lm );
	}
}


static void linewidth( lw )
double	lw;
{
static	double	prev_lw = -1;

	if( lw < 0 ) {
		err( NO, "Bad line width: %.5lg", lw );
		lw = 2;
	}
	if( prev_lw != lw )
		printf( "%.5lg LW\n", prev_lw = lw );
}


static void linemod( lm )
char	*lm;
{
	flushpath();
	if( strcmp(prev_lm,lm) != 0 )
		printf( "%s setdash\n", prev_lm=lm );
}


static void setgray( gray )
double	gray;
{
	if( gray < 0 || gray > 1) {
		err( NO, "Bad gray value: %.5lg", gray );
		gray = 0;
	}
	printf( "%.5lg setgray\n", gray );
}