2021-10-11 18:37:13 -03:00

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);
}