home *** CD-ROM | disk | FTP | other *** search
- /* plot.c - plotting routines
- *
- * 30.Jul.87 jimmc Initial definition
- * 1.Aug.87 jimmc Add PsBox, PText, change args in PInit, add HPGL driver
- * 17.Aug.87 jimmc Add textsize function
- * 19.Aug.87 jimmc Make text device primitive work on one line only
- * 26.Aug.87 jimmc Add PSetWindow
- * 22.Dec.87 jimmc Add call to PSZSetup
- * 18.Jan.88 jimmc lint cleanup
- */
-
- #include <strings.h>
- #include "plot.h"
-
- extern char *malloc();
- extern char *index();
-
- static PDevInfo *infobase;
- static PDevInfo *currentinfo;
- static char *currentfn;
-
- static float Pscale;
- static int Poffsetx,Poffsety;
- static int Pbasex,Pbasey;
- static int TextSizeX, TextSizeY;
- #define SCALEONLY(n) (int)(Pscale*((float)(n)))
- #define SCALEX(x) (Poffsetx+(int)(Pscale*((float)(x-Pbasex))))
- #define SCALEY(y) (Poffsety+(int)(Pscale*((float)(y-Pbasey))))
-
- static double wslx=0.0;
- static double wshx=1.0;
- static double wsly=0.0;
- static double wshy=1.0;
- int wlx,wly,whx,why; /* window boundaries */
-
- static int
- badfunc()
- {
- printf("Bad function pointer in plot package\n");
- }
-
- int /* 1 if OK */
- PSetType(ptype,filename)
- char *ptype; /* plotter type */
- char *filename;
- {
- PDevInfo *p;
-
- for (p=infobase; p; p=p->next)
- if (strcmp(ptype,p->name)==0) break;
- if (!p) {
- printf("no such plot type %s\n", ptype);
- return 0;
- }
- currentinfo = p;
- if (currentfn) free(currentfn);
- currentfn = malloc((unsigned)(strlen(filename)+1));
- if (!currentfn) {
- printf("no memory for filename");
- return 0;
- }
- strcpy(currentfn,filename);
- return 1;
- }
-
- PSetWindow(lx,ly,hx,hy) /* normalized window coords (0.0 to 1.0) */
- double lx,ly,hx,hy;
- {
- double t;
-
- if (hx==lx || hy==ly) return;
- if (hx<lx) { t=hx; hx=lx; lx=t; }
- if (hy<ly) { t=hy; hy=ly; ly=t; }
- if (lx<0.0) lx=0.0;
- if (hx>1.0) hx=1.0;
- if (ly<0.0) ly=0.0;
- if (hy>1.0) hy=1.0;
- wslx=lx;
- wshx=hx;
- wsly=ly;
- wshy=hy;
- }
-
- PInit(lx,ly,hx,hy)
- int lx,ly;
- int hx,hy;
- {
- int devlx,devly,devhx,devhy;
- int devx,devy;
- int vx,vy;
- double xr,yr;
-
- wlx = lx + wslx*(hx-lx); /* do the window scaling */
- whx = lx + wshx*(hx-lx);
- wly = ly + wsly*(hy-ly);
- why = ly + wshy*(hy-ly);
- vx = whx-wlx+1; /* x dimension of virtual drawing area */
- vy = why-wly+1;
- if (!((*currentinfo->init)(currentfn,&devlx,&devly,&devhx,&devhy))) {
- /* get device size */
- return 0; /* no init */
- }
- devx = devhx-devlx+1;
- devy = devhy-devly+1;
- xr = ((double)devx)/((double)vx);
- yr = ((double)devy)/((double)vy);
- Pbasex = wlx;
- Pbasey = wly;
- if (xr>=yr) { /* scale to fix x */
- Pscale = yr*0.95;
- Poffsetx = ((int)(0.025*((double)devx)))+devlx;
- Poffsety = ((int)(0.025*((double)devy)))+devly;
- } else { /* scale to fit y */
- Pscale = xr*0.95;
- Poffsetx = ((int)(0.025*((double)devx)))+devlx;
- Poffsety = ((int)(0.025*((double)devy)))+devly;
- }
- return 1;
- }
-
- PDone()
- {
- (*currentinfo->done)();
- }
-
- PTextSize(x,y)
- int x,y; /* width and height of one character */
- {
- TextSizeX = x;
- TextSizeY = y;
- (*currentinfo->textsize)(SCALEONLY(x),SCALEONLY(y));
- }
-
- #define ASCALE 10000
- typedef int Alphatype;
- #define ALPH(a,l,h) (l+(int)((a*(h-l))/ASCALE))
- #define Paline(lx,ly,hx,hy) \
- (*currentinfo->line)(SCALEX(lx),SCALEY(ly),SCALEX(hx),SCALEY(hy));
-
- static Alphatype
- alpha(l,h,w)
- int l,h;
- int w;
- {
- Alphatype a;
- if (l==h) return 0;
- a = (ASCALE*(w-l))/(h-l);
- if (a<0) return 0;
- if (a>ASCALE) return ASCALE;
- return a;
- }
-
- PLine(lx,ly,hx,hy)
- int lx,ly;
- int hx,hy;
- {
- int t;
- Alphatype aly,ahy;
- Alphatype alx,ahx;
- Alphatype al,ah;
-
- if (hx<wlx || lx>whx || hy<wly || ly>why) return;
- if (lx==hx) { /* vertical line */
- aly = alpha(ly,hy,wly);
- ahy = alpha(ly,hy,why);
- if (aly!=ahy) Paline(lx,ALPH(aly,ly,hy),hx,ALPH(ahy,ly,hy));
- }
- else if (ly==hy) { /* horizontal line */
- alx = alpha(lx,hx,wlx);
- ahx = alpha(lx,hx,whx);
- if (alx!=ahx) Paline(ALPH(alx,lx,hx),ly,ALPH(ahx,lx,hx),hy);
- }
- else { /* angled line */
- #define ORDER(l,h) { \
- if (l>h) { \
- t = l; \
- l = h; \
- h = t; \
- }}
- aly = alpha(ly,hy,wly);
- ahy = alpha(ly,hy,why);
- alx = alpha(lx,hx,wlx);
- ahx = alpha(lx,hx,whx);
- ORDER(aly,ahy)
- ORDER(alx,ahx)
- al = (alx>aly)?alx:aly; /* use highest low and lowest high */
- ah = (ahx<ahy)?ahx:ahy;
- if (al!=ah)
- Paline(ALPH(al,lx,hx),ALPH(al,ly,hy),
- ALPH(ah,lx,hx),ALPH(ah,ly,hy));
- }
- }
-
- PBox(lx,ly,hx,hy)
- int lx,ly;
- int hx,hy;
- {
- PLine(lx,ly,lx,hy);
- PLine(lx,hy,hx,hy);
- PLine(hx,hy,hx,ly);
- PLine(hx,ly,lx,ly);
- }
-
- /* Characters are clipped based on the lower left corner point of each char. */
- PTextLine(lx,ly,text)
- int lx,ly; /* lower left corner of text line */
- char *text;
- {
- int hx;
- int l;
- int oldc=0;
-
- if (!text || !*text) return;
- l = strlen(text);
- hx = lx + l*TextSizeX;
- if (hx<wlx || lx>=whx || ly<wly || ly>=why) return; /* out */
- if (lx<wlx) { /* hangs out the left, lets clip that part */
- l = (wlx-lx+TextSizeX-1)/TextSizeX;
- /* number of chars to clip */
- text += l;
- lx += l*TextSizeX;
- }
- if (hx>whx) { /* hangs out the right */
- l = (hx-whx)/TextSizeX;
- l = strlen(text)-l;
- oldc = text[l];
- text[l] = 0;
- }
- (*currentinfo->text)(SCALEX(lx),SCALEY(ly),text);
- if (oldc) text[l]=oldc; /* restore if we changed it */
- }
-
- PText(x,y,p,text)
- int x,y;
- int p; /* position of (x,y) in text (see plot.h) */
- char *text;
- {
- int sx,sy; /* size of the text block */
- char *t,*e;
- int len;
-
- sx = sy = 0; /* find the size of the text block */
- for (t=text;t;t=e) {
- sy++; /* count lines */
- e = index(t,'\n');
- if (e) len = (e++)-t;
- else len = strlen(t);
- if (len>sx) sx=len; /* count characters */
- }
- if (sx==0 || sy==0) return;
- sx *= TextSizeX;
- sy *= TextSizeY;
- switch (p) { /* convert (x,y) to point to lower left */
- case N: x -= sx/2; y -= sy; break;
- case S: x -= sx/2; break;
- case E: x -= sx; y -= sy/2; break;
- case W: y -= sy/2; break;
- case NE: x -= sx; y -= sy; break;
- case NW: y -= sy; break;
- case SE: x -= sx; break;
- case SW: break; /* this is the default location */
- case C: x -= sx/2; y -= sy/2; break;
- default: break; /* assume default for random stuff */
- }
- y += sy; /* point to upper left corner */
- while (text) {
- y -= TextSizeY; /* point to lower left for this line */
- e = index(text,'\n');
- if (e) *e='\000';
- PTextLine(x,y,text);
- if (e) *(e++)='\n'; /* restore */
- text = e;
- }
- }
-
- PDevInfo *
- Pnew()
- {
- PDevInfo *p;
-
- p = (PDevInfo *)malloc(sizeof(PDevInfo));
- if (!p) {
- printf("no more memory\n"); /*** needs to be more elegant */
- exit(1);
- }
- p->name = "NONAME";
- p->init = badfunc;
- p->done = badfunc;
- p->line = badfunc;
- p->textsize = badfunc;
- p->text = badfunc;
- p->next = infobase; /* add to list */
- infobase = p;
- return p;
- }
-
- PNullSetup()
- {
- PDevInfo *p;
- p = Pnew();
- p->name = "NULL";
- /* leave other stuff as illegal */
- currentinfo = p;
- }
-
- PSetup()
- {
- PNullSetup(); /* set up the non-device */
- /* next, set up each device */
- #ifdef X10
- PXSetup();
- #endif
- PHPSetup();
- PTSetup();
- PSZSetup();
- }
-
- /* end */
-