2021-10-11 18:20:23 -03:00

281 lines
8.5 KiB
C

#ifndef lint
static char sccsid[] = "@(#)polygon.c 1.1 92/07/30 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));
}