home *** CD-ROM | disk | FTP | other *** search
/ Graphics Programming Black Book (Special Edition) / BlackBook.bin / disk1 / source / chapterb / lb-1.c next >
C/C++ Source or Header  |  1997-06-18  |  3KB  |  92 lines

  1. /* *** Listing 17.1 ***
  2.  *
  3.  * Draws a circle of the specified radius and color.
  4.  * Will work on VGA or EGA in 16-color mode.
  5.  * Compiled with Borland C++ 4.02 and linked with L17-2.C in small model.
  6.  * Checked by Jim Mischel 11/30/94
  7.  */
  8.  
  9. #include <math.h>
  10. #include <dos.h>
  11.  
  12. /* Handle differences between Turbo C & MSC. Note that Turbo C accepts
  13.    outp as a synonym for outportb, but not outpw for outport */
  14. #ifdef __TURBOC__
  15. #define outpw    outport
  16. #endif
  17.  
  18. #define SCREEN_WIDTH_IN_BYTES    80    /* # of bytes across one scan
  19.                        line in mode 12h */
  20. #define SCREEN_SEGMENT 0xA000         /* mode 12h display memory seg */
  21. #define GC_INDEX    0x3CE            /* Graphics Controller port */
  22. #define SET_RESET_INDEX 0        /* Set/Reset reg index in GC */
  23. #define SET_RESET_ENABLE_INDEX 1        /* Set/Reset enable reg index in GC */
  24. #define BIT_MASK_INDEX 8            /* Bit Mask reg index in GC */
  25.  
  26. /* Draws a pixel at screen coordinate (X,Y) */
  27. void DrawDot(int X, int Y) {
  28.     unsigned char far *ScreenPtr;
  29.  
  30.    /* Point to the byte the pixel is in */
  31. #ifdef __TURBOC__
  32.    ScreenPtr = MK_FP(SCREEN_SEGMENT,
  33.    (Y * SCREEN_WIDTH_IN_BYTES) + (X / 8));
  34. #else
  35.    FP_SEG(ScreenPtr) = SCREEN_SEGMENT;
  36.    FP_OFF(ScreenPtr) =(Y * SCREEN_WIDTH_IN_BYTES) + (X / 8);
  37. #endif
  38.  
  39. /* Set the bit mask within the byte for the pixel */
  40.    outp(GC_INDEX + 1, 0x80 >> (X & 0x07));
  41.  
  42. /* Draw the pixel. ORed to force read/write to load latches.
  43.    Data written doesn't matter, because set/reset is enabled
  44.    for all planes. Note: don't OR with 0; MSC optimizes that
  45.    statement to no operation */
  46.    *ScreenPtr |= 0xFE;
  47. }
  48.  
  49. /* Draws a circle of radius Radius in color Color centered at
  50.  * screen coordinate (X,Y) */
  51. void DrawCircle(int X, int Y, int Radius, int Color) {
  52.     int MajorAxis, MinorAxis;
  53.    double RadiusSquared = (double) Radius * Radius;
  54.  
  55.    /* Set drawing color via set/reset */
  56.    outpw(GC_INDEX, (0x0F << 8) | SET_RESET_ENABLE_INDEX);
  57.    /* enable set/reset for all planes */
  58.    outpw(GC_INDEX, (Color << 8) | SET_RESET_INDEX);
  59.    /* set set/reset (drawing) color */
  60.    outp(GC_INDEX, BIT_MASK_INDEX);
  61.    /* leave the GC pointing to Bit Mask reg */
  62.  
  63.    /* Set up to draw the circle by setting the initial point to one
  64.    end of the 1/8th of a circle arc we'll draw */
  65.    MajorAxis = 0;
  66.    MinorAxis = Radius;
  67.  
  68.    /* Draw all points along an arc of 1/8th of the circle, drawing
  69.    all 8 symmetries at the same time */
  70.    do {
  71.    /* Draw all 8 symmetries of current point */
  72.       DrawDot(X+MajorAxis, Y-MinorAxis);
  73.       DrawDot(X-MajorAxis, Y-MinorAxis);
  74.       DrawDot(X+MajorAxis, Y+MinorAxis);
  75.       DrawDot(X-MajorAxis, Y+MinorAxis);
  76.       DrawDot(X+MinorAxis, Y-MajorAxis);
  77.       DrawDot(X-MinorAxis, Y-MajorAxis);
  78.       DrawDot(X+MinorAxis, Y+MajorAxis);
  79.       DrawDot(X-MinorAxis, Y+MajorAxis);
  80.       MajorAxis++;        /* advance one pixel along major axis */
  81.       MinorAxis =
  82.     sqrt(RadiusSquared - ((double) MajorAxis * MajorAxis)) + 0.5;
  83.     /* calculate corresponding point along minor axis */
  84.   } while ( MajorAxis <= MinorAxis );
  85.  
  86.     /* Reset the Bit Mask register to normal */
  87.     outp(GC_INDEX + 1, 0xFF);
  88.  
  89.     /* Turn off set/reset enable */
  90.     outpw(GC_INDEX, (0x00 << 8) | SET_RESET_ENABLE_INDEX);
  91. }
  92.