[comp.windows.x] Bug in XDrawArc?

lewin@rocket.sanders.COM (Stu Lewin) (01/22/91)

I am having the weirdest problem with a program. If using a value of
90 degrees for the arc's span, I get an error in the smallest arc. If
I change the span to be less than 90 (89, 80, 70, 45, etc.) it works
fine. If I change it to more than 90 (91, 95, 100, etc.) it also works
fine. It is also only the closest range ring, the others draw as
expected. Changing the invocation as shown (which varies the number of
range rings to draw) causes some of them to be drawn incorrectly and
some not.

I am running on a SPARCstation 1+, color, using MIT's server with
fixes through 18. I compile the program with:
      cc -o xbug xbug.c -lX11
We are running SunOS 4.1.1.

Could someone please either verify this is a bug, or else tell me what
I am doing wrong. As I have a demo on Monday, I'm getting kind of
desperate and would settle for a "Hey stupid, your writing over this
variable" type message, although using the debugger and print
statements I can't see where.

As I can't keep up with this group anymore, please reply directly to
me.

Thanks in advance!

Stu Lewin                                  Lockheed Sanders, Inc.
Ada Projects Leader                        PO Box 2034, MER24-1583C
Signal Processing Center of Technology     Nashua, NH 03061-2034
(usenet)   ...!uunet!rocket!lewin          603/885-0179 (Voice)
(internet) lewin@rocket.sanders.com        603/885-0631 (FAX)


===================<< Begin Included Text >>===========================
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>

#define WHEREX 0
#define WHEREY 0
#define WIDTH  300
#define HEIGHT 300
#define BORDER_WIDTH 5
#ifndef NULL
#define NULL 0
#endif

void x_outline();

Display *display;
Window  pixmap;
GC      white_gc;

int
main( argc, argv )
     int  argc;
     char *argv[];
{
  int           screen;
  XSizeHints    s_hints;
  unsigned long bg_color, fg_color;
  XGCValues     values;
  unsigned long mask;
  unsigned int  done;
  int           key_count;
  XEvent        event;
  KeySym        key;
  char          text[10];

  display = XOpenDisplay();
  if ( ! display )
  {
    fprintf(stderr, "Unable to open display\n");
    exit(1);
  }
  screen = DefaultScreen(display);

  s_hints.x      = WHEREX;
  s_hints.y      = WHEREY;
  s_hints.width  = WIDTH;
  s_hints.height = HEIGHT;
  s_hints.flags  = PPosition | PSize;

  bg_color = BlackPixel( display, screen );
  fg_color = WhitePixel( display, screen );

  pixmap = XCreateSimpleWindow( display, RootWindow( display, screen ),
			       s_hints.x, s_hints.y,
			       s_hints.width, s_hints.height,
			       BORDER_WIDTH,
			       fg_color, bg_color );

  XSetStandardProperties( display, pixmap,
			 "Radar Display", "radar",
			 None, NULL, 0, &s_hints );

  mask = GCFunction;
  values.function = GXcopy;
  white_gc = XCreateGC( display, pixmap, mask, &values );
  XSetBackground( display, white_gc, bg_color);
  XSetForeground( display, white_gc, fg_color);

  XSelectInput( display, pixmap, ButtonPressMask|KeyPressMask|ExposureMask );

  XMapRaised( display, pixmap );

  done = 0;
  while ( !done ) {

    XNextEvent( display, &event );
    switch( event.type ) {

    case Expose:
      x_outline( 90, 200, 91140, 30380 );
/*
 *               ^^ This is the angle that causes problems.
 *
 * Using a value of 90 causes the first range ring to be drawn to
 * something other than 90 degrees of arc, although the rest of them
 * work fine. Using anything other than 90 appears to work correctly.
 *
 * Using these other callls (which varies the number of range rings
 * to be drawn) causes some other weird effects as well. In these
 * cases, some are drawn correctly and some are not.
 *     x_outline( 90, 200, 91140, 15190 );
 *     x_outline( 90, 200, 91140, 7595 );
 */
      break;

    case MappingNotify:
      XRefreshKeyboardMapping( &event );
      break;

    case ButtonPress:
      done = 1;
      break;

    case KeyPress:
      key_count = XLookupString( &event, text, sizeof(text), &key, 0);
      if( key_count == 1 && text[0] == 'q' )
	done = 1;
      break;

    default:
      break;

    }

  }

  XCloseDisplay( display );

}

void
x_outline( scan_angle, maxscans, distance, length)
     int scan_angle;
     int maxscans;
     int distance;
     int length;
{

  int          angle1;
  int          angle2;
  int	       x, y;
  unsigned int increment;
  unsigned int range;
  unsigned int scale;
  unsigned int side;
  XPoint       points[3];

  /*
   * Draw the range rings as circles. They are centered at the
   * lower center of the window, and each cuts through the same
   * angle. The major and minor axes are enlarged each time to get
   * the increasing diameter (or range). This code assumes that
   * the scan_angle is always less than 180 degrees. Remember that
   * angles in X are scaled by 64.
   */
  angle1 = 90 - (scan_angle / 2);
  angle2 = scan_angle;
  angle1 <<= 6;
  angle2 <<= 6;

  /*
   * Start with the smallest range ring (located at the bottom of
   * the window), and work outwards until we've reached the limit
   * of what the radar can display.
   */
  scale = distance / HEIGHT;   /* # feet / pixel */
  x = WIDTH / 2;
  y = HEIGHT;
  increment = length / scale;

  for( side = 0, range = 0; range <= distance; range += length )
  {
    side += (2 * increment);
    x -= increment;
    y -= increment;
    XDrawArc( display, pixmap, white_gc,
	     x, y, side, side, angle1, angle2 );
  }

  /* Now draw the V-shaped outline of the radar display */
  points[0].x = 0;
  points[0].y = HEIGHT / 2;
  points[1].x = WIDTH / 2;
  points[1].y = HEIGHT;
  points[2].x = WIDTH;
  points[2].y = HEIGHT / 2;

  XDrawLines( display, pixmap, white_gc, points, 3, CoordModeOrigin );

}