[comp.windows.x] Slow circles.

jonnyg@aardvark.umd.EDU (Jon Greenblatt) (05/11/89)

	There have been so many complaints about slow/buggy circles, I
though I'd throw in my 70 lines.  This routine, Draw_ellipse, will draw fast
simple ellipses.  It has been set up so that small filled ellipses work
correctly under different raster ops but large and hollow circles need some
work to work with GXor and other raster ops.  I wrote this to do fast
animation using circles and to solve the problem of a buggy clip algorithm
for large hollow circles on my server.  Circulate this as you wish. If
someone is motivated, maybe they can throw this in the server as a speacial
case. Note: no floating point here!


/*
 *	Draw_ellipse. A fast hollow/filled ellipse routine.
 *
 *	Written by:	Jonathan R. Greenblatt (jonnyg@rover.umd.edu)
 *	Organization:	University of Maryland at College Park.
 *	Date:		May 10, 1989
 *
 */
Draw_ellipse(Dpy,win,gc,cx,cy,rx,ry,fill)
Display *Dpy;
Drawable w;
GC gc;
int cy, cy;	/* X/Y coordinates for center of the ellipse */
int rx, ry;	/* X and Y radius for ellipse */
int fill;	/* Boolean for fill mode */
	{
	long int r, r2, xr, yr, xp, yp;
	int x, y, xf, xo, yo, xs, ys;
	XPoint p[256];

	rx = abs(rx);
	ry = abs(ry);
	if (rx == 0) rx = 1;
	if (ry == 0) ry = 1;
	xo = -1; yo = -1; yp = 0l;
	r  = (rx > ry) ? rx: ry;	/* Largest radius */
	xr = rx; yr = ry;
	r2 = r * r;                     /* Radius squared */

	ry = r * 2;
	rx = 0;
        for (xp = r; xp >= 0; xp--)     /* Loop through quarter circle */
        do {
		if (rx > 250) {
			if (fill)
				XDrawSegments(Dpy,win,gc,p,rx/2);
			else	XDrawPoints(Dpy,win,gc,p,rx,CoordModeOrigin);
			rx = 0;
			}
                if ((int)r != (int)yr) {
                        ys = (yp * yr) / r;
                        xs = xp;}
                else    {
                        xs = (xp * xr) / r;
                        ys = yp;};
                if (!(xo == xs && yo == ys))
                if (fill) {		/* Filled */
		    if (ys != ry) { /* Take this conditional  out if you
					are only using GXcopy */
			ry = ys;
			xf = cx + xs;
			x = cx - xs;
			p[rx].x = x; p[rx++].y = cy-ys;
			p[rx].x = xf; p[rx++].y = cy-ys;
			if (ys > 0) {
				p[rx].x = x; p[rx++].y = cy+ys;
				p[rx].x = xf; p[rx++].y = cy+ys;
				}
			}}
                else    {                       /* Hollow */
                        xo = xs; yo = ys;
                        x = cx - xs;
                        y = cy - ys;
			p[rx].x = x; p[rx++].y = y;
                        y = cy + ys;
			p[rx].x = x; p[rx++].y = y;
                        x = cx + xs;
			p[rx].x = x; p[rx++].y = y;
                        y = cy - ys;
			p[rx].x = x; p[rx++].y = y;
                        };
                if ((yp * yp) >= (r2 - xp * xp)) break;
                yp++;
                } while (1);

	if (rx > 0) {
		if (fill)
			XDrawSegments(Dpy,win,gc,p,rx/2);
		else	XDrawPoints(Dpy,win,gc,p,rx,CoordModeOrigin);
		rx = 0;
		}
	}