#ifndef lint static char sccsid[] = "@(#)polygon.c 1.1 94/10/31 Copyr 1985-9 Sun Micro"; #endif /* * Copyright (c) 1985, 1986, 1987, 1988, 1989 by Sun Microsystems, Inc. * Permission to use, copy, modify, and distribute this software for any * purpose and without fee is hereby granted, provided that the above * copyright notice appear in all copies and that both that copyright * notice and this permission notice are retained, and that the name * of Sun Microsystems, Inc., not be used in advertising or publicity * pertaining to this software without specific, written prior permission. * Sun Microsystems, Inc., makes no representations about the suitability * of this software or the interface defined in this software for any * purpose. It is provided "as is" without express or implied warranty. */ /* polygon cgipw_polygon _cgi_draw_global_polygon partial_polygon */ #include "cgipriv.h" Gstate _cgi_state; /* CGI global state */ View_surface *_cgi_vws; /* current view surface */ Outatt *_cgi_att; /* structure containing current attributes */ int _cgi_polybase; /* number of elements in global polygon list */ Ccoor _cgi_global_polylist[MAXPTS]; /* polygon list */ short _cgi_closed_points[MAXPTS]; /* Flags for global polygon * list (see below) */ #define POLY_NORMAL 0 /* Normal drawn polygon edge */ #define POLYLINE_END 1 /* Continue subpolygon, but do not draw edge */ #define POLYGON_END 2 /* End of subpolygon (end of bound) */ /****************************************************************************/ /* */ /* FUNCTION: polygon */ /* */ /* draws non-closed polygon based on global polygon list */ /****************************************************************************/ Cerror polygon(polycoors) Ccoorlist *polycoors; /* list of points */ { int ivw, err; /* error */ err = _cgi_err_check_4(); if (!err) if (polycoors->n > MAXPTS) err = ENMPTSTL; if (!err) { if (!_cgi_state.cgipw_mode) { /* not in cgipw mode */ (void) partial_polygon(polycoors, CLOSE); /* The last subpolygon must be closed. */ _cgi_closed_points[_cgi_polybase - 1] |= POLYGON_END; } else err = ENOTCSTD; /* cgi in cgipw mode */ } if (!err) { ivw = 0; while (_cgi_bump_vws(&ivw)) { /* _cgi_bump_vws sets up _cgi_vws and _cgi_att */ err = _cgi_draw_global_polygon(); } _cgi_polybase = 0; /* Clear global polygon list */ } return (_cgi_errhand(err)); } /****************************************************************************/ /* */ /* FUNCTION: cgipw_polygon */ /* */ /****************************************************************************/ Cerror cgipw_polygon(desc, polycoors) Ccgiwin *desc; Ccoorlist *polycoors; /* list of points */ { int err = NO_ERROR; if (_cgi_state.cgipw_mode) { /* in cgipw mode */ SETUP_CGIWIN(desc); (void) partial_polygon(polycoors, CLOSE); /* The last subpolygon must be closed. */ _cgi_closed_points[_cgi_polybase - 1] |= POLYGON_END; err = _cgi_draw_global_polygon(); _cgi_polybase = 0; /* Clear global polygon list */ } else err = ENOTCSTD; /* not compatible with standard CGI mode */ return (err); } /****************************************************************************/ /* */ /* FUNCTION: _cgi_draw_global_polygon */ /* */ /****************************************************************************/ Cerror _cgi_draw_global_polygon() /* All the points are already on the global polygon list */ { Cerror err = NO_ERROR; Cerror terr; Ccoor devlist[MAXPTS]; /* device coordinate polygon list */ register Ccoor *gpt, *dpt; /* Pointers for global and device lists */ register int i, j, k; /* counters */ int np, npl[MAXPTS]; Clinatt templin; /* Holds line attributes during perimeter */ int itemp; /* converted line width during perimeter */ register u_char *mvP; register Ccoor *coorP; u_char mvlist[MAXPTS]; /* for disjoint perimeter drawing */ Ccoor coorlist[MAXPTS]; /* _cgi_vws->sunview.pw and _cgi_att already set up */ for (gpt = &_cgi_global_polylist[0], dpt = &devlist[0]; (dpt < &devlist[_cgi_polybase]); gpt++, dpt++) { _cgi_devscale(gpt->x, gpt->y, dpt->x, dpt->y); } if (_cgi_polybase >= 3) { pw_lock(_cgi_vws->sunview.pw, &_cgi_vws->sunview.lock_rect); /* set up number of points in each bound, number of bounds */ for (i = 0, j = 0, np = 0; i < _cgi_polybase; i++) { if ((_cgi_closed_points[i] & POLYGON_END) == 0) { j++; } else { npl[np++] = j + 1; j = 0; } } /* fill */ switch (_cgi_att->fill.style) { case SOLIDI: { _cgi_cpw_poly2(devlist, _cgi_polybase, 0, 0, np, npl, 0); break; } case HOLLOW: { break; } case PATTERN: { _cgi_cpw_poly2(devlist, _cgi_polybase, _cgi_att->fill.pattern_index, 1, np, npl, 1); break; } case HATCH: { _cgi_cpw_poly2(devlist, _cgi_polybase, _cgi_att->fill.hatch_index, 0, np, npl, 1); break; } } /* draw perimeter? */ if (_cgi_att->fill.visible == ON) { /* save line attributes while drawing with perimeter attributes */ templin = _cgi_att->line; _cgi_att->line.style = _cgi_att->fill.pstyle; _cgi_att->line.width = _cgi_att->fill.pwidth; itemp = _cgi_vws->conv.line_width; _cgi_vws->conv.line_width = _cgi_vws->conv.perimeter_width; _cgi_att->line.color = _cgi_att->fill.pcolor; mvP = mvlist; *mvP++ = 0; /* don't close individual sub-polygons */ coorP = coorlist; /* * i counts thru list. j counts up polyline. k stays at start of * sub-polygon. */ for (i = j = k = 0; i < _cgi_polybase; i++) { switch (_cgi_closed_points[i]) { case POLY_NORMAL: *mvP++ = 0; *coorP++ = devlist[i]; break; case POLYLINE_END: /* * Reached end of polygon or polyline (i.e., last drawn * edge) */ *mvP++ = 1; /* don't draw to NEXT edge */ *coorP++ = devlist[i]; break; case POLYGON_END: /* * subpolygon end: close back to first point in boundry */ *coorP++ = devlist[i]; *mvP = 0; *coorP = devlist[k]; terr = _cgi_polyline(_cgi_vws, i - k + 2, coorlist, mvlist, DONT_XFORM); if (!err) err = terr; mvP = &mvlist[1]; coorP = coorlist; k = i + 1; /* start of next subpolygon */ break; } } _cgi_att->line = templin; _cgi_vws->conv.line_width = itemp; } /* end (_cgi_att->fill.visible == ON) */ pw_unlock(_cgi_vws->sunview.pw); /* unlock the window */ } else err = EPLMTHPT; /* 1984 standard says 0 points is a no-op, 1, a * dot; 2, line */ return (err); } /****************************************************************************/ /* */ /* FUNCTION: partial_polygon */ /* */ /* adds coordinates to global polyline list */ /****************************************************************************/ Cerror partial_polygon(polycoors, cflag) Ccoorlist *polycoors; /* list of points */ Ccflag cflag; /* close previous subpolygon (or add nondrawn) */ { Cerror err; register Ccoor *point; register int i; err = _cgi_err_check_4(); if (!err) if (polycoors->n > MAXPTS) err = ENMPTSTL; if (!err) { if (_cgi_polybase > 0) _cgi_closed_points[_cgi_polybase - 1] |= (cflag == CLOSE) ? POLYGON_END : POLYLINE_END; /* Add the points from this call to the global polygon list */ for (point = polycoors->ptlist, i = 0; (i < polycoors->n); i++) { _cgi_closed_points[_cgi_polybase] = POLY_NORMAL; _cgi_global_polylist[_cgi_polybase++] = *point++; if (_cgi_polybase > MAXPTS) { /* polygon list is full */ err = EGPLISFL; break; } } } return (_cgi_errhand(err)); }