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