319 lines
10 KiB
C
319 lines
10 KiB
C
#ifndef lint
|
|
static char sccsid[] = "@(#)circle.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.
|
|
*/
|
|
/*
|
|
* CGI circle functions
|
|
*/
|
|
|
|
/*
|
|
circle
|
|
cgipw_circle
|
|
_cgi_circle
|
|
_cgi_inner_circle
|
|
_cgi_circ_pts
|
|
_cgi_pattern_circle
|
|
_cgi_circ_ret_pts
|
|
*/
|
|
|
|
/*
|
|
bugs:
|
|
textured circle
|
|
VP's algorithm
|
|
error numbers
|
|
*/
|
|
|
|
#include "cgipriv.h" /* defines types used in this file */
|
|
#ifndef window_hs_DEFINED
|
|
#include <sunwindow/window_hs.h>
|
|
#endif
|
|
|
|
View_surface *_cgi_vws; /* current view surface */
|
|
Outatt *_cgi_att; /* structure containing current attributes */
|
|
int _cgi_pix_mode; /* pixrect equivalent of drawing mode */
|
|
Pixrect *_cgi_circrect;
|
|
Pixrect *_cgi_pattern();
|
|
|
|
/* Like pw_put, but uses RasterOp code */
|
|
#define PW_PUT_WITH_OP(pw,x,y,op,color) pw_vector(pw, x,y, x,y, op, color)
|
|
|
|
/****************************************************************************/
|
|
/* */
|
|
/* FUNCTION: circle */
|
|
/* */
|
|
/* draws a circle of radius rad centered at c1 */
|
|
/****************************************************************************/
|
|
|
|
Cerror circle(c1, rad)
|
|
Ccoor *c1; /* center */
|
|
Cint rad; /* radius */
|
|
{
|
|
int ivw;
|
|
Cerror err; /* error */
|
|
Ccoor ca;
|
|
|
|
err = _cgi_err_check_4();
|
|
if (!err)
|
|
{
|
|
ca = *c1;
|
|
ivw = 0;
|
|
while (_cgi_bump_vws(&ivw))
|
|
{
|
|
err = _cgi_circle(_cgi_vws, &ca, rad);
|
|
}
|
|
}
|
|
return (_cgi_errhand(err));
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/* */
|
|
/* FUNCTION: cgipw_circle */
|
|
/* */
|
|
/* draws a circle of radius rad centered at c1 */
|
|
/****************************************************************************/
|
|
|
|
Cerror cgipw_circle(desc, c1, rad)
|
|
Ccgiwin *desc;
|
|
Ccoor *c1; /* center */
|
|
Cint rad; /* radius */
|
|
{
|
|
SETUP_CGIWIN(desc);
|
|
return (_cgi_circle(desc->vws, c1, rad));
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/* */
|
|
/* FUNCTION: _cgi_circle */
|
|
/* */
|
|
/* draws a circle of radius rad centered at c1 */
|
|
/****************************************************************************/
|
|
|
|
Cerror _cgi_circle(vws, c1, rad)
|
|
View_surface *vws;
|
|
Ccoor *c1; /* center */
|
|
Cint rad; /* radius */
|
|
{
|
|
register Outatt *attP = vws->att;
|
|
int x1, y1, srad;
|
|
int color, width;
|
|
Cerror err = NO_ERROR;
|
|
Clintype style;
|
|
/* Rect subrect; */
|
|
|
|
if (rad < 0) /* radius is always interpreted as positive as
|
|
* per standard */
|
|
rad = -rad;
|
|
_cgi_devscale(c1->x, c1->y, x1, y1);
|
|
_cgi_devscalen(rad, srad);
|
|
/* rad2 = (srad + srad)++;
|
|
subrect.r_left = (short)(x1 - srad);
|
|
subrect.r_top = (short)(y1 - srad);
|
|
subrect.r_width = (short)(rad2);
|
|
subrect.r_height = (short)(rad2);
|
|
*/
|
|
style = attP->fill.pstyle;
|
|
color = attP->fill.pcolor;
|
|
width = vws->conv.perimeter_width;
|
|
if (rad > 0)
|
|
{
|
|
pw_lock(vws->sunview.pw, &vws->sunview.lock_rect);
|
|
if ((style == SOLID) && (attP->fill.style == SOLIDI) &&
|
|
(attP->fill.visible == ON) &&
|
|
(attP->fill.color == attP->fill.pcolor)
|
|
) /* special case for solid circle */
|
|
_cgi_inner_circle(vws, x1, y1, srad + width,
|
|
attP->fill.color);
|
|
else
|
|
{ /* fill and draw perimeter */
|
|
if (width > srad)
|
|
width = srad;
|
|
else if (width <= 0)
|
|
width = 1;
|
|
/* srad -= width; */
|
|
switch (attP->fill.style)
|
|
{
|
|
case SOLIDI:
|
|
{
|
|
_cgi_inner_circle(vws, x1, y1, srad,
|
|
attP->fill.color);
|
|
break;
|
|
}
|
|
case HOLLOW: /* will need to be changed for full
|
|
* transparency in next CGI */
|
|
{
|
|
break;
|
|
}
|
|
case PATTERN:
|
|
{
|
|
_cgi_pattern_circle(vws, x1, y1, srad,
|
|
attP->fill.color,
|
|
attP->fill.pattern_index, 1);
|
|
break;
|
|
}
|
|
case HATCH:
|
|
{
|
|
_cgi_pattern_circle(vws, x1, y1, srad,
|
|
attP->fill.color,
|
|
attP->fill.hatch_index, 0);
|
|
break;
|
|
}
|
|
}
|
|
srad += width;
|
|
if (attP->fill.visible == ON)
|
|
{
|
|
if (srad)
|
|
_cgi_angle_textured_circle(x1, y1, srad,
|
|
width, color, style);
|
|
}
|
|
}
|
|
pw_unlock(vws->sunview.pw);
|
|
}
|
|
else /* special case for point */
|
|
PW_PUT_WITH_OP(vws->sunview.pw, x1, y1, _cgi_pix_mode, color);
|
|
return (err);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/* */
|
|
/* FUNCTION: _cgi_inner_circle */
|
|
/* */
|
|
/* draws a solid circle with coors in screen space */
|
|
/* Algorithm from Michie by way of Foley and Can Dam */
|
|
/****************************************************************************/
|
|
int _cgi_inner_circle(vws, x0, y0, rad, val)
|
|
View_surface *vws;
|
|
short x0, y0, rad, val;
|
|
{
|
|
register int x, y, d;
|
|
|
|
x = 0;
|
|
d = -rad;
|
|
pw_vector(vws->sunview.pw, x0 - rad, y0, x0 + rad, y0, _cgi_pix_mode, val);
|
|
for (y = rad; y >= 0; y--)
|
|
{
|
|
while (d <= 0)
|
|
{
|
|
d += 2 * x + 1;
|
|
x++;
|
|
}
|
|
d -= 2 * y - 1;
|
|
_cgi_circ_pts(vws, x0, y0, x, y, val);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************/
|
|
/* */
|
|
/* FUNCTION: _cgi_circ_pts */
|
|
/* */
|
|
/* draws scan lines of solid circle using symetry */
|
|
/****************************************************************************/
|
|
_cgi_circ_pts(vws, x0, y0, x, y, color)
|
|
View_surface *vws;
|
|
short x0, y0, x, y, color;
|
|
{ /* draw symmetry points of circle */
|
|
int a1, a3, b2, b4;
|
|
a1 = x0 + x;
|
|
a3 = x0 - x;
|
|
b2 = y0 + y;
|
|
b4 = y0 - y;
|
|
pw_vector(vws->sunview.pw, a3, b2, a1, b2, _cgi_pix_mode, color);
|
|
pw_vector(vws->sunview.pw, a3, b4, a1, b4, _cgi_pix_mode, color);
|
|
}
|
|
|
|
#define pw_pencil(dpw, x, y, w, h, op, stpr, stx, sty, spr, sy, sx) \
|
|
(*(dpw)->pw_ops->pro_stencil) ((dpw)->pw_opshandle, \
|
|
x - (dpw)->pw_opsx, y - (dpw)->pw_opsy, \
|
|
w, h, op, stpr, stx, sty, spr, sy, sx)
|
|
/****************************************************************************/
|
|
/* */
|
|
/* FUNCTION: _cgi_pattern_circle */
|
|
/* */
|
|
/* draws a pattern circle with coors in screen space */
|
|
/* ***********************************************************************/
|
|
int _cgi_pattern_circle(vws, x0, y0, rad, val, index, flag)
|
|
View_surface *vws;
|
|
short x0, y0, rad, val, index, flag;
|
|
{
|
|
int x, y, d, size;
|
|
Pixrect *patrect, *outrect;
|
|
|
|
size = 1 + rad + rad;
|
|
_cgi_circrect = mem_create(size, size, 1);
|
|
outrect = mem_create(size, size, vws->sunview.depth);
|
|
patrect = _cgi_pattern(index, flag);
|
|
(void) pr_replrop(outrect, 0, 0, size, size, PIX_SRC,
|
|
patrect, x0 - rad, y0 - rad); /* ULC of outrect on
|
|
* screen */
|
|
(void) pr_destroy(patrect);
|
|
x = 0;
|
|
y = rad;
|
|
d = 3 - 2 * rad;
|
|
while (x < y)
|
|
{
|
|
_cgi_circ_ret_pts(rad, rad, x, y, val);
|
|
if (d < 0)
|
|
d = d + 4 * x + 6;
|
|
else
|
|
{
|
|
d = d + 4 * (x - y) + 10;
|
|
y = y - 1;
|
|
}
|
|
x += 1;
|
|
}
|
|
if (x = y)
|
|
_cgi_circ_ret_pts(rad, rad, x, y, val);
|
|
/* pw_write(vws->sunview.pw,x0-rad,y0-rad,size,size,_cgi_pix_mode,_cgi_circrect,0,0); */
|
|
/*
|
|
* Except for symmetry of always locking in the same place in the code, and
|
|
* except for locking around the perimeter with the same lock, we wouldn't
|
|
* have to lock, except around the stencil below
|
|
*/
|
|
pw_pencil(vws->sunview.pw, x0 - rad, y0 - rad, size, size,
|
|
_cgi_pix_mode, _cgi_circrect, 0, 0, outrect, 0, 0);
|
|
(void) pr_destroy(outrect);
|
|
(void) pr_destroy(_cgi_circrect);
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/* */
|
|
/* FUNCTION: _cgi_circ_ret_pts */
|
|
/* */
|
|
/* draws non-closed _cgi_circ_ret_pts */
|
|
/****************************************************************************/
|
|
|
|
int _cgi_circ_ret_pts(x0, y0, x, y, color)
|
|
short x0, y0, x, y, color;
|
|
{ /* draw symmetry points of circle */
|
|
int a1, a2, a3, a4, b1, b2, b3, b4;
|
|
int bop;
|
|
|
|
bop = PIX_OPCOLOR(255) | PIX_SRC;
|
|
a1 = x0 + x;
|
|
a2 = x0 + y;
|
|
a3 = x0 - x;
|
|
a4 = x0 - y;
|
|
b1 = y0 + x;
|
|
b2 = y0 + y;
|
|
b3 = y0 - x;
|
|
b4 = y0 - y;
|
|
(void) pr_vector(_cgi_circrect, a4, b1, a2, b1, bop, color);
|
|
(void) pr_vector(_cgi_circrect, a3, b2, a1, b2, bop, color);
|
|
(void) pr_vector(_cgi_circrect, a4, b3, a2, b3, bop, color);
|
|
(void) pr_vector(_cgi_circrect, a3, b4, a1, b4, bop, color);
|
|
}
|