117281Sopcode /*
2*17645Sopcode  * @(#)graphics2.c	1.2	01/03/85
317281Sopcode  *
417281Sopcode  * Line drawing and polygon fill routines for the SUN Gremlin
517281Sopcode  * picture editor.  Line drawing courtesy of dsun.c and polygon
617281Sopcode  * fill courtesy of dvar.c.
717281Sopcode  *
817281Sopcode  * Mark Opperman (opcode@monet.BERKELEY)
917281Sopcode  *
1017281Sopcode  */
1117281Sopcode 
1217281Sopcode #include <suntool/tool_hs.h>
1317281Sopcode #include "gremlin.h"
1417281Sopcode 
1517281Sopcode #define point(sun_x, sun_y)  pr_put(scratch_pr, (sun_x), (sun_y), 1)
1617281Sopcode 
1717281Sopcode /* imports from main.c */
1817281Sopcode 
1917281Sopcode extern struct pixrect *scratch_pr;
2017281Sopcode extern linestyle;		/* type of line (1 - 6) */
2117281Sopcode extern linemod;			/* line drawing mask (SOLID, DOTTED, ...) */
2217281Sopcode extern linethickness;		/* 1, 2, 3 */
2317281Sopcode extern SymbolicLines;		/* TRUE if OK to use pr_vector for all lines */
2417281Sopcode extern SUN_XORIGIN;		/* database x-coord of upper left screen */
2517281Sopcode extern SUN_YORIGIN;		/* database y-coord of upper left screen */
2617281Sopcode 
2717281Sopcode /* imports from display.c */
2817281Sopcode 
2917281Sopcode extern minsunx, maxsunx, minsuny, maxsuny;
3017281Sopcode 
3117281Sopcode /* imports from menu.c */
3217281Sopcode 
3317281Sopcode extern struct _menu menu[];
3417281Sopcode extern int HiStipple[];
3517281Sopcode 
3617281Sopcode /* imports from graphics.c */
3717281Sopcode 
3817281Sopcode extern char stipple_patterns[NSTIPPLES][128];
39*17645Sopcode extern rasterlength;
40*17645Sopcode extern bytesperline;
41*17645Sopcode extern nlines;			/* scratch_pr->pr_size.x */
42*17645Sopcode extern char *fill;		/* zero origin in filling buffer */
4317281Sopcode 
4417281Sopcode /* imports from C */
4517281Sopcode 
4617281Sopcode extern char *calloc();
4717281Sopcode 
4817281Sopcode /* locals */
4917281Sopcode 
5017281Sopcode static char *stipplebits;
5117281Sopcode 
5217281Sopcode typedef struct poly {
5317281Sopcode     struct poly *next;		/* doubly-linked lists of vectors */
5417281Sopcode     struct poly *prev;
5517281Sopcode     int param;			/* bressenham line algorithm parameter */
5617281Sopcode     short dy;			/* delta-y for calculating line */
5717281Sopcode     short dx;			/* delta-x for calculating line */
5817281Sopcode     short curry;		/* current y in this vector */
5917281Sopcode     short endx;			/* where vector ends */
6017281Sopcode } polyvector;
6117281Sopcode 
6217281Sopcode 
6317281Sopcode /*
6417281Sopcode  * Vector from (x1, y1) to (x2, y2) using global linemod and linethickness.
6517281Sopcode  * Parameters in database coordinates system.
6617281Sopcode  * Always write to scratch_pr.
67*17645Sopcode  * Borrowed from dsun.
6817281Sopcode  */
GRVector(dbx1,dby1,dbx2,dby2)6917281Sopcode GRVector(dbx1, dby1, dbx2, dby2)
7017281Sopcode float dbx1, dby1, dbx2, dby2;
7117281Sopcode {
7217281Sopcode     register x0;	/* starting point and line-walking registers */
7317281Sopcode     register y0;
7417281Sopcode     register res;
7517281Sopcode     register i;		/* line-bleeding carrier */
7617281Sopcode     int dx;		/* parameters in the line calculations */
7717281Sopcode     int dy;
7817281Sopcode     int xinc;
7917281Sopcode     int yinc;
8017281Sopcode     int x1;		/* end-point of the line */
8117281Sopcode     int y1;
8217281Sopcode     int radius;
8317281Sopcode     int top;		/* how much to bleed line in "up" (left) direction */
8417281Sopcode     int bottom;		/* how much to bleed line in "down" (right) direction */
8517281Sopcode     int stop1;		/* place to stop making circles at start of line */
8617281Sopcode     int stop2;		/* place to start making circles at end of line */
8717281Sopcode     int halfstop;	/* distance tween stop1 and stop3 */
8817281Sopcode     int stop3;		/* midpoint `tween making circles and lines */
8917281Sopcode 
9017281Sopcode     x0 = dbx_to_win(dbx1);	/* convert endpoints to SUN coordinates */
9117281Sopcode     y0 = dby_to_win(dby1);
9217281Sopcode     x1 = dbx_to_win(dbx2);
9317281Sopcode     y1 = dby_to_win(dby2);
9417281Sopcode 
9517281Sopcode     MINMAX(minsunx, maxsunx, x0);
9617281Sopcode     MINMAX(minsuny, maxsuny, y0);
9717281Sopcode     MINMAX(minsunx, maxsunx, x1);
9817281Sopcode     MINMAX(minsuny, maxsuny, y1);
9917281Sopcode 
10017281Sopcode     if ((SymbolicLines) || (linestyle == 5 /* NARROW */)) {
10117281Sopcode 	pr_vector(scratch_pr, x0, y0, x1, y1, PIX_SRC | PIX_DST, 1);
10217281Sopcode 	return;
10317281Sopcode     }
10417281Sopcode 
10517281Sopcode     xinc = 1;
10617281Sopcode     yinc = 1;
10717281Sopcode     if ((dx = x1 - x0) < 0) {
10817281Sopcode         xinc = -1;
10917281Sopcode         dx = -dx;
11017281Sopcode     }
11117281Sopcode     if ((dy = y1 - y0) < 0) {
11217281Sopcode         yinc = -1;
11317281Sopcode         dy = -dy;
11417281Sopcode     }
11517281Sopcode 
11617281Sopcode     radius = (linethickness - 1) / 2;
11717281Sopcode     RoundEnd(x0, y0, radius, TRUE);	/* add ends of line */
11817281Sopcode     RoundEnd(x1, y1, radius, TRUE);	/* (nice and curvy) */
11917281Sopcode 
12017281Sopcode     top = linethickness;	/* increase line thickness if at an angle */
12117281Sopcode     stop1 = halfstop = 0;
12217281Sopcode     if ((i = (int) (sqrt ((double) (dx * dx + dy * dy)) + 0.01)) < 2)
12317281Sopcode 	return;			/* small lines are done with endpoints */
12417281Sopcode 
12517281Sopcode     if (dx >= dy) {
12617281Sopcode 	top = (linethickness * i) / dx;
12717281Sopcode 	stop1 = (linethickness * dy) / (i + 1);
12817281Sopcode 	halfstop = (radius * dy) / i;
12917281Sopcode     } else {
13017281Sopcode 	top = (linethickness * i) / dy;
13117281Sopcode 	stop1 = (linethickness * dx) / (i + 1);
13217281Sopcode 	halfstop = (radius * dx) / i;
13317281Sopcode     }
13417281Sopcode 
13517281Sopcode     bottom = (top - 1) / 2;
13617281Sopcode     top = top / 2;
13717281Sopcode 
13817281Sopcode     if (dx >= dy) {
13917281Sopcode 	res = (dy >> 1) - (dx >> 1);
14017281Sopcode 	if (linethickness >= i) {
14117281Sopcode 	    stop1 = stop2 = x0;
14217281Sopcode 	    halfstop = i + 1;
14317281Sopcode 	} else if (xinc == 1) {
14417281Sopcode 	    stop2 = x1 - stop1;
14517281Sopcode 	    stop1 = x0 + stop1;
14617281Sopcode 	    stop3 = x0 + halfstop;
14717281Sopcode 	} else {
14817281Sopcode 	    stop2 = x1 + stop1;
14917281Sopcode 	    stop1 = x0 - stop1;
15017281Sopcode 	    stop3 = x0 - halfstop;
15117281Sopcode 	}
15217281Sopcode 
15317281Sopcode 	while (x0 != stop1) {
15417281Sopcode 	    RoundEnd(x0, y0, radius, FALSE);
15517281Sopcode             if ((x0 & linemod) && (xinc == 1 ? x0 > stop3 : x0 < stop3)) {
15617281Sopcode 		for (i=y0-top; i<=y0+bottom; i++)
15717281Sopcode 		    point(x0, i);
15817281Sopcode 	    }
15917281Sopcode             if (res >= 0) {
16017281Sopcode                 res -= dx;
16117281Sopcode                 y0 += yinc;
16217281Sopcode             }
16317281Sopcode             res += dy;
16417281Sopcode             x0 += xinc;
16517281Sopcode 	}
16617281Sopcode 
16717281Sopcode         while (x0 != stop2) {
16817281Sopcode             if (x0 & linemod) {
16917281Sopcode 		for (i=y0-top; i<=y0+bottom; i++)
17017281Sopcode 		    point(x0, i);
17117281Sopcode 	    }
17217281Sopcode             if (res >= 0) {
17317281Sopcode                 res -= dx;
17417281Sopcode                 y0 += yinc;
17517281Sopcode             }
17617281Sopcode             res += dy;
17717281Sopcode             x0 += xinc;
17817281Sopcode         }
17917281Sopcode 
18017281Sopcode 	stop3 = x1 + (xinc == 1 ? -halfstop : halfstop);
18117281Sopcode 
18217281Sopcode         while (x0 != x1) {
18317281Sopcode 	    RoundEnd(x0, y0, radius, FALSE);
18417281Sopcode             if ((x0 &linemod) && (xinc == 1 ? x0 < stop3 : x0 > stop3)) {
18517281Sopcode 		for (i = y0 - top; i <= y0 + bottom; i++)
18617281Sopcode 		    point(x0, i);
18717281Sopcode 	    }
18817281Sopcode             if (res >= 0) {
18917281Sopcode                 res -= dx;
19017281Sopcode                 y0 += yinc;
19117281Sopcode             }
19217281Sopcode             res += dy;
19317281Sopcode             x0 += xinc;
19417281Sopcode         }
19517281Sopcode     } else {
19617281Sopcode 	res = (dx >> 1) - (dy >> 1);
19717281Sopcode 
19817281Sopcode 	if (linethickness >= i) {
19917281Sopcode 	    stop1 = stop2 = y0;
20017281Sopcode 	    halfstop = i + 1;
20117281Sopcode 	} else if (yinc == 1) {
20217281Sopcode 	    stop2 = y1 - stop1;
20317281Sopcode 	    stop1 = y0 + stop1;
20417281Sopcode 	    stop3 = y0 + halfstop;
20517281Sopcode 	} else {
20617281Sopcode 	    stop2 = y1 + stop1;
20717281Sopcode 	    stop1 = y0 - stop1;
20817281Sopcode 	    stop3 = y0 - halfstop;
20917281Sopcode 	}
21017281Sopcode 
21117281Sopcode         while (y0 != stop1) {
21217281Sopcode 	    RoundEnd(x0, y0, radius, FALSE);
21317281Sopcode             if ((y0 & linemod) && (yinc == 1 ? y0 > stop3 : y0 < stop3)) {
21417281Sopcode 		for (i = x0 - top; i <= x0 + bottom; i++)
21517281Sopcode 		    point(i, y0);
21617281Sopcode 	    }
21717281Sopcode             if (res >= 0) {
21817281Sopcode                 res -= dy;
21917281Sopcode                 x0 += xinc;
22017281Sopcode             }
22117281Sopcode 	    res += dx;
22217281Sopcode             y0 += yinc;
22317281Sopcode         }
22417281Sopcode 
22517281Sopcode         while (y0 != stop2) {
22617281Sopcode             if (y0&linemod) {
22717281Sopcode 		for (i=x0-top; i<=x0+bottom; i++)
22817281Sopcode 		    point(i, y0);
22917281Sopcode 	    }
23017281Sopcode             if (res >= 0) {
23117281Sopcode                 res -= dy;
23217281Sopcode                 x0 += xinc;
23317281Sopcode             }
23417281Sopcode 	    res += dx;
23517281Sopcode             y0 += yinc;
23617281Sopcode         }
23717281Sopcode 
23817281Sopcode 	stop3 = y1 + (yinc == 1 ? -halfstop : halfstop);
23917281Sopcode 
24017281Sopcode         while (y0 != y1) {
24117281Sopcode 	    RoundEnd(x0, y0, radius, FALSE);
24217281Sopcode             if ((y0 & linemod) && (yinc == 1 ? y0 < stop3 : y0 > stop3)) {
24317281Sopcode 		for (i=x0-top; i<=x0+bottom; i++)
24417281Sopcode 		    point(i, y0);
24517281Sopcode 	    }
24617281Sopcode             if (res >= 0) {
24717281Sopcode                 res -= dy;
24817281Sopcode                 x0 += xinc;
24917281Sopcode             }
25017281Sopcode 	    res += dx;
25117281Sopcode             y0 += yinc;
25217281Sopcode         }
25317281Sopcode     }
25417281Sopcode }
25517281Sopcode 
25617281Sopcode 
25717281Sopcode /*
25817281Sopcode  * Plots a filled (if requested) circle of the specified radius
25917281Sopcode  * centered about (x, y).
26017281Sopcode  * Coordinates are window relative.
261*17645Sopcode  * Modified from dsun source.
26217281Sopcode  */
RoundEnd(x,y,radius,filled)26317281Sopcode RoundEnd(x, y, radius, filled)
26417281Sopcode register x;
26517281Sopcode register y;
26617281Sopcode int radius, filled;
26717281Sopcode {
26817281Sopcode     float xs, ys, epsilon;
26917281Sopcode     register j, k;
27017281Sopcode 
27117281Sopcode 
27217281Sopcode     point(x, y+radius);		/* do the starting point of the circle */
27317281Sopcode 
27417281Sopcode     if (radius < 1)		/* if circle is tiny, quit now */
27517281Sopcode 	return;
27617281Sopcode 
27717281Sopcode     point(x, y-radius);
27817281Sopcode     if (y-radius < minsuny)
27917281Sopcode 	minsuny = y-radius;
28017281Sopcode 
28117281Sopcode     /* Calculate trajectory of the circle for 1/4 the circumference
28217281Sopcode        (while ys is positive) and mirror to get the other three quadrants. */
28317281Sopcode 
28417281Sopcode     xs = 0.0;
28517281Sopcode     ys = (float) radius;
28617281Sopcode     epsilon = 1.0 / ys;
28717281Sopcode 
28817281Sopcode     while (ys >= 0) {
28917281Sopcode 	j = (int) (xs + 0.5);
29017281Sopcode 	k = (int) (ys + 0.5);
29117281Sopcode         if (filled) {		/* fill from center */
29217281Sopcode 	    do {
29317281Sopcode 		point(j+x, k+y);
29417281Sopcode 		point(j+x, y-k);
29517281Sopcode 		point(x-j, k+y);
29617281Sopcode 		point(x-j, y-k);
29717281Sopcode 	    } while (--k >= 0);
29817281Sopcode         } else {		/* do the perimeter only */
29917281Sopcode 	    point(j+x, k+y);
30017281Sopcode 	    point(j+x, y-k);
30117281Sopcode 	    point(x-j, k+y);
30217281Sopcode 	    point(x-j, y-k);
30317281Sopcode         }
30417281Sopcode         xs += epsilon * ys;	/* generate circumference */
30517281Sopcode         ys -= epsilon * xs;
30617281Sopcode     }
30717281Sopcode }  /* end RoundEnd */;
30817281Sopcode 
30917281Sopcode 
31017281Sopcode /*
31117281Sopcode  * Set drawing parameters for filling polygons.
31217281Sopcode  * Must be called before GRStippleFill().
31317281Sopcode  */
GRSetStippleStyle(style)31417281Sopcode GRSetStippleStyle(style)
31517281Sopcode int style;
31617281Sopcode {
31717281Sopcode     if ((style <= 0) || (style > NSTIPPLES)) {
31817281Sopcode 	fprintf(stderr, "GRSetStippleStyle: bad stipple #%d\n", style);
31917281Sopcode 	return;
32017281Sopcode     }
32117281Sopcode 
32217281Sopcode     stipplebits = stipple_patterns[style-1];
32317281Sopcode }
32417281Sopcode 
32517281Sopcode /* >>> stipple fonts must be 32 x 32 bits <<< */
32617281Sopcode #define MASK 31		/* mask to pick off pixel index into stipple */
32717281Sopcode #define BYTEWIDTH 4	/* glyph width in bytes */
32817281Sopcode #define BYTEMASK 3	/* mask to pick off byte index into stipple */
32917281Sopcode 
33017281Sopcode 
33117281Sopcode /*
332*17645Sopcode  * Fill polygon defined by points in plist using parameters set by
333*17645Sopcode  * previous call to GRSetStippleStyle().
33417281Sopcode  *
335*17645Sopcode  * This routine was modified from source for the varian driver.
336*17645Sopcode  * Because the varian rotates everything 90 degrees before printing,
337*17645Sopcode  * the x and y coordinates from the window are reversed before
338*17645Sopcode  * computing the region.  This is just a kludge to get the code
339*17645Sopcode  * to work as soon as possible.  Better to change this at some point,
340*17645Sopcode  * but I don't have time now.
341*17645Sopcode  *
342*17645Sopcode  * The scan-line algorithm implemented scans from left to right
343*17645Sopcode  * (low x to high x).  It also scans, within a line, from bottom to top
344*17645Sopcode  * (high y to low y).  Stipple patterns MUST be a power of two bytes wide
345*17645Sopcode  * and square (in fact, they must be 32 x 32 bits).
34617281Sopcode  */
GRStippleFill(plist)34717281Sopcode GRStippleFill(plist)
34817281Sopcode POINT *plist;
34917281Sopcode {
35017281Sopcode     int nextx;				/* x value where next vector starts */
35117281Sopcode     int maxx, minx, maxy, miny;		/* finds bounds of polygon */
35217281Sopcode     polyvector *activehead;		/* doing fill, is active edge list */
35317281Sopcode     polyvector *waitinghead;		/* edges waiting to be active */
35417281Sopcode     register polyvector *vectptr;	/* random vector */
35517281Sopcode     register int i;			/* random register */
35617281Sopcode 
35717281Sopcode     char *topstipple;			/* beginning of stipple glyph */
35817281Sopcode     char *leftstipple;			/* beginning of line of stipple */
35917281Sopcode     char *bottompage;			/* the edge of a raster line */
36017281Sopcode 
36117281Sopcode     int x[MAXPOINTS];			/* algorithm requires this form */
36217281Sopcode     int y[MAXPOINTS];
36317281Sopcode     int npts;
36417281Sopcode     POINT *p1, p2;
36517281Sopcode 
36617281Sopcode     p1 = plist;
36717281Sopcode     npts = 0;
36817281Sopcode 
369*17645Sopcode     /*
370*17645Sopcode      * convert coordinates to arrays of integers exchanging x and y,
371*17645Sopcode      * and making origin upper right.
372*17645Sopcode      */
37317281Sopcode     while (!Nullpoint(p1)) {
37417281Sopcode 	npts++;
37517281Sopcode 	x[npts] = dby_to_win(p1->y) - 1;
376*17645Sopcode 	y[npts] = rasterlength - 1 - dbx_to_win(p1->x);
37717281Sopcode 	p1 = PTNextPoint(p1);
37817281Sopcode     }
37917281Sopcode 
38017281Sopcode     topstipple = stipplebits;		/* start of stipple pattern */
38117281Sopcode 
38217281Sopcode     /* allocate space for raster-fill algorithm */
383*17645Sopcode     if ((vectptr = (polyvector *) calloc(sizeof(polyvector), npts + 6)) ==
384*17645Sopcode 							(polyvector *) NULL) {
38517281Sopcode 	fprintf(stderr, "unable to allocate space for polygon");
38617281Sopcode 	return;
38717281Sopcode     }
38817281Sopcode 
38917281Sopcode     waitinghead = vectptr;
39017281Sopcode     minx = maxx = x[1];
39117281Sopcode     miny = maxy = y[1];
392*17645Sopcode     (vectptr++)->prev = (polyvector *) NULL;	/* put dummy entry at start */
39317281Sopcode     waitinghead->next = vectptr;
39417281Sopcode     vectptr->prev = waitinghead;
39517281Sopcode 
39617281Sopcode     i = 1;					/* starting point of coords */
39717281Sopcode     if (y[1] != y[npts] || x[1] != x[npts]) {
39817281Sopcode 	y[0] = y[npts];				/* close polygon if it's not */
39917281Sopcode 	x[0] = x[npts];
40017281Sopcode 	i = 0;
40117281Sopcode     }
40217281Sopcode 
40317281Sopcode     while (i < npts) {				/* set up the vectors */
40417281Sopcode 	register int j;				/* indexes to work off of */
40517281Sopcode 	register int k;
40617281Sopcode 
407*17645Sopcode 	/* remember limits */
408*17645Sopcode 	MINMAX(miny, maxy, y[i]);
409*17645Sopcode 	MINMAX(minx, maxx, x[i]);
41017281Sopcode 
41117281Sopcode 	j = i;			/* j points to the higher (lesser) point */
41217281Sopcode 	k = ++i;
41317281Sopcode 	if (x[j] == x[k])			/* ignore vertical lines */
41417281Sopcode 	    continue;
41517281Sopcode 
41617281Sopcode 	if (x[j] > x[k]) {
41717281Sopcode 	    j++;
41817281Sopcode 	    k--;
41917281Sopcode 	}
42017281Sopcode 	vectptr->next = vectptr + 1;
42117281Sopcode 	vectptr->param = x[j];		/* starting point of vector */
42217281Sopcode 	vectptr->dy = y[k] - y[j];	/* line-calculating parameters */
42317281Sopcode 	vectptr->dx = x[k] - x[j];
42417281Sopcode 	vectptr->curry = y[j];		/* starting point */
42517281Sopcode 	(vectptr++)->endx = x[k];	/* ending point */
42617281Sopcode 	vectptr->prev = vectptr - 1;
42717281Sopcode     }
42817281Sopcode 
429*17645Sopcode     /*
430*17645Sopcode      * keep polygon within bounds of scratch pixrect
431*17645Sopcode      * width is checked when actual drawing is done
432*17645Sopcode      */
433*17645Sopcode     if (maxx >= scratch_pr->pr_size.y)
434*17645Sopcode 	maxx = scratch_pr->pr_size.y - 1;
435*17645Sopcode 
43617281Sopcode     /* set now because we didn't know minx before */
43717281Sopcode     leftstipple = topstipple + (minx & MASK) * BYTEWIDTH;
438*17645Sopcode     bottompage = fill + minx * bytesperline;
43917281Sopcode     waitinghead->param = minx - 1;
44017281Sopcode 
44117281Sopcode     /* if no useable vectors, quit */
44217281Sopcode     if (vectptr == waitinghead + 1) {
44317281Sopcode 	free(waitinghead);
44417281Sopcode 	return;
44517281Sopcode     }
44617281Sopcode 
44717281Sopcode     vectptr->param = maxx + 1;		/* dummy entry at end, too */
448*17645Sopcode     vectptr->next = (polyvector *) NULL;
44917281Sopcode 
45017281Sopcode     activehead = ++vectptr;		/* two dummy entries for active list */
45117281Sopcode     vectptr->curry = maxy + 1;		/* head */
45217281Sopcode     vectptr->endx = maxx + 1;
45317281Sopcode     vectptr->param = vectptr->dx = vectptr->dy = 0;
45417281Sopcode     activehead->next = ++vectptr;
45517281Sopcode     activehead->prev = vectptr;
45617281Sopcode 
45717281Sopcode     vectptr->prev = activehead;		/* tail */
45817281Sopcode     vectptr->next = activehead;
45917281Sopcode     vectptr->curry = miny - 1;
46017281Sopcode     vectptr->endx = maxx + 1;
46117281Sopcode     vectptr->param = vectptr->dx = vectptr->dy = 0;
46217281Sopcode 
46317281Sopcode 
46417281Sopcode     /*
46517281Sopcode      * main loop -- gets vectors off the waiting list, then displays spans
46617281Sopcode      * while updating the vectors in the active list
46717281Sopcode      */
46817281Sopcode     while (minx <= maxx) {
46917281Sopcode 	i = maxx + 1;		/* this is the NEXT time to get a new vector */
470*17645Sopcode 	for (vectptr=waitinghead->next; vectptr!=(polyvector *) NULL; ) {
47117281Sopcode 	    if (minx == vectptr->param) {
47217281Sopcode 		/*
47317281Sopcode 		 * The entry in waiting list (vectptr) is ready to go into
47417281Sopcode 		 * active list.  Need to convert some vector stuff and
47517281Sopcode 		 * sort the entry into the list.
47617281Sopcode 		 */
47717281Sopcode 		register polyvector *p;		/* random vector pointers */
47817281Sopcode 		register polyvector *v;
47917281Sopcode 
48017281Sopcode 		/* convert this entry to active */
48117281Sopcode 		if (vectptr->dy < 0)
48217281Sopcode 		    vectptr->param = (vectptr->dy >> 1) - (vectptr->dx >> 1);
48317281Sopcode 		else
48417281Sopcode 		    vectptr->param = -((vectptr->dx >> 1) + (vectptr->dy >> 1));
48517281Sopcode 
48617281Sopcode 		p = vectptr;			/* remove from the */
48717281Sopcode 		vectptr = vectptr->next;	/* waiting list */
48817281Sopcode 		vectptr->prev = p->prev;
48917281Sopcode 		p->prev->next = vectptr;
49017281Sopcode 
49117281Sopcode 		/*
49217281Sopcode 		 * find where it goes in the active list
49317281Sopcode 		 * (sorted greatest first)
49417281Sopcode 		 */
49517281Sopcode 		for (v=activehead->next; v->curry>p->curry; v=v->next)
49617281Sopcode 		    ;
49717281Sopcode 		p->next = v;		/* insert into active list */
49817281Sopcode 		p->prev = v->prev;	/* before the one it stopped on */
49917281Sopcode 		v->prev = p;
50017281Sopcode 		p->prev->next = p;
50117281Sopcode 	    } else {
50217281Sopcode 		if (i > vectptr->param) {
50317281Sopcode 		    i = vectptr->param;
50417281Sopcode 		}
50517281Sopcode 		vectptr = vectptr->next;
50617281Sopcode 	    }
50717281Sopcode 	}
50817281Sopcode 	nextx = i;
50917281Sopcode 
51017281Sopcode 	/* print the polygon while there are no more vectors to add */
51117281Sopcode 	while (minx < nextx) {
51217281Sopcode 	    /* remove any finished vectors */
51317281Sopcode 	    vectptr = activehead->next;
51417281Sopcode 	    do {
51517281Sopcode 		if (vectptr->endx <= minx) {
51617281Sopcode 		    vectptr->prev->next = vectptr->next;
51717281Sopcode 		    vectptr->next->prev = vectptr->prev;
51817281Sopcode 		}
51917281Sopcode 	    } while ((vectptr = vectptr->next) != activehead);
52017281Sopcode 
52117281Sopcode 	    /* draw the span */
522*17645Sopcode 	    if (((unsigned) minx) < nlines) {
52317281Sopcode 	      vectptr = activehead->next;
52417281Sopcode 	      while (vectptr->next != activehead) {
52517281Sopcode 		register int start;		/* get the beginning */
52617281Sopcode 		register int length;		/* and the end of span */
52717281Sopcode 		register char *glyph;
52817281Sopcode 		register char *raster;
52917281Sopcode 
530*17645Sopcode 		start = (rasterlength - 1) - vectptr->curry;
53117281Sopcode 		vectptr = vectptr->next;
532*17645Sopcode 		length = rasterlength - vectptr->curry;
53317281Sopcode 		vectptr = vectptr->next;
53417281Sopcode 
53517281Sopcode 		/* bound the polygon to the page */
536*17645Sopcode 		if (start >= rasterlength)
53717281Sopcode 		    break;
53817281Sopcode 		if (start < 0)
53917281Sopcode 		    start = 0;
540*17645Sopcode 		if (length > rasterlength)
541*17645Sopcode 		    length = rasterlength;
54217281Sopcode 		length -= start;		/* length is in pixels */
54317281Sopcode 
54417281Sopcode 		i = start & 7;
54517281Sopcode 		start = start >> 3;		/* start is in bytes */
54617281Sopcode 		raster = bottompage + start;
54717281Sopcode 		glyph = leftstipple + (start & BYTEMASK);
54817281Sopcode 
54917281Sopcode 		if (i) {			/* do any piece of byte */
55017281Sopcode 		    register char data;		/* that hangs on the front */
55117281Sopcode 
55217281Sopcode 		    data = (*(glyph++)) & (0x7f >> --i);
55317281Sopcode 		    length -= 7 - i;
55417281Sopcode 		    if (length < 0) {		/* less than one byte wide? */
55517281Sopcode 			data &= 0xff << -length;
55617281Sopcode 			length = 0;	/* force clean stoppage */
55717281Sopcode 		    }
55817281Sopcode 		    *(raster++) |= data;
55917281Sopcode 
56017281Sopcode 		    /* update glyph ptr after first byte */
56117281Sopcode 		    if (!(++start & BYTEMASK))
56217281Sopcode 			glyph = leftstipple;
56317281Sopcode 		}
56417281Sopcode 
56517281Sopcode 		/* fill the line of raster */
56617281Sopcode 		while ((length -= 8) >= 0) {
56717281Sopcode 		    *(raster++) |= *(glyph++);
56817281Sopcode 		    if (!(++start & BYTEMASK))
56917281Sopcode 			glyph = leftstipple;
57017281Sopcode 		}
57117281Sopcode 
57217281Sopcode 		/* add any part hanging off the end */
57317281Sopcode 		if (length & 7) {
57417281Sopcode 		    *raster |= (*glyph) & (0xff << -length);
57517281Sopcode 		}
57617281Sopcode 	      }
57717281Sopcode 	    }
57817281Sopcode 
57917281Sopcode 	    /* update the vectors */
58017281Sopcode 	    vectptr = activehead->next;
58117281Sopcode 	    do {
58217281Sopcode 		if (vectptr->dy > 0) {
58317281Sopcode 		    while (vectptr->param >= 0) {
58417281Sopcode 			vectptr->param -= vectptr->dx;
58517281Sopcode 			vectptr->curry++;
58617281Sopcode 		    }
58717281Sopcode 		    vectptr->param += vectptr->dy;
58817281Sopcode 		} else if (vectptr->dy < 0) {
58917281Sopcode 		    while (vectptr->param >= 0) {
59017281Sopcode 			vectptr->param -= vectptr->dx;
59117281Sopcode 			vectptr->curry--;
59217281Sopcode 		    }
59317281Sopcode 		    vectptr->param -= vectptr->dy;
59417281Sopcode 		}
59517281Sopcode 
59617281Sopcode 		/*
59717281Sopcode 		 * must sort the vectors if updates caused them to cross
59817281Sopcode 		 * also move to next vector here
59917281Sopcode 		 */
60017281Sopcode 		if (vectptr->curry > vectptr->prev->curry) {
60117281Sopcode 		    register polyvector *v;		/* vector to move */
60217281Sopcode 		    register polyvector *p;	/* vector to put it after */
60317281Sopcode 
60417281Sopcode 		    v = vectptr;
60517281Sopcode 		    p = v->prev;
60617281Sopcode 		    while (v->curry > p->curry)	/* find the */
60717281Sopcode 			p = p->prev;		/* right vector */
60817281Sopcode 
60917281Sopcode 		    vectptr = vectptr->next;	/* remove from spot */
61017281Sopcode 		    vectptr->prev = v->prev;
61117281Sopcode 		    v->prev->next = vectptr;
61217281Sopcode 
61317281Sopcode 		    v->prev = p;		/* put in new spot */
61417281Sopcode 		    v->next = p->next;
61517281Sopcode 		    p->next = v;
61617281Sopcode 		    v->next->prev = v;
61717281Sopcode 		} else {
61817281Sopcode 		    vectptr = vectptr->next;
61917281Sopcode 		}
62017281Sopcode 	    } while (vectptr != activehead);
62117281Sopcode 
62217281Sopcode 	    if (++minx & MASK) {
62317281Sopcode 		leftstipple += BYTEWIDTH;
62417281Sopcode 	    } else {
62517281Sopcode 		leftstipple = topstipple;
62617281Sopcode 	    }
627*17645Sopcode 	    bottompage += bytesperline;
62817281Sopcode 	} /* while (minx < nextx) */
62917281Sopcode     } /* while (minx <= maxx) */
63017281Sopcode 
63117281Sopcode     free(waitinghead);
63217281Sopcode }  /* end GRStippleFill */
633