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